├── .gitignore ├── CMakeListsUser.txt ├── LICENSE ├── README.md ├── builder.py ├── builder ├── config.j2.h └── platformio.j2.ini ├── configs └── config.yml.example ├── fakeesp ├── .gitignore ├── CMakeLists.txt ├── ESPAsyncTCP │ ├── .gitignore │ ├── LICENSE.txt │ ├── README.md │ └── src │ │ ├── AsyncPrinter.cpp │ │ ├── AsyncPrinter.h │ │ ├── DebugPrintMacros.h │ │ ├── ESPAsyncTCP.cpp │ │ ├── ESPAsyncTCP.h │ │ ├── ESPAsyncTCPbuffer.cpp │ │ ├── ESPAsyncTCPbuffer.h │ │ └── async_config.h ├── LICENSE.bsd ├── LICENSE.lgpl2 ├── README.md ├── gen_numbers.py ├── include │ ├── Arduino.h │ ├── ArduinoOTA.h │ ├── ArduinoTime.h │ ├── ESP.h │ ├── ESP8266WiFi.h │ ├── ESP8266mDNS.h │ ├── FS.h │ ├── FSImpl.h │ ├── HardwareSerial.h │ ├── Hash.h │ ├── IPAddress.h │ ├── Print.h │ ├── Printable.h │ ├── Stream.h │ ├── WString.h │ ├── c_types.h │ ├── cbuf.h │ ├── esp8266_peri.h │ ├── itoa.h │ ├── libb64 │ │ ├── AUTHORS │ │ ├── LICENSE │ │ ├── cdecode.h │ │ └── cencode.h │ ├── lwip │ │ ├── err.h │ │ ├── init.h │ │ ├── ip_addr.h │ │ └── pbuf.h │ ├── md5.h │ ├── progmem.h │ ├── uart.h │ └── user_interface.h ├── main.cpp └── src │ ├── ArduinoTime.cpp │ ├── FS.cpp │ ├── FakeGPIO.cpp │ ├── GenericStuff.cpp │ ├── Hash.cpp │ ├── IPAddress.cpp │ ├── Print.cpp │ ├── Stream.cpp │ ├── WString.cpp │ ├── cbuf.cpp │ ├── itoa.cpp │ ├── libb64 │ ├── AUTHORS │ ├── LICENSE │ ├── cdecode.cpp │ └── cencode.cpp │ ├── md5.cpp │ └── uart.cpp ├── html ├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── gulpfile.js ├── package.json ├── prettier.config.js ├── src │ ├── components │ │ ├── app.tsx │ │ ├── modal │ │ │ ├── index.tsx │ │ │ └── modal.scss │ │ ├── terminal │ │ │ ├── index.tsx │ │ │ └── overlay.ts │ │ └── zmodem │ │ │ └── index.tsx │ ├── favicon.png │ ├── index.tsx │ ├── style │ │ └── index.scss │ └── template.html ├── tsconfig.json ├── tslint.json ├── webpack.config.js └── yarn.lock ├── include ├── ExtendedSerial.h ├── config.h ├── debug.h ├── html.h ├── server.h ├── ttyd.h ├── version.h └── wise_boards.h ├── platformio.ini ├── requirements.txt └── src ├── ExtendedSerial.cpp ├── main.cpp ├── server.cpp └── ttyd.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | CMakeLists.txt 3 | CMakeListsPrivate.txt 4 | cmake-build-*/ 5 | .idea/ 6 | include/config.h 7 | 8 | .builder/ 9 | configs/*.yml 10 | -------------------------------------------------------------------------------- /CMakeListsUser.txt: -------------------------------------------------------------------------------- 1 | # Needed to work around a CLion integration bug 2 | 3 | SET(CMAKE_C_STANDARD 11) 4 | -------------------------------------------------------------------------------- /builder/config.j2.h: -------------------------------------------------------------------------------- 1 | {# This file generates the config.h header. This is the file you need to edit if you would like to make changes #} 2 | // 3 | // {{ cfg.AUTOGEN_MSG }} 4 | // {{ cfg.AUTOGEN_DATE }} 5 | // 6 | 7 | #include 8 | 9 | #ifndef WI_SE_SW_CONFIG_H 10 | #define WI_SE_SW_CONFIG_H 11 | 12 | // Enables debug messages to debug UART 13 | #define ENABLE_DEBUG {{ cfg.ENABLE_DEBUG }} 14 | // Prints a bunch of timing measurements to debug UART 15 | #define ENABLE_BENCHMARK {{ cfg.ENABLE_BENCHMARK }} 16 | 17 | // Board configuration 18 | // Available board types: 19 | // - 0: generic ESP8266 boards 20 | // - 1: wi-se-rpi-v0.1 21 | // - 2: wi-se-opi4-v0.1 22 | // - 3: wi-se-rewirable-v0.1 23 | #define BOARD_TYPE {{ cfg.BOARD_TYPE }} 24 | 25 | // UART configuration 26 | #define UART_COMM {{ cfg.UART_COMM }} 27 | #define UART_COMM_BAUD {{ cfg.UART_COMM_BAUD }} 28 | #define UART_COMM_CONFIG {{ cfg.UART_COMM_CONFIG }} 29 | 30 | #define UART_DEBUG {{ cfg.UART_DEBUG }} 31 | #define UART_DEBUG_BAUD {{ cfg.UART_DEBUG_BAUD }} 32 | #define UART_DEBUG_CONFIG {{ cfg.UART_DEBUG_CONFIG }} 33 | 34 | // Wi-Fi configuration 35 | // WIFI_STA for client (station) mode 36 | // WIFI_AP for Access Point mode 37 | #define WIFI_MODE {{ cfg.WIFI_MODE }} 38 | 39 | #define WIFI_SSID {{ cfg.WIFI_SSID }} 40 | #define WIFI_PASS {{ cfg.WIFI_PASS }} 41 | #define WIFI_HOSTNAME {{ cfg.WIFI_HOSTNAME }} 42 | 43 | #define DEVICE_PRETTY_NAME {{ cfg.DEVICE_PRETTY_NAME }} 44 | 45 | // Access Point configuration 46 | #define WIFI_CHANNEL {{ cfg.WIFI_CHANNEL }} 47 | #define WIFI_HIDE_SSID {{ cfg.WIFI_HIDE_SSID }} 48 | #define WIFI_MAX_DEVICES {{ cfg.WIFI_MAX_DEVICES }} 49 | 50 | // OTA updates 51 | #define OTA_ENABLE {{ cfg.OTA_ENABLE }} 52 | // You MUST define a password, otherwise OTA won't be enabled. 53 | #define OTA_PASSWORD {{ cfg.OTA_PASSWORD }} 54 | 55 | // Server configuration 56 | #define HTTP_LISTEN_PORT {{ cfg.HTTP_LISTEN_PORT }} 57 | #define HTTP_AUTH_ENABLE {{ cfg.HTTP_AUTH_ENABLE }} 58 | #define HTTP_AUTH_USER {{ cfg.HTTP_AUTH_USER }} 59 | #define HTTP_AUTH_PASS {{ cfg.HTTP_AUTH_PASS }} 60 | 61 | // CORS - Uncomment to allow all origins 62 | //#define CORS_ALLOW_ORIGI cfg.CORS_ALLOW_ORIGINN { 63 | 64 | // WebSocket configuration 65 | #define WS_MAX_CLIENTS {{ cfg.WS_MAX_CLIENTS }} 66 | #define WS_PING_INTERVAL {{ cfg.WS_PING_INTERVAL }} 67 | 68 | // Web TTY configuration 69 | // You can specify any option documented here: https://xtermjs.org/docs/api/terminal/interfaces/iterminaloptions/ 70 | // Make sure it is a valid JSON and that it's also a valid C string. 71 | #define TTYD_WEB_CONFIG {{ cfg.TTYD_WEB_CONFIG }} 72 | 73 | 74 | #if BOARD_TYPE == 0 // don't change 75 | 76 | // LED configuration - only if board type is custom 77 | // Wi-Se board LEDs are pre-configured in wise_boards.h 78 | #define LED_WIFI {{ cfg.LED_WIFI }} 79 | #define LED_STATUS {{ cfg.LED_STATUS }} 80 | #define LED_TX {{ cfg.LED_TX }} 81 | #define LED_RX {{ cfg.LED_RX }} 82 | 83 | #endif //BOARD_TYPE 84 | 85 | // LED timings (milliseconds) 86 | #define LED_ON_TIME {{ cfg.LED_ON_TIME }} 87 | #define LED_OFF_TIME {{ cfg.LED_OFF_TIME }} 88 | 89 | // Advanced buffering parameters 90 | // Tweak if you feel brave. Report any improvements, but make sure you test them at 1500000 8N1 and that it works better 91 | // than the defaults before submitting. 92 | // Note that these buffers do not cause measurable latency, they need to be sort of high so that the WebSocket sender 93 | // can catch up as the UART is being stuffed with high speed data. 94 | 95 | #define UART_RX_BUF_SIZE {{ cfg.UART_RX_BUF_SIZE }} 96 | #define UART_RX_SOFT_MIN {{ cfg.UART_RX_SOFT_MIN }} 97 | #define UART_BUFFER_BELOW_SOFT_MIN_DYNAMIC_DELAY {{ cfg.UART_BUFFER_BELOW_SOFT_MIN_DYNAMIC_DELAY }} 98 | 99 | // Automatic baudrate detection interval 100 | #define UART_AUTOBAUD_TIMEOUT_MILLIS {{ cfg.UART_AUTOBAUD_TIMEOUT_MILLIS }} 101 | #define UART_AUTOBAUD_ATTEMPT_INTERVAL {{ cfg.UART_AUTOBAUD_ATTEMPT_INTERVAL }} 102 | 103 | // UART software flow control, improves stability. It must be supported by the connected device for it to make any 104 | // difference. 105 | #define UART_SW_FLOW_CONTROL {{ cfg.UART_SW_FLOW_CONTROL }} 106 | #define UART_SW_FLOW_CONTROL_LOW_WATERMARK {{ cfg.UART_SW_FLOW_CONTROL_LOW_WATERMARK }} 107 | #define UART_SW_FLOW_CONTROL_HIGH_WATERMARK {{ cfg.UART_SW_FLOW_CONTROL_HIGH_WATERMARK }} 108 | #define UART_SW_LOCAL_FLOW_CONTROL_STOP_MAX_MS {{ cfg.UART_SW_LOCAL_FLOW_CONTROL_STOP_MAX_MS }} 109 | 110 | #define WS_SEND_BUF_SIZE {{ cfg.WS_SEND_BUF_SIZE }} 111 | 112 | #define HEAP_FREE_LOW_WATERMARK {{ cfg.HEAP_FREE_LOW_WATERMARK }} 113 | #define HEAP_FREE_HIGH_WATERMARK {{ cfg.HEAP_FREE_HIGH_WATERMARK }} 114 | 115 | // If we stopped for half a second and the heap is still stuffed like a turkey we might just as well crash instead of 116 | // continue waiting, this code is probably leaky AF anyway. 117 | #define HEAP_CAUSED_WS_FLOW_CTL_STOP_MAX_MS {{ cfg.HEAP_CAUSED_WS_FLOW_CTL_STOP_MAX_MS }} 118 | 119 | // End of configuration 120 | #include "wise_boards.h" 121 | 122 | #endif // WI_SE_SW_CONFIG_H 123 | -------------------------------------------------------------------------------- /builder/platformio.j2.ini: -------------------------------------------------------------------------------- 1 | {# This file generates platformio.ini. This is the file you need to edit if you would like to make changes #} 2 | ; 3 | ; {{ cfg.AUTOGEN_MSG }} 4 | ; {{ cfg.AUTOGEN_DATE }} 5 | ; 6 | 7 | [env:wi_se] 8 | platform = https://github.com/platformio/platform-espressif8266.git 9 | board = esp_wroom_02 10 | framework = arduino 11 | board_build.f_cpu = {{ cfg.cpu_freq }} 12 | board_build.f_flash = 80000000L 13 | board_build.ldscript = eagle.flash.4m.ld 14 | build_unflags = 15 | -Os 16 | build_flags = 17 | -D PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH 18 | -D ARDUINOJSON_USE_LONG_LONG=1 19 | {% if cfg.atomic_ota %} 20 | -D ATOMIC_FS_UPDATE=1 21 | {% endif %} 22 | -D LOCAL_VERSION={{ cfg.local_version }} 23 | -O3 24 | # Suppress warning: 'SPIFFS' is deprecated 25 | -Wno-deprecated-declarations 26 | {% if cfg.upload_protocol == "serial" %} 27 | upload_speed = {{ cfg.serial_baud }} 28 | upload_port = {{ cfg.serial_port }} 29 | {% elif cfg.upload_protocol == "ota" %} 30 | upload_protocol = espota 31 | upload_port = {{ cfg.ota_address }} 32 | upload_flags = 33 | --port=8266 34 | {% if cfg.ota_host_port %} 35 | # Allow host_port/tcp in firewall - the ESP connects to it to download the firmware 36 | --host_port={{ cfg.ota_host_port }} 37 | {% endif %} 38 | --auth={{ cfg.ota_password }} 39 | {% endif %} 40 | lib_deps = 41 | ESP Async WebServer=https://github.com/Depau/ESPAsyncWebServer/archive/wi-se-patches.zip 42 | ESP8266WiFi 43 | ArduinoJson 44 | -------------------------------------------------------------------------------- /configs/config.yml.example: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # 4 | # Wi-Se firmware configuration 5 | # 6 | # Provided values are the defaults and they can be omitted. 7 | # Commented-out values also show the default value of each parameter, but most users won't need to change them 8 | # 9 | 10 | # Give it a name :) 11 | name: "Wi-Se" 12 | 13 | # If enabled, builder.py will not use this configuration when building all configs. It will still use it if requested explicitly. 14 | ignore_unless_requested: false 15 | 16 | # 17 | # Board configuration 18 | # 19 | board: 20 | # Board type. Available types: 21 | # - generic for generic boards such as an ESP8266 breakout (you need to configure the LEDs) 22 | # - wi-se-rpi-v0.1 Wi-Se Raspi Header v0.1 23 | # - wi-se-opi4-v0,1 Wi-Se Orange Pi 4 v0,1 24 | # - wi-se-rewirable-v0.1 Wi-Se Rewirable v0,1 25 | type: generic 26 | # LEDs need to be configured only for generic boards. For Wi-Se boards the LED config is baked-in 27 | # See project homepage for LED meaning 28 | leds: 29 | wifi: 5 30 | status: 13 31 | tx: 14 32 | rx: 12 33 | # On/off timings in milliseconds for RX/TX LEDs 34 | #on_time: 15 35 | #off_time: 15 36 | 37 | # CPU frequency in Hz. Overclocking it higher than this won't provide noticeable improvements. Don't fry your ESPs 38 | #cpu_freq: 160000000 39 | 40 | 41 | # 42 | # Upload (flashing) configuration 43 | # 44 | upload: 45 | # One of 'serial' or 'ota'. In order to use OTA you first need to flash the board through serial with OTA enabled. 46 | method: serial 47 | 48 | # Serial upload config 49 | # Hint: you can keep both sections for convenience, and only change the method when needed 50 | serial: 51 | # i.e. /dev/ttyUSB#, /dev/ttyACM# on Linux, COM# on Windows 52 | port: 'change/me' 53 | # If flashing isn't successful at this rate, try with 460800 54 | baud: 921600 55 | 56 | # OTA upload config 57 | ota: 58 | # IP address of the board 59 | address: '192.168.xx.xx' 60 | # Password for OTA. You should set this to the same value as .ota.password, unless you are changing it 61 | password: '' 62 | # Optional host port. You can set this if you need to allow it in the firewall 63 | #host_port: 8266 64 | 65 | 66 | # 67 | # UART (serial) configuration 68 | # 69 | uart: 70 | # UART used for normal configuration 71 | uart_comm: 72 | # Serial object name to use (0 or 1) 73 | serial: 0 74 | baud: 115200 75 | #config: '(UART_NB_BIT_8 | UART_PARITY_NONE | UART_NB_STOP_BIT_1)' 76 | 77 | # UART used for debugging messages, if enabled 78 | # It can be set to the same UART used for communication, in which case baud/config are ignored 79 | uart_debug: 80 | serial: 0 81 | baud: 115200 82 | #config: '(UART_NB_BIT_8 | UART_PARITY_NONE | UART_NB_STOP_BIT_1)' 83 | 84 | # Advanced UART configuration 85 | advanced: 86 | ## Buffering configuration - buffering is necessary. Don't reduce it unless you want terrible performance and data loss 87 | ## Leave default values if unsure, so that any adjustment to the defaults in new firmware releases will be applied automatically 88 | #rx_buf_size: 10240 89 | #rx_soft_min: '(WS_SEND_BUF_SIZE * 3 / 2)' 90 | #buffer_below_soft_min_dynamic_delay: '(std::min((int) (1000L * WS_SEND_BUF_SIZE * 8L * 2 / 3 / uartBaudRate), 5))' 91 | 92 | # Automatic baud rate detection configuration 93 | #autobaud: 94 | # # Max time in milliseconds the detection can run for 95 | # timeout: 10000 96 | # attempt_interval: 100 97 | 98 | # Software flow control enables requesting the device connected to the UART to stop sending data when the Wi-Fi can't keep up. 99 | # This will noticeably reduce the bandwidth during periods of high throughput, but it will increase reliability by orders of magnitude. 100 | # Disable it if the device you're connecting does not support software flow control since in that case it will only make things worse. 101 | flow_control: 102 | enable: true 103 | #low_watermark: 'UART_RX_SOFT_MIN + 1' 104 | #high_watermark: 'WS_SEND_BUF_SIZE - 1' 105 | #local_max_stop_time: 500 106 | #heap_free_low_watermark: 4096 107 | #heap_free_high_watermark: 10240 108 | #ws_max_stop_time: 500 109 | 110 | 111 | # 112 | # Wireless network configuration 113 | # 114 | wifi: 115 | # Wi-Fi mode. One of WIFI_STA (client mode), WIFI_AP (access point/hotspot) 116 | mode: WIFI_AP 117 | # Network name 118 | # In AP mode it can be omitted or set to null, in which case it will be automatically generated. 119 | # In STA mode it must be specified. 120 | ssid: null 121 | password: "ChangeMeASAP" 122 | # Device hostname - customize 123 | hostname: "Wi-Se" 124 | 125 | # AP specific configuration 126 | ap: 127 | channel: 6 128 | hide_ssid: false 129 | max_clients: 6 130 | 131 | 132 | # 133 | # OTA (Over-The-Air, Wireless) update configuration 134 | # 135 | ota: 136 | enable: false 137 | # Password MUST be provided if OTA is enabled 138 | password: "" 139 | # Enable atomic updates. Atomic updates increase the flashing time by a few seconds and double the flashing-caused wear on the SPI flash 140 | # However they will prevent bricking in case power is lost while an update is being installed. 141 | #atomic: true 142 | 143 | 144 | # 145 | # Web server configuration 146 | # 147 | http: 148 | port: 80 149 | # HTTP authentication configuration 150 | # Wi-Se uses the "Digest" authentication mechanism 151 | auth: 152 | enable: false 153 | user: "" 154 | password: "" 155 | 156 | 157 | # 158 | # WebSocket configuration 159 | # 160 | ws: 161 | # The ESP8266 can safely handle up to 3 clients; more when UART throughput is low 162 | max_clients: 3 163 | # Ping interval used for detecting client disconnections and saving precious resources 164 | #ping_interval: 300 165 | 166 | #advanced: 167 | # buffer_size: 1536 168 | 169 | 170 | # 171 | # ttyd web terminal protocol configuration 172 | # 173 | ttyd: 174 | # Configuration for the Web-based client. This may or may not affect other clients. 175 | # You can specify any option documented here: https://xtermjs.org/docs/api/terminal/interfaces/iterminaloptions/ 176 | web_config: 177 | disableLeaveAlert: true 178 | 179 | 180 | # 181 | # Debugging configuration 182 | # 183 | #debug: 184 | # # Enable debug strings on uart_debug 185 | # enable: false 186 | # # Also enable benchmarking debug strings 187 | # benchmark: false -------------------------------------------------------------------------------- /fakeesp/.gitignore: -------------------------------------------------------------------------------- 1 | config.h 2 | build/ 3 | cmake-build-debug/ 4 | .idea/ -------------------------------------------------------------------------------- /fakeesp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 3.13) 3 | 4 | project("wi-se-sw" CXX) 5 | 6 | add_compile_options( 7 | "-Wall" "-Wpedantic" "-Wextra" "-fno-exceptions" "-Wno-unused-parameter" 8 | "$<$:-O0;-g3;-ggdb;-fno-stack-protector>" 9 | ) 10 | 11 | add_definitions(-D'PLATFORMIO=50004') 12 | add_definitions(-D'ESP8266') 13 | add_definitions(-D'ARDUINO_ARCH_ESP8266') 14 | add_definitions(-D'ARDUINO_ESP8266_ESP_WROOM_02') 15 | add_definitions(-D'PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH') 16 | add_definitions(-D'F_CPU=160000000L') 17 | add_definitions(-D'__ets__') 18 | add_definitions(-D'ICACHE_FLASH') 19 | add_definitions(-D'ARDUINO=10805') 20 | add_definitions(-D'ARDUINO_BOARD=\"PLATFORMIO_ESP_WROOM_02\"') 21 | add_definitions(-D'FLASHMODE_QIO') 22 | add_definitions(-D'LWIP_OPEN_SRC') 23 | add_definitions(-D'NONOSDK22x_190703=1') 24 | add_definitions(-D'VTABLES_IN_FLASH') 25 | 26 | include_directories("/usr/lib/include") 27 | include_directories("${CMAKE_CURRENT_LIST_DIR}/include") 28 | include_directories("${CMAKE_CURRENT_LIST_DIR}/lib") 29 | include_directories("${CMAKE_CURRENT_LIST_DIR}/src") 30 | include_directories("${CMAKE_CURRENT_LIST_DIR}/ESPAsyncTCP/src") 31 | include_directories("${CMAKE_CURRENT_LIST_DIR}/../include") 32 | include_directories("${CMAKE_CURRENT_LIST_DIR}/../src") 33 | include_directories("${CMAKE_CURRENT_LIST_DIR}/../.pio/libdeps/esp_wroom_02/ESP Async WebServer/src") 34 | include_directories("${CMAKE_CURRENT_LIST_DIR}/../.pio/libdeps/esp_wroom_02/ArduinoJson/src") 35 | include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/") 36 | include_directories("$ENV{HOME}/.platformio/packages/framework-arduinoespressif8266/libraries/Hash/src") 37 | 38 | 39 | FILE(GLOB_RECURSE SRC_LIST 40 | "${CMAKE_CURRENT_LIST_DIR}/src/*.*" 41 | "${CMAKE_CURRENT_LIST_DIR}/src/*.*" 42 | "${CMAKE_CURRENT_LIST_DIR}/src/libb64/*.*" 43 | "${CMAKE_CURRENT_LIST_DIR}/lib/*.*" 44 | "${CMAKE_CURRENT_LIST_DIR}/include/*.*" 45 | "${CMAKE_CURRENT_LIST_DIR}/include/libb64/*.*" 46 | "${CMAKE_CURRENT_LIST_DIR}/ESPAsyncTCP/src/*.*" 47 | "${CMAKE_CURRENT_LIST_DIR}/../.pio/libdeps/esp_wroom_02/ESP Async WebServer/src/*.*" 48 | "${CMAKE_CURRENT_LIST_DIR}/../.pio/libdeps/esp_wroom_02/ArduinoJson/src/*.*" 49 | "${CMAKE_CURRENT_LIST_DIR}/../src/*.*" 50 | "${CMAKE_CURRENT_LIST_DIR}/../lib/*.*" 51 | "${CMAKE_CURRENT_LIST_DIR}/../include/*.*" 52 | ) 53 | 54 | list(APPEND SRC_LIST) 55 | 56 | #message(STATUS "SRC_LIST: ${SRC_LIST}") 57 | #message(STATUS "HOME: $ENV{HOME}") 58 | 59 | add_executable(wi-se_fakeesp main.cpp ${SRC_LIST}) 60 | 61 | find_package(OpenSSL REQUIRED) 62 | target_link_libraries(wi-se_fakeesp OpenSSL::SSL) -------------------------------------------------------------------------------- /fakeesp/ESPAsyncTCP/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /fakeesp/ESPAsyncTCP/LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /fakeesp/ESPAsyncTCP/README.md: -------------------------------------------------------------------------------- 1 | # Fake ESPAsyncTCP 2 | 3 | The code in this directory is a fork of ESPAsyncTCP modified to run on Linux using the normal POSIX socket API. 4 | 5 | Not everything is implemented and not everything that is implemented works properly. 6 | In particular, only the async server code is implemented. The client, both async and sync, is not implemented. 7 | It was tested with ESPAsyncWebserver, including the WebSocket server handler. 8 | 9 | The AsyncServer and AsyncClient classes hook up to callbacks in the fake `Arduino.h`/`ArduinoTime.cpp` as soon as possible. 10 | Any time `delay()` or `yield()` are called from the Arduino application code the AsyncTCP hooks will be called and any callbacks delivered. 11 | 12 | Original source code here: https://github.com/me-no-dev/ESPAsyncTCP 13 | Licensed under the GNU General Public License v3.0 14 | 15 | Original README below. 16 | 17 | ---- 18 | 19 | # ESPAsyncTCP 20 | [![Build Status](https://travis-ci.org/me-no-dev/ESPAsyncTCP.svg?branch=master)](https://travis-ci.org/me-no-dev/ESPAsyncTCP) ![](https://github.com/me-no-dev/ESPAsyncTCP/workflows/ESP%20Async%20TCP%20CI/badge.svg) 21 | 22 | ### Async TCP Library for ESP8266 Arduino 23 | 24 | For ESP32 look [HERE](https://github.com/me-no-dev/AsyncTCP) 25 | 26 | [![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 27 | 28 | This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP8266 MCUs. 29 | 30 | This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) 31 | 32 | ## AsyncClient and AsyncServer 33 | The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. 34 | 35 | ## AsyncPrinter 36 | This class can be used to send data like any other ```Print``` interface (```Serial``` for example). 37 | The object then can be used outside of the Async callbacks (the loop) and receive asynchronously data using ```onData```. The object can be checked if the underlying ```AsyncClient```is connected, or hook to the ```onDisconnect``` callback. 38 | 39 | ## AsyncTCPbuffer 40 | This class is really similar to the ```AsyncPrinter```, but it differs in the fact that it can buffer some of the incoming data. 41 | 42 | ## SyncClient 43 | It is exactly what it sounds like. This is a standard, blocking TCP Client, similar to the one included in ```ESP8266WiFi``` 44 | 45 | ## Libraries and projects that use AsyncTCP 46 | - [ESP Async Web Server](https://github.com/me-no-dev/ESPAsyncWebServer) 47 | - [Async MQTT client](https://github.com/marvinroger/async-mqtt-client) 48 | - [arduinoWebSockets](https://github.com/Links2004/arduinoWebSockets) 49 | - [ESP8266 Smart Home](https://github.com/baruch/esp8266_smart_home) 50 | - [KBox Firmware](https://github.com/sarfata/kbox-firmware) 51 | -------------------------------------------------------------------------------- /fakeesp/ESPAsyncTCP/src/AsyncPrinter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Asynchronous TCP library for Espressif MCUs 3 | 4 | Copyright (c) 2016 Hristo Gochkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include "AsyncPrinter.h" 24 | 25 | AsyncPrinter::AsyncPrinter() 26 | : _client(nullptr) 27 | , _data_cb(nullptr) 28 | , _data_arg(nullptr) 29 | , _close_cb(nullptr) 30 | , _close_arg(nullptr) 31 | , _tx_buffer(nullptr) 32 | , _tx_buffer_size(TCP_MSS) 33 | , next(nullptr) 34 | {} 35 | 36 | AsyncPrinter::AsyncPrinter(AsyncClient *client, size_t txBufLen) 37 | : _client(client) 38 | , _data_cb(nullptr) 39 | , _data_arg(nullptr) 40 | , _close_cb(nullptr) 41 | , _close_arg(nullptr) 42 | , _tx_buffer(nullptr) 43 | , _tx_buffer_size(txBufLen) 44 | , next(nullptr) 45 | { 46 | _attachCallbacks(); 47 | _tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size); 48 | if(_tx_buffer == nullptr) { 49 | panic(); //What should we do? 50 | } 51 | } 52 | 53 | AsyncPrinter::~AsyncPrinter(){ 54 | _on_close(); 55 | } 56 | 57 | void AsyncPrinter::onData(ApDataHandler cb, void *arg){ 58 | _data_cb = cb; 59 | _data_arg = arg; 60 | } 61 | 62 | void AsyncPrinter::onClose(ApCloseHandler cb, void *arg){ 63 | _close_cb = cb; 64 | _close_arg = arg; 65 | } 66 | 67 | int AsyncPrinter::connect(IPAddress ip, uint16_t port){ 68 | if(_client != nullptr && connected()) 69 | return 0; 70 | _client = new (std::nothrow) AsyncClient(); 71 | if (_client == nullptr) { 72 | panic(); 73 | } 74 | 75 | _client->onConnect([](void *obj, AsyncClient *c){ ((AsyncPrinter*)(obj))->_onConnect(c); }, this); 76 | if(_client->connect(ip, port)){ 77 | while(_client && _client->state() < 4) 78 | delay(1); 79 | return connected(); 80 | } 81 | return 0; 82 | } 83 | 84 | int AsyncPrinter::connect(const char *host, uint16_t port){ 85 | if(_client != nullptr && connected()) 86 | return 0; 87 | _client = new (std::nothrow) AsyncClient(); 88 | if (_client == nullptr) { 89 | panic(); 90 | } 91 | 92 | _client->onConnect([](void *obj, AsyncClient *c){ ((AsyncPrinter*)(obj))->_onConnect(c); }, this); 93 | if(_client->connect(host, port)){ 94 | while(_client && _client->state() < 4) 95 | delay(1); 96 | return connected(); 97 | } 98 | return 0; 99 | } 100 | 101 | void AsyncPrinter::_onConnect(AsyncClient *c){ 102 | (void)c; 103 | if(_tx_buffer != nullptr){ 104 | cbuf *b = _tx_buffer; 105 | _tx_buffer = nullptr; 106 | delete b; 107 | } 108 | _tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size); 109 | if(_tx_buffer) { 110 | panic(); 111 | } 112 | 113 | _attachCallbacks(); 114 | } 115 | 116 | AsyncPrinter::operator bool(){ return connected(); } 117 | 118 | AsyncPrinter & AsyncPrinter::operator=(const AsyncPrinter &other){ 119 | if(_client != nullptr){ 120 | _client->close(true); 121 | _client = nullptr; 122 | } 123 | _tx_buffer_size = other._tx_buffer_size; 124 | if(_tx_buffer != nullptr){ 125 | cbuf *b = _tx_buffer; 126 | _tx_buffer = nullptr; 127 | delete b; 128 | } 129 | _tx_buffer = new (std::nothrow) cbuf(other._tx_buffer_size); 130 | if(_tx_buffer == nullptr) { 131 | panic(); 132 | } 133 | 134 | _client = other._client; 135 | _attachCallbacks(); 136 | return *this; 137 | } 138 | 139 | size_t AsyncPrinter::write(uint8_t data){ 140 | return write(&data, 1); 141 | } 142 | 143 | size_t AsyncPrinter::write(const uint8_t *data, size_t len){ 144 | if(_tx_buffer == nullptr || !connected()) 145 | return 0; 146 | size_t toWrite = 0; 147 | size_t toSend = len; 148 | while(_tx_buffer->room() < toSend){ 149 | toWrite = _tx_buffer->room(); 150 | _tx_buffer->write((const char*)data, toWrite); 151 | while(connected() && !_client->canSend()) 152 | delay(0); 153 | if(!connected()) 154 | return 0; // or len - toSend; 155 | _sendBuffer(); 156 | toSend -= toWrite; 157 | } 158 | _tx_buffer->write((const char*)(data+(len - toSend)), toSend); 159 | while(connected() && !_client->canSend()) delay(0); 160 | if(!connected()) return 0; // or len - toSend; 161 | _sendBuffer(); 162 | return len; 163 | } 164 | 165 | bool AsyncPrinter::connected(){ 166 | return (_client != nullptr && _client->connected()); 167 | } 168 | 169 | void AsyncPrinter::close(){ 170 | if(_client != nullptr) 171 | _client->close(true); 172 | } 173 | 174 | size_t AsyncPrinter::_sendBuffer(){ 175 | size_t available = _tx_buffer->available(); 176 | if(!connected() || !_client->canSend() || available == 0) 177 | return 0; 178 | size_t sendable = _client->space(); 179 | if(sendable < available) 180 | available= sendable; 181 | char *out = new (std::nothrow) char[available]; 182 | if (out == nullptr) { 183 | panic(); // Connection should be aborted instead 184 | } 185 | 186 | _tx_buffer->read(out, available); 187 | size_t sent = _client->write(out, available); 188 | delete out; 189 | return sent; 190 | } 191 | 192 | void AsyncPrinter::_onData(void *data, size_t len){ 193 | if(_data_cb) 194 | _data_cb(_data_arg, this, (uint8_t*)data, len); 195 | } 196 | 197 | void AsyncPrinter::_on_close(){ 198 | if(_client != nullptr){ 199 | _client = nullptr; 200 | } 201 | if(_tx_buffer != nullptr){ 202 | cbuf *b = _tx_buffer; 203 | _tx_buffer = nullptr; 204 | delete b; 205 | } 206 | if(_close_cb) 207 | _close_cb(_close_arg, this); 208 | } 209 | 210 | void AsyncPrinter::_attachCallbacks(){ 211 | _client->onPoll([](void *obj, AsyncClient* c){ (void)c; ((AsyncPrinter*)(obj))->_sendBuffer(); }, this); 212 | _client->onAck([](void *obj, AsyncClient* c, size_t len, uint32_t time){ (void)c; (void)len; (void)time; ((AsyncPrinter*)(obj))->_sendBuffer(); }, this); 213 | _client->onDisconnect([](void *obj, AsyncClient* c){ ((AsyncPrinter*)(obj))->_on_close(); delete c; }, this); 214 | _client->onData([](void *obj, AsyncClient* c, void *data, size_t len){ (void)c; ((AsyncPrinter*)(obj))->_onData(data, len); }, this); 215 | } 216 | -------------------------------------------------------------------------------- /fakeesp/ESPAsyncTCP/src/AsyncPrinter.h: -------------------------------------------------------------------------------- 1 | /* 2 | Asynchronous TCP library for Espressif MCUs 3 | 4 | Copyright (c) 2016 Hristo Gochkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef ASYNCPRINTER_H_ 23 | #define ASYNCPRINTER_H_ 24 | 25 | #include 26 | #include "ESPAsyncTCP.h" 27 | #include "async_config.h" 28 | 29 | class AsyncPrinter; 30 | 31 | typedef std::function ApDataHandler; 32 | typedef std::function ApCloseHandler; 33 | 34 | class AsyncPrinter { 35 | private: 36 | AsyncClient *_client; 37 | ApDataHandler _data_cb; 38 | void *_data_arg; 39 | ApCloseHandler _close_cb; 40 | void *_close_arg; 41 | cbuf *_tx_buffer; 42 | size_t _tx_buffer_size; 43 | 44 | void _onConnect(AsyncClient *c); 45 | public: 46 | AsyncPrinter *next; 47 | 48 | AsyncPrinter(); 49 | AsyncPrinter(AsyncClient *client, size_t txBufLen = TCP_MSS); 50 | virtual ~AsyncPrinter(); 51 | 52 | int connect(IPAddress ip, uint16_t port); 53 | int connect(const char *host, uint16_t port); 54 | 55 | void onData(ApDataHandler cb, void *arg); 56 | void onClose(ApCloseHandler cb, void *arg); 57 | 58 | operator bool(); 59 | AsyncPrinter & operator=(const AsyncPrinter &other); 60 | 61 | size_t write(uint8_t data); 62 | size_t write(const uint8_t *data, size_t len); 63 | 64 | bool connected(); 65 | void close(); 66 | 67 | size_t _sendBuffer(); 68 | void _onData(void *data, size_t len); 69 | void _on_close(); 70 | void _attachCallbacks(); 71 | }; 72 | 73 | #endif /* ASYNCPRINTER_H_ */ 74 | -------------------------------------------------------------------------------- /fakeesp/ESPAsyncTCP/src/DebugPrintMacros.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEBUG_PRINT_MACROS_H 2 | #define _DEBUG_PRINT_MACROS_H 3 | // Some customizable print macros to suite the debug needs de jour. 4 | 5 | // Debug macros 6 | // #include 7 | // https://stackoverflow.com/questions/8487986/file-macro-shows-full-path 8 | // This value is resolved at compile time. 9 | #define _FILENAME_ strrchr("/" __FILE__, '/') 10 | 11 | // #define DEBUG_ESP_ASYNC_TCP 1 12 | // #define DEBUG_ESP_TCP_SSL 1 13 | // #define DEBUG_ESP_PORT Serial 14 | 15 | #if defined(DEBUG_ESP_PORT) && !defined(DEBUG_TIME_STAMP_FMT) 16 | #define DEBUG_TIME_STAMP_FMT "%06u.%03u " 17 | struct _DEBUG_TIME_STAMP { 18 | unsigned dec; 19 | unsigned whole; 20 | }; 21 | inline struct _DEBUG_TIME_STAMP debugTimeStamp(void) { 22 | struct _DEBUG_TIME_STAMP st; 23 | unsigned now = millis() % 1000000000; 24 | st.dec = now % 1000; 25 | st.whole = now / 1000; 26 | return st; 27 | } 28 | #endif 29 | 30 | #if defined(DEBUG_ESP_PORT) && !defined(DEBUG_GENERIC) 31 | #define DEBUG_GENERIC( module, format, ... ) \ 32 | do { \ 33 | struct _DEBUG_TIME_STAMP st = debugTimeStamp(); \ 34 | DEBUG_ESP_PORT.printf( DEBUG_TIME_STAMP_FMT module " " format, st.whole, st.dec, ##__VA_ARGS__ ); \ 35 | } while(false) 36 | #endif 37 | #if defined(DEBUG_ESP_PORT) && !defined(DEBUG_GENERIC_P) 38 | #define DEBUG_GENERIC_P( module, format, ... ) \ 39 | do { \ 40 | struct _DEBUG_TIME_STAMP st = debugTimeStamp(); \ 41 | DEBUG_ESP_PORT.printf_P(PSTR( DEBUG_TIME_STAMP_FMT module " " format ), st.whole, st.dec, ##__VA_ARGS__ ); \ 42 | } while(false) 43 | #endif 44 | 45 | #if defined(DEBUG_GENERIC) && !defined(ASSERT_GENERIC) 46 | #define ASSERT_GENERIC( a, module ) \ 47 | do { \ 48 | if ( !(a) ) { \ 49 | DEBUG_GENERIC( module, "%s:%s:%u: ASSERT("#a") failed!\n", __FILE__, __func__, __LINE__); \ 50 | DEBUG_ESP_PORT.flush(); \ 51 | } \ 52 | } while(false) 53 | #endif 54 | #if defined(DEBUG_GENERIC_P) && !defined(ASSERT_GENERIC_P) 55 | #define ASSERT_GENERIC_P( a, module ) \ 56 | do { \ 57 | if ( !(a) ) { \ 58 | DEBUG_GENERIC_P( module, "%s:%s:%u: ASSERT("#a") failed!\n", __FILE__, __func__, __LINE__); \ 59 | DEBUG_ESP_PORT.flush(); \ 60 | } \ 61 | } while(false) 62 | #endif 63 | 64 | #ifndef DEBUG_GENERIC 65 | #define DEBUG_GENERIC(...) do { (void)0;} while(false) 66 | #endif 67 | 68 | #ifndef DEBUG_GENERIC_P 69 | #define DEBUG_GENERIC_P(...) do { (void)0;} while(false) 70 | #endif 71 | 72 | #ifndef ASSERT_GENERIC 73 | #define ASSERT_GENERIC(...) do { (void)0;} while(false) 74 | #endif 75 | 76 | #ifndef ASSERT_GENERIC_P 77 | #define ASSERT_GENERIC_P(...) do { (void)0;} while(false) 78 | #endif 79 | 80 | #ifndef DEBUG_ESP_PRINTF 81 | #define DEBUG_ESP_PRINTF( format, ...) DEBUG_GENERIC_P("[%s]", format, &_FILENAME_[1], ##__VA_ARGS__) 82 | #endif 83 | 84 | #if defined(DEBUG_ESP_ASYNC_TCP) && !defined(ASYNC_TCP_DEBUG) 85 | #define ASYNC_TCP_DEBUG( format, ...) DEBUG_GENERIC_P("[ASYNC_TCP]", format, ##__VA_ARGS__) 86 | #endif 87 | 88 | #ifndef ASYNC_TCP_ASSERT 89 | #define ASYNC_TCP_ASSERT( a ) ASSERT_GENERIC_P( (a), "[ASYNC_TCP]") 90 | #endif 91 | 92 | #if defined(DEBUG_ESP_TCP_SSL) && !defined(TCP_SSL_DEBUG) 93 | #define TCP_SSL_DEBUG( format, ...) DEBUG_GENERIC_P("[TCP_SSL]", format, ##__VA_ARGS__) 94 | #endif 95 | 96 | #endif //_DEBUG_PRINT_MACROS_H 97 | -------------------------------------------------------------------------------- /fakeesp/ESPAsyncTCP/src/ESPAsyncTCPbuffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file ESPAsyncTCPbuffer.h 3 | * @date 22.01.2016 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the Asynv TCP for ESP. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #ifndef ESPASYNCTCPBUFFER_H_ 26 | #define ESPASYNCTCPBUFFER_H_ 27 | 28 | //#define DEBUG_ASYNC_TCP(...) while(((U0S >> USTXC) & 0x7F) != 0x00); os_printf( __VA_ARGS__ ); while(((U0S >> USTXC) & 0x7F) != 0x00) 29 | //#define DEBUG_ASYNC_TCP ASYNC_TCP_DEBUG 30 | #ifndef DEBUG_ASYNC_TCP 31 | #define DEBUG_ASYNC_TCP(...) 32 | #endif 33 | 34 | #include 35 | #include 36 | 37 | #include "ESPAsyncTCP.h" 38 | 39 | 40 | 41 | typedef enum { 42 | ATB_RX_MODE_NONE, 43 | ATB_RX_MODE_FREE, 44 | ATB_RX_MODE_READ_BYTES, 45 | ATB_RX_MODE_TERMINATOR, 46 | ATB_RX_MODE_TERMINATOR_STRING 47 | } atbRxMode_t; 48 | 49 | class AsyncTCPbuffer { 50 | 51 | public: 52 | 53 | typedef std::function AsyncTCPbufferDataCb; 54 | typedef std::function AsyncTCPbufferDoneCb; 55 | typedef std::function AsyncTCPbufferDisconnectCb; 56 | 57 | AsyncTCPbuffer(AsyncClient* c); 58 | virtual ~AsyncTCPbuffer(); 59 | 60 | size_t write(String & data); 61 | size_t write(uint8_t data); 62 | size_t write(const char* data); 63 | size_t write(const char *data, size_t len); 64 | size_t write(const uint8_t *data, size_t len); 65 | 66 | void flush(); 67 | 68 | void noCallback(); 69 | 70 | void readStringUntil(char terminator, String * str, AsyncTCPbufferDoneCb done); 71 | 72 | // TODO implement read terminator non string 73 | //void readBytesUntil(char terminator, char *buffer, size_t length, AsyncTCPbufferDoneCb done); 74 | //void readBytesUntil(char terminator, uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done); 75 | 76 | void readBytes(char *buffer, size_t length, AsyncTCPbufferDoneCb done); 77 | void readBytes(uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done); 78 | 79 | // TODO implement 80 | // void setTimeout(size_t timeout); 81 | 82 | void onData(AsyncTCPbufferDataCb cb); 83 | void onDisconnect(AsyncTCPbufferDisconnectCb cb); 84 | 85 | IPAddress remoteIP(); 86 | uint16_t remotePort(); 87 | IPAddress localIP(); 88 | uint16_t localPort(); 89 | 90 | bool connected(); 91 | 92 | void stop(); 93 | void close(); 94 | 95 | protected: 96 | AsyncClient* _client; 97 | cbuf * _TXbufferRead; 98 | cbuf * _TXbufferWrite; 99 | cbuf * _RXbuffer; 100 | atbRxMode_t _RXmode; 101 | size_t _rxSize; 102 | char _rxTerminator; 103 | uint8_t * _rxReadBytesPtr; 104 | String * _rxReadStringPtr; 105 | 106 | AsyncTCPbufferDataCb _cbRX; 107 | AsyncTCPbufferDoneCb _cbDone; 108 | AsyncTCPbufferDisconnectCb _cbDisconnect; 109 | 110 | void _attachCallbacks(); 111 | void _sendBuffer(); 112 | void _on_close(); 113 | void _rxData(uint8_t *buf, size_t len); 114 | size_t _handleRxBuffer(uint8_t *buf, size_t len); 115 | 116 | }; 117 | 118 | #endif /* ESPASYNCTCPBUFFER_H_ */ 119 | -------------------------------------------------------------------------------- /fakeesp/ESPAsyncTCP/src/async_config.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBRARIES_ESPASYNCTCP_SRC_ASYNC_CONFIG_H_ 2 | #define LIBRARIES_ESPASYNCTCP_SRC_ASYNC_CONFIG_H_ 3 | 4 | #ifndef ASYNC_TCP_SSL_ENABLED 5 | #define ASYNC_TCP_SSL_ENABLED 0 6 | #endif 7 | 8 | #ifndef TCP_MSS 9 | // May have been definded as a -DTCP_MSS option on the compile line or not. 10 | // Arduino core 2.3.0 or earlier does not do the -DTCP_MSS option. 11 | // Later versions may set this option with info from board.txt. 12 | // However, Core 2.4.0 and up board.txt does not define TCP_MSS for lwIP v1.4 13 | #define TCP_MSS (1460) 14 | #endif 15 | 16 | // #define ASYNC_TCP_DEBUG(...) ets_printf(__VA_ARGS__) 17 | // #define TCP_SSL_DEBUG(...) ets_printf(__VA_ARGS__) 18 | // #define ASYNC_TCP_ASSERT( a ) do{ if(!(a)){ets_printf("ASSERT: %s %u \n", __FILE__, __LINE__);}}while(0) 19 | 20 | // Starting with Arduino Core 2.4.0 and up the define of DEBUG_ESP_PORT 21 | // can be handled through the Arduino IDE Board options instead of here. 22 | // #define DEBUG_ESP_PORT Serial 23 | 24 | // #define DEBUG_ESP_ASYNC_TCP 1 25 | // #define DEBUG_ESP_TCP_SSL 1 26 | #include 27 | 28 | #ifndef ASYNC_TCP_ASSERT 29 | #define ASYNC_TCP_ASSERT(...) do { (void)0;} while(false) 30 | #endif 31 | #ifndef ASYNC_TCP_DEBUG 32 | #define ASYNC_TCP_DEBUG(...) do { (void)0;} while(false) 33 | #endif 34 | #ifndef TCP_SSL_DEBUG 35 | #define TCP_SSL_DEBUG(...) do { (void)0;} while(false) 36 | #endif 37 | 38 | #endif /* LIBRARIES_ESPASYNCTCP_SRC_ASYNC_CONFIG_H_ */ 39 | -------------------------------------------------------------------------------- /fakeesp/LICENSE.bsd: -------------------------------------------------------------------------------- 1 | Copyright (c) 2001, 2002 Swedish Institute of Computer Science. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 3. The name of the author may not be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 16 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 18 | SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 20 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 24 | OF SUCH DAMAGE. 25 | 26 | -------------------------------------------------------------------------------- /fakeesp/README.md: -------------------------------------------------------------------------------- 1 | # Fake ESP build 2 | 3 | This directory contains some basic infrastructure and stubs to build and run Wi-Se on Linux without any modifications. This is only intended 4 | for local testing against memory corruption bugs and for debugging with a debugger that actually works. 5 | 6 | The code here stubs any Arduino-ESP8266 SDK calls that are used, as well as reimplementing ESPAsyncTCP on top of normal POSIX sockets. 7 | 8 | GPIOs are emulated and the up-to-date GPIO status is written to `/tmp/fakeesp_gpio.txt`. 9 | 10 | The `delay()`, `delayMicrosecond()` and `yield()` functions, in addition to performing their intended purpose, also provide hooks for the 11 | modified ESPAsyncTCP library in order to emulate the asynchronous callbacks from lwIP. 12 | 13 | All the PROGMEM data and strings are turned into `const char *` via preprocessor duct-tape. 14 | 15 | ## Building 16 | 17 | No warranties, but roughly you need to: 18 | 19 | - Make sure GCC, CMake and OpenSSL (needed for hash algorithms) are installed 20 | - Make sure you built the ESP8266 version of the project at least once, so that PlatformIO downloads the dependencies 21 | - `mkdir build; cd build; cmake .. && make -j$(nproc)` 22 | 23 | Then run `./wi-se_fakeesp`. Make sure you're using a high port in `config.h` for the HTTP server, since we don't have enough privileges for 24 | port 80. 25 | 26 | MDNS and ArduinoOTA are completely stubbed, so there's no need to worry about them. 27 | 28 | ## Licenses 29 | 30 | Some of the stub code was written by myself, some of it was copy-pasted and optionally modified. 31 | 32 | #### From [esp8266/Arduino](https://github.com/esp8266/Arduino/) 33 | 34 | The following files are mostly copy-pasted from the ESP8266-Arduino project. Minor modifications have been made to make them play nicely 35 | with the other stub and to use the fake PROGMEM. 36 | 37 | Licensed under the GNU Lesser General Public License v2.1, `./LICENSE.lgpl2` 38 | 39 | - `src/cbuf.cpp` 40 | - `include/cbuf.h` 41 | - `include/c_types.h` 42 | - `src/FS.cpp` 43 | - `include/FS.h` 44 | - `include/FSImpl.h` 45 | - `include/Hash.h` 46 | - `src/IPAddress.h` 47 | - `include/IPAddress.h` 48 | - `include/md5.h` 49 | - `src/Print.h` 50 | - `include/Print,h` 51 | - `include/Printable.h` 52 | - `src/Stream.cpp` 53 | - `include/Stream.h` 54 | - `src/WString.cpp` 55 | - `include/WString.h` 56 | 57 | The following files also come from the same project, but are released under the public domain instead: 58 | 59 | - `src/libb64/` 60 | - `include/libb64/` 61 | 62 | #### From [lwIP](https://savannah.nongnu.org/git/?group=lwip) 63 | 64 | The following headers were mostly copy-pasted from lwIP with minor modifications. 65 | 66 | Licensed under the 3-Clause BSD license, `./LICENSE.bsd` 67 | 68 | - `include/lwip/` 69 | 70 | #### From [ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) 71 | 72 | The following files come from ESPAsyncTCP, but have been heavily modified to use POSIX sockets instead of the ESP SDK. 73 | 74 | Licensed under the GNU General Public License v3.0, `./ESPAsyncTCP/LICENSE` 75 | 76 | - `ESPAsyncTCP/` 77 | 78 | #### From scratch 79 | 80 | The following files were written from scratch to mimic the API they are stubbing. 81 | 82 | Licensed under the main project license, GNU General Public License v3.0, `../LICENSE` 83 | 84 | - `main.cpp` 85 | - `src/ArduinoTime.cpp` 86 | - `src/FakeGPIO.cpp` 87 | - `src/GenericStuff.cpp` 88 | - `src/Hash.cpp` 89 | - `src/itoa.cpp` 90 | - `src/md5.cpp` 91 | - `include/Arduino.h` 92 | - `include/ArduinoOTA.h` 93 | - `include/ESP.h` 94 | - `include/ESP8266WiFi.h` 95 | - `include/ESP8266mDNS.h` 96 | - `include/Serial.h` (with some code from Arduino-ESP8266) 97 | - `include/uart.h` (with some code from Arduino-ESP8266) 98 | -------------------------------------------------------------------------------- /fakeesp/gen_numbers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | 6 | if __name__ == "__main__": 7 | iters = -1 8 | if len(sys.argv) > 1: 9 | iters = int(sys.argv[1]) 10 | 11 | try: 12 | nums = b'.'.join(map(lambda x: ("%02X" % x).encode() ,range(256))) 13 | 14 | while iters == -1 or iters > 0: 15 | sys.stdout.buffer.write(nums) 16 | if iters != -1: 17 | iters -= 1 18 | 19 | except KeyboardInterrupt: 20 | pass 21 | -------------------------------------------------------------------------------- /fakeesp/include/Arduino.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_ARDUINO_H 6 | #define WI_SE_SW_ARDUINO_H 7 | 8 | //#define SIMULATE_BAUDRATE 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "ArduinoTime.h" 15 | #include "ESP.h" 16 | #include "WString.h" 17 | #include "Stream.h" 18 | #include "HardwareSerial.h" 19 | #include "progmem.h" 20 | 21 | typedef bool boolean; 22 | #define __unused 23 | 24 | // Fake ESP OS functions 25 | #define os_strlen strlen 26 | #define ets_printf(...) fprintf(stderr, __VA_ARGS__) 27 | #define RANDOM_REG32 rand() 28 | 29 | #define ADC_MODE(ADC_VCC) void *adc_mode_mock = NULL 30 | 31 | #define HIGH 0x1 32 | #define LOW 0x0 33 | 34 | #define PWMRANGE 1023 35 | 36 | //GPIO FUNCTIONS 37 | #define INPUT 0x00 38 | #define INPUT_PULLUP 0x02 39 | #define INPUT_PULLDOWN_16 0x04 // PULLDOWN only possible for pin16 40 | #define OUTPUT 0x01 41 | #define FAKEMODE_PWM_OUT 0xFF 42 | 43 | #define OUTPUT_OPEN_DRAIN 0x03 44 | 45 | 46 | void pinMode(uint8_t pin, uint8_t mode); 47 | 48 | void digitalWrite(uint8_t pin, uint8_t val); 49 | 50 | int digitalRead(uint8_t pin); 51 | 52 | int analogRead(uint8_t pin); 53 | 54 | void analogReference(uint8_t mode); 55 | 56 | void analogWrite(uint8_t pin, int val); 57 | 58 | void analogWriteFreq(uint32_t freq); 59 | 60 | void analogWriteRange(uint32_t range); 61 | 62 | void panic(); 63 | 64 | long map(long x, long in_min, long in_max, long out_min, long out_max); 65 | 66 | void setup(); 67 | 68 | void loop(); 69 | 70 | 71 | // Monkey-patch ESP Async WebServer/src/WebResponses.cpp 72 | namespace std { 73 | long unsigned int min(long unsigned int n1, unsigned int n2); 74 | } 75 | 76 | #endif //WI_SE_SW_ARDUINO_H 77 | -------------------------------------------------------------------------------- /fakeesp/include/ArduinoOTA.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_ARDUINOOTA_H 6 | #define WI_SE_SW_ARDUINOOTA_H 7 | 8 | #include 9 | 10 | typedef enum { 11 | OTA_AUTH_ERROR, 12 | OTA_BEGIN_ERROR, 13 | OTA_CONNECT_ERROR, 14 | OTA_RECEIVE_ERROR, 15 | OTA_END_ERROR 16 | } ota_error_t; 17 | 18 | class FakeArduinoOTA { 19 | public: 20 | typedef std::function THandlerFunction; 21 | typedef std::function THandlerFunction_Error; 22 | typedef std::function THandlerFunction_Progress; 23 | 24 | void begin() {}; 25 | 26 | void handle() {}; 27 | 28 | void setPassword(char *) {} 29 | 30 | void setPassword(const char *) {} 31 | 32 | void setRebootOnSuccess(bool) {} 33 | 34 | void setHostname(char *) {} 35 | 36 | void setHostname(const char *) {} 37 | 38 | void setPort(int) {} 39 | 40 | void onStart(THandlerFunction) {} 41 | 42 | void onEnd(THandlerFunction fn) {} 43 | 44 | void onError(THandlerFunction_Error fn) {} 45 | 46 | void onProgress(THandlerFunction_Progress fn) {} 47 | 48 | }; 49 | 50 | extern FakeArduinoOTA ArduinoOTA; 51 | 52 | #endif //WI_SE_SW_ARDUINOOTA_H 53 | -------------------------------------------------------------------------------- /fakeesp/include/ArduinoTime.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/8/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_ARDUINOTIME_H 6 | #define WI_SE_SW_ARDUINOTIME_H 7 | 8 | unsigned long millis(); 9 | 10 | unsigned long micros(); 11 | 12 | uint64_t micros64(); 13 | 14 | void delay(unsigned long); 15 | 16 | void delayNoYield(unsigned long); 17 | 18 | void delayMicroseconds(unsigned int us); 19 | 20 | void delayMicrosecondsNoYield(unsigned int us); 21 | 22 | void yield(); 23 | 24 | int32_t registerOnDelayCallback(void (*callback)(void *arg), void *arg); 25 | 26 | void deregisterOnDelayCallback(uint32_t id); 27 | 28 | void callOnDelayCallbacks(); 29 | 30 | #endif //WI_SE_SW_ARDUINOTIME_H 31 | -------------------------------------------------------------------------------- /fakeesp/include/ESP.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_ESP_H 6 | #define WI_SE_SW_ESP_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include "WString.h" 12 | 13 | class FakeESP { 14 | public: 15 | uint32_t getFreeHeap() { return 999999; } 16 | uint16_t getVcc() { return 3300; } 17 | String getFullVersion() { 18 | return String("Totally an ESP8266"); 19 | } 20 | uint32_t getChipId() { 21 | return 0xDEADBEEF; 22 | } 23 | uint32_t random() { 24 | return rand(); // NOLINT(cert-msc50-cpp) 25 | } 26 | void reset() { 27 | fprintf(stderr, "ESP.reset()\n"); 28 | exit(0); 29 | } 30 | void restart() { 31 | fprintf(stderr, "ESP.restart()\n"); 32 | exit(0); 33 | } 34 | uint8_t getCpuFreqMHz() const { 35 | return 69; 36 | } 37 | 38 | uint8_t getHeapFragmentation() { 39 | return 1; 40 | } 41 | }; 42 | 43 | extern FakeESP ESP; 44 | 45 | #endif //WI_SE_SW_ESP_H 46 | -------------------------------------------------------------------------------- /fakeesp/include/ESP8266WiFi.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_ESP8266WIFI_H 6 | #define WI_SE_SW_ESP8266WIFI_H 7 | 8 | #include "lwip/ip_addr.h" 9 | #include "IPAddress.h" 10 | 11 | #include 12 | 13 | typedef enum { 14 | WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library 15 | WL_IDLE_STATUS = 0, 16 | WL_NO_SSID_AVAIL = 1, 17 | WL_SCAN_COMPLETED = 2, 18 | WL_CONNECTED = 3, 19 | WL_CONNECT_FAILED = 4, 20 | WL_CONNECTION_LOST = 5, 21 | WL_DISCONNECTED = 6 22 | } wl_status_t; 23 | 24 | typedef enum WiFiMode { 25 | WIFI_OFF = 0, WIFI_STA = 1, WIFI_AP = 2, WIFI_AP_STA = 3, 26 | /* these two pseudo modes are experimental: */ WIFI_SHUTDOWN = 4, WIFI_RESUME = 8 27 | } WiFiMode_t; 28 | 29 | typedef enum WiFiPhyMode { 30 | WIFI_PHY_MODE_11B = 1, WIFI_PHY_MODE_11G = 2, WIFI_PHY_MODE_11N = 3 31 | } WiFiPhyMode_t; 32 | 33 | typedef enum WiFiSleepType { 34 | WIFI_NONE_SLEEP = 0, WIFI_LIGHT_SLEEP = 1, WIFI_MODEM_SLEEP = 2 35 | } WiFiSleepType_t; 36 | 37 | struct station_config { 38 | }; 39 | 40 | 41 | struct WiFiState 42 | { 43 | uint32_t crc; 44 | struct 45 | { 46 | station_config fwconfig; 47 | ip_info ip; 48 | ip_addr_t dns[2]; 49 | ip_addr_t ntp[2]; 50 | WiFiMode_t mode; 51 | uint8_t channel; 52 | bool persistent; 53 | } state; 54 | }; 55 | 56 | 57 | 58 | class FakeWiFi { 59 | public: 60 | wl_status_t begin() { return WL_CONNECTED; }; 61 | 62 | wl_status_t begin(const char *ssid) { return WL_CONNECTED; }; 63 | 64 | wl_status_t begin(const char *ssid, const char *passphrase) { return WL_CONNECTED; }; 65 | 66 | wl_status_t begin(const char *ssid, const char *passphrase, int32_t channel, const uint8_t *bssid, 67 | bool connect) { return WL_CONNECTED; }; 68 | 69 | wl_status_t status() { return WL_CONNECTED; }; 70 | 71 | void setOutputPower(float dBm) {}; 72 | 73 | bool setPhyMode(WiFiPhyMode_t mode) { return true; }; 74 | 75 | bool setSleepMode(WiFiSleepType_t type) { return true; }; 76 | 77 | bool setSleepMode(WiFiSleepType_t type, uint8_t listenInterval) { return true; }; 78 | 79 | 80 | bool mode(WiFiMode_t m) { return true; } 81 | 82 | bool mode(WiFiMode_t m, WiFiState* state) { return true; } 83 | 84 | bool hostname(const char* aHostname) { return true; }; 85 | 86 | bool softAP(const char* ssid, const char* passphrase, int channel, int ssid_hidden, int max_connection) { return true; } 87 | 88 | String SSID() const { 89 | return String("LollerinoWiFi"); 90 | } 91 | 92 | String BSSIDstr() { 93 | return String("de:ad:be:ef:00"); 94 | } 95 | 96 | String macAddress() { 97 | return String("f0:0d:ba:be:00"); 98 | } 99 | 100 | IPAddress localIP() { 101 | fprintf(stderr, "STUB WiFi.localIP()"); 102 | return IPAddress(0x01010101); 103 | } 104 | 105 | IPAddress subnetMask() { 106 | fprintf(stderr, "STUB WiFi.subnetMask()"); 107 | return IPAddress(0x00FFFFFF); 108 | } 109 | 110 | IPAddress gatewayIP() { 111 | fprintf(stderr, "STUB WiFi.gatewayIP()"); 112 | return IPAddress(0x09090909); 113 | } 114 | 115 | int32_t RSSI() { 116 | return 42; 117 | } 118 | }; 119 | 120 | extern FakeWiFi WiFi; 121 | 122 | #endif //WI_SE_SW_ESP8266WIFI_H 123 | -------------------------------------------------------------------------------- /fakeesp/include/ESP8266mDNS.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_ESP8266MDNS_H 6 | #define WI_SE_SW_ESP8266MDNS_H 7 | 8 | #include "IPAddress.h" 9 | 10 | class FakeMDNS { 11 | public: 12 | bool begin(const char *p_pcHostname) { return true; } 13 | 14 | bool begin(const char *p_pcHostname, const IPAddress &p_IPAddress, uint32_t p_u32TTL) { return true; } 15 | 16 | void addService(const char *, const char *, int) {} 17 | }; 18 | 19 | extern FakeMDNS MDNS; 20 | 21 | #endif //WI_SE_SW_ESP8266MDNS_H 22 | -------------------------------------------------------------------------------- /fakeesp/include/FS.h: -------------------------------------------------------------------------------- 1 | /* 2 | FS.h - file system wrapper 3 | Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. 4 | This file is part of the esp8266 core for Arduino environment. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef FS_H 22 | #define FS_H 23 | 24 | #include 25 | #include 26 | #include "Stream.h" 27 | #include <../include/time.h> // See issue #6714 28 | 29 | class SDClass; 30 | 31 | namespace fs { 32 | 33 | class File; 34 | class Dir; 35 | class FS; 36 | 37 | class FileImpl; 38 | typedef std::shared_ptr FileImplPtr; 39 | class FSImpl; 40 | typedef std::shared_ptr FSImplPtr; 41 | class DirImpl; 42 | typedef std::shared_ptr DirImplPtr; 43 | 44 | template 45 | bool mount(Tfs& fs, const char* mountPoint); 46 | 47 | enum SeekMode { 48 | SeekSet = 0, 49 | SeekCur = 1, 50 | SeekEnd = 2 51 | }; 52 | 53 | class File : public Stream 54 | { 55 | public: 56 | File(FileImplPtr p = FileImplPtr(), FS *baseFS = nullptr) : _p(p), _fakeDir(nullptr), _baseFS(baseFS) { } 57 | 58 | // Print methods: 59 | size_t write(uint8_t) override; 60 | size_t write(const uint8_t *buf, size_t size) override; 61 | 62 | // Stream methods: 63 | int available() override; 64 | int read() override; 65 | int peek() override; 66 | void flush() override; 67 | size_t readBytes(char *buffer, size_t length) override { 68 | return read((uint8_t*)buffer, length); 69 | } 70 | size_t read(uint8_t* buf, size_t size); 71 | bool seek(uint32_t pos, SeekMode mode); 72 | bool seek(uint32_t pos) { 73 | return seek(pos, SeekSet); 74 | } 75 | size_t position() const; 76 | size_t size() const; 77 | void close(); 78 | operator bool() const; 79 | const char* name() const; 80 | const char* fullName() const; // Includes path 81 | bool truncate(uint32_t size); 82 | 83 | bool isFile() const; 84 | bool isDirectory() const; 85 | 86 | // Arduino "class SD" methods for compatibility 87 | template size_t write(T &src){ 88 | uint8_t obuf[256]; 89 | size_t doneLen = 0; 90 | size_t sentLen; 91 | int i; 92 | 93 | while (src.available() > sizeof(obuf)){ 94 | src.read(obuf, sizeof(obuf)); 95 | sentLen = write(obuf, sizeof(obuf)); 96 | doneLen = doneLen + sentLen; 97 | if(sentLen != sizeof(obuf)){ 98 | return doneLen; 99 | } 100 | } 101 | 102 | size_t leftLen = src.available(); 103 | src.read(obuf, leftLen); 104 | sentLen = write(obuf, leftLen); 105 | doneLen = doneLen + sentLen; 106 | return doneLen; 107 | } 108 | 109 | void rewindDirectory(); 110 | File openNextFile(); 111 | 112 | String readString() override; 113 | 114 | time_t getLastWrite(); 115 | time_t getCreationTime(); 116 | void setTimeCallback(time_t (*cb)(void)); 117 | 118 | protected: 119 | FileImplPtr _p; 120 | 121 | // Arduino SD class emulation 122 | std::shared_ptr _fakeDir; 123 | FS *_baseFS; 124 | }; 125 | 126 | class Dir { 127 | public: 128 | Dir(DirImplPtr impl = DirImplPtr(), FS *baseFS = nullptr): _impl(impl), _baseFS(baseFS) { } 129 | 130 | File openFile(const char* mode); 131 | 132 | String fileName(); 133 | size_t fileSize(); 134 | time_t fileTime(); 135 | time_t fileCreationTime(); 136 | bool isFile() const; 137 | bool isDirectory() const; 138 | 139 | bool next(); 140 | bool rewind(); 141 | 142 | void setTimeCallback(time_t (*cb)(void)); 143 | 144 | protected: 145 | DirImplPtr _impl; 146 | FS *_baseFS; 147 | time_t (*timeCallback)(void) = nullptr; 148 | }; 149 | 150 | // Backwards compatible, <4GB filesystem usage 151 | struct FSInfo { 152 | size_t totalBytes; 153 | size_t usedBytes; 154 | size_t blockSize; 155 | size_t pageSize; 156 | size_t maxOpenFiles; 157 | size_t maxPathLength; 158 | }; 159 | 160 | // Support > 4GB filesystems (SD, etc.) 161 | struct FSInfo64 { 162 | uint64_t totalBytes; 163 | uint64_t usedBytes; 164 | size_t blockSize; 165 | size_t pageSize; 166 | size_t maxOpenFiles; 167 | size_t maxPathLength; 168 | }; 169 | 170 | 171 | class FSConfig 172 | { 173 | public: 174 | static constexpr uint32_t FSId = 0x00000000; 175 | 176 | FSConfig(uint32_t type = FSId, bool autoFormat = true) : _type(type), _autoFormat(autoFormat) { } 177 | 178 | FSConfig setAutoFormat(bool val = true) { 179 | _autoFormat = val; 180 | return *this; 181 | } 182 | 183 | uint32_t _type; 184 | bool _autoFormat; 185 | }; 186 | 187 | class SPIFFSConfig : public FSConfig 188 | { 189 | public: 190 | static constexpr uint32_t FSId = 0x53504946; 191 | SPIFFSConfig(bool autoFormat = true) : FSConfig(FSId, autoFormat) { } 192 | 193 | // Inherit _type and _autoFormat 194 | // nothing yet, enableTime TBD when SPIFFS has metadate 195 | }; 196 | 197 | class FS 198 | { 199 | public: 200 | FS(FSImplPtr impl) : _impl(impl) { timeCallback = _defaultTimeCB; } 201 | 202 | bool setConfig(const FSConfig &cfg); 203 | 204 | bool begin(); 205 | void end(); 206 | 207 | bool format(); 208 | bool info(FSInfo& info); 209 | bool info64(FSInfo64& info); 210 | 211 | File open(const char* path, const char* mode); 212 | File open(const String& path, const char* mode); 213 | 214 | bool exists(const char* path); 215 | bool exists(const String& path); 216 | 217 | Dir openDir(const char* path); 218 | Dir openDir(const String& path); 219 | 220 | bool remove(const char* path); 221 | bool remove(const String& path); 222 | 223 | bool rename(const char* pathFrom, const char* pathTo); 224 | bool rename(const String& pathFrom, const String& pathTo); 225 | 226 | bool mkdir(const char* path); 227 | bool mkdir(const String& path); 228 | 229 | bool rmdir(const char* path); 230 | bool rmdir(const String& path); 231 | 232 | // Low-level FS routines, not needed by most applications 233 | bool gc(); 234 | bool check(); 235 | 236 | void setTimeCallback(time_t (*cb)(void)); 237 | 238 | friend class ::SDClass; // More of a frenemy, but SD needs internal implementation to get private FAT bits 239 | protected: 240 | FSImplPtr _impl; 241 | FSImplPtr getImpl() { return _impl; } 242 | time_t (*timeCallback)(void); 243 | static time_t _defaultTimeCB(void) { return time(NULL); } 244 | }; 245 | 246 | } // namespace fs 247 | 248 | extern "C" 249 | { 250 | void close_all_fs(void); 251 | void littlefs_request_end(void); 252 | void spiffs_request_end(void); 253 | } 254 | 255 | #ifndef FS_NO_GLOBALS 256 | using fs::FS; 257 | using fs::File; 258 | using fs::Dir; 259 | using fs::SeekMode; 260 | using fs::SeekSet; 261 | using fs::SeekCur; 262 | using fs::SeekEnd; 263 | using fs::FSInfo; 264 | using fs::FSConfig; 265 | using fs::SPIFFSConfig; 266 | #endif //FS_NO_GLOBALS 267 | 268 | #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SPIFFS) 269 | extern fs::FS SPIFFS __attribute__((deprecated("SPIFFS has been deprecated. Please consider moving to LittleFS or other filesystems."))); 270 | #endif 271 | 272 | #endif //FS_H 273 | -------------------------------------------------------------------------------- /fakeesp/include/FSImpl.h: -------------------------------------------------------------------------------- 1 | /* 2 | FSImpl.h - base file system interface 3 | Copyright (c) 2015 Ivan Grokhotkov. All rights reserved. 4 | This file is part of the esp8266 core for Arduino environment. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | #ifndef FSIMPL_H 21 | #define FSIMPL_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | namespace fs { 28 | 29 | class FileImpl { 30 | public: 31 | virtual ~FileImpl() { } 32 | virtual size_t write(const uint8_t *buf, size_t size) = 0; 33 | virtual size_t read(uint8_t* buf, size_t size) = 0; 34 | virtual void flush() = 0; 35 | virtual bool seek(uint32_t pos, SeekMode mode) = 0; 36 | virtual size_t position() const = 0; 37 | virtual size_t size() const = 0; 38 | virtual bool truncate(uint32_t size) = 0; 39 | virtual void close() = 0; 40 | virtual const char* name() const = 0; 41 | virtual const char* fullName() const = 0; 42 | virtual bool isFile() const = 0; 43 | virtual bool isDirectory() const = 0; 44 | 45 | // Filesystems *may* support a timestamp per-file, so allow the user to override with 46 | // their own callback for *this specific* file (as opposed to the FSImpl call of the 47 | // same name. The default implementation simply returns time(&null) 48 | virtual void setTimeCallback(time_t (*cb)(void)) { timeCallback = cb; } 49 | 50 | // Return the last written time for a file. Undefined when called on a writable file 51 | // as the FS is allowed to return either the time of the last write() operation or the 52 | // time present in the filesystem metadata (often the last time the file was closed) 53 | virtual time_t getLastWrite() { return 0; } // Default is to not support timestamps 54 | // Same for creation time. 55 | virtual time_t getCreationTime() { return 0; } // Default is to not support timestamps 56 | 57 | protected: 58 | time_t (*timeCallback)(void) = nullptr; 59 | }; 60 | 61 | enum OpenMode { 62 | OM_DEFAULT = 0, 63 | OM_CREATE = 1, 64 | OM_APPEND = 2, 65 | OM_TRUNCATE = 4 66 | }; 67 | 68 | enum AccessMode { 69 | AM_READ = 1, 70 | AM_WRITE = 2, 71 | AM_RW = AM_READ | AM_WRITE 72 | }; 73 | 74 | class DirImpl { 75 | public: 76 | virtual ~DirImpl() { } 77 | virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0; 78 | virtual const char* fileName() = 0; 79 | virtual size_t fileSize() = 0; 80 | // Return the last written time for a file. Undefined when called on a writable file 81 | // as the FS is allowed to return either the time of the last write() operation or the 82 | // time present in the filesystem metadata (often the last time the file was closed) 83 | virtual time_t fileTime() { return 0; } // By default, FS doesn't report file times 84 | virtual time_t fileCreationTime() { return 0; } // By default, FS doesn't report file times 85 | virtual bool isFile() const = 0; 86 | virtual bool isDirectory() const = 0; 87 | virtual bool next() = 0; 88 | virtual bool rewind() = 0; 89 | 90 | // Filesystems *may* support a timestamp per-file, so allow the user to override with 91 | // their own callback for *this specific* file (as opposed to the FSImpl call of the 92 | // same name. The default implementation simply returns time(&null) 93 | virtual void setTimeCallback(time_t (*cb)(void)) { timeCallback = cb; } 94 | 95 | protected: 96 | time_t (*timeCallback)(void) = nullptr; 97 | }; 98 | 99 | class FSImpl { 100 | public: 101 | virtual ~FSImpl () { } 102 | virtual bool setConfig(const FSConfig &cfg) = 0; 103 | virtual bool begin() = 0; 104 | virtual void end() = 0; 105 | virtual bool format() = 0; 106 | virtual bool info(FSInfo& info) = 0; 107 | virtual bool info64(FSInfo64& info) = 0; 108 | virtual FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) = 0; 109 | virtual bool exists(const char* path) = 0; 110 | virtual DirImplPtr openDir(const char* path) = 0; 111 | virtual bool rename(const char* pathFrom, const char* pathTo) = 0; 112 | virtual bool remove(const char* path) = 0; 113 | virtual bool mkdir(const char* path) = 0; 114 | virtual bool rmdir(const char* path) = 0; 115 | virtual bool gc() { return true; } // May not be implemented in all file systems. 116 | virtual bool check() { return true; } // May not be implemented in all file systems. 117 | 118 | // Filesystems *may* support a timestamp per-file, so allow the user to override with 119 | // their own callback for all files on this FS. The default implementation simply 120 | // returns the present time as reported by time(&null) 121 | virtual void setTimeCallback(time_t (*cb)(void)) { timeCallback = cb; } 122 | 123 | protected: 124 | time_t (*timeCallback)(void) = nullptr; 125 | }; 126 | 127 | } // namespace fs 128 | 129 | #endif //FSIMPL_H 130 | -------------------------------------------------------------------------------- /fakeesp/include/HardwareSerial.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_HARDWARESERIAL_H 6 | #define WI_SE_SW_HARDWARESERIAL_H 7 | 8 | #include "Stream.h" 9 | #include "Arduino.h" 10 | #include "ArduinoTime.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "uart.h" 17 | #include "HardwareSerial.h" 18 | 19 | #define FAKESERIAL_BUF_LEN 10000 20 | 21 | enum SerialConfig { 22 | SERIAL_5N1 = UART_5N1, 23 | SERIAL_6N1 = UART_6N1, 24 | SERIAL_7N1 = UART_7N1, 25 | SERIAL_8N1 = UART_8N1, 26 | SERIAL_5N2 = UART_5N2, 27 | SERIAL_6N2 = UART_6N2, 28 | SERIAL_7N2 = UART_7N2, 29 | SERIAL_8N2 = UART_8N2, 30 | SERIAL_5E1 = UART_5E1, 31 | SERIAL_6E1 = UART_6E1, 32 | SERIAL_7E1 = UART_7E1, 33 | SERIAL_8E1 = UART_8E1, 34 | SERIAL_5E2 = UART_5E2, 35 | SERIAL_6E2 = UART_6E2, 36 | SERIAL_7E2 = UART_7E2, 37 | SERIAL_8E2 = UART_8E2, 38 | SERIAL_5O1 = UART_5O1, 39 | SERIAL_6O1 = UART_6O1, 40 | SERIAL_7O1 = UART_7O1, 41 | SERIAL_8O1 = UART_8O1, 42 | SERIAL_5O2 = UART_5O2, 43 | SERIAL_6O2 = UART_6O2, 44 | SERIAL_7O2 = UART_7O2, 45 | SERIAL_8O2 = UART_8O2, 46 | }; 47 | 48 | enum SerialMode { 49 | SERIAL_FULL = UART_FULL, 50 | SERIAL_RX_ONLY = UART_RX_ONLY, 51 | SERIAL_TX_ONLY = UART_TX_ONLY 52 | }; 53 | 54 | 55 | class FakeSerial : public Stream { 56 | private: 57 | FILE *fd; 58 | char buffer[FAKESERIAL_BUF_LEN] = {0}; 59 | size_t seekPos = 0; 60 | size_t bufLen = 0; 61 | double rate = 115200 / 8; 62 | 63 | public: 64 | FakeSerial(FILE *fd) : fd{fd} {} 65 | 66 | virtual ~FakeSerial() = default;; 67 | 68 | void begin(unsigned long baud) { 69 | begin(baud, SERIAL_8N1, SERIAL_FULL, 1, false); 70 | } 71 | 72 | void begin(unsigned long baud, SerialConfig config) { 73 | begin(baud, config, SERIAL_FULL, 1, false); 74 | } 75 | 76 | void begin(unsigned long baud, SerialConfig config, SerialMode mode) { 77 | begin(baud, config, mode, 1, false); 78 | } 79 | 80 | void begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin) { 81 | begin(baud, config, mode, tx_pin, false); 82 | } 83 | 84 | void begin(unsigned long baud, SerialConfig config, SerialMode mode, uint8_t tx_pin, bool invert) { 85 | rate = ((double) baud) / 8.0; 86 | } 87 | 88 | void end() {} 89 | 90 | void simulateBaudrate(uint64_t callTimeUs, size_t bytesTransceived) { 91 | #ifdef SIMULATE_BAUDRATE 92 | uint64_t now = micros(); 93 | uint64_t transferDuration = (uint64_t) (bytesTransceived * 1000000 / rate); 94 | delayMicrosecondsNoYield((callTimeUs - now) + transferDuration); 95 | #endif 96 | } 97 | 98 | unsigned long detectBaudrate(time_t timeoutMillis) { 99 | for (int iters = std::max((int) timeoutMillis / 100, 1); iters > 0; iters--) { 100 | delay(100); 101 | } 102 | return 115200; 103 | } 104 | 105 | size_t write(uint8_t uint8) override { 106 | uint64_t now = micros(); 107 | fputc(uint8, fd); 108 | simulateBaudrate(now, 1); 109 | return 1; 110 | } 111 | 112 | size_t write(const uint8_t *outBuffer, size_t size) override { 113 | uint64_t now = micros(); 114 | size_t ret = fwrite(outBuffer, sizeof(uint8_t), size, fd); 115 | fflush(fd); 116 | simulateBaudrate(now, size); 117 | return ret; 118 | } 119 | 120 | void flush() override { 121 | fflush(fd); 122 | } 123 | 124 | int available() override { 125 | // fd_set readfds; 126 | // FD_ZERO(&readfds); 127 | // FD_SET(STDIN_FILENO, &readfds); 128 | // struct timeval timeout{}; 129 | // timeout.tv_sec = 0; 130 | // timeout.tv_usec = 0; 131 | // if (select(1, &readfds, nullptr, nullptr, &timeout) <= 0) { 132 | // return 0; 133 | // } 134 | size_t bread = ::read(fileno(stdin), buffer + seekPos, FAKESERIAL_BUF_LEN - bufLen); 135 | if (bread != -1 || errno != EWOULDBLOCK) { 136 | bufLen += bread; // NOLINT(cppcoreguidelines-narrowing-conversions) 137 | } 138 | return bufLen - seekPos; 139 | } 140 | 141 | int read() override { 142 | simulateBaudrate(0, 1); 143 | if (bufLen == 0) { 144 | return fgetc(stdin); 145 | } 146 | return buffer[seekPos++]; 147 | } 148 | 149 | int peek() override { 150 | if (bufLen == 0) { 151 | int c = fgetc(stdin); 152 | buffer[0] = c; // NOLINT(cppcoreguidelines-narrowing-conversions) 153 | return c; 154 | } 155 | return buffer[seekPos]; 156 | } 157 | 158 | size_t readBytes(char *outBuffer, size_t length) override { 159 | uint64_t now = micros(); 160 | if (bufLen == 0) { 161 | available(); 162 | } 163 | if (bufLen == 0) { 164 | return 0; 165 | } 166 | size_t readLen = std::min(length, bufLen - seekPos); 167 | // Copy internal buffer into output buffer 168 | memcpy(outBuffer, buffer + seekPos, sizeof(char) * readLen); 169 | seekPos += readLen; 170 | if (seekPos >= bufLen) { 171 | // Reset internal buffer 172 | seekPos = 0; 173 | bufLen = 0; 174 | } else if (seekPos < bufLen) { 175 | // Move internal buffer contents to the beginning 176 | memcpy(buffer, buffer + seekPos, sizeof(char) * (bufLen - seekPos)); 177 | bufLen -= seekPos; 178 | seekPos = 0; 179 | } 180 | simulateBaudrate(now, readLen); 181 | return readLen; 182 | } 183 | 184 | size_t readBytes(uint8_t *outBuffer, size_t length) override { 185 | return readBytes((char *) buffer, length); 186 | } 187 | 188 | String readString() override { 189 | char buf[1000]; 190 | size_t len = readBytes(buf, 999); 191 | buf[len] = 0; 192 | return String(buf); 193 | } 194 | 195 | size_t setRxBufferSize(size_t size) { return size; } 196 | 197 | bool operator!=(const FakeSerial &other) const { 198 | return fd == other.fd; 199 | } 200 | }; 201 | 202 | class HardwareSerial : public FakeSerial { 203 | public: 204 | HardwareSerial(FILE *fd) : FakeSerial(fd) {}; 205 | }; 206 | 207 | extern HardwareSerial Serial; 208 | extern HardwareSerial Serial1; 209 | 210 | #endif //WI_SE_SW_HARDWARESERIAL_H 211 | -------------------------------------------------------------------------------- /fakeesp/include/Hash.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Hash.h 3 | * @date 20.05.2015 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the esp8266 core for Arduino environment. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #ifndef HASH_H_ 26 | #define HASH_H_ 27 | 28 | //#define DEBUG_SHA1 29 | 30 | void sha1(const uint8_t* data, uint32_t size, uint8_t hash[20]); 31 | void sha1(const char* data, uint32_t size, uint8_t hash[20]); 32 | void sha1(const String& data, uint8_t hash[20]); 33 | 34 | String sha1(const uint8_t* data, uint32_t size); 35 | String sha1(const char* data, uint32_t size); 36 | String sha1(const String& data); 37 | 38 | #endif /* HASH_H_ */ 39 | -------------------------------------------------------------------------------- /fakeesp/include/IPAddress.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_IPADDRESS_H 6 | #define WI_SE_SW_IPADDRESS_H 7 | 8 | /* 9 | IPAddress.h - Base class that provides IPAddress 10 | Copyright (c) 2011 Adrian McEwen. All right reserved. 11 | 12 | This library is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU Lesser General Public 14 | License as published by the Free Software Foundation; either 15 | version 2.1 of the License, or (at your option) any later version. 16 | 17 | This library is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | Lesser General Public License for more details. 21 | 22 | You should have received a copy of the GNU Lesser General Public 23 | License along with this library; if not, write to the Free Software 24 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 | */ 26 | 27 | #include 28 | #include 29 | #include "lwip/ip_addr.h" 30 | 31 | // compatibility macros to make lwIP-v1 compiling lwIP-v2 API 32 | #define LWIP_IPV6_NUM_ADDRESSES 0 33 | #define ip_2_ip4(x) (x) 34 | #define ipv4_addr ip_addr 35 | #define ipv4_addr_t ip_addr_t 36 | #define IP_IS_V4_VAL(x) (1) 37 | #define IP_SET_TYPE_VAL(x,y) do { (void)0; } while (0) 38 | #define IP_ANY_TYPE &ip_any_type 39 | #define IP4_ADDR_ANY IPADDR_ANY 40 | #define IP4_ADDR_ANY4 IP_ADDR_ANY 41 | #define IPADDR4_INIT(x) { x } 42 | #define CONST /* nothing: lwIP-v1 does not use const */ 43 | #define ip4_addr_netcmp ip_addr_netcmp 44 | #define netif_dhcp_data(netif) ((netif)->dhcp) 45 | 46 | // A class to make it easier to handle and pass around IP addresses 47 | // IPv6 update: 48 | // IPAddress is now a decorator class for lwIP's ip_addr_t 49 | // fully backward compatible with legacy IPv4-only Arduino's 50 | // with unchanged footprint when IPv6 is disabled 51 | 52 | class IPAddress { 53 | private: 54 | 55 | ip_addr_t _ip{}; 56 | 57 | // Access the raw byte array containing the address. Because this returns a pointer 58 | // to the internal structure rather than a copy of the address this function should only 59 | // be used when you know that the usage of the returned uint8_t* will be transient and not 60 | // stored. 61 | uint8_t* raw_address() { 62 | return reinterpret_cast(&v4()); 63 | } 64 | const uint8_t* raw_address() const { 65 | return reinterpret_cast(&v4()); 66 | } 67 | 68 | void ctor32 (uint32_t); 69 | 70 | public: 71 | // Constructors 72 | IPAddress(); 73 | IPAddress(const IPAddress& from); 74 | IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); 75 | IPAddress(uint32_t address) { ctor32(address); } 76 | IPAddress(int address) { ctor32(address); } 77 | IPAddress(const uint8_t *address); 78 | 79 | bool fromString(const char *address); 80 | bool fromString(const String &address) { return fromString(address.c_str()); } 81 | 82 | // Overloaded cast operator to allow IPAddress objects to be used where a pointer 83 | // to a four-byte uint8_t array is expected 84 | operator uint32_t() const { return isV4()? v4(): (uint32_t)0; } 85 | operator uint32_t() { return isV4()? v4(): (uint32_t)0; } 86 | 87 | bool isSet () const; 88 | operator bool () const { return isSet(); } // <- 89 | operator bool () { return isSet(); } // <- both are needed 90 | 91 | // generic IPv4 wrapper to uint32-view like arduino loves to see it 92 | const uint32_t& v4() const { return ip_2_ip4(&_ip)->addr; } // for raw_address(const) 93 | uint32_t& v4() { return ip_2_ip4(&_ip)->addr; } 94 | 95 | bool operator==(const IPAddress& addr) const { 96 | return ip_addr_cmp(&_ip, &addr._ip); 97 | } 98 | bool operator!=(const IPAddress& addr) const { 99 | return !ip_addr_cmp(&_ip, &addr._ip); 100 | } 101 | bool operator==(uint32_t addr) const { 102 | return isV4() && v4() == addr; 103 | } 104 | bool operator!=(uint32_t addr) const { 105 | return !(isV4() && v4() == addr); 106 | } 107 | bool operator==(const uint8_t* addr) const; 108 | 109 | int operator>>(int n) const { 110 | return isV4()? v4() >> n: 0; 111 | } 112 | 113 | // Overloaded index operator to allow getting and setting individual octets of the address 114 | uint8_t operator[](int index) const { 115 | return isV4()? *(raw_address() + index): 0; 116 | } 117 | uint8_t& operator[](int index) { 118 | setV4(); 119 | return *(raw_address() + index); 120 | } 121 | 122 | // Overloaded copy operators to allow initialisation of IPAddress objects from other types 123 | IPAddress& operator=(const uint8_t *address); 124 | IPAddress& operator=(uint32_t address); 125 | IPAddress& operator=(const IPAddress&) = default; 126 | 127 | String toString() const; 128 | 129 | /* 130 | check if input string(arg) is a valid IPV4 address or not. 131 | return true on valid. 132 | return false on invalid. 133 | */ 134 | static bool isValid(const String& arg); 135 | static bool isValid(const char* arg); 136 | 137 | friend class EthernetClass; 138 | friend class UDP; 139 | friend class Client; 140 | friend class Server; 141 | friend class DhcpClass; 142 | friend class DNSClient; 143 | 144 | /* 145 | lwIP address compatibility 146 | */ 147 | IPAddress(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; } 148 | IPAddress(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; } 149 | 150 | IPAddress& operator=(const ipv4_addr& fw_addr) { setV4(); v4() = fw_addr.addr; return *this; } 151 | IPAddress& operator=(const ipv4_addr* fw_addr) { setV4(); v4() = fw_addr->addr; return *this; } 152 | 153 | operator ip_addr_t () const { return _ip; } 154 | operator const ip_addr_t*() const { return &_ip; } 155 | operator ip_addr_t*() { return &_ip; } 156 | 157 | bool isV4() const { return IP_IS_V4_VAL(_ip); } 158 | void setV4() { IP_SET_TYPE_VAL(_ip, IPADDR_TYPE_V4); } 159 | 160 | bool isLocal () const { return ip_addr_islinklocal(&_ip); } 161 | 162 | // allow portable code when IPv6 is not enabled 163 | 164 | uint16_t* raw6() { return nullptr; } 165 | const uint16_t* raw6() const { return nullptr; } 166 | bool isV6() const { return false; } 167 | void setV6() { } 168 | 169 | protected: 170 | bool fromString4(const char *address); 171 | 172 | }; 173 | 174 | 175 | #endif //WI_SE_SW_IPADDRESS_H 176 | -------------------------------------------------------------------------------- /fakeesp/include/Print.h: -------------------------------------------------------------------------------- 1 | /* 2 | Print.h - Base class that provides print() and println() 3 | Copyright (c) 2008 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef Print_h 21 | #define Print_h 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "Arduino.h" 28 | #include "WString.h" 29 | #include "Printable.h" 30 | #include "progmem.h" 31 | 32 | 33 | #define DEC 10 34 | #define HEX 16 35 | #define OCT 8 36 | #define BIN 2 37 | 38 | class Print { 39 | private: 40 | int write_error; 41 | size_t printNumber(unsigned long, uint8_t); 42 | size_t printFloat(double, uint8_t); 43 | protected: 44 | void setWriteError(int err = 1) { 45 | write_error = err; 46 | } 47 | public: 48 | Print() : 49 | write_error(0) { 50 | } 51 | 52 | int getWriteError() { 53 | return write_error; 54 | } 55 | void clearWriteError() { 56 | setWriteError(0); 57 | } 58 | 59 | virtual size_t write(uint8_t) = 0; 60 | size_t write(const char *str) { 61 | if(str == NULL) 62 | return 0; 63 | return write((const uint8_t *) str, strlen(str)); 64 | } 65 | virtual size_t write(const uint8_t *buffer, size_t size); 66 | size_t write(const char *buffer, size_t size) { 67 | return write((const uint8_t *) buffer, size); 68 | } 69 | // These handle ambiguity for write(0) case, because (0) can be a pointer or an integer 70 | inline size_t write(short t) { return write((uint8_t)t); } 71 | inline size_t write(unsigned short t) { return write((uint8_t)t); } 72 | inline size_t write(int t) { return write((uint8_t)t); } 73 | inline size_t write(unsigned int t) { return write((uint8_t)t); } 74 | inline size_t write(long t) { return write((uint8_t)t); } 75 | inline size_t write(unsigned long t) { return write((uint8_t)t); } 76 | // Enable write(char) to fall through to write(uint8_t) 77 | inline size_t write(char c) { return write((uint8_t) c); } 78 | inline size_t write(int8_t c) { return write((uint8_t) c); } 79 | 80 | size_t printf(const char * format, ...) __attribute__ ((format (printf, 2, 3))); 81 | size_t printf_P(PGM_P format, ...) __attribute__((format(printf, 2, 3))); 82 | size_t print(const __FlashStringHelper *); 83 | size_t print(const String &); 84 | size_t print(const char[]); 85 | size_t print(char); 86 | size_t print(unsigned char, int = DEC); 87 | size_t print(int, int = DEC); 88 | size_t print(unsigned int, int = DEC); 89 | size_t print(long, int = DEC); 90 | size_t print(unsigned long, int = DEC); 91 | size_t print(double, int = 2); 92 | size_t print(const Printable&); 93 | 94 | size_t println(const __FlashStringHelper *); 95 | size_t println(const String &s); 96 | size_t println(const char[]); 97 | size_t println(char); 98 | size_t println(unsigned char, int = DEC); 99 | size_t println(int, int = DEC); 100 | size_t println(unsigned int, int = DEC); 101 | size_t println(long, int = DEC); 102 | size_t println(unsigned long, int = DEC); 103 | size_t println(double, int = 2); 104 | size_t println(const Printable&); 105 | size_t println(void); 106 | 107 | virtual void flush() { /* Empty implementation for backward compatibility */ } 108 | }; 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /fakeesp/include/Printable.h: -------------------------------------------------------------------------------- 1 | /* 2 | Printable.h - Interface class that allows printing of complex types 3 | Copyright (c) 2011 Adrian McEwen. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #ifndef Printable_h 21 | #define Printable_h 22 | 23 | #include 24 | 25 | class Print; 26 | 27 | /** The Printable class provides a way for new classes to allow themselves to be printed. 28 | By deriving from Printable and implementing the printTo method, it will then be possible 29 | for users to print out instances of this class by passing them into the usual 30 | Print::print and Print::println methods. 31 | */ 32 | 33 | class Printable { 34 | public: 35 | virtual size_t printTo(Print& p) const = 0; 36 | }; 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /fakeesp/include/Stream.h: -------------------------------------------------------------------------------- 1 | /* 2 | Stream.h - base class for character-based streams. 3 | Copyright (c) 2010 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | parsing functions based on TextFinder library by Michael Margolis 20 | */ 21 | 22 | #ifndef Stream_h 23 | #define Stream_h 24 | 25 | #include 26 | #include "Print.h" 27 | 28 | // compatability macros for testing 29 | /* 30 | #define getInt() parseInt() 31 | #define getInt(skipChar) parseInt(skipchar) 32 | #define getFloat() parseFloat() 33 | #define getFloat(skipChar) parseFloat(skipChar) 34 | #define getString( pre_string, post_string, buffer, length) 35 | readBytesBetween( pre_string, terminator, buffer, length) 36 | */ 37 | 38 | class Stream: public Print { 39 | protected: 40 | unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read 41 | unsigned long _startMillis; // used for timeout measurement 42 | int timedRead(); // private method to read stream with timeout 43 | int timedPeek(); // private method to peek stream with timeout 44 | int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout 45 | 46 | public: 47 | virtual int available() = 0; 48 | virtual int read() = 0; 49 | virtual int peek() = 0; 50 | 51 | Stream() { 52 | _timeout = 1000; 53 | } 54 | 55 | // parsing methods 56 | 57 | void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second 58 | 59 | bool find(const char *target); // reads data from the stream until the target string is found 60 | bool find(uint8_t *target) { 61 | return find((char *) target); 62 | } 63 | // returns true if target string is found, false if timed out (see setTimeout) 64 | 65 | bool find(const char *target, size_t length); // reads data from the stream until the target string of given length is found 66 | bool find(const uint8_t *target, size_t length) { 67 | return find((char *) target, length); 68 | } 69 | // returns true if target string is found, false if timed out 70 | 71 | bool find(char target) { return find (&target, 1); } 72 | 73 | bool findUntil(const char *target, const char *terminator); // as find but search ends if the terminator string is found 74 | bool findUntil(const uint8_t *target, const char *terminator) { 75 | return findUntil((char *) target, terminator); 76 | } 77 | 78 | bool findUntil(const char *target, size_t targetLen, const char *terminate, size_t termLen); // as above but search ends if the terminate string is found 79 | bool findUntil(const uint8_t *target, size_t targetLen, const char *terminate, size_t termLen) { 80 | return findUntil((char *) target, targetLen, terminate, termLen); 81 | } 82 | 83 | long parseInt(); // returns the first valid (long) integer value from the current position. 84 | // initial characters that are not digits (or the minus sign) are skipped 85 | // integer is terminated by the first character that is not a digit. 86 | 87 | float parseFloat(); // float version of parseInt 88 | 89 | virtual size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer 90 | virtual size_t readBytes(uint8_t *buffer, size_t length) { 91 | return readBytes((char *) buffer, length); 92 | } 93 | // terminates if length characters have been read or timeout (see setTimeout) 94 | // returns the number of characters placed in the buffer (0 means no valid data found) 95 | 96 | size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character 97 | size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { 98 | return readBytesUntil(terminator, (char *) buffer, length); 99 | } 100 | // terminates if length characters have been read, timeout, or if the terminator character detected 101 | // returns the number of characters placed in the buffer (0 means no valid data found) 102 | 103 | // Arduino String functions to be added here 104 | virtual String readString(); 105 | String readStringUntil(char terminator); 106 | 107 | protected: 108 | long parseInt(char skipChar); // as above but the given skipChar is ignored 109 | // as above but the given skipChar is ignored 110 | // this allows format characters (typically commas) in values to be ignored 111 | 112 | float parseFloat(char skipChar); // as above but the given skipChar is ignored 113 | }; 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /fakeesp/include/c_types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRESSIF MIT License 3 | * 4 | * Copyright (c) 2016 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef _C_TYPES_H_ 26 | #define _C_TYPES_H_ 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | typedef signed char sint8_t; 33 | typedef signed short sint16_t; 34 | typedef signed long sint32_t; 35 | typedef signed long long sint64_t; 36 | typedef float real32_t; 37 | typedef double real64_t; 38 | 39 | typedef unsigned char uint8; 40 | typedef unsigned char u8; 41 | typedef signed char sint8; 42 | typedef signed char int8; 43 | typedef signed char s8; 44 | typedef unsigned short uint16; 45 | typedef unsigned short u16; 46 | typedef signed short sint16; 47 | typedef signed short s16; 48 | typedef unsigned int uint32; 49 | typedef unsigned int u_int; 50 | typedef unsigned int u32; 51 | typedef signed int sint32; 52 | typedef signed int s32; 53 | typedef int int32; 54 | typedef signed long long sint64; 55 | typedef unsigned long long uint64; 56 | typedef unsigned long long u64; 57 | typedef float real32; 58 | typedef double real64; 59 | 60 | #define __le16 u16 61 | 62 | #define LOCAL static 63 | 64 | #ifndef NULL 65 | #define NULL (void *)0 66 | #endif /* NULL */ 67 | 68 | /* probably should not put STATUS here */ 69 | typedef enum { 70 | OK = 0, 71 | FAIL, 72 | PENDING, 73 | BUSY, 74 | CANCEL, 75 | } STATUS; 76 | 77 | #define BIT(nr) (1UL << (nr)) 78 | 79 | #define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b)) 80 | #define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b)) 81 | 82 | #define DMEM_ATTR __attribute__((section(".bss"))) 83 | #define SHMEM_ATTR 84 | 85 | #ifdef ICACHE_FLASH 86 | #define __ICACHE_STRINGIZE_NX(A) #A 87 | #define __ICACHE_STRINGIZE(A) __ICACHE_STRINGIZE_NX(A) 88 | #define ICACHE_FLASH_ATTR __attribute__((section("\".irom0.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\""))) 89 | #define ICACHE_RAM_ATTR __attribute__((section("\".iram.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\""))) 90 | #else 91 | #define ICACHE_FLASH_ATTR 92 | #define ICACHE_RAM_ATTR 93 | #endif /* ICACHE_FLASH */ 94 | 95 | // counterpart https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp8266-compat.h 96 | #define IRAM_ATTR ICACHE_RAM_ATTR 97 | 98 | #define STORE_ATTR __attribute__((aligned(4))) 99 | 100 | #ifndef __cplusplus 101 | #define BOOL bool 102 | #define TRUE true 103 | #define FALSE false 104 | 105 | 106 | #endif /* !__cplusplus */ 107 | 108 | #endif /* _C_TYPES_H_ */ 109 | -------------------------------------------------------------------------------- /fakeesp/include/cbuf.h: -------------------------------------------------------------------------------- 1 | /* 2 | cbuf.h - Circular buffer implementation 3 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 4 | This file is part of the esp8266 core for Arduino environment. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #ifndef __cbuf_h 22 | #define __cbuf_h 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | class cbuf { 29 | public: 30 | cbuf(size_t size); 31 | ~cbuf(); 32 | 33 | size_t resizeAdd(size_t addSize); 34 | size_t resize(size_t newSize); 35 | size_t available() const; 36 | size_t size(); 37 | 38 | size_t room() const; 39 | 40 | inline bool empty() const { 41 | return _begin == _end; 42 | } 43 | 44 | inline bool full() const { 45 | return wrap_if_bufend(_end + 1) == _begin; 46 | } 47 | 48 | int peek(); 49 | size_t peek(char *dst, size_t size); 50 | 51 | int read(); 52 | size_t read(char* dst, size_t size); 53 | 54 | size_t write(char c); 55 | size_t write(const char* src, size_t size); 56 | 57 | void flush(); 58 | size_t remove(size_t size); 59 | 60 | cbuf *next; 61 | 62 | private: 63 | inline char* wrap_if_bufend(char* ptr) const { 64 | return (ptr == _bufend) ? _buf : ptr; 65 | } 66 | 67 | size_t _size; 68 | char* _buf; 69 | const char* _bufend; 70 | char* _begin; 71 | char* _end; 72 | 73 | }; 74 | 75 | #endif//__cbuf_h 76 | -------------------------------------------------------------------------------- /fakeesp/include/esp8266_peri.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/11/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_ESP8266_PERI_H 6 | #define WI_SE_SW_ESP8266_PERI_H 7 | 8 | #endif //WI_SE_SW_ESP8266_PERI_H 9 | -------------------------------------------------------------------------------- /fakeesp/include/itoa.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_ITOA_H 6 | #define WI_SE_SW_ITOA_H 7 | 8 | char* itoa (int val, char *s, int radix); 9 | 10 | char* ltoa (long val, char *s, int radix); 11 | 12 | char* utoa (unsigned int val, char *s, int radix); 13 | 14 | char* ultoa (unsigned long val, char *s, int radix); 15 | 16 | char* dtostrf (double val, signed char width, unsigned char prec, char *s); 17 | 18 | //void reverse(char* begin, char* end); 19 | 20 | #endif //WI_SE_SW_ITOA_H 21 | -------------------------------------------------------------------------------- /fakeesp/include/libb64/AUTHORS: -------------------------------------------------------------------------------- 1 | libb64: Base64 Encoding/Decoding Routines 2 | ====================================== 3 | 4 | Authors: 5 | ------- 6 | 7 | Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com 8 | -------------------------------------------------------------------------------- /fakeesp/include/libb64/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright-Only Dedication (based on United States law) 2 | or Public Domain Certification 3 | 4 | The person or persons who have associated work with this document (the 5 | "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of 6 | his knowledge, the work of authorship identified is in the public domain of the 7 | country from which the work is published, or (b) hereby dedicates whatever 8 | copyright the dedicators holds in the work of authorship identified below (the 9 | "Work") to the public domain. A certifier, moreover, dedicates any copyright 10 | interest he may have in the associated work, and for these purposes, is 11 | described as a "dedicator" below. 12 | 13 | A certifier has taken reasonable steps to verify the copyright status of this 14 | work. Certifier recognizes that his good faith efforts may not shield him from 15 | liability if in fact the work certified is not in the public domain. 16 | 17 | Dedicator makes this dedication for the benefit of the public at large and to 18 | the detriment of the Dedicator's heirs and successors. Dedicator intends this 19 | dedication to be an overt act of relinquishment in perpetuity of all present 20 | and future rights under copyright law, whether vested or contingent, in the 21 | Work. Dedicator understands that such relinquishment of all rights includes 22 | the relinquishment of all rights to enforce (by lawsuit or otherwise) those 23 | copyrights in the Work. 24 | 25 | Dedicator recognizes that, once placed in the public domain, the Work may be 26 | freely reproduced, distributed, transmitted, used, modified, built upon, or 27 | otherwise exploited by anyone for any purpose, commercial or non-commercial, 28 | and in any way, including by methods that have not yet been invented or 29 | conceived. -------------------------------------------------------------------------------- /fakeesp/include/libb64/cdecode.h: -------------------------------------------------------------------------------- 1 | /* 2 | cdecode.h - c header for a base64 decoding algorithm 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifndef BASE64_CDECODE_H 9 | #define BASE64_CDECODE_H 10 | 11 | #define base64_decode_expected_len(n) ((n * 3) / 4) 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | typedef enum { 18 | step_a, step_b, step_c, step_d 19 | } base64_decodestep; 20 | 21 | typedef struct { 22 | base64_decodestep step; 23 | char plainchar; 24 | } base64_decodestate; 25 | 26 | void base64_init_decodestate(base64_decodestate* state_in); 27 | 28 | int base64_decode_value(char value_in); 29 | 30 | int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); 31 | 32 | int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out); 33 | 34 | #ifdef __cplusplus 35 | } // extern "C" 36 | #endif 37 | 38 | #endif /* BASE64_CDECODE_H */ 39 | -------------------------------------------------------------------------------- /fakeesp/include/libb64/cencode.h: -------------------------------------------------------------------------------- 1 | /* 2 | cencode.h - c header for a base64 encoding algorithm 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifndef BASE64_CENCODE_H 9 | #define BASE64_CENCODE_H 10 | 11 | #define BASE64_CHARS_PER_LINE 72 12 | 13 | #define base64_encode_expected_len_nonewlines(n) ((((4 * (n)) / 3) + 3) & ~3) 14 | #define base64_encode_expected_len(n) \ 15 | (base64_encode_expected_len_nonewlines(n) + ((n / ((BASE64_CHARS_PER_LINE * 3) / 4)) + 1)) 16 | 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | typedef enum { 23 | step_A, step_B, step_C 24 | } base64_encodestep; 25 | 26 | typedef struct { 27 | base64_encodestep step; 28 | char result; 29 | int stepcount; 30 | int stepsnewline; 31 | } base64_encodestate; 32 | 33 | void base64_init_encodestate(base64_encodestate* state_in); 34 | void base64_init_encodestate_nonewlines(base64_encodestate* state_in); 35 | 36 | char base64_encode_value(char value_in); 37 | 38 | int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); 39 | 40 | int base64_encode_blockend(char* code_out, base64_encodestate* state_in); 41 | 42 | int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out); 43 | 44 | #ifdef __cplusplus 45 | } // extern "C" 46 | #endif 47 | 48 | #endif /* BASE64_CENCODE_H */ 49 | -------------------------------------------------------------------------------- /fakeesp/include/lwip/err.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 19 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 20 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 21 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 25 | * OF SUCH DAMAGE. 26 | * 27 | * This file is part of the lwIP TCP/IP stack. 28 | * 29 | * Author: Adam Dunkels 30 | * 31 | */ 32 | #ifndef __LWIP_ERR_H__ 33 | #define __LWIP_ERR_H__ 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /** Define LWIP_ERR_T in cc.h if you want to use 40 | * a different type for your platform (must be signed). */ 41 | #ifdef LWIP_ERR_T 42 | typedef LWIP_ERR_T err_t; 43 | #else /* LWIP_ERR_T */ 44 | typedef int8_t err_t; 45 | #endif /* LWIP_ERR_T*/ 46 | 47 | /* Definitions for error constants. */ 48 | 49 | #define ERR_OK 0 /* No error, everything OK. */ 50 | #define ERR_MEM -1 /* Out of memory error. */ 51 | #define ERR_BUF -2 /* Buffer error. */ 52 | #define ERR_TIMEOUT -3 /* Timeout. */ 53 | #define ERR_RTE -4 /* Routing problem. */ 54 | #define ERR_INPROGRESS -5 /* Operation in progress */ 55 | #define ERR_VAL -6 /* Illegal value. */ 56 | #define ERR_WOULDBLOCK -7 /* Operation would block. */ 57 | 58 | #define ERR_IS_FATAL(e) ((e) < ERR_WOULDBLOCK) 59 | 60 | #define ERR_ABRT -8 /* Connection aborted. */ 61 | #define ERR_RST -9 /* Connection reset. */ 62 | #define ERR_CLSD -10 /* Connection closed. */ 63 | #define ERR_CONN -11 /* Not connected. */ 64 | 65 | #define ERR_ARG -12 /* Illegal argument. */ 66 | 67 | #define ERR_USE -13 /* Address in use. */ 68 | 69 | #define ERR_IF -14 /* Low-level netif error */ 70 | #define ERR_ISCONN -15 /* Already connected. */ 71 | 72 | 73 | #ifdef LWIP_DEBUG 74 | extern const char *lwip_strerr(err_t err)ICACHE_FLASH_ATTR; 75 | #else 76 | #define lwip_strerr(x) "" 77 | #endif /* LWIP_DEBUG */ 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif /* __LWIP_ERR_H__ */ 84 | -------------------------------------------------------------------------------- /fakeesp/include/lwip/init.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_INIT_H 6 | #define WI_SE_SW_INIT_H 7 | 8 | #endif //WI_SE_SW_INIT_H 9 | -------------------------------------------------------------------------------- /fakeesp/include/lwip/pbuf.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_PBUF_H 6 | #define WI_SE_SW_PBUF_H 7 | 8 | #endif //WI_SE_SW_PBUF_H 9 | -------------------------------------------------------------------------------- /fakeesp/include/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | md5.h - exposed md5 ROM functions for esp8266 3 | 4 | Copyright (c) 2015 Hristo Gochkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | original C source from https://github.com/morrissinger/ESP8266-Websocket/raw/master/MD5.h 8 | 9 | This library is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU Lesser General Public 11 | License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. 13 | 14 | This library is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public 20 | License along with this library; if not, write to the Free Software 21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | */ 23 | #ifndef __ESP8266_MD5__ 24 | #define __ESP8266_MD5__ 25 | 26 | #include 27 | #include 28 | 29 | #define md5_context_t MD5_CTX 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | extern void MD5Init (md5_context_t *); 36 | extern void MD5Update (md5_context_t *, const uint8_t *, const uint16_t); 37 | extern void MD5Final (uint8_t [16], md5_context_t *); 38 | 39 | #ifdef __cplusplus 40 | } // extern "C" 41 | #endif 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /fakeesp/include/progmem.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/7/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_PROGMEM_H 6 | #define WI_SE_SW_PROGMEM_H 7 | 8 | // Fake progmem 9 | #define PROGMEM 10 | #define PGM_P const char * 11 | #define __FlashStringHelper char * 12 | #define memcpy_P memcpy 13 | #define memmove_P memmove 14 | #define strlen_P strlen 15 | #define strcpy_P strcpy 16 | #define vsnprintf_P vsnprintf 17 | #define pgm_read_byte(arg) (*(arg)) 18 | 19 | #endif //WI_SE_SW_PROGMEM_H 20 | -------------------------------------------------------------------------------- /fakeesp/include/uart.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_UART_H 6 | #define WI_SE_SW_UART_H 7 | 8 | #define UART_CLK_FREQ 115200 9 | 10 | #define UART0 0 11 | #define UART1 1 12 | #define UART_NO -1 13 | 14 | // Options for `config` argument of uart_init 15 | #define UART_NB_BIT_MASK 0B00001100 16 | #define UART_NB_BIT_5 0B00000000 17 | #define UART_NB_BIT_6 0B00000100 18 | #define UART_NB_BIT_7 0B00001000 19 | #define UART_NB_BIT_8 0B00001100 20 | 21 | #define UART_PARITY_MASK 0B00000011 22 | #define UART_PARITY_NONE 0B00000000 23 | #define UART_PARITY_EVEN 0B00000010 24 | #define UART_PARITY_ODD 0B00000011 25 | 26 | #define UART_NB_STOP_BIT_MASK 0B00110000 27 | #define UART_NB_STOP_BIT_0 0B00000000 28 | #define UART_NB_STOP_BIT_1 0B00010000 29 | #define UART_NB_STOP_BIT_15 0B00100000 30 | #define UART_NB_STOP_BIT_2 0B00110000 31 | 32 | #define UART_5N1 ( UART_NB_BIT_5 | UART_PARITY_NONE | UART_NB_STOP_BIT_1 ) 33 | #define UART_6N1 ( UART_NB_BIT_6 | UART_PARITY_NONE | UART_NB_STOP_BIT_1 ) 34 | #define UART_7N1 ( UART_NB_BIT_7 | UART_PARITY_NONE | UART_NB_STOP_BIT_1 ) 35 | #define UART_8N1 ( UART_NB_BIT_8 | UART_PARITY_NONE | UART_NB_STOP_BIT_1 ) 36 | #define UART_5N2 ( UART_NB_BIT_5 | UART_PARITY_NONE | UART_NB_STOP_BIT_2 ) 37 | #define UART_6N2 ( UART_NB_BIT_6 | UART_PARITY_NONE | UART_NB_STOP_BIT_2 ) 38 | #define UART_7N2 ( UART_NB_BIT_7 | UART_PARITY_NONE | UART_NB_STOP_BIT_2 ) 39 | #define UART_8N2 ( UART_NB_BIT_8 | UART_PARITY_NONE | UART_NB_STOP_BIT_2 ) 40 | #define UART_5E1 ( UART_NB_BIT_5 | UART_PARITY_EVEN | UART_NB_STOP_BIT_1 ) 41 | #define UART_6E1 ( UART_NB_BIT_6 | UART_PARITY_EVEN | UART_NB_STOP_BIT_1 ) 42 | #define UART_7E1 ( UART_NB_BIT_7 | UART_PARITY_EVEN | UART_NB_STOP_BIT_1 ) 43 | #define UART_8E1 ( UART_NB_BIT_8 | UART_PARITY_EVEN | UART_NB_STOP_BIT_1 ) 44 | #define UART_5E2 ( UART_NB_BIT_5 | UART_PARITY_EVEN | UART_NB_STOP_BIT_2 ) 45 | #define UART_6E2 ( UART_NB_BIT_6 | UART_PARITY_EVEN | UART_NB_STOP_BIT_2 ) 46 | #define UART_7E2 ( UART_NB_BIT_7 | UART_PARITY_EVEN | UART_NB_STOP_BIT_2 ) 47 | #define UART_8E2 ( UART_NB_BIT_8 | UART_PARITY_EVEN | UART_NB_STOP_BIT_2 ) 48 | #define UART_5O1 ( UART_NB_BIT_5 | UART_PARITY_ODD | UART_NB_STOP_BIT_1 ) 49 | #define UART_6O1 ( UART_NB_BIT_6 | UART_PARITY_ODD | UART_NB_STOP_BIT_1 ) 50 | #define UART_7O1 ( UART_NB_BIT_7 | UART_PARITY_ODD | UART_NB_STOP_BIT_1 ) 51 | #define UART_8O1 ( UART_NB_BIT_8 | UART_PARITY_ODD | UART_NB_STOP_BIT_1 ) 52 | #define UART_5O2 ( UART_NB_BIT_5 | UART_PARITY_ODD | UART_NB_STOP_BIT_2 ) 53 | #define UART_6O2 ( UART_NB_BIT_6 | UART_PARITY_ODD | UART_NB_STOP_BIT_2 ) 54 | #define UART_7O2 ( UART_NB_BIT_7 | UART_PARITY_ODD | UART_NB_STOP_BIT_2 ) 55 | #define UART_8O2 ( UART_NB_BIT_8 | UART_PARITY_ODD | UART_NB_STOP_BIT_2 ) 56 | 57 | /* 58 | #define UART_5N1 0x10 59 | #define UART_6N1 0x14 60 | #define UART_7N1 0x18 61 | #define UART_8N1 0x1c 62 | #define UART_5N2 0x30 63 | #define UART_6N2 0x34 64 | #define UART_7N2 0x38 65 | #define UART_8N2 0x3c 66 | #define UART_5E1 0x12 67 | #define UART_6E1 0x16 68 | #define UART_7E1 0x1a 69 | #define UART_8E1 0x1e 70 | #define UART_5E2 0x32 71 | #define UART_6E2 0x36 72 | #define UART_7E2 0x3a 73 | #define UART_8E2 0x3e 74 | #define UART_5O1 0x13 75 | #define UART_6O1 0x17 76 | #define UART_7O1 0x1b 77 | #define UART_8O1 0x1f 78 | #define UART_5O2 0x33 79 | #define UART_6O2 0x37 80 | #define UART_7O2 0x3b 81 | #define UART_8O2 0x3f 82 | */ 83 | 84 | // Options for `mode` argument of uart_init 85 | #define UART_FULL 0 86 | #define UART_RX_ONLY 1 87 | #define UART_TX_ONLY 2 88 | 89 | #define UART_TX_FIFO_SIZE 0x80 90 | 91 | void uart_start_detect_baudrate(int); 92 | int uart_baudrate_detect(int, int); 93 | 94 | #endif //WI_SE_SW_UART_H 95 | -------------------------------------------------------------------------------- /fakeesp/include/user_interface.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/11/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_USER_INTERFACE_H 6 | #define WI_SE_SW_USER_INTERFACE_H 7 | 8 | #endif //WI_SE_SW_USER_INTERFACE_H 9 | -------------------------------------------------------------------------------- /fakeesp/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main() { 15 | int fdno = fileno(stdin); 16 | int flags = fcntl(fdno, F_GETFL); 17 | if (flags < 0) { 18 | perror("Unable to get flags stdin"); 19 | exit(1); 20 | } 21 | if (fcntl(fdno, F_SETFL, flags | O_NONBLOCK) < 0) { 22 | perror("Unable to set non blocking stdin"); 23 | exit(1); 24 | } 25 | srand(time(NULL)); 26 | 27 | setup(); 28 | #pragma clang diagnostic push 29 | #pragma ide diagnostic ignored "EndlessLoop" 30 | for (;;) { 31 | loop(); 32 | } 33 | #pragma clang diagnostic pop 34 | } -------------------------------------------------------------------------------- /fakeesp/src/ArduinoTime.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "ArduinoTime.h" 10 | 11 | #define ODJT_LEN 50 12 | 13 | #ifndef NULL 14 | #define NULL 0 15 | #endif 16 | 17 | void (*onDelayJumpTable[ODJT_LEN])(void *arg) = {0}; 18 | void *onDelayArgs[ODJT_LEN] = {0}; 19 | 20 | 21 | int32_t registerOnDelayCallback(void (*callback)(void *arg), void *arg) { 22 | for (int32_t i = 0; i < ODJT_LEN; i++) { 23 | if (onDelayJumpTable[i] == NULL) { 24 | onDelayJumpTable[i] = callback; 25 | onDelayArgs[i] = arg; 26 | return i; 27 | } 28 | } 29 | return -1; 30 | } 31 | 32 | void deregisterOnDelayCallback(uint32_t id) { 33 | onDelayJumpTable[id] = nullptr; 34 | onDelayArgs[id] = nullptr; 35 | } 36 | 37 | void callOnDelayCallbacks() { 38 | for (int i = 0; i < ODJT_LEN; i++) { 39 | if (onDelayJumpTable[i] != nullptr) { 40 | (*onDelayJumpTable[i])(onDelayArgs[i]); 41 | } 42 | } 43 | } 44 | 45 | void yield() { 46 | delay(1); 47 | } 48 | 49 | unsigned long millis() { 50 | return micros64() / 1000; 51 | } 52 | 53 | unsigned long micros() { 54 | return micros64(); 55 | } 56 | 57 | uint64_t micros64() { 58 | struct timeval tv = {0}; 59 | gettimeofday(&tv, nullptr); 60 | return (1000000 * tv.tv_sec) + tv.tv_usec; 61 | } 62 | 63 | void delay(unsigned long ms) { 64 | delayMicroseconds(ms * 1000); 65 | } 66 | 67 | void delayNoYield(unsigned long ms) { 68 | delayMicrosecondsNoYield(ms * 1000); 69 | } 70 | 71 | void delayMicroseconds(unsigned int us) { 72 | callOnDelayCallbacks(); 73 | delayMicrosecondsNoYield(us); 74 | } 75 | 76 | void delayMicrosecondsNoYield(unsigned int us) { 77 | struct timespec delta = {us / (1000 * 1000), (us % (1000 * 1000)) * 1000}; 78 | while (nanosleep(&delta, &delta)); 79 | } -------------------------------------------------------------------------------- /fakeesp/src/FakeGPIO.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "Arduino.h" 11 | 12 | #define FAKEESP_ENU_PINS 17 13 | 14 | char fakeEspDefaultGpioFilePath[] = "/tmp/fakeesp_gpio.txt"; 15 | 16 | uint8_t pinModes[FAKEESP_ENU_PINS] = {42}; // Init to invalid pin mode 17 | int pinValues[FAKEESP_ENU_PINS] = {0}; 18 | 19 | 20 | char *getGpioFilePath() { 21 | char *path = getenv("FAKEESP_GPIO_FILE"); 22 | if (path == NULL) { 23 | return fakeEspDefaultGpioFilePath; 24 | } 25 | return path; 26 | } 27 | 28 | void writePinFile() { 29 | FILE *file = fopen(getGpioFilePath(), "w"); 30 | if (file == NULL) { 31 | fprintf(stderr, "Unable to open fake GPIO file (%d): %s\n", errno, strerror(errno)); 32 | return; 33 | } 34 | fprintf(file, "PIN: "); 35 | for (int i = 0; i < FAKEESP_ENU_PINS; i++) { 36 | fprintf(file, " %3d ", i); 37 | } 38 | fprintf(file, "\n------"); 39 | for (int i = 0; i < FAKEESP_ENU_PINS; i++) { 40 | fprintf(file, "-----"); 41 | } 42 | fprintf(file, "\nMODE: "); 43 | for (int i = 0; i < FAKEESP_ENU_PINS; i++) { 44 | if (pinModes[i] == OUTPUT) { 45 | fprintf(file, " OUT "); 46 | } else if (pinModes[i] == INPUT) { 47 | fprintf(file, " INP "); 48 | } else if (pinModes[i] == FAKEMODE_PWM_OUT) { 49 | fprintf(file, " PWM "); 50 | } else { 51 | fprintf(file, " ??? "); 52 | } 53 | } 54 | fprintf(file, "\nVALUE:"); 55 | for (int i = 0; i < FAKEESP_ENU_PINS; i++) { 56 | fprintf(file, " %3d ", pinValues[i]); 57 | } 58 | fputc('\n', file); 59 | fclose(file); 60 | } 61 | 62 | void pinMode(uint8_t pin, uint8_t mode) { 63 | callOnDelayCallbacks(); 64 | pinModes[pin] = mode; 65 | } 66 | 67 | void digitalWrite(uint8_t pin, uint8_t val) { 68 | callOnDelayCallbacks(); 69 | if (pinModes[pin] == FAKEMODE_PWM_OUT) { 70 | pinModes[pin] = OUTPUT; 71 | } 72 | pinValues[pin] = val != 0; 73 | writePinFile(); 74 | } 75 | 76 | int digitalRead(uint8_t pin) { 77 | callOnDelayCallbacks(); 78 | return pinValues[pin] != 0; 79 | } 80 | 81 | int analogRead(uint8_t pin) { 82 | callOnDelayCallbacks(); 83 | return pinValues[pin]; 84 | } 85 | 86 | void analogReference(uint8_t mode) {} 87 | 88 | void analogWrite(uint8_t pin, int val) { 89 | callOnDelayCallbacks(); 90 | pinModes[pin] = FAKEMODE_PWM_OUT; 91 | pinValues[pin] = val; 92 | writePinFile(); 93 | } 94 | 95 | void analogWriteFreq(uint32_t freq) {} 96 | 97 | void analogWriteRange(uint32_t range) {} 98 | 99 | -------------------------------------------------------------------------------- /fakeesp/src/GenericStuff.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "Arduino.h" 10 | 11 | void panic() { 12 | fflush(stderr); 13 | fflush(stdout); 14 | exit(1); 15 | } 16 | 17 | 18 | long map(long x, long in_min, long in_max, long out_min, long out_max) { 19 | const long dividend = out_max - out_min; 20 | const long divisor = in_max - in_min; 21 | const long delta = x - in_min; 22 | 23 | return (delta * dividend + (divisor / 2)) / divisor + out_min; 24 | } 25 | 26 | // Monkey-patch ESP Async WebServer/src/WebResponses.cpp 27 | namespace std { // NOLINT(cert-dcl58-cpp) 28 | long unsigned int min(long unsigned int n1, unsigned int n2) { 29 | return min(n1, (long unsigned int) n2); 30 | } 31 | } 32 | 33 | 34 | 35 | FakeESP ESP; 36 | HardwareSerial Serial(stdout); 37 | HardwareSerial Serial1(stderr); 38 | FakeArduinoOTA ArduinoOTA; 39 | FakeWiFi WiFi; 40 | FakeMDNS MDNS; -------------------------------------------------------------------------------- /fakeesp/src/Hash.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Hash.cpp 3 | * @date 20.05.2015 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the esp8266 core for Arduino environment. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #include 26 | #include 27 | 28 | #include "WString.h" 29 | #include "Hash.h" 30 | 31 | /** 32 | * create a sha1 hash from data 33 | * @param data uint8_t * 34 | * @param size uint32_t 35 | * @param hash uint8_t[20] 36 | */ 37 | void sha1(const uint8_t *data, uint32_t size, uint8_t hash[20]) { 38 | SHA_CTX ctx; 39 | SHA1_Init(&ctx); 40 | SHA1_Update(&ctx, data, size); 41 | SHA1_Final(hash, &ctx); 42 | } 43 | 44 | void sha1(const char *data, uint32_t size, uint8_t hash[20]) { 45 | sha1((const uint8_t *) data, size, hash); 46 | } 47 | 48 | void sha1(const String &data, uint8_t hash[20]) { 49 | sha1(data.c_str(), data.length(), hash); 50 | } 51 | 52 | String sha1(const uint8_t *data, uint32_t size) { 53 | uint8_t hash[20]; 54 | String hashStr((const char *) nullptr); 55 | hashStr.reserve(20 * 2 + 1); 56 | 57 | sha1(&data[0], size, &hash[0]); 58 | 59 | for (unsigned char i : hash) { 60 | char hex[3]; 61 | snprintf(hex, sizeof(hex), "%02x", i); 62 | hashStr += hex; 63 | } 64 | 65 | return hashStr; 66 | } 67 | 68 | String sha1(const char *data, uint32_t size) { 69 | return sha1((const uint8_t *) data, size); 70 | } 71 | 72 | String sha1(const String &data) { 73 | return sha1(data.c_str(), data.length()); 74 | } 75 | 76 | -------------------------------------------------------------------------------- /fakeesp/src/IPAddress.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | /* 6 | IPAddress.cpp - Base class that provides IPAddress 7 | Copyright (c) 2011 Adrian McEwen. All right reserved. 8 | 9 | This library is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU Lesser General Public 11 | License as published by the Free Software Foundation; either 12 | version 2.1 of the License, or (at your option) any later version. 13 | 14 | This library is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | Lesser General Public License for more details. 18 | 19 | You should have received a copy of the GNU Lesser General Public 20 | License along with this library; if not, write to the Free Software 21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | ip_addr_t ip_any_type = {0}; 29 | 30 | 31 | IPAddress::IPAddress(const IPAddress& from) 32 | { 33 | ip_addr_copy(_ip, from._ip); 34 | } 35 | 36 | IPAddress::IPAddress() { 37 | _ip = *IP_ANY_TYPE; // lwIP's v4-or-v6 generic address 38 | } 39 | 40 | bool IPAddress::isSet () const { 41 | return !ip_addr_isany(&_ip); 42 | } 43 | 44 | IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { 45 | setV4(); 46 | (*this)[0] = first_octet; 47 | (*this)[1] = second_octet; 48 | (*this)[2] = third_octet; 49 | (*this)[3] = fourth_octet; 50 | } 51 | 52 | void IPAddress::ctor32(uint32_t address) { 53 | setV4(); 54 | v4() = address; 55 | } 56 | 57 | IPAddress::IPAddress(const uint8_t *address) { 58 | setV4(); 59 | (*this)[0] = address[0]; 60 | (*this)[1] = address[1]; 61 | (*this)[2] = address[2]; 62 | (*this)[3] = address[3]; 63 | } 64 | 65 | bool IPAddress::fromString(const char *address) { 66 | if (!fromString4(address)) { 67 | #if LWIP_IPV6 68 | return fromString6(address); 69 | #else 70 | return false; 71 | #endif 72 | } 73 | return true; 74 | } 75 | 76 | bool IPAddress::fromString4(const char *address) { 77 | // TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats 78 | 79 | uint16_t acc = 0; // Accumulator 80 | uint8_t dots = 0; 81 | 82 | while (*address) 83 | { 84 | char c = *address++; 85 | if (c >= '0' && c <= '9') 86 | { 87 | acc = acc * 10 + (c - '0'); 88 | if (acc > 255) { 89 | // Value out of [0..255] range 90 | return false; 91 | } 92 | } 93 | else if (c == '.') 94 | { 95 | if (dots == 3) { 96 | // Too much dots (there must be 3 dots) 97 | return false; 98 | } 99 | (*this)[dots++] = acc; 100 | acc = 0; 101 | } 102 | else 103 | { 104 | // Invalid char 105 | return false; 106 | } 107 | } 108 | 109 | if (dots != 3) { 110 | // Too few dots (there must be 3 dots) 111 | return false; 112 | } 113 | (*this)[3] = acc; 114 | 115 | setV4(); 116 | return true; 117 | } 118 | 119 | IPAddress& IPAddress::operator=(const uint8_t *address) { 120 | setV4(); 121 | v4() = *reinterpret_cast(address); 122 | return *this; 123 | } 124 | 125 | IPAddress& IPAddress::operator=(uint32_t address) { 126 | setV4(); 127 | v4() = address; 128 | return *this; 129 | } 130 | 131 | 132 | 133 | bool IPAddress::operator==(const uint8_t* addr) const { 134 | return isV4() && v4() == *reinterpret_cast(addr); 135 | } 136 | 137 | bool IPAddress::isValid(const String& arg) { 138 | return IPAddress().fromString(arg); 139 | } 140 | 141 | bool IPAddress::isValid(const char* arg) { 142 | return IPAddress().fromString(arg); 143 | } 144 | 145 | String IPAddress::toString() const { 146 | char buf[20]; 147 | sprintf(buf, "%d.%d.%d.%d", (*this)[0], (*this)[1], (*this)[2], (*this)[3]); 148 | return String(buf); 149 | } 150 | 151 | /**************************************/ 152 | 153 | #if LWIP_IPV6 154 | 155 | bool IPAddress::fromString6(const char *address) { 156 | // TODO: test test test 157 | 158 | uint32_t acc = 0; // Accumulator 159 | int dots = 0, doubledots = -1; 160 | 161 | while (*address) 162 | { 163 | char c = tolower(*address++); 164 | if (isalnum(c)) { 165 | if (c >= 'a') 166 | c -= 'a' - '0' - 10; 167 | acc = acc * 16 + (c - '0'); 168 | if (acc > 0xffff) 169 | // Value out of range 170 | return false; 171 | } 172 | else if (c == ':') { 173 | if (*address == ':') { 174 | if (doubledots >= 0) 175 | // :: allowed once 176 | return false; 177 | // remember location 178 | doubledots = dots + !!acc; 179 | address++; 180 | } 181 | if (dots == 7) 182 | // too many separators 183 | return false; 184 | raw6()[dots++] = PP_HTONS(acc); 185 | acc = 0; 186 | } 187 | else 188 | // Invalid char 189 | return false; 190 | } 191 | 192 | if (doubledots == -1 && dots != 7) 193 | // Too few separators 194 | return false; 195 | raw6()[dots++] = PP_HTONS(acc); 196 | 197 | if (doubledots != -1) { 198 | for (int i = dots - doubledots - 1; i >= 0; i--) 199 | raw6()[8 - dots + doubledots + i] = raw6()[doubledots + i]; 200 | for (int i = doubledots; i < 8 - dots + doubledots; i++) 201 | raw6()[i] = 0; 202 | } 203 | 204 | setV6(); 205 | return true; 206 | } 207 | 208 | #endif 209 | -------------------------------------------------------------------------------- /fakeesp/src/Print.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Print.cpp - Base class that provides print() and println() 3 | Copyright (c) 2008 David A. Mellis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | Modified 23 November 2006 by David A. Mellis 20 | Modified December 2014 by Ivan Grokhotkov 21 | Modified May 2015 by Michael C. Miller - esp8266 progmem support 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "Print.h" 33 | #include "progmem.h" 34 | 35 | // Public Methods ////////////////////////////////////////////////////////////// 36 | 37 | /* default implementation: may be overridden */ 38 | size_t Print::write(const uint8_t *buffer, size_t size) { 39 | 40 | #ifdef DEBUG_ESP_CORE 41 | static char not_the_best_way [] PROGMEM STORE_ATTR = "Print::write(data,len) should be overridden for better efficiency\r\n"; 42 | static bool once = false; 43 | if (!once) { 44 | once = true; 45 | os_printf_plus(not_the_best_way); 46 | } 47 | #endif 48 | 49 | return 0; 50 | } 51 | 52 | size_t Print::printf(const char *format, ...) { 53 | va_list arg; 54 | va_start(arg, format); 55 | char temp[64]; 56 | char* buffer = temp; 57 | size_t len = vsnprintf(temp, sizeof(temp), format, arg); 58 | va_end(arg); 59 | if (len > sizeof(temp) - 1) { 60 | buffer = new char[len + 1]; 61 | if (!buffer) { 62 | return 0; 63 | } 64 | va_start(arg, format); 65 | vsnprintf(buffer, len + 1, format, arg); 66 | va_end(arg); 67 | } 68 | len = write((const uint8_t*) buffer, len); 69 | if (buffer != temp) { 70 | delete[] buffer; 71 | } 72 | return len; 73 | } 74 | 75 | size_t Print::printf_P(PGM_P format, ...) { 76 | va_list arg; 77 | va_start(arg, format); 78 | char temp[64]; 79 | char* buffer = temp; 80 | size_t len = vsnprintf(temp, sizeof(temp), format, arg); 81 | va_end(arg); 82 | if (len > sizeof(temp) - 1) { 83 | buffer = new char[len + 1]; 84 | if (!buffer) { 85 | return 0; 86 | } 87 | va_start(arg, format); 88 | vsnprintf(buffer, len + 1, format, arg); 89 | va_end(arg); 90 | } 91 | len = write((const uint8_t*) buffer, len); 92 | if (buffer != temp) { 93 | delete[] buffer; 94 | } 95 | return len; 96 | } 97 | 98 | size_t Print::print(const __FlashStringHelper *ifsh) { 99 | PGM_P p = reinterpret_cast(ifsh); 100 | 101 | char buff[128] __attribute__ ((aligned(4))); 102 | auto len = strlen(p); 103 | size_t n = 0; 104 | while (n < len) { 105 | int to_write = std::min(sizeof(buff), len - n); 106 | memcpy(buff, p, to_write); 107 | auto written = write(buff, to_write); 108 | n += written; 109 | p += written; 110 | if (!written) { 111 | // Some error, write() should write at least 1 byte before returning 112 | break; 113 | } 114 | } 115 | return n; 116 | } 117 | 118 | size_t Print::print(const String &s) { 119 | return write(s.c_str(), s.length()); 120 | } 121 | 122 | size_t Print::print(const char str[]) { 123 | return write(str); 124 | } 125 | 126 | size_t Print::print(char c) { 127 | return write(c); 128 | } 129 | 130 | size_t Print::print(unsigned char b, int base) { 131 | return print((unsigned long) b, base); 132 | } 133 | 134 | size_t Print::print(int n, int base) { 135 | return print((long) n, base); 136 | } 137 | 138 | size_t Print::print(unsigned int n, int base) { 139 | return print((unsigned long) n, base); 140 | } 141 | 142 | size_t Print::print(long n, int base) { 143 | if(base == 0) { 144 | return write(n); 145 | } else if(base == 10) { 146 | if(n < 0) { 147 | int t = print('-'); 148 | n = -n; 149 | return printNumber(n, 10) + t; 150 | } 151 | return printNumber(n, 10); 152 | } else { 153 | return printNumber(n, base); 154 | } 155 | } 156 | 157 | size_t Print::print(unsigned long n, int base) { 158 | if(base == 0) 159 | return write(n); 160 | else 161 | return printNumber(n, base); 162 | } 163 | 164 | size_t Print::print(double n, int digits) { 165 | return printFloat(n, digits); 166 | } 167 | 168 | size_t Print::println(const __FlashStringHelper *ifsh) { 169 | size_t n = print(ifsh); 170 | n += println(); 171 | return n; 172 | } 173 | 174 | size_t Print::print(const Printable& x) { 175 | return x.printTo(*this); 176 | } 177 | 178 | size_t Print::println(void) { 179 | return print("\r\n"); 180 | } 181 | 182 | size_t Print::println(const String &s) { 183 | size_t n = print(s); 184 | n += println(); 185 | return n; 186 | } 187 | 188 | size_t Print::println(const char c[]) { 189 | size_t n = print(c); 190 | n += println(); 191 | return n; 192 | } 193 | 194 | size_t Print::println(char c) { 195 | size_t n = print(c); 196 | n += println(); 197 | return n; 198 | } 199 | 200 | size_t Print::println(unsigned char b, int base) { 201 | size_t n = print(b, base); 202 | n += println(); 203 | return n; 204 | } 205 | 206 | size_t Print::println(int num, int base) { 207 | size_t n = print(num, base); 208 | n += println(); 209 | return n; 210 | } 211 | 212 | size_t Print::println(unsigned int num, int base) { 213 | size_t n = print(num, base); 214 | n += println(); 215 | return n; 216 | } 217 | 218 | size_t Print::println(long num, int base) { 219 | size_t n = print(num, base); 220 | n += println(); 221 | return n; 222 | } 223 | 224 | size_t Print::println(unsigned long num, int base) { 225 | size_t n = print(num, base); 226 | n += println(); 227 | return n; 228 | } 229 | 230 | size_t Print::println(double num, int digits) { 231 | size_t n = print(num, digits); 232 | n += println(); 233 | return n; 234 | } 235 | 236 | size_t Print::println(const Printable& x) { 237 | size_t n = print(x); 238 | n += println(); 239 | return n; 240 | } 241 | 242 | // Private Methods ///////////////////////////////////////////////////////////// 243 | 244 | size_t Print::printNumber(unsigned long n, uint8_t base) { 245 | char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. 246 | char *str = &buf[sizeof(buf) - 1]; 247 | 248 | *str = '\0'; 249 | 250 | // prevent crash if called with base == 1 251 | if(base < 2) 252 | base = 10; 253 | 254 | do { 255 | unsigned long m = n; 256 | n /= base; 257 | char c = m - base * n; 258 | *--str = c < 10 ? c + '0' : c + 'A' - 10; 259 | } while(n); 260 | 261 | return write(str); 262 | } 263 | 264 | size_t Print::printFloat(double number, uint8_t digits) { 265 | return 0; 266 | } 267 | -------------------------------------------------------------------------------- /fakeesp/src/cbuf.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | cbuf.cpp - Circular buffer implementation 3 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 4 | This file is part of the esp8266 core for Arduino environment. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | #include "cbuf.h" 22 | #include "c_types.h" 23 | 24 | cbuf::cbuf(size_t size) : 25 | next(NULL), _size(size), _buf(new char[size]), _bufend(_buf + size), _begin(_buf), _end(_begin) { 26 | } 27 | 28 | cbuf::~cbuf() { 29 | delete[] _buf; 30 | } 31 | 32 | size_t cbuf::resizeAdd(size_t addSize) { 33 | return resize(_size + addSize); 34 | } 35 | 36 | size_t cbuf::resize(size_t newSize) { 37 | 38 | size_t bytes_available = available(); 39 | 40 | // not lose any data 41 | // if data can be lost use remove or flush before resize 42 | if((newSize <= bytes_available) || (newSize == _size)) { 43 | return _size; 44 | } 45 | 46 | char *newbuf = new char[newSize]; 47 | char *oldbuf = _buf; 48 | 49 | if(!newbuf) { 50 | return _size; 51 | } 52 | 53 | if(_buf) { 54 | read(newbuf, bytes_available); 55 | memset((newbuf + bytes_available), 0x00, (newSize - bytes_available)); 56 | } 57 | 58 | _begin = newbuf; 59 | _end = newbuf + bytes_available; 60 | _bufend = newbuf + newSize; 61 | _size = newSize; 62 | 63 | _buf = newbuf; 64 | delete[] oldbuf; 65 | 66 | return _size; 67 | } 68 | 69 | size_t ICACHE_RAM_ATTR cbuf::available() const { 70 | if(_end >= _begin) { 71 | return _end - _begin; 72 | } 73 | return _size - (_begin - _end); 74 | } 75 | 76 | size_t cbuf::size() { 77 | return _size; 78 | } 79 | 80 | size_t cbuf::room() const { 81 | if(_end >= _begin) { 82 | return _size - (_end - _begin) - 1; 83 | } 84 | return _begin - _end - 1; 85 | } 86 | 87 | int cbuf::peek() { 88 | if(empty()) 89 | return -1; 90 | 91 | return static_cast(*_begin); 92 | } 93 | 94 | size_t cbuf::peek(char *dst, size_t size) { 95 | size_t bytes_available = available(); 96 | size_t size_to_read = (size < bytes_available) ? size : bytes_available; 97 | size_t size_read = size_to_read; 98 | char * begin = _begin; 99 | if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) { 100 | size_t top_size = _bufend - _begin; 101 | memcpy(dst, _begin, top_size); 102 | begin = _buf; 103 | size_to_read -= top_size; 104 | dst += top_size; 105 | } 106 | memcpy(dst, begin, size_to_read); 107 | return size_read; 108 | } 109 | 110 | int ICACHE_RAM_ATTR cbuf::read() { 111 | if(empty()) 112 | return -1; 113 | 114 | char result = *_begin; 115 | _begin = wrap_if_bufend(_begin + 1); 116 | return static_cast(result); 117 | } 118 | 119 | size_t cbuf::read(char* dst, size_t size) { 120 | size_t bytes_available = available(); 121 | size_t size_to_read = (size < bytes_available) ? size : bytes_available; 122 | size_t size_read = size_to_read; 123 | if(_end < _begin && size_to_read > (size_t) (_bufend - _begin)) { 124 | size_t top_size = _bufend - _begin; 125 | memcpy(dst, _begin, top_size); 126 | _begin = _buf; 127 | size_to_read -= top_size; 128 | dst += top_size; 129 | } 130 | memcpy(dst, _begin, size_to_read); 131 | _begin = wrap_if_bufend(_begin + size_to_read); 132 | return size_read; 133 | } 134 | 135 | size_t ICACHE_RAM_ATTR cbuf::write(char c) { 136 | if(full()) 137 | return 0; 138 | 139 | *_end = c; 140 | _end = wrap_if_bufend(_end + 1); 141 | return 1; 142 | } 143 | 144 | size_t cbuf::write(const char* src, size_t size) { 145 | size_t bytes_available = room(); 146 | size_t size_to_write = (size < bytes_available) ? size : bytes_available; 147 | size_t size_written = size_to_write; 148 | if(_end >= _begin && size_to_write > (size_t) (_bufend - _end)) { 149 | size_t top_size = _bufend - _end; 150 | memcpy(_end, src, top_size); 151 | _end = _buf; 152 | size_to_write -= top_size; 153 | src += top_size; 154 | } 155 | memcpy(_end, src, size_to_write); 156 | _end = wrap_if_bufend(_end + size_to_write); 157 | return size_written; 158 | } 159 | 160 | void cbuf::flush() { 161 | _begin = _buf; 162 | _end = _buf; 163 | } 164 | 165 | size_t cbuf::remove(size_t size) { 166 | size_t bytes_available = available(); 167 | if(size >= bytes_available) { 168 | flush(); 169 | return 0; 170 | } 171 | size_t size_to_remove = (size < bytes_available) ? size : bytes_available; 172 | if(_end < _begin && size_to_remove > (size_t) (_bufend - _begin)) { 173 | size_t top_size = _bufend - _begin; 174 | _begin = _buf; 175 | size_to_remove -= top_size; 176 | } 177 | _begin = wrap_if_bufend(_begin + size_to_remove); 178 | return available(); 179 | } 180 | -------------------------------------------------------------------------------- /fakeesp/src/itoa.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/6/21. 3 | // 4 | 5 | #include 6 | 7 | char *itoa(int val, char *s, int radix) { 8 | if (radix == 16) { 9 | sprintf(s, "%x", val); 10 | } else { 11 | sprintf(s, "%d", val); 12 | } 13 | return s; 14 | } 15 | 16 | char *ltoa(long val, char *s, int radix) { 17 | if (radix == 16) { 18 | sprintf(s, "%lx", val); 19 | } else { 20 | sprintf(s, "%ld", val); 21 | } 22 | return s; 23 | } 24 | 25 | char *utoa(unsigned int val, char *s, int radix) { 26 | if (radix == 16) { 27 | sprintf(s, "%x", val); 28 | } else { 29 | sprintf(s, "%d", val); 30 | } 31 | return s; 32 | } 33 | 34 | char *ultoa(unsigned long val, char *s, int radix) { 35 | if (radix == 16) { 36 | sprintf(s, "%lx", val); 37 | } else { 38 | sprintf(s, "%ld", val); 39 | } 40 | return s; 41 | } 42 | 43 | char *dtostrf(double val, signed char width, unsigned char prec, char *s) { 44 | sprintf(s, "%f", val); 45 | return s; 46 | } 47 | 48 | 49 | #include "itoa.h" 50 | -------------------------------------------------------------------------------- /fakeesp/src/libb64/AUTHORS: -------------------------------------------------------------------------------- 1 | libb64: Base64 Encoding/Decoding Routines 2 | ====================================== 3 | 4 | Authors: 5 | ------- 6 | 7 | Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com 8 | -------------------------------------------------------------------------------- /fakeesp/src/libb64/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright-Only Dedication (based on United States law) 2 | or Public Domain Certification 3 | 4 | The person or persons who have associated work with this document (the 5 | "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of 6 | his knowledge, the work of authorship identified is in the public domain of the 7 | country from which the work is published, or (b) hereby dedicates whatever 8 | copyright the dedicators holds in the work of authorship identified below (the 9 | "Work") to the public domain. A certifier, moreover, dedicates any copyright 10 | interest he may have in the associated work, and for these purposes, is 11 | described as a "dedicator" below. 12 | 13 | A certifier has taken reasonable steps to verify the copyright status of this 14 | work. Certifier recognizes that his good faith efforts may not shield him from 15 | liability if in fact the work certified is not in the public domain. 16 | 17 | Dedicator makes this dedication for the benefit of the public at large and to 18 | the detriment of the Dedicator's heirs and successors. Dedicator intends this 19 | dedication to be an overt act of relinquishment in perpetuity of all present 20 | and future rights under copyright law, whether vested or contingent, in the 21 | Work. Dedicator understands that such relinquishment of all rights includes 22 | the relinquishment of all rights to enforce (by lawsuit or otherwise) those 23 | copyrights in the Work. 24 | 25 | Dedicator recognizes that, once placed in the public domain, the Work may be 26 | freely reproduced, distributed, transmitted, used, modified, built upon, or 27 | otherwise exploited by anyone for any purpose, commercial or non-commercial, 28 | and in any way, including by methods that have not yet been invented or 29 | conceived. -------------------------------------------------------------------------------- /fakeesp/src/libb64/cdecode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | cdecoder.c - c source to a base64 decoding algorithm implementation 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #include 9 | 10 | #include "progmem.h" 11 | #include "libb64/cdecode.h" 12 | 13 | extern "C" { 14 | 15 | static int base64_decode_value_signed(int8_t value_in){ 16 | static const int8_t decoding[] PROGMEM = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; 17 | static const int8_t decoding_size = sizeof(decoding); 18 | value_in -= 43; 19 | if (value_in < 0 || value_in > decoding_size) return -1; 20 | return pgm_read_byte( &decoding[(int)value_in] ); 21 | } 22 | 23 | void base64_init_decodestate(base64_decodestate* state_in){ 24 | state_in->step = step_a; 25 | state_in->plainchar = 0; 26 | } 27 | 28 | static int base64_decode_block_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out, base64_decodestate* state_in){ 29 | const int8_t* codechar = code_in; 30 | int8_t* plainchar = plaintext_out; 31 | int8_t fragment; 32 | 33 | *plainchar = state_in->plainchar; 34 | 35 | switch (state_in->step){ 36 | while (1){ 37 | case step_a: 38 | do { 39 | if (codechar == code_in+length_in){ 40 | state_in->step = step_a; 41 | state_in->plainchar = *plainchar; 42 | return plainchar - plaintext_out; 43 | } 44 | fragment = (int8_t)base64_decode_value_signed(*codechar++); 45 | } while (fragment < 0); 46 | *plainchar = (fragment & 0x03f) << 2; 47 | // falls through 48 | case step_b: 49 | do { 50 | if (codechar == code_in+length_in){ 51 | state_in->step = step_b; 52 | state_in->plainchar = *plainchar; 53 | return plainchar - plaintext_out; 54 | } 55 | fragment = (int8_t)base64_decode_value_signed(*codechar++); 56 | } while (fragment < 0); 57 | *plainchar++ |= (fragment & 0x030) >> 4; 58 | *plainchar = (fragment & 0x00f) << 4; 59 | // falls through 60 | case step_c: 61 | do { 62 | if (codechar == code_in+length_in){ 63 | state_in->step = step_c; 64 | state_in->plainchar = *plainchar; 65 | return plainchar - plaintext_out; 66 | } 67 | fragment = (int8_t)base64_decode_value_signed(*codechar++); 68 | } while (fragment < 0); 69 | *plainchar++ |= (fragment & 0x03c) >> 2; 70 | *plainchar = (fragment & 0x003) << 6; 71 | // falls through 72 | case step_d: 73 | do { 74 | if (codechar == code_in+length_in){ 75 | state_in->step = step_d; 76 | state_in->plainchar = *plainchar; 77 | return plainchar - plaintext_out; 78 | } 79 | fragment = (int8_t)base64_decode_value_signed(*codechar++); 80 | } while (fragment < 0); 81 | *plainchar++ |= (fragment & 0x03f); 82 | } 83 | } 84 | /* control should not reach here */ 85 | return plainchar - plaintext_out; 86 | } 87 | 88 | static int base64_decode_chars_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out){ 89 | base64_decodestate _state; 90 | base64_init_decodestate(&_state); 91 | int len = base64_decode_block_signed(code_in, length_in, plaintext_out, &_state); 92 | if(len > 0) plaintext_out[len] = 0; 93 | return len; 94 | } 95 | 96 | int base64_decode_value(char value_in){ 97 | return base64_decode_value_signed(*((int8_t *) &value_in)); 98 | } 99 | 100 | int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in){ 101 | return base64_decode_block_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out, state_in); 102 | } 103 | 104 | int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out){ 105 | return base64_decode_chars_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out); 106 | } 107 | 108 | }; 109 | -------------------------------------------------------------------------------- /fakeesp/src/libb64/cencode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | cencoder.c - c source to a base64 encoding algorithm implementation 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #include "libb64/cencode.h" 9 | 10 | extern "C" { 11 | 12 | void base64_init_encodestate(base64_encodestate* state_in){ 13 | state_in->step = step_A; 14 | state_in->result = 0; 15 | state_in->stepcount = 0; 16 | state_in->stepsnewline = BASE64_CHARS_PER_LINE; 17 | } 18 | 19 | 20 | void base64_init_encodestate_nonewlines(base64_encodestate* state_in){ 21 | base64_init_encodestate(state_in); 22 | state_in->stepsnewline = -1; 23 | } 24 | 25 | char base64_encode_value(const char n) { 26 | char r; 27 | 28 | if (n < 26) 29 | r = n + 'A'; 30 | else if (n < 26 + 26) 31 | r = n - 26 + 'a'; 32 | else if (n < 26 + 26 + 10 ) 33 | r = n - 26 - 26 + '0'; 34 | else if (n == 62 ) 35 | r = '+'; 36 | else 37 | r = '/'; 38 | return r; 39 | } 40 | 41 | int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in){ 42 | const char* plainchar = plaintext_in; 43 | const char* const plaintextend = plaintext_in + length_in; 44 | char* codechar = code_out; 45 | char result; 46 | char fragment; 47 | 48 | result = state_in->result; 49 | 50 | switch (state_in->step){ 51 | while (1){ 52 | case step_A: 53 | if (plainchar == plaintextend){ 54 | state_in->result = result; 55 | state_in->step = step_A; 56 | return codechar - code_out; 57 | } 58 | fragment = *plainchar++; 59 | result = (fragment & 0x0fc) >> 2; 60 | *codechar++ = base64_encode_value(result); 61 | result = (fragment & 0x003) << 4; 62 | // falls through 63 | case step_B: 64 | if (plainchar == plaintextend){ 65 | state_in->result = result; 66 | state_in->step = step_B; 67 | return codechar - code_out; 68 | } 69 | fragment = *plainchar++; 70 | result |= (fragment & 0x0f0) >> 4; 71 | *codechar++ = base64_encode_value(result); 72 | result = (fragment & 0x00f) << 2; 73 | // falls through 74 | case step_C: 75 | if (plainchar == plaintextend){ 76 | state_in->result = result; 77 | state_in->step = step_C; 78 | return codechar - code_out; 79 | } 80 | fragment = *plainchar++; 81 | result |= (fragment & 0x0c0) >> 6; 82 | *codechar++ = base64_encode_value(result); 83 | result = (fragment & 0x03f) >> 0; 84 | *codechar++ = base64_encode_value(result); 85 | 86 | ++(state_in->stepcount); 87 | if ((state_in->stepcount == BASE64_CHARS_PER_LINE/4) && (state_in->stepsnewline > 0)){ 88 | *codechar++ = '\n'; 89 | state_in->stepcount = 0; 90 | } 91 | } 92 | } 93 | /* control should not reach here */ 94 | return codechar - code_out; 95 | } 96 | 97 | int base64_encode_blockend(char* code_out, base64_encodestate* state_in){ 98 | char* codechar = code_out; 99 | 100 | switch (state_in->step){ 101 | case step_B: 102 | *codechar++ = base64_encode_value(state_in->result); 103 | *codechar++ = '='; 104 | *codechar++ = '='; 105 | break; 106 | case step_C: 107 | *codechar++ = base64_encode_value(state_in->result); 108 | *codechar++ = '='; 109 | break; 110 | case step_A: 111 | break; 112 | } 113 | *codechar = 0x00; 114 | 115 | return codechar - code_out; 116 | } 117 | 118 | int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out){ 119 | base64_encodestate _state; 120 | base64_init_encodestate(&_state); 121 | int len = base64_encode_block(plaintext_in, length_in, code_out, &_state); 122 | return len + base64_encode_blockend((code_out + len), &_state); 123 | } 124 | 125 | }; 126 | -------------------------------------------------------------------------------- /fakeesp/src/md5.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/7/21. 3 | // 4 | 5 | #include "md5.h" 6 | 7 | #include 8 | 9 | 10 | void MD5Init(md5_context_t *c) { 11 | MD5_Init(c); 12 | } 13 | 14 | void MD5Update(md5_context_t *c, const uint8_t *data, const uint16_t len) { 15 | MD5_Update(c, data, len); 16 | } 17 | 18 | void MD5Final(uint8_t md[16], md5_context_t *c) { 19 | MD5_Final(md, c); 20 | } -------------------------------------------------------------------------------- /fakeesp/src/uart.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/11/21. 3 | // 4 | 5 | #include "uart.h" 6 | 7 | void uart_start_detect_baudrate(int uart_nr) {} 8 | 9 | int uart_baudrate_detect(int p1, int p2) { 10 | return 1; 11 | } -------------------------------------------------------------------------------- /html/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_size = 4 6 | indent_style = space 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [{*.json, *.scss}] 11 | indent_size = 2 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /html/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /build 3 | /dist 4 | /*.log -------------------------------------------------------------------------------- /html/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Shuanglei Tao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /html/README.md: -------------------------------------------------------------------------------- 1 | The HTML has been adapted from ttyd: 2 | 3 | https://github.com/tsl0922/ttyd/ 4 | 5 | ## Prerequisites 6 | 7 | install [Yarn](https://yarnpkg.com), and run: `yarn install`. 8 | 9 | ## Development 10 | 11 | 1. Start ttyd: `ttyd bash` 12 | 2. Start the dev server: `yarn run start` 13 | 14 | ## Publish 15 | 16 | Run `yarn run build`, this will compile the inlined html to `../src/html.h`. 17 | -------------------------------------------------------------------------------- /html/gulpfile.js: -------------------------------------------------------------------------------- 1 | const { src, dest, task, series } = require("gulp"); 2 | const clean = require('gulp-clean'); 3 | const gzip = require('gulp-gzip'); 4 | const inlineSource = require('gulp-inline-source'); 5 | const rename = require("gulp-rename"); 6 | const through2 = require('through2'); 7 | 8 | const genHeader = (size, buf, len) => { 9 | let idx = 0; 10 | let data = "// #### This file is automatically generated #### \n"; 11 | data += "// Source: html/dist/index.html\n\n" 12 | 13 | data += `unsigned int index_html_len = ${len};\n`; 14 | data += `unsigned int index_html_size = ${size};\n\n`; 15 | 16 | data += "const uint8_t index_html[] PROGMEM = {\n "; 17 | for (const value of buf) { 18 | idx++; 19 | 20 | let current = value < 0 ? value + 256 : value; 21 | 22 | data += "0x"; 23 | data += (current >>> 4).toString(16); 24 | data += (current & 0xF).toString(16); 25 | 26 | if (idx === len) { 27 | data += "\n"; 28 | } else { 29 | data += idx % 19 === 0 ? ",\n " : ", "; 30 | } 31 | } 32 | 33 | data += "};\n"; 34 | return data; 35 | }; 36 | let fileSize = 0; 37 | 38 | task('clean', () => { 39 | return src('dist', { read: false, allowEmpty: true }) 40 | .pipe(clean()); 41 | }); 42 | 43 | task('inline', () => { 44 | return src('dist/index.html') 45 | .pipe(inlineSource()) 46 | .pipe(rename("inline.html")) 47 | .pipe(dest('dist/')); 48 | }); 49 | 50 | task('default', series('inline', () => { 51 | return src('dist/inline.html') 52 | .pipe(through2.obj((file, enc, cb) => { 53 | fileSize = file.contents.length; 54 | return cb(null, file); 55 | })) 56 | .pipe(gzip({ level: 9 })) 57 | .pipe(through2.obj((file, enc, cb) => { 58 | const buf = file.contents; 59 | file.contents = Buffer.from(genHeader(fileSize, buf, buf.length)); 60 | return cb(null, file); 61 | })) 62 | .pipe(rename("html.h")) 63 | .pipe(dest('../include/')); 64 | })); 65 | 66 | -------------------------------------------------------------------------------- /html/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "ttyd", 4 | "version": "1.0.0", 5 | "description": "Share your terminal over the web", 6 | "repository": { 7 | "url": "git@github.com:tsl0922/ttyd.git", 8 | "type": "git" 9 | }, 10 | "author": "Shuanglei Tao ", 11 | "license": "MIT", 12 | "scripts": { 13 | "prestart": "gulp clean", 14 | "start": "webpack serve", 15 | "build": "NODE_ENV=production webpack && gulp", 16 | "inline": "NODE_ENV=production webpack && gulp inline", 17 | "check": "gts check", 18 | "fix": "gts fix" 19 | }, 20 | "lint-staged": { 21 | "src/**/*.ts": [ 22 | "gts fix", 23 | "git add" 24 | ], 25 | "src/**/*.scss": [ 26 | "scssfmt", 27 | "git add" 28 | ] 29 | }, 30 | "devDependencies": { 31 | "copy-webpack-plugin": "^6.4.1", 32 | "css-loader": "^5.0.1", 33 | "gts": "^1.1.2", 34 | "gulp": "^4.0.2", 35 | "gulp-clean": "^0.4.0", 36 | "gulp-gzip": "^1.4.2", 37 | "gulp-inline-source": "^4.0.0", 38 | "gulp-rename": "^2.0.0", 39 | "html-webpack-plugin": "^4.5.1", 40 | "lint-staged": "^10.5.3", 41 | "mini-css-extract-plugin": "^1.3.4", 42 | "node-sass": "^5.0.0", 43 | "optimize-css-assets-webpack-plugin": "^5.0.4", 44 | "sass-loader": "^10.1.1", 45 | "scssfmt": "^1.0.7", 46 | "style-loader": "^2.0.0", 47 | "terser-webpack-plugin": "^4.2.3", 48 | "through2": "^4.0.2", 49 | "ts-loader": "^8.0.14", 50 | "tslint": "^6.1.3", 51 | "tslint-loader": "^3.5.4", 52 | "typescript": "^3.9.7", 53 | "webpack": "4.46.0", 54 | "webpack-cli": "^4.4.0", 55 | "webpack-dev-server": "^3.11.2", 56 | "webpack-merge": "^5.7.3" 57 | }, 58 | "dependencies": { 59 | "backoff": "^2.5.0", 60 | "decko": "^1.2.0", 61 | "file-saver": "^2.0.5", 62 | "preact": "^10.5.11", 63 | "whatwg-fetch": "^3.5.0", 64 | "xterm": "^4.9.0", 65 | "xterm-addon-fit": "^0.4.0", 66 | "xterm-addon-web-links": "^0.4.0", 67 | "xterm-addon-webgl": "^0.9.0", 68 | "zmodem.js": "^0.1.10" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /html/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: "es5", 3 | tabWidth: 4, 4 | printWidth: 120, 5 | singleQuote: true, 6 | }; 7 | -------------------------------------------------------------------------------- /html/src/components/app.tsx: -------------------------------------------------------------------------------- 1 | import { h, Component } from 'preact'; 2 | 3 | import { ITerminalOptions, ITheme } from 'xterm'; 4 | import { ClientOptions, Xterm } from './terminal'; 5 | 6 | if ((module as any).hot) { 7 | // tslint:disable-next-line:no-var-requires 8 | require('preact/debug'); 9 | } 10 | 11 | const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; 12 | const path = window.location.pathname.replace(/[\/]+$/, ''); 13 | const wsUrl = [protocol, '//', window.location.host, path, '/ws', window.location.search].join(''); 14 | const tokenUrl = [window.location.protocol, '//', window.location.host, path, '/token'].join(''); 15 | const clientOptions = { 16 | rendererType: 'webgl', 17 | disableLeaveAlert: false, 18 | disableResizeOverlay: false, 19 | titleFixed: null, 20 | } as ClientOptions; 21 | const termOptions = { 22 | fontSize: 13, 23 | fontFamily: 'Menlo For Powerline,Consolas,Liberation Mono,Menlo,Courier,monospace', 24 | theme: { 25 | foreground: '#d2d2d2', 26 | background: '#2b2b2b', 27 | cursor: '#adadad', 28 | black: '#000000', 29 | red: '#d81e00', 30 | green: '#5ea702', 31 | yellow: '#cfae00', 32 | blue: '#427ab3', 33 | magenta: '#89658e', 34 | cyan: '#00a7aa', 35 | white: '#dbded8', 36 | brightBlack: '#686a66', 37 | brightRed: '#f54235', 38 | brightGreen: '#99e343', 39 | brightYellow: '#fdeb61', 40 | brightBlue: '#84b0d8', 41 | brightMagenta: '#bc94b7', 42 | brightCyan: '#37e6e8', 43 | brightWhite: '#f1f1f0', 44 | } as ITheme, 45 | } as ITerminalOptions; 46 | 47 | export class App extends Component { 48 | render() { 49 | return ( 50 | 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /html/src/components/modal/index.tsx: -------------------------------------------------------------------------------- 1 | import { h, Component, ComponentChildren } from 'preact'; 2 | 3 | import './modal.scss'; 4 | 5 | interface Props { 6 | show: boolean; 7 | children: ComponentChildren; 8 | } 9 | 10 | export class Modal extends Component { 11 | constructor(props: Props) { 12 | super(props); 13 | } 14 | 15 | render({ show, children }: Props) { 16 | return ( 17 | show && ( 18 |
19 |
20 |
21 |
{children}
22 |
23 |
24 | ) 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /html/src/components/modal/modal.scss: -------------------------------------------------------------------------------- 1 | .modal { 2 | bottom: 0; 3 | left: 0; 4 | right: 0; 5 | top: 0; 6 | align-items: center; 7 | display: flex; 8 | overflow: hidden; 9 | position: fixed; 10 | z-index: 40; 11 | } 12 | 13 | .modal-background { 14 | bottom: 0; 15 | left: 0; 16 | position: absolute; 17 | right: 0; 18 | top: 0; 19 | background-color: #4a4a4acc; 20 | } 21 | 22 | .modal-content { 23 | margin: 0 20px; 24 | max-height: calc(100vh - 160px); 25 | overflow: auto; 26 | position: relative; 27 | width: 100%; 28 | 29 | .box { 30 | background-color: #fff; 31 | color: #4a4a4a; 32 | display: block; 33 | padding: 1.25rem; 34 | } 35 | 36 | header { 37 | font-weight: bold; 38 | text-align: center; 39 | padding-bottom: 10px; 40 | margin-bottom: 10px; 41 | border-bottom: 1px solid #ddd; 42 | } 43 | 44 | .file-input { 45 | height: .01em; 46 | left: 0; 47 | outline: none; 48 | position: absolute; 49 | top: 0; 50 | width: .01em; 51 | } 52 | 53 | .file-cta { 54 | cursor: pointer; 55 | background-color: #f5f5f5; 56 | color: #6200ee; 57 | outline: none; 58 | align-items: center; 59 | box-shadow: none; 60 | display: inline-flex; 61 | height: 2.25em; 62 | justify-content: flex-start; 63 | line-height: 1.5; 64 | position: relative; 65 | vertical-align: top; 66 | border-color: #dbdbdb; 67 | border-radius: 3px; 68 | font-size: 1em; 69 | font-weight: 500; 70 | padding: calc(.375em - 1px) 1em; 71 | white-space: nowrap; 72 | } 73 | } 74 | 75 | @media print, screen and (min-width: 769px) { 76 | .modal-content { 77 | margin: 0 auto; 78 | max-height: calc(100vh - 40px); 79 | width: 640px; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /html/src/components/terminal/overlay.ts: -------------------------------------------------------------------------------- 1 | // ported from hterm.Terminal.prototype.showOverlay 2 | // https://chromium.googlesource.com/apps/libapps/+/master/hterm/js/hterm_terminal.js 3 | import { ITerminalAddon, Terminal } from 'xterm'; 4 | 5 | export class OverlayAddon implements ITerminalAddon { 6 | private terminal: Terminal | undefined; 7 | private overlayNode: HTMLElement | null; 8 | private overlayTimeout: number | null; 9 | 10 | constructor() { 11 | this.overlayNode = document.createElement('div'); 12 | this.overlayNode.style.cssText = `border-radius: 15px; 13 | font-size: xx-large; 14 | opacity: 0.75; 15 | padding: 0.2em 0.5em 0.2em 0.5em; 16 | position: absolute; 17 | -webkit-user-select: none; 18 | -webkit-transition: opacity 180ms ease-in; 19 | -moz-user-select: none; 20 | -moz-transition: opacity 180ms ease-in;`; 21 | 22 | this.overlayNode.addEventListener( 23 | 'mousedown', 24 | e => { 25 | e.preventDefault(); 26 | e.stopPropagation(); 27 | }, 28 | true 29 | ); 30 | } 31 | 32 | activate(terminal: Terminal): void { 33 | this.terminal = terminal; 34 | } 35 | 36 | dispose(): void {} 37 | 38 | showOverlay(msg: string, timeout?: number): void { 39 | const { terminal, overlayNode } = this; 40 | 41 | overlayNode.style.color = '#101010'; 42 | overlayNode.style.backgroundColor = '#f0f0f0'; 43 | overlayNode.textContent = msg; 44 | overlayNode.style.opacity = '0.75'; 45 | 46 | if (!overlayNode.parentNode) { 47 | terminal.element.appendChild(overlayNode); 48 | } 49 | 50 | const divSize = terminal.element.getBoundingClientRect(); 51 | const overlaySize = overlayNode.getBoundingClientRect(); 52 | 53 | overlayNode.style.top = (divSize.height - overlaySize.height) / 2 + 'px'; 54 | overlayNode.style.left = (divSize.width - overlaySize.width) / 2 + 'px'; 55 | 56 | if (this.overlayTimeout) { 57 | clearTimeout(this.overlayTimeout); 58 | } 59 | if (timeout === null) { 60 | return; 61 | } 62 | 63 | const self = this; 64 | self.overlayTimeout = setTimeout(() => { 65 | overlayNode.style.opacity = '0'; 66 | self.overlayTimeout = setTimeout(() => { 67 | if (overlayNode.parentNode) { 68 | overlayNode.parentNode.removeChild(overlayNode); 69 | } 70 | self.overlayTimeout = null; 71 | overlayNode.style.opacity = '0.75'; 72 | }, 200) as any; 73 | }, timeout || 1500) as any; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /html/src/components/zmodem/index.tsx: -------------------------------------------------------------------------------- 1 | import { bind } from 'decko'; 2 | import { h, Component } from 'preact'; 3 | import { saveAs } from 'file-saver'; 4 | import { IDisposable, ITerminalAddon, Terminal } from 'xterm'; 5 | import * as Zmodem from 'zmodem.js/src/zmodem_browser'; 6 | 7 | import { Modal } from '../modal'; 8 | 9 | export interface FlowControl { 10 | limit: number; 11 | highWater: number; 12 | lowWater: number; 13 | 14 | pause: () => void; 15 | resume: () => void; 16 | } 17 | 18 | interface Props { 19 | sender: (data: ArrayLike) => void; 20 | control: FlowControl; 21 | } 22 | 23 | interface State { 24 | modal: boolean; 25 | } 26 | 27 | export class ZmodemAddon extends Component implements ITerminalAddon { 28 | private terminal: Terminal | undefined; 29 | private keyDispose: IDisposable | undefined; 30 | private sentry: Zmodem.Sentry; 31 | private session: Zmodem.Session; 32 | 33 | private written = 0; 34 | private pending = 0; 35 | 36 | constructor(props: Props) { 37 | super(props); 38 | 39 | this.zmodemInit(); 40 | } 41 | 42 | render(_, { modal }: State) { 43 | return ( 44 | 45 | 49 | 50 | ); 51 | } 52 | 53 | activate(terminal: Terminal): void { 54 | this.terminal = terminal; 55 | } 56 | 57 | dispose(): void {} 58 | 59 | consume(data: ArrayBuffer) { 60 | const { sentry, handleError } = this; 61 | try { 62 | sentry.consume(data); 63 | } catch (e) { 64 | handleError(e, 'consume'); 65 | } 66 | } 67 | 68 | @bind 69 | private handleError(e: Error, reason: string) { 70 | console.error(`[ttyd] zmodem ${reason}: `, e); 71 | this.zmodemReset(); 72 | } 73 | 74 | @bind 75 | private zmodemInit() { 76 | this.session = null; 77 | this.sentry = new Zmodem.Sentry({ 78 | to_terminal: (octets: ArrayBuffer) => this.zmodemWrite(octets), 79 | sender: (octets: ArrayLike) => this.zmodemSend(octets), 80 | on_retract: () => this.zmodemReset(), 81 | on_detect: (detection: Zmodem.Detection) => this.zmodemDetect(detection), 82 | }); 83 | } 84 | 85 | @bind 86 | private zmodemReset() { 87 | this.terminal.setOption('disableStdin', false); 88 | 89 | if (this.keyDispose) { 90 | this.keyDispose.dispose(); 91 | this.keyDispose = null; 92 | } 93 | this.zmodemInit(); 94 | 95 | this.terminal.focus(); 96 | } 97 | 98 | @bind 99 | private zmodemWrite(data: ArrayBuffer): void { 100 | const { limit, highWater, lowWater, pause, resume } = this.props.control; 101 | const { terminal } = this; 102 | const rawData = new Uint8Array(data); 103 | 104 | this.written += rawData.length; 105 | if (this.written > limit) { 106 | terminal.write(rawData, () => { 107 | this.pending = Math.max(this.pending - 1, 0); 108 | if (this.pending < lowWater) { 109 | resume(); 110 | } 111 | }); 112 | this.pending++; 113 | this.written = 0; 114 | if (this.pending > highWater) { 115 | pause(); 116 | } 117 | } else { 118 | terminal.write(rawData); 119 | } 120 | } 121 | 122 | @bind 123 | private zmodemSend(data: ArrayLike): void { 124 | this.props.sender(data); 125 | } 126 | 127 | @bind 128 | private zmodemDetect(detection: Zmodem.Detection): void { 129 | const { terminal, receiveFile, zmodemReset } = this; 130 | terminal.setOption('disableStdin', true); 131 | 132 | this.keyDispose = terminal.onKey(e => { 133 | const event = e.domEvent; 134 | if (event.ctrlKey && event.key === 'c') { 135 | detection.deny(); 136 | } 137 | }); 138 | 139 | this.session = detection.confirm(); 140 | this.session.on('session_end', zmodemReset); 141 | 142 | if (this.session.type === 'send') { 143 | this.setState({ modal: true }); 144 | } else { 145 | receiveFile(); 146 | } 147 | } 148 | 149 | @bind 150 | private sendFile(event: Event) { 151 | this.setState({ modal: false }); 152 | 153 | const { session, writeProgress, handleError } = this; 154 | const files: FileList = (event.target as HTMLInputElement).files; 155 | 156 | Zmodem.Browser.send_files(session, files, { 157 | on_progress: (_, offer: Zmodem.Offer) => writeProgress(offer), 158 | }) 159 | .then(() => session.close()) 160 | .catch(e => handleError(e, 'send')); 161 | } 162 | 163 | @bind 164 | private receiveFile() { 165 | const { session, writeProgress, handleError } = this; 166 | 167 | session.on('offer', (offer: Zmodem.Offer) => { 168 | const fileBuffer = []; 169 | offer.on('input', payload => { 170 | writeProgress(offer); 171 | fileBuffer.push(new Uint8Array(payload)); 172 | }); 173 | offer 174 | .accept() 175 | .then(() => { 176 | const blob = new Blob(fileBuffer, { type: 'application/octet-stream' }); 177 | saveAs(blob, offer.get_details().name); 178 | }) 179 | .catch(e => handleError(e, 'receive')); 180 | }); 181 | 182 | session.start(); 183 | } 184 | 185 | @bind 186 | private writeProgress(offer: Zmodem.Offer) { 187 | const { terminal, bytesHuman } = this; 188 | 189 | const file = offer.get_details(); 190 | const name = file.name; 191 | const size = file.size; 192 | const offset = offer.get_offset(); 193 | const percent = ((100 * offset) / size).toFixed(2); 194 | 195 | terminal.write(`${name} ${percent}% ${bytesHuman(offset, 2)}/${bytesHuman(size, 2)}\r`); 196 | } 197 | 198 | private bytesHuman(bytes: any, precision: number): string { 199 | if (!/^([-+])?|(\.\d+)(\d+(\.\d+)?|(\d+\.)|Infinity)$/.test(bytes)) { 200 | return '-'; 201 | } 202 | if (bytes === 0) return '0'; 203 | if (typeof precision === 'undefined') precision = 1; 204 | const units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB']; 205 | const num = Math.floor(Math.log(bytes) / Math.log(1024)); 206 | const value = (bytes / Math.pow(1024, Math.floor(num))).toFixed(precision); 207 | return `${value} ${units[num]}`; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /html/src/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/depau/wi-se-sw/3bfddb768d171e0a287b264fdbad77cff7a54144/html/src/favicon.png -------------------------------------------------------------------------------- /html/src/index.tsx: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | import { h, render } from 'preact'; 3 | import { App } from './components/app'; 4 | import './style/index.scss'; 5 | 6 | render(, document.body); 7 | -------------------------------------------------------------------------------- /html/src/style/index.scss: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | min-height: 100%; 5 | margin: 0; 6 | overflow: hidden; 7 | } 8 | 9 | #terminal-container { 10 | width: auto; 11 | height: 100%; 12 | margin: 0 auto; 13 | padding: 0; 14 | .terminal { 15 | padding: 5px; 16 | height: calc(100% - 10px); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /html/src/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | <% for (const css in htmlWebpackPlugin.files.css) { %> 9 | 10 | <% } %> 11 | 12 | 13 | <% for (const js in htmlWebpackPlugin.files.js) { %> 14 | 15 | <% } %> 16 | 17 | 18 | -------------------------------------------------------------------------------- /html/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "module": "es2015", 5 | "lib": [ 6 | "es2015", 7 | "dom" 8 | ], 9 | "allowJs": true, 10 | "jsx": "react", 11 | "jsxFactory": "h", 12 | "sourceMap": true, 13 | "moduleResolution": "node", 14 | "esModuleInterop": true, 15 | "experimentalDecorators": true, 16 | "noImplicitReturns": true, 17 | "noUnusedParameters": true 18 | }, 19 | "include": [ 20 | "src/**/*.tsx", 21 | "src/**/*.ts" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /html/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "gts/tslint.json", 3 | "rules": { 4 | "deprecation": false, 5 | "no-any": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /html/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { merge } = require('webpack-merge'); 3 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 6 | const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); 7 | const TerserPlugin = require('terser-webpack-plugin'); 8 | 9 | const devMode = process.env.NODE_ENV !== 'production'; 10 | 11 | const baseConfig = { 12 | context: path.resolve(__dirname, 'src'), 13 | entry: { 14 | app: './index.tsx' 15 | }, 16 | output: { 17 | path: path.resolve(__dirname, 'dist'), 18 | filename: devMode ? '[name].js' : '[name].[hash].js', 19 | }, 20 | module: { 21 | rules: [ 22 | { 23 | test: /\.ts$/, 24 | enforce: 'pre', 25 | use: 'tslint-loader', 26 | }, 27 | { 28 | test: /\.tsx?$/, 29 | use: 'ts-loader', 30 | exclude: /node_modules/ 31 | }, 32 | { 33 | test: /\.s?[ac]ss$/, 34 | use: [ 35 | devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 36 | 'css-loader', 37 | 'sass-loader', 38 | ], 39 | }, 40 | ] 41 | }, 42 | resolve: { 43 | extensions: [ '.tsx', '.ts', '.js' ] 44 | }, 45 | plugins: [ 46 | new CopyWebpackPlugin({ 47 | patterns:[ 48 | { from: './favicon.png', to: '.' } 49 | ], 50 | }), 51 | new MiniCssExtractPlugin({ 52 | filename: devMode ? '[name].css' : '[name].[hash].css', 53 | chunkFilename: devMode ? '[id].css' : '[id].[hash].css', 54 | }), 55 | new HtmlWebpackPlugin({ 56 | inject: false, 57 | minify: { 58 | removeComments: true, 59 | collapseWhitespace: true, 60 | }, 61 | title: 'Wi-Se - Terminal', 62 | template: './template.html' 63 | }) 64 | ], 65 | performance : { 66 | hints : false 67 | }, 68 | }; 69 | 70 | const devConfig = { 71 | mode: 'development', 72 | devServer: { 73 | contentBase: path.join(__dirname, 'dist'), 74 | compress: true, 75 | port: 9000, 76 | proxy: [{ 77 | context: ['/token', '/ws'], 78 | target: 'http://localhost:7681', 79 | ws: true 80 | }] 81 | }, 82 | devtool: 'inline-source-map', 83 | }; 84 | 85 | const prodConfig = { 86 | mode: 'production', 87 | optimization: { 88 | minimizer: [ 89 | new TerserPlugin({ 90 | sourceMap: true 91 | }), 92 | new OptimizeCSSAssetsPlugin({ 93 | cssProcessorOptions: { 94 | map: { 95 | inline: false, 96 | annotation: true 97 | } 98 | } 99 | }), 100 | ] 101 | }, 102 | devtool: 'source-map', 103 | }; 104 | 105 | 106 | module.exports = merge(baseConfig, devMode ? devConfig : prodConfig); 107 | -------------------------------------------------------------------------------- /include/ExtendedSerial.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/13/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_EXTENDEDSERIAL_H 6 | #define WI_SE_SW_EXTENDEDSERIAL_H 7 | 8 | 9 | #include 10 | 11 | class ExtendedSerial : public HardwareSerial { 12 | 13 | public: 14 | ExtendedSerial(int uart_nr) : HardwareSerial(uart_nr) {}; 15 | 16 | // This is uart_detect_baudrate from esp8266-arduino, modified to return the measured value. 17 | // The closest standard rate can be obtained by calling ::autobaudGetClosestStdRate 18 | int autobaudMeasure(); 19 | 20 | static int autobaudGetClosestStdRate(int32_t rawBaud); 21 | 22 | void sendBreak(); 23 | }; 24 | 25 | 26 | extern ExtendedSerial ExtSerial0; 27 | extern ExtendedSerial ExtSerial1; 28 | 29 | 30 | #endif //WI_SE_SW_EXTENDEDSERIAL_H 31 | -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | // 2 | // AUTOMATICALLY GENERATED, DO NOT EDIT. 3 | // Generated on Sat Mar 13 22:44:43 2021. 4 | // 5 | 6 | #include 7 | 8 | #ifndef WI_SE_SW_CONFIG_H 9 | #define WI_SE_SW_CONFIG_H 10 | 11 | // Enables debug messages to debug UART 12 | #define ENABLE_DEBUG 0 13 | // Prints a bunch of timing measurements to debug UART 14 | #define ENABLE_BENCHMARK 0 15 | 16 | // Board configuration 17 | // Available board types: 18 | // - 0: generic ESP8266 boards 19 | // - 1: wi-se-rpi-v0.1 20 | // - 2: wi-se-opi4-v0.1 21 | // - 3: wi-se-rewirable-v0.1 22 | #define BOARD_TYPE 0 23 | 24 | // UART configuration 25 | #define UART_COMM ExtSerial0 26 | #define UART_COMM_BAUD 115200 27 | #define UART_COMM_CONFIG (UART_NB_BIT_8 | UART_PARITY_NONE | UART_NB_STOP_BIT_1) 28 | 29 | #define UART_DEBUG ExtSerial0 30 | #define UART_DEBUG_BAUD 115200 31 | #define UART_DEBUG_CONFIG (UART_NB_BIT_8 | UART_PARITY_NONE | UART_NB_STOP_BIT_1) 32 | 33 | // Wi-Fi configuration 34 | // WIFI_STA for client (station) mode 35 | // WIFI_AP for Access Point mode 36 | #define WIFI_MODE WIFI_AP 37 | 38 | #define WIFI_SSID nullptr 39 | #define WIFI_PASS "ChangeMeASAP" 40 | #define WIFI_HOSTNAME "Wi-Se" 41 | 42 | #define DEVICE_PRETTY_NAME "Wi-Se" 43 | 44 | // Access Point configuration 45 | #define WIFI_CHANNEL 6 46 | #define WIFI_HIDE_SSID 0 47 | #define WIFI_MAX_DEVICES 6 48 | 49 | // OTA updates 50 | #define OTA_ENABLE 0 51 | // You MUST define a password, otherwise OTA won't be enabled. 52 | #define OTA_PASSWORD "" 53 | 54 | // Server configuration 55 | #define HTTP_LISTEN_PORT 80 56 | #define HTTP_AUTH_ENABLE 0 57 | #define HTTP_AUTH_USER "" 58 | #define HTTP_AUTH_PASS "" 59 | 60 | // CORS - Uncomment to allow all origins 61 | //#define CORS_ALLOW_ORIGI cfg.CORS_ALLOW_ORIGINN { 62 | 63 | // WebSocket configuration 64 | #define WS_MAX_CLIENTS 3 65 | #define WS_PING_INTERVAL 300 66 | 67 | // Web TTY configuration 68 | // You can specify any option documented here: https://xtermjs.org/docs/api/terminal/interfaces/iterminaloptions/ 69 | // Make sure it is a valid JSON and that it's also a valid C string. 70 | #define TTYD_WEB_CONFIG "{\"disableLeaveAlert\": true}" 71 | 72 | 73 | #if BOARD_TYPE == 0 // don't change 74 | 75 | // LED configuration - only if board type is custom 76 | // Wi-Se board LEDs are pre-configured in wise_boards.h 77 | #define LED_WIFI 5 78 | #define LED_STATUS 13 79 | #define LED_TX 14 80 | #define LED_RX 12 81 | 82 | #endif //BOARD_TYPE 83 | 84 | // LED timings (milliseconds) 85 | #define LED_ON_TIME 15 86 | #define LED_OFF_TIME 15 87 | 88 | // Advanced buffering parameters 89 | // Tweak if you feel brave. Report any improvements, but make sure you test them at 1500000 8N1 and that it works better 90 | // than the defaults before submitting. 91 | // Note that these buffers do not cause measurable latency, they need to be sort of high so that the WebSocket sender 92 | // can catch up as the UART is being stuffed with high speed data. 93 | 94 | #define UART_RX_BUF_SIZE 10240 95 | #define UART_RX_SOFT_MIN (WS_SEND_BUF_SIZE * 3 / 2) 96 | #define UART_BUFFER_BELOW_SOFT_MIN_DYNAMIC_DELAY (std::min((int) (1000L * WS_SEND_BUF_SIZE * 8L * 2 / 3 / uartBaudRate), 5)) 97 | 98 | // Automatic baudrate detection interval 99 | #define UART_AUTOBAUD_TIMEOUT_MILLIS 10000 100 | #define UART_AUTOBAUD_ATTEMPT_INTERVAL 100 101 | 102 | // UART software flow control, improves stability. It must be supported by the connected device for it to make any 103 | // difference. 104 | #define UART_SW_FLOW_CONTROL 1 105 | #define UART_SW_FLOW_CONTROL_LOW_WATERMARK UART_RX_SOFT_MIN + 1 106 | #define UART_SW_FLOW_CONTROL_HIGH_WATERMARK WS_SEND_BUF_SIZE - 1 107 | #define UART_SW_LOCAL_FLOW_CONTROL_STOP_MAX_MS 500 108 | 109 | #define WS_SEND_BUF_SIZE 1536 110 | 111 | #define HEAP_FREE_LOW_WATERMARK 4096 112 | #define HEAP_FREE_HIGH_WATERMARK 10240 113 | 114 | // If we stopped for half a second and the heap is still stuffed like a turkey we might just as well crash instead of 115 | // continue waiting, this code is probably leaky AF anyway. 116 | #define HEAP_CAUSED_WS_FLOW_CTL_STOP_MAX_MS 500 117 | 118 | // End of configuration 119 | #include "wise_boards.h" 120 | 121 | #endif // WI_SE_SW_CONFIG_H -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 1/27/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_DEBUG_H 6 | #define WI_SE_SW_DEBUG_H 7 | 8 | #include "config.h" 9 | 10 | #if ENABLE_DEBUG == 1 11 | #define debugf(...) UART_DEBUG.printf(__VA_ARGS__) 12 | #else 13 | #define debugf(...) do {} while(0) 14 | #endif 15 | 16 | #if ENABLE_BENCHMARK == 1 17 | #define BENCH if (1) 18 | #else 19 | #define BENCH if (0) 20 | #endif 21 | 22 | #endif //WI_SE_SW_DEBUG_H 23 | -------------------------------------------------------------------------------- /include/server.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 1/26/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_SERVER_H 6 | #define WI_SE_SW_SERVER_H 7 | 8 | #include "ttyd.h" 9 | #include "debug.h" 10 | #include "version.h" 11 | 12 | #define MASK_UART_PARITY 0B00000011 13 | #define MASK_UART_BITS 0B00001100 14 | #define MASK_UART_STOP 0B00110000 15 | 16 | #define WS_CMD_CACHE_EMPTY_SENTINEL 0xFFFFFFFFFFFFFFFF 17 | 18 | #define HTTP_AUTH_TOKEN_LEN 16 19 | 20 | enum WsCloseReason { 21 | WS_CLOSE_OK = 1000, 22 | WS_CLOSE_GOING_AWAY = 1001, 23 | WS_CLOSE_PROTOCOL_ERROR = 1002, 24 | WS_CLOSE_DATA_NOT_SUPPORTED = 1003, 25 | WS_CLOSE_BAD_DATA = 1007, 26 | WS_CLOSE_POLICY_VIOLATION = 1008, 27 | WS_CLOSE_TOO_BIG = 1009, 28 | WS_CLOSE_MISSING_EXTN = 1010, 29 | WS_CLOSE_BAD_CONDITION = 1011, 30 | }; 31 | 32 | class WiSeServer { 33 | private: 34 | // Use larger data type to be able to mark emptyness 35 | uint64_t wsFragClientCommandCacheClientIds[WS_MAX_CLIENTS] = {WS_CMD_CACHE_EMPTY_SENTINEL}; 36 | uint8_t wsFragClientCommandCache[WS_MAX_CLIENTS] = {0}; 37 | char serverHeader[100] = {0}; 38 | 39 | public: 40 | char *token; 41 | AsyncWebServer *httpd; 42 | AsyncWebSocket *websocket; 43 | TTY *ttyd; 44 | 45 | WiSeServer(char *token, AsyncWebServer *httpd, AsyncWebSocket *websocket, TTY *ttyd) : 46 | token{token}, 47 | httpd{httpd}, 48 | websocket{websocket}, 49 | ttyd{ttyd} { 50 | // Format server header 51 | snprintf(serverHeader, sizeof(serverHeader) / sizeof(char), "%s", "Wi-Se/" VERSION); 52 | }; 53 | 54 | void begin(); 55 | 56 | void end() const; 57 | 58 | static bool checkHttpBasicAuth(AsyncWebServerRequest *request); 59 | 60 | static void handleIndex(AsyncWebServerRequest *request); 61 | 62 | void handleStatsRequest(AsyncWebServerRequest *request) const; 63 | 64 | void handleSttyRequest(AsyncWebServerRequest *request) const; 65 | 66 | void handleSttyBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) const; 67 | 68 | void sttySendResponse(AsyncWebServerRequest *request) const; 69 | 70 | void handleToken(AsyncWebServerRequest *request) const; 71 | 72 | 73 | void 74 | onWebSocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, 75 | size_t len); 76 | 77 | private: 78 | bool garbageCollectCommandCache() { 79 | bool foundGarbage = false; 80 | for (unsigned long long clientId : wsFragClientCommandCacheClientIds) { 81 | if (clientId == WS_CMD_CACHE_EMPTY_SENTINEL) { 82 | continue; 83 | } 84 | if (ttyd->isClientBlocked(clientId) || !ttyd->isClientAuthenticated(clientId)) { 85 | foundGarbage = true; 86 | deleteCachedCommand(clientId); 87 | } 88 | } 89 | return foundGarbage; 90 | } 91 | 92 | int findCommandCacheSlot(uint32_t clientId, bool doGc = true) { 93 | int firstEmpty = -1; 94 | for (int i = 0; i < WS_MAX_CLIENTS; i++) { 95 | if (wsFragClientCommandCacheClientIds[i] == clientId) { 96 | return i; 97 | } 98 | if (firstEmpty == -1 && wsFragClientCommandCacheClientIds[i] == WS_CMD_CACHE_EMPTY_SENTINEL) { 99 | firstEmpty = i; 100 | } 101 | } 102 | 103 | if (firstEmpty == -1 && doGc && garbageCollectCommandCache()) { 104 | return findCommandCacheSlot(clientId, false); 105 | } 106 | if (firstEmpty == -1) { 107 | debugf("Critical error, all client command caches full\r\n"); 108 | debugf("Client IDs of cached commands: "); 109 | for(__unused unsigned long long clientDataBufClientId : wsFragClientCommandCacheClientIds) { 110 | debugf("%llu ", clientDataBufClientId); 111 | } 112 | debugf("\r\n"); 113 | panic(); 114 | } 115 | 116 | return firstEmpty; 117 | } 118 | 119 | char getCachedCommand(uint32_t clientId) { 120 | int slot = findCommandCacheSlot(clientId); 121 | if (wsFragClientCommandCacheClientIds[slot] != clientId) { 122 | debugf("Warning, tried to retrieve command cache for %d but never set!\r\n", clientId); 123 | return 0; 124 | } 125 | return wsFragClientCommandCache[slot]; 126 | } 127 | 128 | void storeCommandCache(uint32_t clientId, char command) { 129 | int slot = findCommandCacheSlot(clientId); 130 | wsFragClientCommandCacheClientIds[slot] = clientId; 131 | wsFragClientCommandCache[slot] = command; 132 | } 133 | 134 | void deleteCachedCommand(uint32_t clientId) { 135 | int slot = findCommandCacheSlot(clientId); 136 | wsFragClientCommandCacheClientIds[slot] = WS_CMD_CACHE_EMPTY_SENTINEL; 137 | wsFragClientCommandCache[slot] = 0; 138 | } 139 | }; 140 | 141 | #endif //WI_SE_SW_SERVER_H 142 | -------------------------------------------------------------------------------- /include/ttyd.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 1/27/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_TTYD_H 6 | #define WI_SE_SW_TTYD_H 7 | 8 | #include 9 | #include "config.h" 10 | 11 | // client message 12 | #define CMD_INPUT '0' 13 | #define CMD_RESIZE_TERMINAL '1' 14 | #define CMD_PAUSE '2' 15 | #define CMD_RESUME '3' 16 | #define CMD_JSON_DATA '{' 17 | #define CMD_DETECT_BAUD 'B' 18 | #define CMD_SEND_BREAK 'b' 19 | 20 | // server message 21 | #define CMD_OUTPUT '0' 22 | #define CMD_SET_WINDOW_TITLE '1' 23 | // Defined as a string to be concatenated below 24 | #define CMD_SET_PREFERENCES "2" 25 | 26 | #define CMD_SERVER_PAUSE 'S' 27 | #define CMD_SERVER_RESUME 'Q' 28 | #define CMD_SERVER_DETECTED_BAUD 'B' 29 | 30 | const char ttydWebConfig[] = CMD_SET_PREFERENCES TTYD_WEB_CONFIG; 31 | 32 | #define LED_HANDLE_EVERY_MILLIS 5 33 | #define CLIENT_PING_EVERY_MILLIS (WS_PING_INTERVAL * 1000) 34 | #define CLIENT_TIMEOUT_CHECK_EVERY_MILLIS 10000 35 | #define COLLECT_STATS_EVERY_MILLIS 1000 36 | 37 | #define CLIENT_TIMEOUT_MILLIS (WS_PING_INTERVAL * 1033) // WS_PING_INTERVAL * 103.3% == ~310s with a default of 300s 38 | 39 | #define FLOW_CTL_SRC_LOCAL 0b01 40 | #define FLOW_CTL_SRC_REMOTE 0b10 41 | 42 | #define FLOW_CTL_XOFF 0x13 43 | #define FLOW_CTL_XON 0x11 44 | 45 | #define WS_MAX_BLOCKED_CLIENTS 50 46 | #define WS_CLIENT_BLOCK_EXPIRE_MILLIS 5000 47 | 48 | struct led_blink_request_t { 49 | bool rx; 50 | bool tx; 51 | }; 52 | 53 | union led_blink_request_u { 54 | struct led_blink_request_t leds; 55 | bool array[2]; 56 | }; 57 | 58 | struct led_blink_schedule_t { 59 | uint64_t rx; 60 | uint64_t tx; 61 | }; 62 | 63 | union led_blink_schedule_u { 64 | struct led_blink_schedule_t leds; 65 | uint64_t array[2]; 66 | }; 67 | 68 | class TTY { 69 | private: 70 | char *token; 71 | AsyncWebSocket *websocket; 72 | 73 | uint32_t uartBaudRate = UART_COMM_BAUD; 74 | uint8_t uartConfig = UART_COMM_CONFIG; 75 | bool uartBegun = false; 76 | 77 | uint8_t wsClientsLen = 0; 78 | uint32_t wsClients[WS_MAX_CLIENTS] = {0}; 79 | uint64_t wsClientsLastSeen[WS_MAX_CLIENTS] = {0}; 80 | uint8_t pendingAuthClients = 0; 81 | 82 | uint8_t wsBlockedClientsLen = 0; 83 | uint32_t wsBlockedClients[WS_MAX_BLOCKED_CLIENTS] = {0}; 84 | uint64_t wsClientBlockedAtMillis[WS_MAX_BLOCKED_CLIENTS] = {0}; 85 | 86 | uint64_t lastClientPingMillis = millis(); 87 | uint64_t lastClientTimeoutCheckMillis = millis(); 88 | uint64_t lastLedHandleMillis = millis(); 89 | 90 | union led_blink_request_u requestLedBlink = {{false, false}}; 91 | union led_blink_schedule_u scheduledLedsOffMillis = {{0}}; 92 | union led_blink_schedule_u ledsBusyUntilMillis = {{0}}; 93 | 94 | uint8_t uartFlowControlStatus = 0; 95 | uint64_t uartFlowControlEngagedMillis = 0; 96 | 97 | // We won't take care of flow control commands coming from UART for the time being, it's O(n) but we don't have much 98 | // time too waste. Also, chances are that it will be handled already by the remote terminal. 99 | bool wsFlowControlStopped = false; 100 | uint64_t wsFlowControlEngagedMillis = 0; 101 | 102 | bool pendingAutobaud = false; 103 | uint64_t autobaudStartedAtMillis = 0; 104 | uint64_t autobaudLastAttemptAtMillis = 0; 105 | 106 | // Stats refer to the UART side 107 | uint64_t lastStatsCollectMillis = millis(); 108 | uint64_t prevTx = 0; 109 | uint64_t prevRx = 0; 110 | uint64_t totalTx = 0; 111 | uint64_t totalRx = 0; 112 | 113 | uint64_t txRate = 0; 114 | uint64_t rxRate = 0; 115 | 116 | public: 117 | explicit TTY(char *token, AsyncWebSocket *websocket) : token{token}, websocket{websocket} {} 118 | 119 | uint32_t getUartBaudRate() const { 120 | return uartBaudRate; 121 | } 122 | 123 | uint8_t getUartConfig() const { 124 | return uartConfig; 125 | } 126 | 127 | uint64_t getTotalRx() const { return totalRx; } 128 | 129 | uint64_t getTotalTx() const { return totalTx; } 130 | 131 | uint64_t getRxRate() const { return rxRate; } 132 | 133 | uint64_t getTxRate() const { return txRate; } 134 | 135 | void stty(uint32_t baudrate, uint8_t config); 136 | 137 | bool onNewWebSocketClient(uint32_t clientId); 138 | 139 | void removeClient(uint32_t clientId); 140 | 141 | void handleWebSocketMessage(uint32_t clientId, const uint8_t *buf, size_t len, char fragmentCachedCommand = 0); 142 | 143 | void dispatchUart(); 144 | 145 | void performHousekeeping(); 146 | 147 | void handleWebSocketPong(uint32_t clientId); 148 | 149 | void shrinkBuffers(); 150 | 151 | void blockClient(uint32_t clientId); 152 | 153 | bool isClientBlocked(uint32_t clientId); 154 | 155 | bool isClientAuthenticated(uint32_t clientId); 156 | 157 | private: 158 | 159 | int findClientIndex(uint32_t clientId) { 160 | for (int i = 0; i < wsClientsLen; i++) { 161 | if (wsClients[i] == clientId) { 162 | return i; 163 | } 164 | } 165 | return -1; 166 | } 167 | 168 | void clientSeen(uint32_t clientId) { 169 | int i = findClientIndex(clientId); 170 | if (i >= 0) { 171 | wsClientsLastSeen[i] = millis(); 172 | } 173 | } 174 | 175 | void pingClients(); 176 | 177 | void checkClientTimeouts(); 178 | 179 | void handleLedBlinkRequests(); 180 | 181 | void markClientAuthenticated(uint32_t clientId); 182 | 183 | void nukeClient(uint32_t clientId, uint16_t closeReason); 184 | 185 | void sendInitialMessages(uint32_t clientId); 186 | 187 | void sendClientConfiguration(uint32_t clientId); 188 | 189 | size_t snprintWindowTitle(char *dest, size_t len) const; 190 | 191 | void sendWindowTitle(int64_t clientId = -1); 192 | 193 | void flowControlUartRequestStop(uint8_t source); 194 | 195 | void flowControlUartRequestResume(uint8_t source); 196 | 197 | bool wsCanSend(); 198 | 199 | bool areAllClientsAuthenticated() const; 200 | 201 | void broadcastBufferToClients(AsyncWebSocketMessageBuffer *wsBuffer); 202 | 203 | void flowControlWebSocketRequest(bool stop); 204 | 205 | bool performFlowControl_SlowWiFi(size_t uartAvailable); 206 | 207 | bool performFlowControl_HeapFull(); 208 | 209 | void collectStats(); 210 | 211 | void removeExpiredClientBlocks(); 212 | 213 | void requestAutobaud(); 214 | 215 | void sendBaurateDetectionResult(int64_t bestApprox, int64_t measured); 216 | 217 | void unlockUartFlowControlIfTimedOut(); 218 | 219 | void autobaud(); 220 | }; 221 | 222 | #endif //WI_SE_SW_TTYD_H 223 | -------------------------------------------------------------------------------- /include/version.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 1/29/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_VERSION_H 6 | #define WI_SE_SW_VERSION_H 7 | 8 | #ifndef LOCAL_VERSION 9 | #define LOCAL_VERSION "" 10 | #endif 11 | 12 | #define VERSION "v0.1" LOCAL_VERSION 13 | 14 | #endif //WI_SE_SW_VERSION_H 15 | -------------------------------------------------------------------------------- /include/wise_boards.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 1/26/21. 3 | // 4 | 5 | #ifndef WI_SE_SW_WISE_BOARDS_H 6 | #define WI_SE_SW_WISE_BOARDS_H 7 | 8 | #define BOARD_CUSTOM 0 9 | #define BOARD_WI_SE_RPI_V01 1 10 | #define BOARD_WI_SE_OPI4_V01 2 11 | #define BOARD_WI_SE_REWIRABLE_V01 3 12 | 13 | #if BOARD_TYPE == BOARD_WI_SE_REWIRABLE_V01 14 | #define LED_WIFI 5 15 | #define LED_STATUS 13 16 | #define LED_TX 14 17 | #define LED_RX 12 18 | #elif BOARD_TYPE == BOARD_WI_SE_RPI_V01 || BOARD_TYPE == BOARD_WI_SE_OPI4_V01 19 | #define LED_WIFI 5 20 | #define LED_STATUS 14 21 | #define LED_TX 13 22 | #define LED_RX 12 23 | #endif //BOARD_TYPE 24 | 25 | #define LED_COUNT 4 26 | 27 | #ifndef LED_ORDER 28 | #define LED_ORDER {LED_WIFI, LED_STATUS, LED_RX, LED_TX}; 29 | #endif 30 | 31 | #if BOARD_TYPE == BOARD_CUSTOM 32 | #define BOARD_NAME "Generic ESP8266 board" 33 | #elif BOARD_TYPE == BOARD_WI_SE_RPI_V01 34 | #define BOARD_NAME "Wi-Se Raspberry Pi Header v0.1" 35 | #elif BOARD_TYPE == BOARD_WI_SE_OPI4_V01 36 | #define BOARD_NAME "Wi-Se Orange Pi 4 v0.1" 37 | #elif BOARD_TYPE == BOARD_WI_SE_REWIRABLE_V01 38 | #define BOARD_NAME "Wi-Se Rewirable v0.1" 39 | #else 40 | #define BOARD_NAME "Unknown" 41 | #endif 42 | 43 | #endif //WI_SE_SW_WISE_BOARDS_H 44 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; 2 | ; AUTOMATICALLY GENERATED, DO NOT EDIT. 3 | ; Generated on Wed Sep 14 22:58:17 2022. 4 | ; 5 | 6 | [env:wi_se] 7 | platform = https://github.com/platformio/platform-espressif8266.git 8 | board = esp_wroom_02 9 | framework = arduino 10 | board_build.f_cpu = 160000000L 11 | board_build.f_flash = 80000000L 12 | board_build.ldscript = eagle.flash.4m.ld 13 | build_unflags = 14 | -Os 15 | build_flags = 16 | -D PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH 17 | -D ARDUINOJSON_USE_LONG_LONG=1 18 | -D ATOMIC_FS_UPDATE=1 19 | -D LOCAL_VERSION="\"-6ac570b-dirty\"" 20 | -O3 21 | # Suppress warning: 'SPIFFS' is deprecated 22 | -Wno-deprecated-declarations 23 | upload_speed = 921600 24 | upload_port = "change/me" 25 | lib_deps = 26 | ESP Async WebServer=https://github.com/Depau/ESPAsyncWebServer/archive/wi-se-patches.zip 27 | ESP8266WiFi 28 | ArduinoJson -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyyaml 2 | jinja2 3 | jq 4 | -------------------------------------------------------------------------------- /src/ExtendedSerial.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by depau on 3/13/21. 3 | // 4 | 5 | #include "../include/ExtendedSerial.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int ExtendedSerial::autobaudMeasure() { 13 | static bool doTrigger = true; 14 | 15 | if (doTrigger) { 16 | uart_start_detect_baudrate(_uart_nr); 17 | doTrigger = false; 18 | } 19 | 20 | int32_t divisor = uart_baudrate_detect(_uart_nr, 1); 21 | if (!divisor) { 22 | return 0; 23 | } 24 | 25 | doTrigger = true; // Initialize for a next round 26 | int32_t baudrate = UART_CLK_FREQ / divisor; 27 | 28 | return baudrate; 29 | } 30 | 31 | int ExtendedSerial::autobaudGetClosestStdRate(int32_t rawBaud) { 32 | static const int default_rates[] = {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 33 | 256000, 460800, 921600, 1500000, 1843200, 3686400}; 34 | 35 | size_t i; 36 | for (i = 1; i < sizeof(default_rates) / sizeof(default_rates[0]) - 1; i++) // find the nearest real baudrate 37 | { 38 | if (rawBaud <= default_rates[i]) { 39 | if (rawBaud - default_rates[i - 1] < default_rates[i] - rawBaud) { 40 | i--; 41 | } 42 | break; 43 | } 44 | } 45 | 46 | return default_rates[i]; 47 | } 48 | 49 | #pragma clang diagnostic push 50 | #pragma clang diagnostic ignored "-Wint-to-pointer-cast" 51 | void ExtendedSerial::sendBreak() { 52 | uart_wait_tx_empty(_uart); 53 | USC0(_uart_nr) |= BIT(UCBRK); 54 | // 10ms should be enough to convince agetty we sent a break without breaking Wi-Fi 55 | delayMicroseconds(10 * 1000); 56 | USC0(_uart_nr) &= ~BIT(UCBRK); 57 | } 58 | #pragma clang diagnostic pop 59 | 60 | 61 | ExtendedSerial ExtSerial0(UART0); 62 | ExtendedSerial ExtSerial1(UART1); 63 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "config.h" 7 | #include "server.h" 8 | #include "debug.h" 9 | #include "ExtendedSerial.h" 10 | 11 | ADC_MODE(ADC_VCC); 12 | 13 | char token[HTTP_AUTH_TOKEN_LEN + 1] = {0}; 14 | 15 | AsyncWebServer *httpd; 16 | AsyncWebSocket *websocket; 17 | 18 | TTY *ttyd; 19 | WiSeServer *server; 20 | 21 | bool otaRunning = false; 22 | 23 | void blinkError() { 24 | digitalWrite(LED_WIFI, LOW); 25 | digitalWrite(LED_STATUS, LOW); 26 | digitalWrite(LED_RX, LOW); 27 | digitalWrite(LED_TX, LOW); 28 | 29 | for (int i = 0; i <= 10; i++) { 30 | digitalWrite(LED_RX, i % 2 == 0); 31 | digitalWrite(LED_TX, i % 2 != 0); 32 | delay(200); 33 | } 34 | } 35 | 36 | void setup() { 37 | // Generate token 38 | if (HTTP_AUTH_ENABLE) { 39 | const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!/?_=;':"; 40 | for (int i = 0; i < HTTP_AUTH_TOKEN_LEN; i++) { 41 | token[i] = charset[ESP.random() % (int) (sizeof charset - 1)]; 42 | } 43 | } 44 | 45 | httpd = new AsyncWebServer(HTTP_LISTEN_PORT); 46 | websocket = new AsyncWebSocket("/ws"); 47 | ttyd = new TTY(token, websocket); 48 | server = new WiSeServer(token, httpd, websocket, ttyd); 49 | 50 | // Init UART 51 | ttyd->stty(UART_COMM_BAUD, UART_COMM_CONFIG); 52 | 53 | #if ENABLE_DEBUG == 1 54 | if (UART_COMM != UART_DEBUG) { 55 | UART_DEBUG.begin(UART_DEBUG_BAUD, (SerialConfig) UART_DEBUG_CONFIG); 56 | } 57 | #endif 58 | 59 | // Init LEDs 60 | pinMode(LED_WIFI, OUTPUT); 61 | pinMode(LED_STATUS, OUTPUT); 62 | pinMode(LED_RX, OUTPUT); 63 | pinMode(LED_TX, OUTPUT); 64 | 65 | digitalWrite(LED_WIFI, LOW); 66 | digitalWrite(LED_RX, LOW); 67 | digitalWrite(LED_TX, LOW); 68 | digitalWrite(LED_STATUS, HIGH); 69 | 70 | // Init Wi-Fi 71 | WiFi.mode(WIFI_MODE); 72 | WiFi.hostname(WIFI_HOSTNAME); 73 | 74 | debugf("\r\n\r\n"); 75 | if (WIFI_MODE == WIFI_STA) { 76 | debugf("Wi-Fi STA connecting\r\n"); 77 | 78 | WiFi.setOutputPower(17.5); 79 | WiFi.setPhyMode(WIFI_PHY_MODE_11N); 80 | WiFi.setSleepMode(WIFI_NONE_SLEEP); 81 | 82 | analogWriteRange(0xFF); 83 | WiFi.begin(WIFI_SSID, WIFI_PASS); 84 | while (WiFi.status() != WL_CONNECTED) { 85 | for (int i = 0; i < 0xFF; i++) { 86 | analogWrite(LED_WIFI, i); 87 | delay(1); 88 | } 89 | for (int i = 0xFF; i >= 0; i--) { 90 | analogWrite(LED_WIFI, i); 91 | delay(1); 92 | } 93 | } 94 | 95 | debugf("Wi-Fi STA connected\r\n"); 96 | } else { 97 | debugf("Turning on soft AP\r\n"); 98 | 99 | char wifiSsid[30] = {0}; 100 | if (WIFI_SSID == nullptr) { 101 | snprintf(wifiSsid, sizeof(wifiSsid), "Wi-Se_%04X", ESP.getChipId() & 0xFFFF); 102 | } else { 103 | strncpy(wifiSsid, WIFI_SSID, sizeof(wifiSsid)); 104 | } 105 | 106 | WiFi.softAP(wifiSsid, WIFI_PASS, WIFI_CHANNEL, WIFI_HIDE_SSID, WIFI_MAX_DEVICES); 107 | } 108 | 109 | // It turns out that PWMing the LED costs ~100kbps due to the fact that ESP8266 doesn't have hardware PWM 110 | //analogWrite(LED_WIFI, 40); 111 | digitalWrite(LED_WIFI, HIGH); // too bright 112 | digitalWrite(LED_STATUS, LOW); 113 | 114 | // Set-up Arduino OTA 115 | // TODO: actually do it 116 | // ArduinoOTA.setHostname(WIFI_HOSTNAME); 117 | 118 | 119 | server->begin(); 120 | httpd->begin(); 121 | debugf("HTTP server is up\r\n"); 122 | 123 | MDNS.begin(WIFI_HOSTNAME); 124 | 125 | #if OTA_ENABLE == 1 126 | if (OTA_PASSWORD[0] != '\0') { 127 | ArduinoOTA.setPassword(OTA_PASSWORD); 128 | ArduinoOTA.setRebootOnSuccess(true); 129 | 130 | ArduinoOTA.setHostname(WIFI_HOSTNAME); 131 | ArduinoOTA.setPort(8266); 132 | 133 | ArduinoOTA.onStart([]() { 134 | otaRunning = true; 135 | 136 | debugf("Shutting down for OTA\r\n"); 137 | UART_DEBUG.flush(); 138 | 139 | delay(50); 140 | 141 | ttyd->shrinkBuffers(); 142 | server->end(); 143 | httpd->end(); 144 | 145 | // LED animation 146 | uint8_t leds[LED_COUNT] = LED_ORDER; 147 | 148 | for (int count = 0; count < 2; count++) { 149 | for (int i = 0; i < 255; i++) { 150 | analogWrite(leds[LED_COUNT - 1], i); 151 | delayMicroseconds(400); 152 | } 153 | for (int led = LED_COUNT - 2; led >= 0; led--) { 154 | for (int i = 0; i < 255; i++) { 155 | analogWrite(leds[led], i); 156 | analogWrite(leds[led + 1], 255 - i); 157 | delayMicroseconds(400); 158 | } 159 | digitalWrite(leds[led], HIGH); 160 | digitalWrite(leds[led + 1], LOW); 161 | } 162 | for (int i = 255; i >= 0; i--) { 163 | analogWrite(leds[0], i); 164 | delayMicroseconds(400); 165 | } 166 | } 167 | 168 | for (uint8_t led : leds) { 169 | digitalWrite(led, LOW); 170 | } 171 | }); 172 | 173 | ArduinoOTA.onProgress([](uint32_t progress, uint32_t total) { 174 | // Use LEDs as progress bar 175 | uint8_t leds[LED_COUNT] = LED_ORDER; 176 | uint32_t ledThresh = total / LED_COUNT + 1; 177 | uint8_t curLed = progress / ledThresh; 178 | uint32_t ledProgress = map(progress % ledThresh, 0, ledThresh, 0, 255); 179 | 180 | for (int led = 0; led < curLed; led++) { 181 | digitalWrite(curLed, HIGH); 182 | } 183 | for (int led = curLed + 1; led < LED_COUNT; led++) { 184 | digitalWrite(curLed, LOW); 185 | } 186 | 187 | if (curLed < LED_COUNT) { 188 | analogWrite(leds[curLed], ledProgress); 189 | } 190 | }); 191 | 192 | ArduinoOTA.onEnd([]() { 193 | debugf("OTA finished\r\nPlease wait for the atomic firmware copy\r\n"); 194 | UART_DEBUG.flush(); 195 | 196 | uint8_t leds[LED_COUNT] = LED_ORDER; 197 | digitalWrite(LED_WIFI, HIGH); 198 | digitalWrite(LED_WIFI, HIGH); 199 | 200 | if (LED_COUNT >= 3) { 201 | digitalWrite(leds[LED_COUNT - 1], LOW); 202 | delay(400); 203 | digitalWrite(leds[LED_COUNT - 2], LOW); 204 | delay(400); 205 | digitalWrite(leds[LED_COUNT - 3], LOW); 206 | } 207 | }); 208 | 209 | ArduinoOTA.onError([](ota_error_t err) { 210 | debugf("OTA error: "); 211 | switch (err) { 212 | case OTA_AUTH_ERROR: 213 | debugf("AUTH\r\n"); break; 214 | case OTA_BEGIN_ERROR: 215 | debugf("BEGIN\r\n"); break; 216 | case OTA_CONNECT_ERROR: 217 | debugf("CONNECT\r\n"); break; 218 | case OTA_RECEIVE_ERROR: 219 | debugf("RECEIVE\r\n"); break; 220 | case OTA_END_ERROR: 221 | debugf("END\r\n"); break; 222 | } 223 | 224 | // Blink red LEDs, then reset 225 | blinkError(); 226 | ESP.reset(); 227 | }); 228 | 229 | ArduinoOTA.begin(); 230 | debugf("OTA server is up\r\n"); 231 | } 232 | 233 | MDNS.addService("http", "tcp", 80); 234 | #endif 235 | } 236 | 237 | void loop() { 238 | ArduinoOTA.handle(); 239 | if (otaRunning) { 240 | return yield(); 241 | } 242 | 243 | if (WIFI_MODE == WIFI_STA && WiFi.status() != WL_CONNECTED) { 244 | blinkError(); 245 | ESP.reset(); 246 | } 247 | 248 | ttyd->dispatchUart(); 249 | yield(); 250 | ttyd->performHousekeeping(); 251 | yield(); 252 | } --------------------------------------------------------------------------------