Compare commits
91
Commits
1.1.0
...
new-codepages
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e49a8b0adf
|
||
|
|
81c3e426e7
|
||
|
|
00153656f1
|
||
|
|
aa920aee27
|
||
|
|
7b8c936559
|
||
|
|
17c18ed1c9
|
||
|
|
274e3b359b
|
||
|
|
73c98eb2d1
|
||
|
|
022e882001
|
||
|
|
dc08512397
|
||
|
|
6c1ab28e75
|
||
|
|
2796709624
|
||
|
|
d2edcd7fd5
|
||
|
|
76272530ec
|
||
|
|
a514601897
|
||
|
|
935e05a56a
|
||
|
|
a72e2bed63
|
||
|
|
679f0adbae
|
||
|
|
791f6e716f
|
||
|
|
9a5bc0a274
|
||
|
|
dca02976a7
|
||
|
|
6665b5c183
|
||
|
|
55afcca955
|
||
|
|
7ffc947f1a
|
||
|
|
0eeed9c7d9
|
||
|
|
253473daed
|
||
|
|
9321cd4ebb
|
||
|
|
faffa68794
|
||
|
|
a6ee808a1d
|
||
|
|
5150cc32eb
|
||
|
|
42d5f6bc89
|
||
|
|
d2fe37403f
|
||
|
|
f6c2b06d8a
|
||
|
|
b6c5648690
|
||
|
|
062b0e6188
|
||
|
|
c83b68405f
|
||
|
|
97552b30c3
|
||
|
|
1c23e79c59
|
||
|
|
b70c65868b
|
||
|
|
1614194d76
|
||
|
|
7bca46384e
|
||
|
|
03c7f4d0ad
|
||
|
|
da6c5bf5be
|
||
|
|
2e0648be8e
|
||
|
|
404ccaeb20
|
||
|
|
7300e0003c
|
||
|
|
8c55202b42
|
||
|
|
65977bfbae
|
||
|
|
74d52a0c61
|
||
|
|
0fae510207
|
||
|
|
1a8d3cb332
|
||
|
|
ca5a7e3de9
|
||
|
|
fa5489ccfc
|
||
|
|
502babf7b0
|
||
|
|
47f6cd38cd
|
||
|
|
0f10d84a59
|
||
|
|
cb71586138
|
||
|
|
58bd27a082
|
||
|
|
7eb1bdeec6
|
||
|
|
674e89c8c3
|
||
|
|
62a0925586
|
||
|
|
4f4ea95c06
|
||
|
|
2ede271c65
|
||
|
|
692b2c4d11
|
||
|
|
948bcb62ff
|
||
|
|
7607b639b0 | ||
|
|
2e8ec41115 | ||
|
|
80e8e4f7da | ||
|
|
357a9d43e3 | ||
|
|
a464a73a0e | ||
|
|
38b3ce2dc8 | ||
|
|
37de3a095d | ||
|
|
82961568b8 | ||
|
|
3849e161e5 | ||
|
|
43241c2679 | ||
|
|
3bfd51061e | ||
|
|
781cf8825b | ||
|
|
079b522540 | ||
|
|
471aa95c34 | ||
|
|
ac56b1dc61 | ||
|
|
82fd9e5ad1 | ||
|
|
92a454a2cf | ||
|
|
0012c92c4a | ||
|
|
0e8af5712b | ||
|
|
51e97232c5 | ||
|
|
7e2491cd7b | ||
|
|
cd79d5cf25 | ||
|
|
184c772b57 | ||
|
|
6e2978492b | ||
|
|
0d0246b12b | ||
|
|
62888d4473 |
@@ -12,6 +12,7 @@ html_compressed/
|
|||||||
ldscript_memspecific.ld
|
ldscript_memspecific.ld
|
||||||
eagle.app.sym
|
eagle.app.sym
|
||||||
node_modules
|
node_modules
|
||||||
|
esphttpdconfig.mk
|
||||||
|
|
||||||
# Garbage added by CLion
|
# Garbage added by CLion
|
||||||
.idea/
|
.idea/
|
||||||
@@ -19,3 +20,4 @@ cmake-build-debug/
|
|||||||
.sass-cache
|
.sass-cache
|
||||||
|
|
||||||
*.map
|
*.map
|
||||||
|
.gitignore
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
[submodule "libesphttpd"]
|
[submodule "libesphttpd"]
|
||||||
path = libesphttpd
|
path = libesphttpd
|
||||||
url = git@github.com:MightyPork/libesphttpd.git
|
url = git@github.com:MightyPork/libesphttpd.git
|
||||||
|
branch = master
|
||||||
[submodule "front-end"]
|
[submodule "front-end"]
|
||||||
path = front-end
|
path = front-end
|
||||||
url = git@github.com:espterm/espterm-front-end.git
|
url = git@github.com:espterm/espterm-front-end.git
|
||||||
|
|||||||
+40
-5
@@ -56,6 +56,8 @@ set(SOURCE_FILES
|
|||||||
libesphttpd/util/cgiwebsocket.c
|
libesphttpd/util/cgiwebsocket.c
|
||||||
libesphttpd/util/cgiflash.c
|
libesphttpd/util/cgiflash.c
|
||||||
libesphttpd/util/captdns.c
|
libesphttpd/util/captdns.c
|
||||||
|
libesphttpd/esphttpclient/httpclient.c
|
||||||
|
libesphttpd/include/httpclient.h
|
||||||
|
|
||||||
esp_iot_sdk_v1.5.2/include/user_interface.h
|
esp_iot_sdk_v1.5.2/include/user_interface.h
|
||||||
esp_iot_sdk_v1.5.2/include/upgrade.h
|
esp_iot_sdk_v1.5.2/include/upgrade.h
|
||||||
@@ -85,9 +87,9 @@ set(SOURCE_FILES
|
|||||||
esp_iot_sdk_v1.5.2/include/json/jsontree.h
|
esp_iot_sdk_v1.5.2/include/json/jsontree.h
|
||||||
esp_iot_sdk_v1.5.2/include/json/jsonparse.h
|
esp_iot_sdk_v1.5.2/include/json/jsonparse.h
|
||||||
esp_iot_sdk_v1.5.2/include/json/json.h
|
esp_iot_sdk_v1.5.2/include/json/json.h
|
||||||
|
|
||||||
include/user_config.h
|
include/user_config.h
|
||||||
include/ets_sys_extra.h
|
include/ets_sys_extra.h
|
||||||
|
include/helpers.h
|
||||||
user/io.c
|
user/io.c
|
||||||
user/io.h
|
user/io.h
|
||||||
user/cgi_wifi.c
|
user/cgi_wifi.c
|
||||||
@@ -121,7 +123,6 @@ set(SOURCE_FILES
|
|||||||
user/wifimgr.h
|
user/wifimgr.h
|
||||||
user/persist.c
|
user/persist.c
|
||||||
user/persist.h
|
user/persist.h
|
||||||
include/helpers.h
|
|
||||||
user/syscfg.c
|
user/syscfg.c
|
||||||
user/syscfg.h
|
user/syscfg.h
|
||||||
user/ascii.h
|
user/ascii.h
|
||||||
@@ -139,9 +140,18 @@ set(SOURCE_FILES
|
|||||||
user/apars_osc.c
|
user/apars_osc.c
|
||||||
user/apars_osc.h
|
user/apars_osc.h
|
||||||
user/apars_dcs.c
|
user/apars_dcs.c
|
||||||
user/apars_dcs.h user/uart_buffer.c user/uart_buffer.h user/jstring.c user/jstring.h user/character_sets.h user/utf8.h user/utf8.c user/cgi_logging.h)
|
user/apars_dcs.h
|
||||||
|
user/uart_buffer.c
|
||||||
|
user/uart_buffer.h
|
||||||
|
user/jstring.c
|
||||||
|
user/jstring.h
|
||||||
|
user/character_sets.h
|
||||||
|
user/utf8.h
|
||||||
|
user/utf8.c
|
||||||
|
user/cgi_logging.h)
|
||||||
|
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
|
include_directories(libesphttpd/esphttpclient)
|
||||||
include_directories(user)
|
include_directories(user)
|
||||||
include_directories(libesphttpd/include)
|
include_directories(libesphttpd/include)
|
||||||
include_directories(libesphttpd/espfs)
|
include_directories(libesphttpd/espfs)
|
||||||
@@ -153,16 +163,41 @@ include_directories(esp_iot_sdk_v1.5.2/include)
|
|||||||
add_definitions(
|
add_definitions(
|
||||||
-D__ets__
|
-D__ets__
|
||||||
-DICACHE_FLASH
|
-DICACHE_FLASH
|
||||||
|
-DDEBUG_LOGBUF_SIZE=2048
|
||||||
-DUSE_OPTIMIZE_PRINTF=1
|
-DUSE_OPTIMIZE_PRINTF=1
|
||||||
-DHTTPD_MAX_CONNECTIONS=5
|
-DHTTPD_MAX_CONNECTIONS=5
|
||||||
-DHTTPD_STACKSIZE=1000
|
-DHTTPD_STACKSIZE=1000
|
||||||
-DICACHE_FLASH_ATTR=
|
-DICACHE_FLASH_ATTR=
|
||||||
-DICACHE_RODATA_ATTR=
|
-DICACHE_RODATA_ATTR=
|
||||||
-DFLAG_GZIP=2
|
-DFLAG_GZIP=2
|
||||||
-DADMIN_PASSWORD="asdf"
|
-DESP_LANG="en"
|
||||||
|
|
||||||
|
-DGIT_HASH_BACKEND="asdf"
|
||||||
|
-DGIT_HASH_FRONTEND="asdf"
|
||||||
-DGIT_HASH="blabla"
|
-DGIT_HASH="blabla"
|
||||||
|
|
||||||
|
-D__TIMEZONE__="UTC"
|
||||||
|
-DESPFS_HEATSHRINK
|
||||||
|
|
||||||
|
-DDEBUG_ANSI=1
|
||||||
|
-DDEBUG_ANSI_NOIMPL=1
|
||||||
|
-DDEBUG_CAPTDNS=1
|
||||||
|
-DDEBUG_CGI=0
|
||||||
|
-DDEBUG_ESPFS=1
|
||||||
-DDEBUG_HEAP=1
|
-DDEBUG_HEAP=1
|
||||||
|
-DDEBUG_HTTP=1
|
||||||
|
-DDEBUG_HTTPC=1
|
||||||
|
-DDEBUG_INPUT=1
|
||||||
-DDEBUG_MALLOC=1
|
-DDEBUG_MALLOC=1
|
||||||
-DESPFS_HEATSHRINK)
|
-DDEBUG_PERSIST=1
|
||||||
|
-DDEBUG_ROUTER=1
|
||||||
|
-DDEBUG_UTFCACHE=1
|
||||||
|
-DDEBUG_WIFI=1
|
||||||
|
-DDEBUG_WS=1
|
||||||
|
-DDEBUG_ROUTER=1
|
||||||
|
)
|
||||||
|
# all the debug keys should be listed here ^ so clion thinks they are used
|
||||||
|
# and doesn't mess up the formatting and inspections
|
||||||
|
|
||||||
|
|
||||||
add_executable(ESPTerm ${SOURCE_FILES})
|
add_executable(ESPTerm ${SOURCE_FILES})
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ LIBS = c gcc hal phy pp net80211 wpa main lwip crypto
|
|||||||
#Add in esphttpd lib
|
#Add in esphttpd lib
|
||||||
LIBS += esphttpd
|
LIBS += esphttpd
|
||||||
|
|
||||||
|
ifndef ESP_LANG
|
||||||
|
ESP_LANG = en
|
||||||
|
endif
|
||||||
|
|
||||||
# compiler flags using during compilation of source files -ggdb
|
# compiler flags using during compilation of source files -ggdb
|
||||||
CFLAGS = -Os -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
|
CFLAGS = -Os -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
|
||||||
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
|
-nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \
|
||||||
@@ -69,7 +73,7 @@ CFLAGS = -Os -std=gnu99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inli
|
|||||||
|
|
||||||
CFLAGS += -DGIT_HASH_BACKEND='"$(shell git rev-parse --short HEAD)"'
|
CFLAGS += -DGIT_HASH_BACKEND='"$(shell git rev-parse --short HEAD)"'
|
||||||
CFLAGS += -DGIT_HASH_FRONTEND='"$(shell cd front-end && git rev-parse --short HEAD)"'
|
CFLAGS += -DGIT_HASH_FRONTEND='"$(shell cd front-end && git rev-parse --short HEAD)"'
|
||||||
CFLAGS += -DADMIN_PASSWORD=$(ADMIN_PASSWORD)
|
CFLAGS += -D__TIMEZONE__='"$(shell date +%Z)"' -DESP_LANG='"$(ESP_LANG)"'
|
||||||
|
|
||||||
ifdef GLOBAL_CFLAGS
|
ifdef GLOBAL_CFLAGS
|
||||||
CFLAGS += $(GLOBAL_CFLAGS)
|
CFLAGS += $(GLOBAL_CFLAGS)
|
||||||
@@ -194,6 +198,10 @@ endef
|
|||||||
web:
|
web:
|
||||||
$(Q) ./build_web.sh
|
$(Q) ./build_web.sh
|
||||||
|
|
||||||
|
updweb:
|
||||||
|
$(Q) cd front-end && git pull
|
||||||
|
$(Q) ./build_web.sh
|
||||||
|
|
||||||
parser:
|
parser:
|
||||||
$(Q) ./build_parser.sh
|
$(Q) ./build_parser.sh
|
||||||
|
|
||||||
@@ -206,13 +214,16 @@ espmac:
|
|||||||
all: checkdirs
|
all: checkdirs
|
||||||
$(Q) make actual_all -j4 -B
|
$(Q) make actual_all -j4 -B
|
||||||
|
|
||||||
|
release:
|
||||||
|
$(Q) ./release.sh
|
||||||
|
|
||||||
actual_all: parser $(TARGET_OUT) $(FW_BASE)
|
actual_all: parser $(TARGET_OUT) $(FW_BASE)
|
||||||
|
|
||||||
libesphttpd/Makefile:
|
libesphttpd/Makefile:
|
||||||
$(Q) [[ -e "libesphttpd/Makefile" ]] || echo -e "\e[31mlibesphttpd submodule missing.\nIf build fails, run \"git submodule init\" and \"git submodule update\".\e[0m"
|
$(Q) [[ -e "libesphttpd/Makefile" ]] || echo -e "\e[31mlibesphttpd submodule missing.\nIf build fails, run \"git submodule init\" and \"git submodule update\".\e[0m"
|
||||||
|
|
||||||
libesphttpd: libesphttpd/Makefile
|
libesphttpd: libesphttpd/Makefile
|
||||||
$(Q) make -C libesphttpd USE_OPENSDK=$(USE_OPENSDK) SERVERNAME_PREFIX="ESPTerm " -j4
|
$(Q) make -C libesphttpd USE_OPENSDK=$(USE_OPENSDK) -j4
|
||||||
|
|
||||||
$(APP_AR): libesphttpd $(OBJ)
|
$(APP_AR): libesphttpd $(OBJ)
|
||||||
$(vecho) "AR $@"
|
$(vecho) "AR $@"
|
||||||
|
|||||||
@@ -30,6 +30,26 @@ emulator backend that runs on the ESP8266. The web version will be updated to ma
|
|||||||
after each minor release (and sometimes in between for testing; the version currently being show-cased
|
after each minor release (and sometimes in between for testing; the version currently being show-cased
|
||||||
can be read on the About page of the demo).
|
can be read on the About page of the demo).
|
||||||
|
|
||||||
|
### Browser support
|
||||||
|
|
||||||
|
Use the above linked online demo to verify compatibility with your browser.
|
||||||
|
|
||||||
|
To our knowledge, ESPTerm **works with**:
|
||||||
|
- Google Chrome (desktop, mobile)
|
||||||
|
- Firefox (desktop, mobile not tested)
|
||||||
|
- Safari (desktop, mobile)
|
||||||
|
- Chromium
|
||||||
|
- Opera
|
||||||
|
- Brave
|
||||||
|
- Konqueror
|
||||||
|
|
||||||
|
It **does not work with**:
|
||||||
|
- Microsoft Edge - runs, but is extremely laggy
|
||||||
|
- Internet Explorer (any version) - crashes, missing JS features
|
||||||
|
- Opera Mini - crashes, missing JS and CSS features
|
||||||
|
- Blackberry browser - not tested, but unlikely
|
||||||
|
- Old Android Browser (before 4.4?) - not tested, likely missing JS features
|
||||||
|
|
||||||
## Main features
|
## Main features
|
||||||
|
|
||||||
- **Almost complete VT102 emulation** with some extras from Xterm, eg.
|
- **Almost complete VT102 emulation** with some extras from Xterm, eg.
|
||||||
@@ -47,6 +67,16 @@ can be read on the About page of the demo).
|
|||||||
- **User-friendly comprehensive WiFi configuration** (Demo: [WiFi][demo-wifi], [network][demo-network] config)
|
- **User-friendly comprehensive WiFi configuration** (Demo: [WiFi][demo-wifi], [network][demo-network] config)
|
||||||
- Static IP, DHCP, channel selection, power
|
- Static IP, DHCP, channel selection, power
|
||||||
- SSID search utility for finding your existing network
|
- SSID search utility for finding your existing network
|
||||||
|
|
||||||
|
## Bugs? Ideas?
|
||||||
|
|
||||||
|
To ask any questions or discuss new features you'd like to see added, it's best to use
|
||||||
|
the **[ESPTerm Dev mailing list](https://groups.google.com/forum/#!forum/espterm-dev)**
|
||||||
|
|
||||||
|
Subscribe to the mailing list to also receive new release announcements.
|
||||||
|
|
||||||
|
If you found a bug (that happens alot!), please submit it to our [bug tracker](https://github.com/espterm/espterm-firmware/issues).
|
||||||
|
We also use it to track planned ideas. If you don't want to create a GitHub account for that, just send it to the mailing list.
|
||||||
|
|
||||||
## Running ESPTerm
|
## Running ESPTerm
|
||||||
|
|
||||||
|
|||||||
@@ -3,3 +3,6 @@
|
|||||||
echo "-- Building parser from Ragel source --"
|
echo "-- Building parser from Ragel source --"
|
||||||
|
|
||||||
ragel -L -G0 user/ansi_parser.rl -o user/ansi_parser.c
|
ragel -L -G0 user/ansi_parser.rl -o user/ansi_parser.c
|
||||||
|
|
||||||
|
sed -i "s/static const char _ansi_actions\[\]/static const char _ansi_actions\[\] ESP_CONST_DATA/" user/ansi_parser.c
|
||||||
|
sed -i "s/static const char _ansi_eof_actions\[\]/static const char _ansi_eof_actions\[\] ESP_CONST_DATA/" user/ansi_parser.c
|
||||||
|
|||||||
@@ -38,15 +38,15 @@ OUTPUT_TYPE = combined
|
|||||||
# SPI flash size, in K
|
# SPI flash size, in K
|
||||||
ESP_SPI_FLASH_SIZE_K = 1024
|
ESP_SPI_FLASH_SIZE_K = 1024
|
||||||
|
|
||||||
# Admin password, used to store settings to flash as defaults
|
|
||||||
ADMIN_PASSWORD = "19738426"
|
|
||||||
|
|
||||||
GLOBAL_CFLAGS = \
|
GLOBAL_CFLAGS = \
|
||||||
|
-DASYNC_LOG=1 \
|
||||||
|
-DDEBUG_D2D=0 \
|
||||||
-DDEBUG_ROUTER=0 \
|
-DDEBUG_ROUTER=0 \
|
||||||
-DDEBUG_CAPTDNS=0 \
|
-DDEBUG_CAPTDNS=0 \
|
||||||
-DDEBUG_HTTP=0 \
|
-DDEBUG_HTTP=0 \
|
||||||
|
-DDEBUG_HTTPC=0 \
|
||||||
-DDEBUG_ESPFS=0 \
|
-DDEBUG_ESPFS=0 \
|
||||||
-DDEBUG_PERSIST=0 \
|
-DDEBUG_PERSIST=1 \
|
||||||
-DDEBUG_UTFCACHE=0 \
|
-DDEBUG_UTFCACHE=0 \
|
||||||
-DDEBUG_CGI=0 \
|
-DDEBUG_CGI=0 \
|
||||||
-DDEBUG_WIFI=0 \
|
-DDEBUG_WIFI=0 \
|
||||||
@@ -59,5 +59,6 @@ GLOBAL_CFLAGS = \
|
|||||||
-DHTTPD_MAX_BACKLOG_SIZE=8192 \
|
-DHTTPD_MAX_BACKLOG_SIZE=8192 \
|
||||||
-DHTTPD_MAX_HEAD_LEN=1024 \
|
-DHTTPD_MAX_HEAD_LEN=1024 \
|
||||||
-DHTTPD_MAX_POST_LEN=512 \
|
-DHTTPD_MAX_POST_LEN=512 \
|
||||||
|
-DDEBUG_LOGBUF_SIZE=1024 \
|
||||||
-mforce-l32 \
|
-mforce-l32 \
|
||||||
-DUSE_OPTIMIZE_PRINTF=1
|
-DUSE_OPTIMIZE_PRINTF=1
|
||||||
+1
-1
Submodule front-end updated: b2174fc528...8b610aa95b
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/10/03.
|
||||||
|
//
|
||||||
|
// helper for building release packages
|
||||||
|
//
|
||||||
|
// Run with `tcc -run`
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "user/version.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
printf(FW_VERSION);
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
|
|||||||
+1
-1
Submodule libesphttpd updated: 3479ab3efc...e4ecf0724e
@@ -0,0 +1,21 @@
|
|||||||
|
This is a release archive of ESPTerm,
|
||||||
|
the VT100 terminal emulator for ESP8266.
|
||||||
|
|
||||||
|
--------------------------------------------
|
||||||
|
Version: %VERS%
|
||||||
|
Locale : %LANG%
|
||||||
|
Built : %DATETIME%
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
Source repository:
|
||||||
|
https://github.com/espterm/espterm-firmware
|
||||||
|
|
||||||
|
Report any bugs to our bug-tracker at
|
||||||
|
https://github.com/espterm/espterm-firmware/issues
|
||||||
|
or send them to out mailing list
|
||||||
|
espterm-dev@googlegroups.com
|
||||||
|
|
||||||
|
On-line demo is available at
|
||||||
|
https://espterm.github.io/term.html
|
||||||
|
|
||||||
|
[EOF]
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# The parameters ESPTOOL, ESPPORT and ESPBAUD can be customized
|
||||||
|
# - export your preferred values in .bashrc
|
||||||
|
|
||||||
|
echo -e "\e[32;1mFlashing ESPTerm %VERS% (%LANG%)\e[0m"
|
||||||
|
|
||||||
|
if [ -z ${ESPTOOL} ]; then
|
||||||
|
ESPTOOL='esptool'
|
||||||
|
which ${ESPTOOL} &>/dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
ESPTOOL='esptool.py'
|
||||||
|
which ${ESPTOOL} &>/dev/null
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo -e '\e[31;1mesptool not found!\e[0m'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -z ESPPORT ] && ESPPORT=/dev/ttyUSB0
|
||||||
|
[ -z ESPBAUD ] && ESPBAUD=460800
|
||||||
|
|
||||||
|
set -x
|
||||||
|
${ESPTOOL} --port ${ESPPORT} --baud ${ESPBAUD} \
|
||||||
|
write_flash 0x00000 '%FILE0%' 0x40000 '%FILE4%'
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
!flash-tpl.sh
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
vers=$(tcc -run get_version.c)
|
||||||
|
else
|
||||||
|
vers=$1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git pull
|
||||||
|
|
||||||
|
echo -n -e "\e[1;36mBuilding packages for version $vers\e[0m"
|
||||||
|
|
||||||
|
cd front-end
|
||||||
|
git pull
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
function buildlang() {
|
||||||
|
lang=$1
|
||||||
|
|
||||||
|
echo -e "\n\e[33;1m------ Building \"${lang}\" package ------\e[0m\n"
|
||||||
|
|
||||||
|
make clean
|
||||||
|
ESP_LANG=${lang} make web
|
||||||
|
ESP_LANG=${lang} make actual_all -B -j4
|
||||||
|
|
||||||
|
cd release
|
||||||
|
|
||||||
|
destdir="$vers-$lang"
|
||||||
|
file0=${vers}-0x00000-${lang}.bin
|
||||||
|
file4=${vers}-0x40000-${lang}.bin
|
||||||
|
[ -e ${destdir} ] && rm -r ${destdir}
|
||||||
|
mkdir ${destdir}
|
||||||
|
cp ../firmware/0x00000.bin ${destdir}/${file0}
|
||||||
|
cp ../firmware/0x40000.bin ${destdir}/${file4}
|
||||||
|
|
||||||
|
flashsh=${destdir}/flash.sh
|
||||||
|
cp ../rel-tpl/flash.sh ${flashsh}
|
||||||
|
sed -i s/%FILE0%/${file0}/ ${flashsh}
|
||||||
|
sed -i s/%FILE4%/${file4}/ ${flashsh}
|
||||||
|
sed -i s/%VERS%/${vers}/ ${flashsh}
|
||||||
|
sed -i s/%LANG%/${lang}/ ${flashsh}
|
||||||
|
chmod +x ${flashsh}
|
||||||
|
|
||||||
|
readmefil=${destdir}/README.txt
|
||||||
|
cp ../rel-tpl/README.txt ${readmefil}
|
||||||
|
sed -i s/%VERS%/${vers}/ ${readmefil}
|
||||||
|
sed -i s/%LANG%/${lang}/ ${readmefil}
|
||||||
|
dt=$(LC_TIME=en_US.UTF-8 date '+%c')
|
||||||
|
sed -i "s#%DATETIME%#${dt}#" ${readmefil}
|
||||||
|
unix2dos ${readmefil}
|
||||||
|
|
||||||
|
cd ${destdir}
|
||||||
|
sha256sum ${file0} ${file4} README.txt flash.sh > checksums.txt
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
targetfile=espterm-${vers}-${lang}.zip
|
||||||
|
[[ -e ${targetfile}.zip ]] && rm ${targetfile}.zip
|
||||||
|
pwd
|
||||||
|
zip -9 ${targetfile} ${destdir}/*
|
||||||
|
cd ..
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "$ESP_LANG" ]; then
|
||||||
|
buildlang cs
|
||||||
|
buildlang en
|
||||||
|
buildlang de
|
||||||
|
else
|
||||||
|
buildlang ${ESP_LANG}
|
||||||
|
fi
|
||||||
+43
-37
@@ -5,11 +5,12 @@
|
|||||||
#include "ansi_parser_callbacks.h"
|
#include "ansi_parser_callbacks.h"
|
||||||
#include "ascii.h"
|
#include "ascii.h"
|
||||||
#include "apars_logging.h"
|
#include "apars_logging.h"
|
||||||
|
#include "screen.h"
|
||||||
|
|
||||||
/* Ragel constants block */
|
/* Ragel constants block */
|
||||||
|
|
||||||
/* #line 12 "user/ansi_parser.c" */
|
/* #line 13 "user/ansi_parser.c" */
|
||||||
static const char _ansi_actions[] = {
|
static const char _ansi_actions[] ESP_CONST_DATA = {
|
||||||
0, 1, 0, 1, 1, 1, 2, 1,
|
0, 1, 0, 1, 1, 1, 2, 1,
|
||||||
3, 1, 4, 1, 5, 1, 6, 1,
|
3, 1, 4, 1, 5, 1, 6, 1,
|
||||||
7, 1, 8, 1, 9, 1, 10, 1,
|
7, 1, 8, 1, 9, 1, 10, 1,
|
||||||
@@ -17,7 +18,7 @@ static const char _ansi_actions[] = {
|
|||||||
15
|
15
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char _ansi_eof_actions[] = {
|
static const char _ansi_eof_actions[] ESP_CONST_DATA = {
|
||||||
0, 1, 1, 1, 1, 1, 1, 1,
|
0, 1, 1, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 0, 0, 0, 0
|
1, 1, 1, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
@@ -32,18 +33,15 @@ static const int ansi_en_charsetcmd_body = 10;
|
|||||||
static const int ansi_en_main = 1;
|
static const int ansi_en_main = 1;
|
||||||
|
|
||||||
|
|
||||||
/* #line 11 "user/ansi_parser.rl" */
|
/* #line 12 "user/ansi_parser.rl" */
|
||||||
|
|
||||||
|
|
||||||
// Max nr of CSI parameters
|
|
||||||
#define CSI_N_MAX 10
|
|
||||||
#define ANSI_STR_LEN 64
|
|
||||||
|
|
||||||
static volatile int cs = -1;
|
static volatile int cs = -1;
|
||||||
static volatile bool inside_string = false;
|
static volatile bool inside_string = false;
|
||||||
|
|
||||||
// public
|
// public
|
||||||
volatile u32 ansi_parser_char_cnt = 0;
|
volatile u32 ansi_parser_char_cnt = 0;
|
||||||
|
volatile bool ansi_parser_inhibit = 0;
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
ansi_parser_reset(void) {
|
ansi_parser_reset(void) {
|
||||||
@@ -108,18 +106,25 @@ ansi_parser(char newchar)
|
|||||||
static char string_buffer[ANSI_STR_LEN];
|
static char string_buffer[ANSI_STR_LEN];
|
||||||
static int str_ni;
|
static int str_ni;
|
||||||
|
|
||||||
|
if (ansi_parser_inhibit) return;
|
||||||
|
|
||||||
// This is used to detect timeout delay (time since last rx char)
|
// This is used to detect timeout delay (time since last rx char)
|
||||||
ansi_parser_char_cnt++;
|
ansi_parser_char_cnt++;
|
||||||
|
|
||||||
|
if (termconf->ascii_debug) {
|
||||||
|
apars_handle_plainchar(newchar);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Init Ragel on the first run
|
// Init Ragel on the first run
|
||||||
if (cs == -1) {
|
if (cs == -1) {
|
||||||
|
|
||||||
/* #line 118 "user/ansi_parser.c" */
|
/* #line 123 "user/ansi_parser.c" */
|
||||||
{
|
{
|
||||||
cs = ansi_start;
|
cs = ansi_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #line 92 "user/ansi_parser.rl" */
|
/* #line 97 "user/ansi_parser.rl" */
|
||||||
|
|
||||||
#if DEBUG_ANSI
|
#if DEBUG_ANSI
|
||||||
memset(history, 0, sizeof(history));
|
memset(history, 0, sizeof(history));
|
||||||
@@ -133,6 +138,13 @@ ansi_parser(char newchar)
|
|||||||
history[HISTORY_LEN-1] = newchar;
|
history[HISTORY_LEN-1] = newchar;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// THose should work always, even inside a string
|
||||||
|
if (newchar == CAN || newchar == SUB) {
|
||||||
|
// Cancel the active sequence
|
||||||
|
cs = ansi_start;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle simple characters immediately (bypass parser)
|
// Handle simple characters immediately (bypass parser)
|
||||||
if (newchar < ' ' && !inside_string) {
|
if (newchar < ' ' && !inside_string) {
|
||||||
switch (newchar) {
|
switch (newchar) {
|
||||||
@@ -174,12 +186,6 @@ ansi_parser(char newchar)
|
|||||||
apars_handle_enq();
|
apars_handle_enq();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Cancel the active sequence
|
|
||||||
case CAN:
|
|
||||||
case SUB:
|
|
||||||
cs = ansi_start;
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Discard all other control codes
|
// Discard all other control codes
|
||||||
return;
|
return;
|
||||||
@@ -199,7 +205,7 @@ ansi_parser(char newchar)
|
|||||||
|
|
||||||
// The parser
|
// The parser
|
||||||
|
|
||||||
/* #line 203 "user/ansi_parser.c" */
|
/* #line 209 "user/ansi_parser.c" */
|
||||||
{
|
{
|
||||||
const char *_acts;
|
const char *_acts;
|
||||||
unsigned int _nacts;
|
unsigned int _nacts;
|
||||||
@@ -389,7 +395,7 @@ execFuncs:
|
|||||||
while ( _nacts-- > 0 ) {
|
while ( _nacts-- > 0 ) {
|
||||||
switch ( *_acts++ ) {
|
switch ( *_acts++ ) {
|
||||||
case 0:
|
case 0:
|
||||||
/* #line 179 "user/ansi_parser.rl" */
|
/* #line 185 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
ansi_warn("Parser error.");
|
ansi_warn("Parser error.");
|
||||||
apars_show_context();
|
apars_show_context();
|
||||||
@@ -398,7 +404,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* #line 188 "user/ansi_parser.rl" */
|
/* #line 194 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
if ((*p) != 0) {
|
if ((*p) != 0) {
|
||||||
apars_handle_plainchar((*p));
|
apars_handle_plainchar((*p));
|
||||||
@@ -406,7 +412,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
/* #line 196 "user/ansi_parser.rl" */
|
/* #line 202 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
// Reset the CSI builder
|
// Reset the CSI builder
|
||||||
leadchar = NUL;
|
leadchar = NUL;
|
||||||
@@ -423,13 +429,13 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
/* #line 211 "user/ansi_parser.rl" */
|
/* #line 217 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
leadchar = (*p);
|
leadchar = (*p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
/* #line 215 "user/ansi_parser.rl" */
|
/* #line 221 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
if (arg_cnt == 0) arg_cnt = 1;
|
if (arg_cnt == 0) arg_cnt = 1;
|
||||||
// x10 + digit
|
// x10 + digit
|
||||||
@@ -439,7 +445,7 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* #line 223 "user/ansi_parser.rl" */
|
/* #line 229 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
if (arg_cnt == 0) arg_cnt = 1; // handle case when first arg is empty
|
if (arg_cnt == 0) arg_cnt = 1; // handle case when first arg is empty
|
||||||
arg_cnt++;
|
arg_cnt++;
|
||||||
@@ -447,20 +453,20 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
/* #line 229 "user/ansi_parser.rl" */
|
/* #line 235 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
interchar = (*p);
|
interchar = (*p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
/* #line 233 "user/ansi_parser.rl" */
|
/* #line 239 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_csi(leadchar, arg, arg_cnt, interchar, (*p));
|
apars_handle_csi(leadchar, arg, arg_cnt, interchar, (*p));
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
/* #line 245 "user/ansi_parser.rl" */
|
/* #line 251 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
leadchar = (*p);
|
leadchar = (*p);
|
||||||
str_ni = 0;
|
str_ni = 0;
|
||||||
@@ -470,13 +476,13 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
/* #line 253 "user/ansi_parser.rl" */
|
/* #line 259 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
string_buffer[str_ni++] = (*p);
|
string_buffer[str_ni++] = (*p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
/* #line 257 "user/ansi_parser.rl" */
|
/* #line 263 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
inside_string = false;
|
inside_string = false;
|
||||||
string_buffer[str_ni++] = '\0';
|
string_buffer[str_ni++] = '\0';
|
||||||
@@ -485,41 +491,41 @@ execFuncs:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
/* #line 270 "user/ansi_parser.rl" */
|
/* #line 276 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_hash_cmd((*p));
|
apars_handle_hash_cmd((*p));
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
/* #line 275 "user/ansi_parser.rl" */
|
/* #line 281 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_short_cmd((*p));
|
apars_handle_short_cmd((*p));
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
/* #line 280 "user/ansi_parser.rl" */
|
/* #line 286 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_space_cmd((*p));
|
apars_handle_space_cmd((*p));
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
/* #line 287 "user/ansi_parser.rl" */
|
/* #line 293 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
leadchar = (*p);
|
leadchar = (*p);
|
||||||
{cs = 10;goto _again;}
|
{cs = 10;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
/* #line 292 "user/ansi_parser.rl" */
|
/* #line 298 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
apars_handle_chs_designate(leadchar, (*p));
|
apars_handle_chs_designate(leadchar, (*p));
|
||||||
{cs = 1;goto _again;}
|
{cs = 1;goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* #line 523 "user/ansi_parser.c" */
|
/* #line 529 "user/ansi_parser.c" */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
goto _again;
|
goto _again;
|
||||||
@@ -537,7 +543,7 @@ _again:
|
|||||||
while ( __nacts-- > 0 ) {
|
while ( __nacts-- > 0 ) {
|
||||||
switch ( *__acts++ ) {
|
switch ( *__acts++ ) {
|
||||||
case 0:
|
case 0:
|
||||||
/* #line 179 "user/ansi_parser.rl" */
|
/* #line 185 "user/ansi_parser.rl" */
|
||||||
{
|
{
|
||||||
ansi_warn("Parser error.");
|
ansi_warn("Parser error.");
|
||||||
apars_show_context();
|
apars_show_context();
|
||||||
@@ -547,7 +553,7 @@ _again:
|
|||||||
goto _again;}
|
goto _again;}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* #line 551 "user/ansi_parser.c" */
|
/* #line 557 "user/ansi_parser.c" */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -555,6 +561,6 @@ goto _again;}
|
|||||||
_out: {}
|
_out: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #line 315 "user/ansi_parser.rl" */
|
/* #line 321 "user/ansi_parser.rl" */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define CSI_N_MAX 12
|
||||||
|
#define ANSI_STR_LEN 256
|
||||||
|
|
||||||
|
extern volatile bool ansi_parser_inhibit; // discard all characters
|
||||||
|
|
||||||
void ansi_parser_reset(void);
|
void ansi_parser_reset(void);
|
||||||
|
|
||||||
extern volatile u32 ansi_parser_char_cnt;
|
extern volatile u32 ansi_parser_char_cnt;
|
||||||
|
|||||||
+16
-10
@@ -3,6 +3,7 @@
|
|||||||
#include "ansi_parser_callbacks.h"
|
#include "ansi_parser_callbacks.h"
|
||||||
#include "ascii.h"
|
#include "ascii.h"
|
||||||
#include "apars_logging.h"
|
#include "apars_logging.h"
|
||||||
|
#include "screen.h"
|
||||||
|
|
||||||
/* Ragel constants block */
|
/* Ragel constants block */
|
||||||
%%{
|
%%{
|
||||||
@@ -10,15 +11,12 @@
|
|||||||
write data;
|
write data;
|
||||||
}%%
|
}%%
|
||||||
|
|
||||||
// Max nr of CSI parameters
|
|
||||||
#define CSI_N_MAX 10
|
|
||||||
#define ANSI_STR_LEN 64
|
|
||||||
|
|
||||||
static volatile int cs = -1;
|
static volatile int cs = -1;
|
||||||
static volatile bool inside_string = false;
|
static volatile bool inside_string = false;
|
||||||
|
|
||||||
// public
|
// public
|
||||||
volatile u32 ansi_parser_char_cnt = 0;
|
volatile u32 ansi_parser_char_cnt = 0;
|
||||||
|
volatile bool ansi_parser_inhibit = 0;
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
ansi_parser_reset(void) {
|
ansi_parser_reset(void) {
|
||||||
@@ -83,9 +81,16 @@ ansi_parser(char newchar)
|
|||||||
static char string_buffer[ANSI_STR_LEN];
|
static char string_buffer[ANSI_STR_LEN];
|
||||||
static int str_ni;
|
static int str_ni;
|
||||||
|
|
||||||
|
if (ansi_parser_inhibit) return;
|
||||||
|
|
||||||
// This is used to detect timeout delay (time since last rx char)
|
// This is used to detect timeout delay (time since last rx char)
|
||||||
ansi_parser_char_cnt++;
|
ansi_parser_char_cnt++;
|
||||||
|
|
||||||
|
if (termconf->ascii_debug) {
|
||||||
|
apars_handle_plainchar(newchar);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Init Ragel on the first run
|
// Init Ragel on the first run
|
||||||
if (cs == -1) {
|
if (cs == -1) {
|
||||||
%% write init;
|
%% write init;
|
||||||
@@ -102,6 +107,13 @@ ansi_parser(char newchar)
|
|||||||
history[HISTORY_LEN-1] = newchar;
|
history[HISTORY_LEN-1] = newchar;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// THose should work always, even inside a string
|
||||||
|
if (newchar == CAN || newchar == SUB) {
|
||||||
|
// Cancel the active sequence
|
||||||
|
cs = ansi_start;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle simple characters immediately (bypass parser)
|
// Handle simple characters immediately (bypass parser)
|
||||||
if (newchar < ' ' && !inside_string) {
|
if (newchar < ' ' && !inside_string) {
|
||||||
switch (newchar) {
|
switch (newchar) {
|
||||||
@@ -143,12 +155,6 @@ ansi_parser(char newchar)
|
|||||||
apars_handle_enq();
|
apars_handle_enq();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Cancel the active sequence
|
|
||||||
case CAN:
|
|
||||||
case SUB:
|
|
||||||
cs = ansi_start;
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Discard all other control codes
|
// Discard all other control codes
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -11,6 +11,14 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "uart_buffer.h"
|
#include "uart_buffer.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
#include "wifimgr.h"
|
||||||
|
|
||||||
|
volatile bool enquiry_suppressed = false;
|
||||||
|
ETSTimer enqTimer;
|
||||||
|
void ICACHE_FLASH_ATTR enqTimerCb(void *unused)
|
||||||
|
{
|
||||||
|
enquiry_suppressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a response to UART0
|
* Send a response to UART0
|
||||||
@@ -19,6 +27,7 @@
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
apars_respond(const char *str)
|
apars_respond(const char *str)
|
||||||
{
|
{
|
||||||
|
// Using the Tx buffer causes issues with large data (eg. from http requests)
|
||||||
UART_SendAsync(str, -1);
|
UART_SendAsync(str, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,8 +46,32 @@ apars_handle_bel(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
apars_handle_enq(void)
|
apars_handle_enq(void)
|
||||||
{
|
{
|
||||||
|
if (enquiry_suppressed) return;
|
||||||
|
|
||||||
|
u8 mac[6];
|
||||||
|
wifi_get_macaddr(SOFTAP_IF, mac);
|
||||||
|
|
||||||
|
char buf100[100];
|
||||||
|
char *buf = buf100;
|
||||||
|
buf += sprintf(buf, "\x1bX");
|
||||||
|
buf += sprintf(buf, "ESPTerm "VERSION_STRING" ");
|
||||||
|
buf += sprintf(buf, "#"GIT_HASH_BACKEND"+"GIT_HASH_FRONTEND" ");
|
||||||
|
buf += sprintf(buf, "id=%02X%02X%02X ", mac[3], mac[4], mac[5]);
|
||||||
|
int x = getStaIpAsString(buf);
|
||||||
|
if (x) buf += x;
|
||||||
|
else buf--; // remove the trailing space
|
||||||
|
buf += sprintf(buf, "\x1b\\");
|
||||||
|
|
||||||
|
(void)buf;
|
||||||
|
|
||||||
// version encased in SOS and ST
|
// version encased in SOS and ST
|
||||||
apars_respond("\x1bXESPTerm " FIRMWARE_VERSION "\x1b\\");
|
apars_respond(buf100);
|
||||||
|
|
||||||
|
// Throttle enquiry - this is a single-character-invoked response,
|
||||||
|
// so it tends to happen randomly when throwing garbage at the ESP.
|
||||||
|
// We don't want to fill the output buffer with dozens of enquiry responses
|
||||||
|
enquiry_suppressed = true;
|
||||||
|
TIMER_START(&enqTimer, enqTimerCb, 500, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
|
|||||||
+21
-23
@@ -551,31 +551,27 @@ do_csi_sgr(CSI_Data *opts)
|
|||||||
else if (n >= SGR_FG_BRT_START && n <= SGR_FG_BRT_END) screen_set_fg((Color) ((n - SGR_FG_BRT_START) + 8)); // AIX bright fg
|
else if (n >= SGR_FG_BRT_START && n <= SGR_FG_BRT_END) screen_set_fg((Color) ((n - SGR_FG_BRT_START) + 8)); // AIX bright fg
|
||||||
else if (n >= SGR_BG_BRT_START && n <= SGR_BG_BRT_END) screen_set_bg((Color) ((n - SGR_BG_BRT_START) + 8)); // AIX bright bg
|
else if (n >= SGR_BG_BRT_START && n <= SGR_BG_BRT_END) screen_set_bg((Color) ((n - SGR_BG_BRT_START) + 8)); // AIX bright bg
|
||||||
// reset color
|
// reset color
|
||||||
else if (n == SGR_FG_DEFAULT) screen_set_fg(termconf_live.default_fg); // default fg
|
else if (n == SGR_FG_DEFAULT) screen_set_default_fg();
|
||||||
else if (n == SGR_BG_DEFAULT) screen_set_bg(termconf_live.default_bg); // default bg
|
else if (n == SGR_BG_DEFAULT) screen_set_default_bg();
|
||||||
// 256 colors
|
// 256 colors
|
||||||
else if (n == SGR_FG_256 || n == SGR_BG_256) {
|
else if (n == SGR_FG_256 || n == SGR_BG_256) {
|
||||||
if (i < count-2) {
|
if (i >= count-2) {
|
||||||
if (opts->n[i + 1] == 5) {
|
|
||||||
u8 color = (u8) opts->n[i + 2];
|
|
||||||
bool fg = n == SGR_FG_256;
|
|
||||||
if (fg) {
|
|
||||||
screen_set_fg(color);
|
|
||||||
} else {
|
|
||||||
screen_set_bg(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ansi_warn("SGR syntax err");
|
|
||||||
apars_show_context();
|
|
||||||
break; // abandon further
|
|
||||||
}
|
|
||||||
i += 2;
|
|
||||||
} else {
|
|
||||||
ansi_warn("SGR syntax err");
|
ansi_warn("SGR syntax err");
|
||||||
apars_show_context();
|
apars_show_context();
|
||||||
break; // abandon further
|
break; // abandon further
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts->n[i + 1] != 5) {
|
||||||
|
ansi_warn("SGR syntax err");
|
||||||
|
apars_show_context();
|
||||||
|
break; // abandon further
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 color = (u8) opts->n[i + 2];
|
||||||
|
bool fg = n == SGR_FG_256;
|
||||||
|
if (fg) screen_set_fg(color);
|
||||||
|
else screen_set_bg(color);
|
||||||
|
i += 2;
|
||||||
}
|
}
|
||||||
// -- set attr --
|
// -- set attr --
|
||||||
else if (n == SGR_BOLD) screen_set_sgr(ATTR_BOLD, 1);
|
else if (n == SGR_BOLD) screen_set_sgr(ATTR_BOLD, 1);
|
||||||
@@ -585,7 +581,7 @@ do_csi_sgr(CSI_Data *opts)
|
|||||||
else if (n == SGR_BLINK || n == SGR_BLINK_FAST) screen_set_sgr(ATTR_BLINK, 1); // 6 - rapid blink, not supported
|
else if (n == SGR_BLINK || n == SGR_BLINK_FAST) screen_set_sgr(ATTR_BLINK, 1); // 6 - rapid blink, not supported
|
||||||
else if (n == SGR_STRIKE) screen_set_sgr(ATTR_STRIKE, 1);
|
else if (n == SGR_STRIKE) screen_set_sgr(ATTR_STRIKE, 1);
|
||||||
else if (n == SGR_FRAKTUR) screen_set_sgr(ATTR_FRAKTUR, 1);
|
else if (n == SGR_FRAKTUR) screen_set_sgr(ATTR_FRAKTUR, 1);
|
||||||
else if (n == SGR_INVERSE) screen_set_sgr_inverse(1);
|
else if (n == SGR_INVERSE) screen_set_sgr(ATTR_INVERSE, 1);
|
||||||
else if (n == SGR_CONCEAL) screen_set_sgr_conceal(1);
|
else if (n == SGR_CONCEAL) screen_set_sgr_conceal(1);
|
||||||
else if (n == SGR_OVERLINE) screen_set_sgr(ATTR_OVERLINE, 1);
|
else if (n == SGR_OVERLINE) screen_set_sgr(ATTR_OVERLINE, 1);
|
||||||
// -- clear attr --
|
// -- clear attr --
|
||||||
@@ -595,7 +591,7 @@ do_csi_sgr(CSI_Data *opts)
|
|||||||
else if (n == SGR_NO_UNDERLINE) screen_set_sgr(ATTR_UNDERLINE, 0);
|
else if (n == SGR_NO_UNDERLINE) screen_set_sgr(ATTR_UNDERLINE, 0);
|
||||||
else if (n == SGR_NO_BLINK) screen_set_sgr(ATTR_BLINK, 0);
|
else if (n == SGR_NO_BLINK) screen_set_sgr(ATTR_BLINK, 0);
|
||||||
else if (n == SGR_NO_STRIKE) screen_set_sgr(ATTR_STRIKE, 0);
|
else if (n == SGR_NO_STRIKE) screen_set_sgr(ATTR_STRIKE, 0);
|
||||||
else if (n == SGR_NO_INVERSE) screen_set_sgr_inverse(0);
|
else if (n == SGR_NO_INVERSE) screen_set_sgr(ATTR_INVERSE, 0);
|
||||||
else if (n == SGR_NO_CONCEAL) screen_set_sgr_conceal(0);
|
else if (n == SGR_NO_CONCEAL) screen_set_sgr_conceal(0);
|
||||||
else if (n == SGR_NO_OVERLINE) screen_set_sgr(ATTR_OVERLINE, 0);
|
else if (n == SGR_NO_OVERLINE) screen_set_sgr(ATTR_OVERLINE, 0);
|
||||||
else {
|
else {
|
||||||
@@ -713,6 +709,8 @@ do_csi_set_private_option(CSI_Data *opts)
|
|||||||
mouse_tracking.mode,
|
mouse_tracking.mode,
|
||||||
mouse_tracking.encoding,
|
mouse_tracking.encoding,
|
||||||
mouse_tracking.focus_tracking);
|
mouse_tracking.focus_tracking);
|
||||||
|
|
||||||
|
screen_notifyChange(TOPIC_CHANGE_SCREEN_OPTS);
|
||||||
}
|
}
|
||||||
else if (n == 12) {
|
else if (n == 12) {
|
||||||
screen_cursor_blink(yn);
|
screen_cursor_blink(yn);
|
||||||
@@ -761,11 +759,11 @@ do_csi_set_private_option(CSI_Data *opts)
|
|||||||
}
|
}
|
||||||
else if (n == 800) { // ESPTerm: Toggle display of buttons
|
else if (n == 800) { // ESPTerm: Toggle display of buttons
|
||||||
termconf_live.show_buttons = yn;
|
termconf_live.show_buttons = yn;
|
||||||
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
|
screen_notifyChange(TOPIC_CHANGE_SCREEN_OPTS); // this info is included in the screen preamble
|
||||||
}
|
}
|
||||||
else if (n == 801) { // ESPTerm: Toggle display of config links
|
else if (n == 801) { // ESPTerm: Toggle display of config links
|
||||||
termconf_live.show_config_links = yn;
|
termconf_live.show_config_links = yn;
|
||||||
screen_notifyChange(CHANGE_CONTENT); // this info is included in the screen preamble
|
screen_notifyChange(TOPIC_CHANGE_SCREEN_OPTS); // this info is included in the screen preamble
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ansi_noimpl("?OPTION %d", n);
|
ansi_noimpl("?OPTION %d", n);
|
||||||
|
|||||||
+5
-3
@@ -30,7 +30,7 @@
|
|||||||
* @param buffer - the DCS body (after DCS and before ST)
|
* @param buffer - the DCS body (after DCS and before ST)
|
||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
apars_handle_dcs(const char *buffer)
|
apars_handle_dcs(char *buffer)
|
||||||
{
|
{
|
||||||
char buf[64]; // just about big enough for full-house SGR
|
char buf[64]; // just about big enough for full-house SGR
|
||||||
size_t len = strlen(buffer);
|
size_t len = strlen(buffer);
|
||||||
@@ -47,7 +47,9 @@ apars_handle_dcs(const char *buffer)
|
|||||||
}
|
}
|
||||||
else if (buffer[2] == 'r') {
|
else if (buffer[2] == 'r') {
|
||||||
// DECSTBM - Query scrolling region
|
// DECSTBM - Query scrolling region
|
||||||
sprintf(buf, "\033P1$r%d;%dr\033\\", 1, termconf_live.height); // 1-80 TODO real extent of scrolling region
|
int v0, v1;
|
||||||
|
screen_region_get(&v0, &v1);
|
||||||
|
sprintf(buf, "\033P1$r%d;%dr\033\\", v0+1, v1+1);
|
||||||
apars_respond(buf);
|
apars_respond(buf);
|
||||||
}
|
}
|
||||||
else if (buffer[2] == 's') {
|
else if (buffer[2] == 's') {
|
||||||
@@ -64,7 +66,7 @@ apars_handle_dcs(const char *buffer)
|
|||||||
}
|
}
|
||||||
else if (strneq(buffer+2, " q", 2)) {
|
else if (strneq(buffer+2, " q", 2)) {
|
||||||
// DECSCUSR - Query cursor style
|
// DECSCUSR - Query cursor style
|
||||||
sprintf(buf, "\033P1$r%d q\033\\", 1);
|
sprintf(buf, "\033P1$r%d q\033\\", termconf_live.cursor_shape);
|
||||||
/*
|
/*
|
||||||
Ps = 0 -> blinking block.
|
Ps = 0 -> blinking block.
|
||||||
Ps = 1 -> blinking block (default).
|
Ps = 1 -> blinking block (default).
|
||||||
|
|||||||
+1
-1
@@ -5,6 +5,6 @@
|
|||||||
#ifndef ESP_VT100_FIRMWARE_APARS_DCS_H
|
#ifndef ESP_VT100_FIRMWARE_APARS_DCS_H
|
||||||
#define ESP_VT100_FIRMWARE_APARS_DCS_H
|
#define ESP_VT100_FIRMWARE_APARS_DCS_H
|
||||||
|
|
||||||
void apars_handle_dcs(const char *buffer);
|
void apars_handle_dcs(char *buffer);
|
||||||
|
|
||||||
#endif //ESP_VT100_FIRMWARE_APARS_DCS_H
|
#endif //ESP_VT100_FIRMWARE_APARS_DCS_H
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/08/20.
|
||||||
|
//
|
||||||
|
// Handle privacy messages
|
||||||
|
// PM Pt ST
|
||||||
|
// (PM = ESC ^)
|
||||||
|
//
|
||||||
|
// Those are used for device-to-device communication.
|
||||||
|
// They were not used for anything in the original VT100 and are not
|
||||||
|
// used by Xterm or any other common emulator, but they should be safely discarded.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <esp8266.h>
|
||||||
|
#include <httpclient.h>
|
||||||
|
#include "apars_pm.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "ansi_parser_callbacks.h"
|
||||||
|
#include "screen.h"
|
||||||
|
#include "apars_logging.h"
|
||||||
|
#include "cgi_d2d.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to parse incoming DCS (Device Control String)
|
||||||
|
* @param msg - the DCS body (after DCS and before ST)
|
||||||
|
*/
|
||||||
|
void ICACHE_FLASH_ATTR
|
||||||
|
apars_handle_pm(char *msg)
|
||||||
|
{
|
||||||
|
if (d2d_parse_command(msg)) return;
|
||||||
|
|
||||||
|
return;
|
||||||
|
fail:
|
||||||
|
ansi_warn("D2D message error: %s", msg);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/08/20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESP_VT100_FIRMWARE_APARS_PM_H
|
||||||
|
#define ESP_VT100_FIRMWARE_APARS_PM_H
|
||||||
|
|
||||||
|
void apars_handle_pm(char *msg);
|
||||||
|
|
||||||
|
#endif //ESP_VT100_FIRMWARE_APARS_PM_H
|
||||||
@@ -42,9 +42,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <esp8266.h>
|
#include <esp8266.h>
|
||||||
|
#include <httpclient.h>
|
||||||
#include "apars_short.h"
|
#include "apars_short.h"
|
||||||
#include "apars_logging.h"
|
#include "apars_logging.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
#include "ansi_parser_callbacks.h"
|
||||||
|
|
||||||
// ----- Character Set ---
|
// ----- Character Set ---
|
||||||
|
|
||||||
@@ -103,6 +105,11 @@ void ICACHE_FLASH_ATTR apars_handle_hash_cmd(char c)
|
|||||||
screen_fill_with_E();
|
screen_fill_with_E();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// development codes - do not use!
|
||||||
|
case '7':
|
||||||
|
http_get("http://wtfismyip.com/text", NULL, http_callback_example);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ansi_noimpl("ESC # %c", c);
|
ansi_noimpl("ESC # %c", c);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -17,6 +17,7 @@
|
|||||||
#include "apars_logging.h"
|
#include "apars_logging.h"
|
||||||
#include "ansi_parser_callbacks.h"
|
#include "ansi_parser_callbacks.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
#include "apars_pm.h"
|
||||||
|
|
||||||
// ----- Generic String cmd - disambiguation -----
|
// ----- Generic String cmd - disambiguation -----
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ void ICACHE_FLASH_ATTR
|
|||||||
apars_handle_string_cmd(char leadchar, char *buffer)
|
apars_handle_string_cmd(char leadchar, char *buffer)
|
||||||
{
|
{
|
||||||
switch (leadchar) {
|
switch (leadchar) {
|
||||||
case 'k': // ESC k TITLE ST (defined in GNU screen manpage)
|
case 'k': // ESC k TITLE ST (defined in GNU screen manpage, probably not standard)
|
||||||
screen_set_title(buffer);
|
screen_set_title(buffer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ apars_handle_string_cmd(char leadchar, char *buffer)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '^': // PM - Privacy Message
|
case '^': // PM - Privacy Message
|
||||||
|
apars_handle_pm(buffer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '_': // APC - Application Program Command
|
case '_': // APC - Application Program Command
|
||||||
|
|||||||
+166
-26
@@ -8,9 +8,13 @@
|
|||||||
#include "apars_utf8.h"
|
#include "apars_utf8.h"
|
||||||
#include "apars_logging.h"
|
#include "apars_logging.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
#include "uart_driver.h"
|
||||||
|
#include "ansi_parser_callbacks.h"
|
||||||
|
#include "ansi_parser.h"
|
||||||
|
#include "ascii.h"
|
||||||
|
|
||||||
static char utf_collect[4];
|
static u8 bytes[4];
|
||||||
static int utf_i = 0;
|
static int utf_len = 0;
|
||||||
static int utf_j = 0;
|
static int utf_j = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,11 +24,121 @@ static int utf_j = 0;
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
apars_reset_utf8buffer(void)
|
apars_reset_utf8buffer(void)
|
||||||
{
|
{
|
||||||
utf_i = 0;
|
utf_len = 0;
|
||||||
utf_j = 0;
|
utf_j = 0;
|
||||||
memset(utf_collect, 0, 4);
|
memset(bytes, 0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Code Points First Byte Second Byte Third Byte Fourth Byte
|
||||||
|
// U+0000 - U+007F 00 - 7F
|
||||||
|
// U+0080 - U+07FF C2 - DF 80 - BF
|
||||||
|
// U+0800 - U+0FFF E0 *A0 - BF 80 - BF
|
||||||
|
// U+1000 - U+CFFF E1 - EC 80 - BF 80 - BF
|
||||||
|
// U+D000 - U+D7FF ED 80 - *9F 80 - BF
|
||||||
|
// U+E000 - U+FFFF EE - EF 80 - BF 80 - BF
|
||||||
|
// U+10000 - U+3FFFF F0 *90 - BF 80 - BF 80 - BF
|
||||||
|
// U+40000 - U+FFFFF F1 - F3 80 - BF 80 - BF 80 - BF
|
||||||
|
// U+100000 - U+10FFFF F4 80 - *8F 80 - BF 80 - BF
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR screen_print_ascii(const char *str)
|
||||||
|
{
|
||||||
|
char gly[2];
|
||||||
|
gly[1] = 0;
|
||||||
|
for(int j = 0;str[j]!=0;j++) {
|
||||||
|
gly[0] = str[j];
|
||||||
|
screen_putchar(gly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR hdump_spaces_eol(int needed)
|
||||||
|
{
|
||||||
|
if (needed == 0) needed = 5;
|
||||||
|
int x, y;
|
||||||
|
screen_cursor_get(&y, &x);
|
||||||
|
if (x > termconf_live.width - needed) {
|
||||||
|
screen_clear_in_line(CLEAR_FROM_CURSOR);
|
||||||
|
screen_putchar("\n");
|
||||||
|
screen_putchar("\r");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR hdump_good(const char *ch)
|
||||||
|
{
|
||||||
|
char buf[10];
|
||||||
|
hdump_spaces_eol(6);
|
||||||
|
|
||||||
|
screen_set_fg(7);
|
||||||
|
screen_set_bg(0);
|
||||||
|
if(ch[0]<32) {
|
||||||
|
screen_set_fg(7);
|
||||||
|
screen_set_bg(2);
|
||||||
|
switch (ch[0]) {
|
||||||
|
case NUL: screen_print_ascii("NUL"); break;
|
||||||
|
case SOH: screen_print_ascii("SOH"); break;
|
||||||
|
case STX: screen_print_ascii("STX"); break;
|
||||||
|
case ETX: screen_print_ascii("ETX"); break;
|
||||||
|
case EOT: screen_print_ascii("EOT"); break;
|
||||||
|
case ENQ: screen_print_ascii("ENQ"); break;
|
||||||
|
case ACK: screen_print_ascii("ACK"); break;
|
||||||
|
case BEL: screen_print_ascii("BEL"); break;
|
||||||
|
case BS: screen_print_ascii("BS"); break;
|
||||||
|
case TAB: screen_print_ascii("TAB"); break;
|
||||||
|
case LF: screen_print_ascii("LF"); break;
|
||||||
|
case VT: screen_print_ascii("VT"); break;
|
||||||
|
case FF: screen_print_ascii("FF"); break;
|
||||||
|
case CR: screen_print_ascii("CR"); break;
|
||||||
|
case SO: screen_print_ascii("SO"); break;
|
||||||
|
case SI: screen_print_ascii("SI"); break;
|
||||||
|
case DLE: screen_print_ascii("DLE"); break;
|
||||||
|
case DC1: screen_print_ascii("DC1"); break;
|
||||||
|
case DC2: screen_print_ascii("DC2"); break;
|
||||||
|
case DC3: screen_print_ascii("DC3"); break;
|
||||||
|
case DC4: screen_print_ascii("DC4"); break;
|
||||||
|
case NAK: screen_print_ascii("NAK"); break;
|
||||||
|
case SYN: screen_print_ascii("SYN"); break;
|
||||||
|
case ETB: screen_print_ascii("ETB"); break;
|
||||||
|
case CAN: screen_print_ascii("CAN"); break;
|
||||||
|
case EM: screen_print_ascii("EM"); break;
|
||||||
|
case SUB: screen_print_ascii("SUB"); break;
|
||||||
|
case ESC: screen_print_ascii("ESC"); break;
|
||||||
|
case FS: screen_print_ascii("FS"); break;
|
||||||
|
case GS: screen_print_ascii("GS"); break;
|
||||||
|
case RS: screen_print_ascii("RS"); break;
|
||||||
|
case US: screen_print_ascii("US"); break;
|
||||||
|
case SP: screen_print_ascii("SP"); break;
|
||||||
|
case DEL: screen_print_ascii("DEL"); break;
|
||||||
|
default:
|
||||||
|
sprintf(buf, "%02Xh", ch[0]);
|
||||||
|
screen_print_ascii(buf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
screen_putchar(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
screen_set_default_bg();
|
||||||
|
screen_set_default_fg();
|
||||||
|
screen_print_ascii(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR hdump_bad(const char *ch, int len)
|
||||||
|
{
|
||||||
|
char buf[10];
|
||||||
|
hdump_spaces_eol(len*5);
|
||||||
|
|
||||||
|
screen_set_fg(7);
|
||||||
|
screen_set_bg(1);
|
||||||
|
for (int i=0;i<len;i++) {
|
||||||
|
sprintf(buf, "%02Xh", ch[i]);
|
||||||
|
screen_print_ascii(buf);
|
||||||
|
if(i<len-1) screen_print_ascii(" ");
|
||||||
|
}
|
||||||
|
screen_set_default_bg();
|
||||||
|
screen_set_default_fg();
|
||||||
|
screen_print_ascii(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle a received plain character
|
* Handle a received plain character
|
||||||
* @param c - received character
|
* @param c - received character
|
||||||
@@ -32,53 +146,79 @@ apars_reset_utf8buffer(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
apars_handle_plainchar(char c)
|
apars_handle_plainchar(char c)
|
||||||
{
|
{
|
||||||
|
u8 uc = (u8)c;
|
||||||
// collecting unicode glyphs...
|
// collecting unicode glyphs...
|
||||||
if (c & 0x80) {
|
if (uc & 0x80) {
|
||||||
if (utf_i == 0) {
|
if (utf_len == 0) {
|
||||||
|
bytes[0] = uc;
|
||||||
|
utf_j = 1;
|
||||||
|
|
||||||
// start
|
// start
|
||||||
if (c == 192 || c == 193 || c >= 245) {
|
if (uc == 0xC0 || uc == 0xC1 || uc > 0xF4) {
|
||||||
// forbidden codes (would be an overlong sequence)
|
// forbidden start codes
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c & 0xE0) == 0xC0) {
|
if ((uc & 0xE0) == 0xC0) {
|
||||||
utf_i = 2;
|
utf_len = 2;
|
||||||
}
|
}
|
||||||
else if ((c & 0xF0) == 0xE0) {
|
else if ((uc & 0xF0) == 0xE0) {
|
||||||
utf_i = 3;
|
utf_len = 3;
|
||||||
}
|
}
|
||||||
else if ((c & 0xF8) == 0xF0) {
|
else if ((uc & 0xF8) == 0xF0) {
|
||||||
utf_i = 4;
|
utf_len = 4;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// chars over 127 that don't start unicode sequences
|
// chars over 127 that don't start unicode sequences
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
utf_collect[0] = c;
|
|
||||||
utf_j = 1;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((c & 0xC0) != 0x80) {
|
if ((uc & 0xC0) != 0x80) {
|
||||||
|
bytes[utf_j++] = uc;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
utf_collect[utf_j++] = c;
|
bytes[utf_j++] = uc;
|
||||||
if (utf_j >= utf_i) {
|
if (utf_j >= utf_len) {
|
||||||
screen_putchar(utf_collect);
|
// check for bad sequences - overlong or some other problem
|
||||||
|
if (bytes[0] == 0xF4 && bytes[1] > 0x8F) goto fail;
|
||||||
|
if (bytes[0] == 0xF0 && bytes[1] < 0x90) goto fail;
|
||||||
|
if (bytes[0] == 0xED && bytes[1] > 0x9F) goto fail;
|
||||||
|
if (bytes[0] == 0xE0 && bytes[1] < 0xA0) goto fail;
|
||||||
|
|
||||||
|
// trap for surrogates - those break javascript
|
||||||
|
if (bytes[0] == 0xED && bytes[1] >= 0xA0 && bytes[1] <= 0xBF) goto fail;
|
||||||
|
|
||||||
|
if (termconf_live.ascii_debug) {
|
||||||
|
hdump_good((const char *) bytes);
|
||||||
|
} else {
|
||||||
|
screen_putchar((const char *) bytes);
|
||||||
|
}
|
||||||
apars_reset_utf8buffer();
|
apars_reset_utf8buffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
utf_collect[0] = c;
|
bytes[0] = uc;
|
||||||
utf_collect[1] = 0; // just to make sure it's closed...
|
bytes[1] = 0; // just to make sure it's closed...
|
||||||
screen_putchar(utf_collect);
|
if (termconf_live.ascii_debug) {
|
||||||
|
hdump_good((const char *) bytes);
|
||||||
|
} else {
|
||||||
|
screen_putchar((const char *) bytes);
|
||||||
|
}
|
||||||
|
apars_reset_utf8buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
fail:
|
fail:
|
||||||
ansi_warn("Bad UTF-8: %0Xh", c);
|
if (termconf_live.ascii_debug) {
|
||||||
|
hdump_bad((const char *) bytes, utf_j);
|
||||||
|
} else {
|
||||||
|
screen_putchar("\xEF\xBF\xBD");
|
||||||
|
}
|
||||||
|
//ansi_warn("BAD UTF8!");
|
||||||
|
//apars_show_context();
|
||||||
apars_reset_utf8buffer();
|
apars_reset_utf8buffer();
|
||||||
}
|
}
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/10/01.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESPTERM_API_H
|
||||||
|
#define ESPTERM_API_H
|
||||||
|
|
||||||
|
// TODO use X-MACRO for access restrictions etc
|
||||||
|
|
||||||
|
#define API_D2D_MSG "/api/v1/msg"
|
||||||
|
#define API_REBOOT "/api/v1/reboot"
|
||||||
|
#define API_PING "/api/v1/ping"
|
||||||
|
#define API_CLEAR "/api/v1/clear"
|
||||||
|
|
||||||
|
#endif //ESPTERM_API_H
|
||||||
+324
@@ -0,0 +1,324 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/10/01.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <esp8266.h>
|
||||||
|
#include "cgi_d2d.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "ansi_parser_callbacks.h"
|
||||||
|
#include "api.h"
|
||||||
|
#include "uart_driver.h"
|
||||||
|
#include <httpclient.h>
|
||||||
|
#include <esp_utils.h>
|
||||||
|
|
||||||
|
#define D2D_TIMEOUT_MS 2000
|
||||||
|
|
||||||
|
#define D2D_HEADERS \
|
||||||
|
"User-Agent: ESPTerm "VERSION_STRING" like curl wget HTTPie\r\n" \
|
||||||
|
"Content-Type: text/plain; charset=utf-8\r\n" \
|
||||||
|
"Accept-Encoding: identity\r\n" \
|
||||||
|
"Accept-Charset: utf-8\r\n" \
|
||||||
|
"Accept: text/*, application/json\r\n" \
|
||||||
|
"Cache-Control: no-cache,private,max-age=0\r\n"
|
||||||
|
|
||||||
|
struct d2d_request_opts {
|
||||||
|
bool want_body;
|
||||||
|
bool want_head;
|
||||||
|
size_t max_result_len;
|
||||||
|
char *nonce;
|
||||||
|
};
|
||||||
|
|
||||||
|
volatile bool request_pending = false;
|
||||||
|
|
||||||
|
// NOTE! We bypass the async buffer here - used for user input and
|
||||||
|
// responses to queries {apars_respond()}. In rare situations this could
|
||||||
|
// lead to a race condition and mixing two different messages
|
||||||
|
static inline void ICACHE_FLASH_ATTR sendResponseToUART(const char *str)
|
||||||
|
{
|
||||||
|
UART_WriteString(UART0, str, UART_TIMEOUT_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR
|
||||||
|
requestNoopCb(int http_status,
|
||||||
|
char *response_headers,
|
||||||
|
char *response_body,
|
||||||
|
size_t body_size,
|
||||||
|
void *userArg)
|
||||||
|
{
|
||||||
|
request_pending = false;
|
||||||
|
if (userArg != NULL) free(userArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR
|
||||||
|
requestCb(int http_status,
|
||||||
|
char *response_headers,
|
||||||
|
char *response_body,
|
||||||
|
size_t body_size,
|
||||||
|
void *userArg)
|
||||||
|
{
|
||||||
|
if (userArg == NULL) {
|
||||||
|
request_pending = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct d2d_request_opts *opts = userArg;
|
||||||
|
|
||||||
|
// ensure positive - would be hard to parse
|
||||||
|
if (http_status < 0) http_status = -http_status;
|
||||||
|
|
||||||
|
char buff100[100];
|
||||||
|
int len = 0;
|
||||||
|
size_t headers_size = strlen(response_headers);
|
||||||
|
|
||||||
|
if (opts->want_head) len += headers_size;
|
||||||
|
if (opts->want_body) len += body_size + (opts->want_head*2);
|
||||||
|
if (opts->max_result_len > 0 && len > opts->max_result_len)
|
||||||
|
len = (int) opts->max_result_len;
|
||||||
|
|
||||||
|
d2d_info("Rx HTTP response, code %d, len %d, nonce \"%s\"", http_status, len, opts->nonce?opts->nonce:"");
|
||||||
|
|
||||||
|
char *bb = buff100;
|
||||||
|
bb += sprintf(bb, "\x1b^h;%d;", http_status);
|
||||||
|
const char *comma = "";
|
||||||
|
|
||||||
|
if (opts->want_head) {
|
||||||
|
bb += sprintf(bb, "%sH", comma);
|
||||||
|
comma = ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts->want_body) {
|
||||||
|
bb += sprintf(bb, "%sB", comma);
|
||||||
|
comma = ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts->nonce) {
|
||||||
|
bb += sprintf(bb, "%sN=%s", comma, opts->nonce);
|
||||||
|
comma = ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts->want_head || opts->want_body) {
|
||||||
|
bb += sprintf(bb, "%sL=%d", comma, len);
|
||||||
|
//comma = ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
// semicolon only if more data is to be sent
|
||||||
|
if (opts->want_head || opts->want_body) sprintf(bb, ";");
|
||||||
|
|
||||||
|
sendResponseToUART(buff100);
|
||||||
|
|
||||||
|
//d2d_dbg("Headers (part) %100s", response_headers);
|
||||||
|
//d2d_dbg("Body (part) %100s", response_body);
|
||||||
|
|
||||||
|
// head and payload separated by \r\n\r\n (one \r\n is at the end of head - maybe)
|
||||||
|
if (opts->want_head) {
|
||||||
|
// truncate
|
||||||
|
if (headers_size > len) {
|
||||||
|
response_headers[len] = 0;
|
||||||
|
opts->want_body = false; // soz, it wouldn't fit
|
||||||
|
}
|
||||||
|
sendResponseToUART(response_headers);
|
||||||
|
if(opts->want_body) sendResponseToUART("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(opts->want_body) {
|
||||||
|
// truncate
|
||||||
|
if (opts->want_head*(headers_size+2)+body_size > len) {
|
||||||
|
response_body[len - (opts->want_head*(headers_size+2))] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponseToUART(response_body);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendResponseToUART("\a");
|
||||||
|
|
||||||
|
free(opts->nonce);
|
||||||
|
free(opts);
|
||||||
|
|
||||||
|
request_pending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ICACHE_FLASH_ATTR
|
||||||
|
d2d_parse_command(char *msg)
|
||||||
|
{
|
||||||
|
char buff40[40];
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
#define FIND_NEXT(target, delim) do { \
|
||||||
|
p = strchr(msg, (delim)); \
|
||||||
|
if (p == NULL) return false; \
|
||||||
|
*p = '\0'; \
|
||||||
|
(target) = msg; \
|
||||||
|
msg = p + 1; \
|
||||||
|
} while(0) \
|
||||||
|
|
||||||
|
if (strstarts(msg, "M;")) {
|
||||||
|
if (request_pending) return false;
|
||||||
|
|
||||||
|
// Send a esp-esp message
|
||||||
|
msg += 2;
|
||||||
|
const char *ip;
|
||||||
|
FIND_NEXT(ip, ';');
|
||||||
|
const char *payload = msg;
|
||||||
|
|
||||||
|
d2d_info("D2D Tx,dest=%s,msg=%s", ip, payload);
|
||||||
|
sprintf(buff40, "http://%s" API_D2D_MSG, ip);
|
||||||
|
|
||||||
|
httpclient_args args;
|
||||||
|
httpclient_args_init(&args);
|
||||||
|
args.method = HTTPD_METHOD_POST;
|
||||||
|
args.body = payload;
|
||||||
|
args.headers = D2D_HEADERS;
|
||||||
|
args.timeout = D2D_TIMEOUT_MS;
|
||||||
|
args.url = buff40; // "escapes scope" warning - can ignore, strdup is used
|
||||||
|
|
||||||
|
request_pending = true;
|
||||||
|
http_request(&args, requestNoopCb);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (strstarts(msg, "H;")) {
|
||||||
|
if (request_pending) return false;
|
||||||
|
|
||||||
|
// Send a esp-esp message
|
||||||
|
msg += 2;
|
||||||
|
const char *method = NULL;
|
||||||
|
const char *params = NULL;
|
||||||
|
const char *nonce = NULL;
|
||||||
|
const char *url = NULL;
|
||||||
|
const char *payload = NULL;
|
||||||
|
httpd_method methodNum;
|
||||||
|
|
||||||
|
FIND_NEXT(method, ';');
|
||||||
|
|
||||||
|
if (streq(method, "GET")) methodNum = HTTPD_METHOD_GET;
|
||||||
|
else if (streq(method, "POST")) methodNum = HTTPD_METHOD_POST;
|
||||||
|
else if (streq(method, "OPTIONS")) methodNum = HTTPD_METHOD_OPTIONS;
|
||||||
|
else if (streq(method, "PUT")) methodNum = HTTPD_METHOD_PUT;
|
||||||
|
else if (streq(method, "DELETE")) methodNum = HTTPD_METHOD_DELETE;
|
||||||
|
else if (streq(method, "PATCH")) methodNum = HTTPD_METHOD_PATCH;
|
||||||
|
else if (streq(method, "HEAD")) methodNum = HTTPD_METHOD_HEAD;
|
||||||
|
else {
|
||||||
|
d2d_warn("BAD METHOD: %s", method);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FIND_NEXT(params, ';');
|
||||||
|
|
||||||
|
d2d_info("HTTP request");
|
||||||
|
d2d_dbg("Method %s", method);
|
||||||
|
size_t max_buf_len = HTTPCLIENT_DEF_MAX_LEN;
|
||||||
|
size_t max_result_len = 0; // 0 = no truncate
|
||||||
|
uint timeout = HTTPCLIENT_DEF_TIMEOUT_MS;
|
||||||
|
bool want_body = 0;
|
||||||
|
bool want_head = 0;
|
||||||
|
bool no_resp = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
p = strchr(params, ',');
|
||||||
|
if (p != NULL) *p = '\0';
|
||||||
|
const char *param = params;
|
||||||
|
if (params[0] == 0) break; // no params
|
||||||
|
|
||||||
|
if(streq(param, "H")) want_head = 1; // Return head
|
||||||
|
else if(streq(param, "B")) want_body = 1; // Return body
|
||||||
|
else if(streq(param, "X")) no_resp = 1; // X - no response, no callback
|
||||||
|
else if(strstarts(param, "l=")) { // max buffer length
|
||||||
|
max_buf_len = (size_t) atoi(param + 2);
|
||||||
|
} else if(strstarts(param, "L=")) { // max length
|
||||||
|
max_result_len = (size_t) atoi(param + 2);
|
||||||
|
} else if(strstarts(param, "T=")) { // timeout
|
||||||
|
timeout = (uint) atoi(param + 2);
|
||||||
|
} else if(strstarts(param, "N=")) { // Nonce
|
||||||
|
nonce = param+2;
|
||||||
|
} else {
|
||||||
|
d2d_warn("BAD PARAM: %s", param);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
d2d_dbg("- param %s", params);
|
||||||
|
|
||||||
|
if (p == NULL) break;
|
||||||
|
params = p + 1;
|
||||||
|
} while(1);
|
||||||
|
|
||||||
|
p = strchr(msg, '\n');
|
||||||
|
if (p != NULL) *p = '\0';
|
||||||
|
url = msg;
|
||||||
|
d2d_dbg("URL: %s", url);
|
||||||
|
|
||||||
|
if (p != NULL) {
|
||||||
|
payload = p + 1;
|
||||||
|
d2d_dbg("Payload: %s", payload);
|
||||||
|
} else {
|
||||||
|
payload = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpclient_args args;
|
||||||
|
httpclient_args_init(&args);
|
||||||
|
args.method = methodNum;
|
||||||
|
args.body = payload;
|
||||||
|
args.headers = D2D_HEADERS;
|
||||||
|
args.timeout = timeout;
|
||||||
|
args.max_response_len = max_buf_len;
|
||||||
|
args.url = url;
|
||||||
|
|
||||||
|
if (!no_resp) {
|
||||||
|
struct d2d_request_opts *opts = malloc(sizeof(struct d2d_request_opts));
|
||||||
|
opts->want_body = want_body;
|
||||||
|
opts->want_head = want_head;
|
||||||
|
opts->max_result_len = max_result_len;
|
||||||
|
opts->nonce = esp_strdup(nonce);
|
||||||
|
args.userData = opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
request_pending = true;
|
||||||
|
http_request(&args, no_resp ? requestNoopCb : requestCb);
|
||||||
|
|
||||||
|
d2d_dbg("Request sent.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpd_cgi_state ICACHE_FLASH_ATTR cgiD2DMessage(HttpdConnData *connData)
|
||||||
|
{
|
||||||
|
if (connData->conn==NULL) {
|
||||||
|
//Connection aborted. Clean up.
|
||||||
|
return HTTPD_CGI_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = 0;
|
||||||
|
if (connData->post && connData->post->buff)
|
||||||
|
len = strlen(connData->post->buff);
|
||||||
|
else if (connData->getArgs)
|
||||||
|
len = strlen(connData->getArgs);
|
||||||
|
else
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
u8 *ip = connData->remote_ip;
|
||||||
|
char buf[20];
|
||||||
|
sprintf(buf, "\x1b^m;"IPSTR";L=%d;", ip[0], ip[1], ip[2], ip[3], (int)len);
|
||||||
|
sendResponseToUART(buf);
|
||||||
|
|
||||||
|
if (connData->post && connData->post->buff)
|
||||||
|
sendResponseToUART(connData->post->buff);
|
||||||
|
else if (connData->getArgs)
|
||||||
|
sendResponseToUART(connData->getArgs);
|
||||||
|
|
||||||
|
sendResponseToUART("\a");
|
||||||
|
|
||||||
|
d2d_info("D2D Rx src="IPSTR",len=%d", ip[0], ip[1], ip[2], ip[3],len);
|
||||||
|
|
||||||
|
// Received a msg
|
||||||
|
|
||||||
|
httdResponseOptions(connData, 0);
|
||||||
|
httdSetTransferMode(connData, HTTPD_TRANSFER_CLOSE);
|
||||||
|
|
||||||
|
httpdStartResponse(connData, 200);
|
||||||
|
httpdHeader(connData, "Content-Type", "text/plain");
|
||||||
|
httpdEndHeaders(connData);
|
||||||
|
|
||||||
|
httpdSend(connData, "message received\r\n", -1);
|
||||||
|
|
||||||
|
return HTTPD_CGI_DONE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Created by MightyPork on 2017/10/01.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ESPTERM_CGI_D2D_H
|
||||||
|
#define ESPTERM_CGI_D2D_H
|
||||||
|
|
||||||
|
#include <esp8266.h>
|
||||||
|
#include <httpd.h>
|
||||||
|
|
||||||
|
#if DEBUG_D2D
|
||||||
|
#define d2d_warn warn
|
||||||
|
#define d2d_dbg dbg
|
||||||
|
#define d2d_info info
|
||||||
|
#else
|
||||||
|
#define d2d_warn(fmt, ...)
|
||||||
|
#define d2d_dbg(fmt, ...)
|
||||||
|
#define d2d_info(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool d2d_parse_command(char *msg);
|
||||||
|
|
||||||
|
httpd_cgi_state cgiD2DMessage(HttpdConnData *connData);
|
||||||
|
|
||||||
|
#endif //ESPTERM_CGI_D2D_H
|
||||||
+8
-12
@@ -25,18 +25,14 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplScreen(HttpdConnData *connData, char *token
|
|||||||
|
|
||||||
char buff[150];
|
char buff[150];
|
||||||
|
|
||||||
if (streq(token, "labels_seq")) {
|
if (streq(token, "want_all_fn")) {
|
||||||
screenSerializeLabelsToBuffer(buff, 150);
|
|
||||||
tplSend(connData, buff, -1);
|
|
||||||
}
|
|
||||||
else if (streq(token, "theme")) {
|
|
||||||
sprintf(buff, "%d", termconf->theme);
|
|
||||||
tplSend(connData, buff, -1);
|
|
||||||
}
|
|
||||||
else if (streq(token, "want_all_fn")) {
|
|
||||||
sprintf(buff, "%d", termconf->want_all_fn);
|
sprintf(buff, "%d", termconf->want_all_fn);
|
||||||
tplSend(connData, buff, -1);
|
tplSend(connData, buff, -1);
|
||||||
}
|
}
|
||||||
|
else if (streq(token, "debugbar")) {
|
||||||
|
sprintf(buff, "%d", termconf->debugbar);
|
||||||
|
tplSend(connData, buff, -1);
|
||||||
|
}
|
||||||
|
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
@@ -48,19 +44,19 @@ tplAbout(HttpdConnData *connData, char *token, void **arg)
|
|||||||
if (token == NULL) return HTTPD_CGI_DONE;
|
if (token == NULL) return HTTPD_CGI_DONE;
|
||||||
|
|
||||||
if (streq(token, "vers_fw")) {
|
if (streq(token, "vers_fw")) {
|
||||||
tplSend(connData, FIRMWARE_VERSION, -1);
|
tplSend(connData, VERSION_STRING, -1);
|
||||||
}
|
}
|
||||||
else if (streq(token, "date")) {
|
else if (streq(token, "date")) {
|
||||||
tplSend(connData, __DATE__, -1);
|
tplSend(connData, __DATE__, -1);
|
||||||
}
|
}
|
||||||
else if (streq(token, "time")) {
|
else if (streq(token, "time")) {
|
||||||
tplSend(connData, __TIME__, -1);
|
tplSend(connData, __TIME__" "__TIMEZONE__, -1);
|
||||||
}
|
}
|
||||||
else if (streq(token, "vers_httpd")) {
|
else if (streq(token, "vers_httpd")) {
|
||||||
tplSend(connData, httpdGetVersion(), -1);
|
tplSend(connData, httpdGetVersion(), -1);
|
||||||
}
|
}
|
||||||
else if (streq(token, "vers_sdk")) {
|
else if (streq(token, "vers_sdk")) {
|
||||||
tplSend(connData, STR(ESP_SDK_VERSION), -1);
|
tplSend(connData, system_get_sdk_version(), -1);
|
||||||
}
|
}
|
||||||
else if (streq(token, "hash_backend")) {
|
else if (streq(token, "hash_backend")) {
|
||||||
tplSend(connData, GIT_HASH_BACKEND, -1);
|
tplSend(connData, GIT_HASH_BACKEND, -1);
|
||||||
|
|||||||
+15
-1
@@ -41,6 +41,11 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData)
|
|||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WiFiConfigBundle *wificonf_backup = malloc(sizeof(WiFiConfigBundle));
|
||||||
|
WiFiConfChangeFlags *wcf_backup = malloc(sizeof(WiFiConfChangeFlags));
|
||||||
|
memcpy(wificonf_backup, wificonf, sizeof(WiFiConfigBundle));
|
||||||
|
memcpy(wcf_backup, &wifi_change_flags, sizeof(WiFiConfChangeFlags));
|
||||||
|
|
||||||
// ---- AP DHCP server lease time ----
|
// ---- AP DHCP server lease time ----
|
||||||
|
|
||||||
if (GET_ARG("ap_dhcp_time")) {
|
if (GET_ARG("ap_dhcp_time")) {
|
||||||
@@ -176,6 +181,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(void) redir_url;
|
||||||
|
|
||||||
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
||||||
// All was OK
|
// All was OK
|
||||||
cgi_info("Set network params - success, applying in 1000 ms");
|
cgi_info("Set network params - success, applying in 1000 ms");
|
||||||
@@ -189,12 +196,19 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiNetworkSetParams(HttpdConnData *connData)
|
|||||||
os_timer_setfn(&timer, applyNetSettingsLaterCb, NULL);
|
os_timer_setfn(&timer, applyNetSettingsLaterCb, NULL);
|
||||||
os_timer_arm(&timer, 1000, false);
|
os_timer_arm(&timer, 1000, false);
|
||||||
|
|
||||||
httpdRedirect(connData, SET_REDIR_SUC);
|
httpdRedirect(connData, SET_REDIR_SUC "?msg=Settings%20saved%20and%20applied.");
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Some WiFi settings did not validate, asking for correction");
|
cgi_warn("Some WiFi settings did not validate, asking for correction");
|
||||||
|
|
||||||
|
memcpy(wificonf, wificonf_backup, sizeof(WiFiConfigBundle));
|
||||||
|
memcpy(&wifi_change_flags, wcf_backup, sizeof(WiFiConfChangeFlags));
|
||||||
|
|
||||||
// Some errors, appended to the URL as ?err=
|
// Some errors, appended to the URL as ?err=
|
||||||
httpdRedirect(connData, redir_url_buf);
|
httpdRedirect(connData, redir_url_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(wificonf_backup);
|
||||||
|
free(wcf_backup);
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-7
@@ -8,14 +8,12 @@ Cgi/template routines for configuring non-wifi settings
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "cgi_logging.h"
|
#include "cgi_logging.h"
|
||||||
|
|
||||||
#define SET_REDIR_SUC "/cfg/admin"
|
#define SET_REDIR_SUC "/cfg/system"
|
||||||
|
|
||||||
static bool ICACHE_FLASH_ATTR
|
static bool ICACHE_FLASH_ATTR
|
||||||
verify_admin_pw(const char *pw)
|
verify_admin_pw(const char *pw)
|
||||||
{
|
{
|
||||||
// This is not really for security, but to prevent someone who
|
return streq(pw, persist.admin.pw);
|
||||||
// shouldn't touch those settings from fucking it up.
|
|
||||||
return streq(pw, STR(ADMIN_PASSWORD)); // the PW comes from the makefile
|
|
||||||
}
|
}
|
||||||
|
|
||||||
httpd_cgi_state ICACHE_FLASH_ATTR
|
httpd_cgi_state ICACHE_FLASH_ATTR
|
||||||
@@ -36,7 +34,7 @@ cgiPersistWriteDefaults(HttpdConnData *connData)
|
|||||||
|
|
||||||
persist_set_as_default();
|
persist_set_as_default();
|
||||||
|
|
||||||
httpdRedirect(connData, SET_REDIR_SUC);
|
httpdRedirect(connData, SET_REDIR_SUC "?msg=Default%20settings%20updated.");
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
// if pw failed, show the same error as if it's wrong
|
// if pw failed, show the same error as if it's wrong
|
||||||
@@ -57,7 +55,7 @@ cgiPersistRestoreDefaults(HttpdConnData *connData)
|
|||||||
|
|
||||||
persist_restore_default();
|
persist_restore_default();
|
||||||
|
|
||||||
httpdRedirect(connData, SET_REDIR_SUC);
|
httpdRedirect(connData, SET_REDIR_SUC "?msg=All%20settings%20restored%20to%20saved%20defaults.");
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,6 +71,6 @@ cgiPersistRestoreHard(HttpdConnData *connData)
|
|||||||
// Defaults are not changed.
|
// Defaults are not changed.
|
||||||
persist_load_hard_default();
|
persist_load_hard_default();
|
||||||
|
|
||||||
httpdRedirect(connData, SET_REDIR_SUC);
|
httpdRedirect(connData, SET_REDIR_SUC "?msg=All%20settings%20restored%20to%20factory%20defaults.");
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|||||||
+118
-64
@@ -8,7 +8,6 @@
|
|||||||
#include "ansi_parser.h"
|
#include "ansi_parser.h"
|
||||||
#include "jstring.h"
|
#include "jstring.h"
|
||||||
#include "uart_driver.h"
|
#include "uart_driver.h"
|
||||||
#include "cgi_logging.h"
|
|
||||||
|
|
||||||
// Heartbeat interval in ms
|
// Heartbeat interval in ms
|
||||||
#define HB_TIME 1000
|
#define HB_TIME 1000
|
||||||
@@ -17,20 +16,29 @@
|
|||||||
// Must be less than httpd sendbuf
|
// Must be less than httpd sendbuf
|
||||||
#define SOCK_BUF_LEN 2000
|
#define SOCK_BUF_LEN 2000
|
||||||
|
|
||||||
|
volatile ScreenNotifyTopics pendingBroadcastTopics = 0;
|
||||||
|
|
||||||
|
// flags for screen update timeouts
|
||||||
volatile bool notify_available = true;
|
volatile bool notify_available = true;
|
||||||
volatile bool notify_cooldown = false;
|
volatile bool notify_cooldown = false;
|
||||||
|
volatile bool notify_scheduled = false;
|
||||||
|
|
||||||
|
/** True if we sent XOFF to browser to stop uploading,
|
||||||
|
* and we have to tell it we're ready again */
|
||||||
volatile bool browser_wants_xon = false;
|
volatile bool browser_wants_xon = false;
|
||||||
|
|
||||||
static ETSTimer notifyContentTim;
|
static ETSTimer updateNotifyTim;
|
||||||
static ETSTimer notifyLabelsTim;
|
|
||||||
static ETSTimer notifyCooldownTim;
|
static ETSTimer notifyCooldownTim;
|
||||||
static ETSTimer heartbeatTim;
|
static ETSTimer heartbeatTim;
|
||||||
|
|
||||||
|
volatile int term_active_clients = 0;
|
||||||
|
|
||||||
// we're trying to do a kind of mutex here, without the actual primitives
|
// we're trying to do a kind of mutex here, without the actual primitives
|
||||||
// this might glitch, very rarely.
|
// this might glitch, very rarely.
|
||||||
// it's recommended to put some delay between setting labels and updating the screen.
|
// it's recommended to put some delay between setting labels and updating the screen.
|
||||||
|
|
||||||
|
static void resetHeartbeatTimer(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cooldown delay is over
|
* Cooldown delay is over
|
||||||
* @param arg
|
* @param arg
|
||||||
@@ -46,31 +54,29 @@ notifyCooldownTimCb(void *arg)
|
|||||||
* @param arg
|
* @param arg
|
||||||
*/
|
*/
|
||||||
static void ICACHE_FLASH_ATTR
|
static void ICACHE_FLASH_ATTR
|
||||||
notifyContentTimCb(void *arg)
|
updateNotify_do(Websock *ws, ScreenNotifyTopics topics)
|
||||||
{
|
{
|
||||||
Websock *ws = arg;
|
|
||||||
void *data = NULL;
|
void *data = NULL;
|
||||||
int max_bl, total_bl;
|
|
||||||
char sock_buff[SOCK_BUF_LEN];
|
char sock_buff[SOCK_BUF_LEN];
|
||||||
|
|
||||||
cgiWebsockMeasureBacklog(URL_WS_UPDATE, &max_bl, &total_bl);
|
|
||||||
|
|
||||||
if (!notify_available || notify_cooldown || (max_bl > 2048)) { // do not send if we have anything significant backlogged
|
|
||||||
// postpone a little
|
|
||||||
TIMER_START(¬ifyContentTim, notifyContentTimCb, 5, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
notify_available = false;
|
notify_available = false;
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
httpd_cgi_state cont = screenSerializeToBuffer(sock_buff, SOCK_BUF_LEN, &data);
|
if (! ws) {
|
||||||
int flg = 0;
|
// broadcast
|
||||||
|
topics = pendingBroadcastTopics;
|
||||||
|
pendingBroadcastTopics = 0;
|
||||||
|
}
|
||||||
|
httpd_cgi_state cont = screenSerializeToBuffer(sock_buff, SOCK_BUF_LEN, topics, &data);
|
||||||
|
|
||||||
|
int flg = 0; //WEBSOCK_FLAG_BIN
|
||||||
if (cont == HTTPD_CGI_MORE) flg |= WEBSOCK_FLAG_MORE;
|
if (cont == HTTPD_CGI_MORE) flg |= WEBSOCK_FLAG_MORE;
|
||||||
if (i > 0) flg |= WEBSOCK_FLAG_CONT;
|
if (i > 0) flg |= WEBSOCK_FLAG_CONT;
|
||||||
if (ws) {
|
if (ws) {
|
||||||
cgiWebsocketSend(ws, sock_buff, (int) strlen(sock_buff), flg);
|
cgiWebsocketSend(ws, sock_buff, (int) strlen(sock_buff), flg);
|
||||||
} else {
|
} else {
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), flg);
|
cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), flg);
|
||||||
|
resetHeartbeatTimer();
|
||||||
}
|
}
|
||||||
if (cont == HTTPD_CGI_DONE) break;
|
if (cont == HTTPD_CGI_DONE) break;
|
||||||
|
|
||||||
@@ -78,45 +84,45 @@ notifyContentTimCb(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
screenSerializeToBuffer(NULL, SOCK_BUF_LEN, &data);
|
screenSerializeToBuffer(NULL, 0, 0, &data);
|
||||||
|
|
||||||
notify_cooldown = true;
|
|
||||||
notify_available = true;
|
notify_available = true;
|
||||||
|
|
||||||
TIMER_START(¬ifyCooldownTim, notifyCooldownTimCb, termconf->display_cooldown_ms, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell browsers about the new text labels
|
* Tell browser we have new content
|
||||||
* @param arg
|
* @param arg
|
||||||
*/
|
*/
|
||||||
static void ICACHE_FLASH_ATTR
|
static void ICACHE_FLASH_ATTR
|
||||||
notifyLabelsTimCb(void *arg)
|
updateNotifyCb(void *arg)
|
||||||
{
|
{
|
||||||
char sock_buff[SOCK_BUF_LEN];
|
int max_bl, total_bl;
|
||||||
|
cgiWebsockMeasureBacklog(URL_WS_UPDATE, &max_bl, &total_bl);
|
||||||
|
|
||||||
if (!notify_available || notify_cooldown) {
|
inp_dbg("Notify broadcast +%02Xh?", pendingBroadcastTopics);
|
||||||
|
|
||||||
|
if (!notify_available || notify_cooldown || (max_bl > 2048)) { // do not send if we have anything significant backlogged
|
||||||
// postpone a little
|
// postpone a little
|
||||||
TIMER_START(¬ifyLabelsTim, notifyLabelsTimCb, 1, 0);
|
TIMER_START(&updateNotifyTim, updateNotifyCb, 4, 0);
|
||||||
|
inp_dbg("postpone notify; avail? %d coold? %d maxbl? %d", notify_available, notify_cooldown, max_bl);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
notify_available = false;
|
|
||||||
|
|
||||||
screenSerializeLabelsToBuffer(sock_buff, SOCK_BUF_LEN);
|
updateNotify_do(arg, 0);
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), 0);
|
|
||||||
|
|
||||||
|
notify_scheduled = false;
|
||||||
notify_cooldown = true;
|
notify_cooldown = true;
|
||||||
notify_available = true;
|
|
||||||
|
|
||||||
TIMER_START(¬ifyCooldownTim, notifyCooldownTimCb, termconf->display_cooldown_ms, 0);
|
TIMER_START(¬ifyCooldownTim, notifyCooldownTimCb, termconf->display_cooldown_ms, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Beep */
|
/** Beep */
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
send_beep(void)
|
send_beep(void)
|
||||||
{
|
{
|
||||||
// here's some potential for a race error with the other broadcast functions :C
|
if (term_active_clients == 0) return;
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, "B", 1, 0);
|
screen_notifyChange(TOPIC_BELL); // XXX has latency, maybe better to send directly
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -124,9 +130,12 @@ send_beep(void)
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
notify_growl(char *msg)
|
notify_growl(char *msg)
|
||||||
{
|
{
|
||||||
// TODO via timer...
|
if (term_active_clients == 0) return;
|
||||||
// here's some potential for a race error with the other broadcast functions :C
|
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, msg, (int) strlen(msg), 0);
|
// here's some potential for a race error with the other broadcast functions
|
||||||
|
// - we assume app won't send notifications in the middle of updating content
|
||||||
|
cgiWebsockBroadcast(URL_WS_UPDATE, msg, (int) strlen(msg), WEBSOCK_FLAG_BIN);
|
||||||
|
resetHeartbeatTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -135,22 +144,20 @@ notify_growl(char *msg)
|
|||||||
* This is a callback for the Screen module,
|
* This is a callback for the Screen module,
|
||||||
* called after each visible screen modification.
|
* called after each visible screen modification.
|
||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR screen_notifyChange(ScreenNotifyChangeTopic topic)
|
void ICACHE_FLASH_ATTR screen_notifyChange(ScreenNotifyTopics topics)
|
||||||
{
|
{
|
||||||
// this is not the most ideal/cleanest implementation
|
if (term_active_clients == 0) return;
|
||||||
// PRs are welcome for a nicer update "queue" solution
|
|
||||||
if (termconf->display_tout_ms == 0) termconf->display_tout_ms = SCR_DEF_DISPLAY_TOUT_MS;
|
|
||||||
|
|
||||||
// NOTE: the timers are restarted if already running
|
inp_dbg("Notify +%02Xh", topics);
|
||||||
|
|
||||||
if (topic == CHANGE_LABELS) {
|
pendingBroadcastTopics |= topics;
|
||||||
// separate timer from content change timer, to avoid losing that update
|
|
||||||
TIMER_START(¬ifyLabelsTim, notifyLabelsTimCb, termconf->display_tout_ms, 0);
|
int time = termconf->display_tout_ms;
|
||||||
}
|
if (time == 0 && notify_scheduled) return; // do not reset the timer if already scheduled
|
||||||
else if (topic == CHANGE_CONTENT) {
|
|
||||||
// throttle delay
|
notify_scheduled = true;
|
||||||
TIMER_START(¬ifyContentTim, notifyContentTimCb, termconf->display_tout_ms, 0);
|
// NOTE: the timer is restarted if already running
|
||||||
}
|
TIMER_START(&updateNotifyTim, updateNotifyCb, time, 0); // note - this adds latency to beep
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -161,7 +168,7 @@ void ICACHE_FLASH_ATTR screen_notifyChange(ScreenNotifyChangeTopic topic)
|
|||||||
* @param button - which button, 1-based. 0=none
|
* @param button - which button, 1-based. 0=none
|
||||||
* @param mods - modifier keys bitmap: meta|alt|shift|ctrl
|
* @param mods - modifier keys bitmap: meta|alt|shift|ctrl
|
||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR sendMouseAction(char evt, int y, int x, int button, u8 mods)
|
static void ICACHE_FLASH_ATTR sendMouseAction(char evt, int y, int x, int button, u8 mods)
|
||||||
{
|
{
|
||||||
// one-based
|
// one-based
|
||||||
x++;
|
x++;
|
||||||
@@ -223,19 +230,19 @@ void ICACHE_FLASH_ATTR sendMouseAction(char evt, int y, int x, int button, u8 mo
|
|||||||
sprintf(buf, "\x1b[<%d;%d;%d%c", eventcode, x, y, (evt == 'p'||(evt=='m'&&button>0)) ? 'M' : 'm');
|
sprintf(buf, "\x1b[<%d;%d;%d%c", eventcode, x, y, (evt == 'p'||(evt=='m'&&button>0)) ? 'M' : 'm');
|
||||||
}
|
}
|
||||||
else if (mte == MTE_URXVT) {
|
else if (mte == MTE_URXVT) {
|
||||||
sprintf(buf, "\x1b[%d;%d;%dM", (u8)(32+eventcode), (u8)(32+x), (u8)(32+y));
|
sprintf(buf, "\x1b[%d;%d;%dM", (u8)(32+eventcode), (u8)(x), (u8)(y));
|
||||||
}
|
}
|
||||||
|
|
||||||
UART_SendAsync(buf, -1);
|
UART_SendAsync(buf, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Socket received a message */
|
/** Socket received a message */
|
||||||
void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags)
|
static void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags)
|
||||||
{
|
{
|
||||||
// Add terminator if missing (seems to randomly happen)
|
// Add terminator if missing (seems to randomly happen)
|
||||||
data[len] = 0;
|
data[len] = 0;
|
||||||
|
|
||||||
ws_dbg("Sock RX str: %s, len %d", data, len);
|
inp_dbg("Sock RX str: %s, len %d", data, len);
|
||||||
|
|
||||||
int y, x, m, b;
|
int y, x, m, b;
|
||||||
u8 btnNum;
|
u8 btnNum;
|
||||||
@@ -253,7 +260,7 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags)
|
|||||||
|
|
||||||
// TODO base this on the actual buffer empty space, not rx chunk size
|
// TODO base this on the actual buffer empty space, not rx chunk size
|
||||||
if ((UART_AsyncTxGetEmptySpace() < 256) && !browser_wants_xon) {
|
if ((UART_AsyncTxGetEmptySpace() < 256) && !browser_wants_xon) {
|
||||||
UART_WriteChar(UART1, '-', 100);
|
//UART_WriteChar(UART1, '-', 100);
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, "-", 1, 0);
|
cgiWebsockBroadcast(URL_WS_UPDATE, "-", 1, 0);
|
||||||
browser_wants_xon = true;
|
browser_wants_xon = true;
|
||||||
|
|
||||||
@@ -271,8 +278,8 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags)
|
|||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
// requests initial load
|
// requests initial load
|
||||||
ws_dbg("Client requests initial load");
|
inp_dbg("Client requests initial load");
|
||||||
notifyContentTimCb(ws);
|
updateNotify_do(ws, TOPIC_INITIAL|TOPIC_FLAG_NOCLEAN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
@@ -290,39 +297,86 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ws_warn("Bad command.");
|
inp_warn("Bad command.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Send a heartbeat msg */
|
/** Send a heartbeat msg */
|
||||||
void ICACHE_FLASH_ATTR heartbeatTimCb(void *unused)
|
static void ICACHE_FLASH_ATTR heartbeatTimCb(void *unused)
|
||||||
{
|
{
|
||||||
if (notify_available) {
|
static u32 hbcnt=0;
|
||||||
// Heartbeat packet - indicate we're still connected
|
|
||||||
// JS reloads the page if heartbeat is lost for a couple seconds
|
if (term_active_clients > 0) {
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, ".", 1, 0);
|
if (notify_available) {
|
||||||
|
inp_dbg(".");
|
||||||
|
|
||||||
|
// Heartbeat packet - indicate we're still connected
|
||||||
|
// JS reloads the page if heartbeat is lost for a couple seconds
|
||||||
|
char buf[10];
|
||||||
|
sprintf(buf, ".%d", hbcnt++);
|
||||||
|
cgiWebsockBroadcast(URL_WS_UPDATE, buf, (int) strlen(buf), 0);
|
||||||
|
|
||||||
|
// schedule next tick
|
||||||
|
TIMER_START(&heartbeatTim, heartbeatTimCb, HB_TIME, 0);
|
||||||
|
} else {
|
||||||
|
// postpone...
|
||||||
|
TIMER_START(&heartbeatTim, heartbeatTimCb, 10, 0);
|
||||||
|
inp_dbg("postpone heartbeat");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR resetHeartbeatTimer(void)
|
||||||
|
{
|
||||||
|
TIMER_START(&heartbeatTim, heartbeatTimCb, HB_TIME, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR closeSockCb(Websock *ws)
|
||||||
|
{
|
||||||
|
term_active_clients--;
|
||||||
|
inp_dbg("Close socket CB, remain %d clients", term_active_clients);
|
||||||
|
if (term_active_clients <= 0) {
|
||||||
|
term_active_clients = 0;
|
||||||
|
|
||||||
|
if (mouse_tracking.focus_tracking) {
|
||||||
|
UART_SendAsync("\x1b[O", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop the timer
|
||||||
|
os_timer_disarm(&heartbeatTim);
|
||||||
|
inp_dbg("Stop HB timer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Socket connected for updates */
|
/** Socket connected for updates */
|
||||||
void ICACHE_FLASH_ATTR updateSockConnect(Websock *ws)
|
void ICACHE_FLASH_ATTR updateSockConnect(Websock *ws)
|
||||||
{
|
{
|
||||||
ws_info("Socket connected to "URL_WS_UPDATE);
|
inp_info("Socket connected to "URL_WS_UPDATE);
|
||||||
ws->recvCb = updateSockRx;
|
ws->recvCb = updateSockRx;
|
||||||
|
ws->closeCb = closeSockCb;
|
||||||
|
|
||||||
TIMER_START(&heartbeatTim, heartbeatTimCb, HB_TIME, 1);
|
if (term_active_clients == 0) {
|
||||||
|
if (mouse_tracking.focus_tracking) {
|
||||||
|
UART_SendAsync("\x1b[I", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetHeartbeatTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
term_active_clients++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ETSTimer xonTim;
|
ETSTimer xonTim;
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR notify_empty_txbuf_cb(void *unused)
|
static void ICACHE_FLASH_ATTR notify_empty_txbuf_cb(void *unused)
|
||||||
{
|
{
|
||||||
UART_WriteChar(UART1, '+', 100);
|
//UART_WriteChar(UART1, '+', 100);
|
||||||
cgiWebsockBroadcast(URL_WS_UPDATE, "+", 1, 0);
|
cgiWebsockBroadcast(URL_WS_UPDATE, "+", 1, 0);
|
||||||
|
resetHeartbeatTimer();
|
||||||
browser_wants_xon = false;
|
browser_wants_xon = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void notify_empty_txbuf(void)
|
void notify_empty_txbuf(void)
|
||||||
{
|
{
|
||||||
if (browser_wants_xon) {
|
if (browser_wants_xon) {
|
||||||
|
|||||||
+8
-6
@@ -15,15 +15,17 @@ void send_beep(void);
|
|||||||
/** open pop-up notification */
|
/** open pop-up notification */
|
||||||
void notify_growl(char *msg);
|
void notify_growl(char *msg);
|
||||||
|
|
||||||
|
extern volatile int term_active_clients;
|
||||||
|
|
||||||
// defined in the makefile
|
// defined in the makefile
|
||||||
#if DEBUG_INPUT
|
#if DEBUG_INPUT
|
||||||
#define ws_warn warn
|
#define inp_warn warn
|
||||||
#define ws_dbg dbg
|
#define inp_dbg dbg
|
||||||
#define ws_info info
|
#define inp_info info
|
||||||
#else
|
#else
|
||||||
#define ws_warn(...)
|
#define inp_warn(...)
|
||||||
#define ws_dbg(...)
|
#define inp_dbg(...)
|
||||||
#define ws_info(...)
|
#define inp_info(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //CGI_SOCKETS_H
|
#endif //CGI_SOCKETS_H
|
||||||
|
|||||||
+132
-55
@@ -6,7 +6,6 @@
|
|||||||
#include "cgi_system.h"
|
#include "cgi_system.h"
|
||||||
#include "persist.h"
|
#include "persist.h"
|
||||||
#include "syscfg.h"
|
#include "syscfg.h"
|
||||||
#include "uart_driver.h"
|
|
||||||
#include "ansi_parser.h"
|
#include "ansi_parser.h"
|
||||||
#include "cgi_logging.h"
|
#include "cgi_logging.h"
|
||||||
|
|
||||||
@@ -51,7 +50,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiResetDevice(HttpdConnData *connData)
|
|||||||
os_timer_setfn(&tmr, tmrCb, NULL);
|
os_timer_setfn(&tmr, tmrCb, NULL);
|
||||||
os_timer_arm(&tmr, 100, false);
|
os_timer_arm(&tmr, 100, false);
|
||||||
|
|
||||||
httpdSend(connData, "system reset\n", -1);
|
httpdSend(connData, "system reset\r\n", -1);
|
||||||
|
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
@@ -67,7 +66,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiPing(HttpdConnData *connData)
|
|||||||
httpdHeader(connData, "Content-Type", "text/plain");
|
httpdHeader(connData, "Content-Type", "text/plain");
|
||||||
httpdEndHeaders(connData);
|
httpdEndHeaders(connData);
|
||||||
|
|
||||||
httpdSend(connData, "pong\n", -1);
|
httpdSend(connData, "pong\r\n", -1);
|
||||||
|
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
@@ -78,7 +77,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiPing(HttpdConnData *connData)
|
|||||||
httpd_cgi_state ICACHE_FLASH_ATTR
|
httpd_cgi_state ICACHE_FLASH_ATTR
|
||||||
cgiSystemCfgSetParams(HttpdConnData *connData)
|
cgiSystemCfgSetParams(HttpdConnData *connData)
|
||||||
{
|
{
|
||||||
char buff[50];
|
char buff[65];
|
||||||
|
char buff2[65];
|
||||||
char redir_url_buf[100];
|
char redir_url_buf[100];
|
||||||
|
|
||||||
char *redir_url = redir_url_buf;
|
char *redir_url = redir_url_buf;
|
||||||
@@ -90,53 +90,113 @@ cgiSystemCfgSetParams(HttpdConnData *connData)
|
|||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("uart_baud")) {
|
AdminConfigBlock *admin_backup = malloc(sizeof(AdminConfigBlock));
|
||||||
cgi_dbg("Baud rate: %s", buff);
|
SystemConfigBundle *sysconf_backup = malloc(sizeof(SystemConfigBundle));
|
||||||
int baud = atoi(buff);
|
memcpy(admin_backup, &persist.admin, sizeof(AdminConfigBlock));
|
||||||
if (baud == BIT_RATE_300 ||
|
memcpy(sysconf_backup, sysconf, sizeof(SystemConfigBundle));
|
||||||
baud == BIT_RATE_600 ||
|
|
||||||
baud == BIT_RATE_1200 ||
|
do {
|
||||||
baud == BIT_RATE_2400 ||
|
if (!GET_ARG("pw")) {
|
||||||
baud == BIT_RATE_4800 ||
|
break; // if no PW in GET, not trying to configure anything protected
|
||||||
baud == BIT_RATE_9600 ||
|
}
|
||||||
baud == BIT_RATE_19200 ||
|
|
||||||
baud == BIT_RATE_38400 ||
|
if (!streq(buff, persist.admin.pw)) {
|
||||||
baud == BIT_RATE_57600 ||
|
warn("Bad admin pw!");
|
||||||
baud == BIT_RATE_74880 ||
|
redir_url += sprintf(redir_url, "pw,");
|
||||||
baud == BIT_RATE_115200 ||
|
break;
|
||||||
baud == BIT_RATE_230400 ||
|
}
|
||||||
baud == BIT_RATE_460800 ||
|
|
||||||
baud == BIT_RATE_921600 ||
|
// authenticated OK
|
||||||
baud == BIT_RATE_1843200 ||
|
if (GET_ARG("pwlock")) {
|
||||||
baud == BIT_RATE_3686400) {
|
cgi_dbg("pwlock: %s", buff);
|
||||||
sysconf->uart_baudrate = (u32) baud;
|
int pwlock = atoi(buff);
|
||||||
} else {
|
if (pwlock < 0 || pwlock >= PWLOCK_MAX) {
|
||||||
cgi_warn("Bad baud rate %s", buff);
|
cgi_warn("Bad pwlock %s", buff);
|
||||||
redir_url += sprintf(redir_url, "uart_baud,");
|
redir_url += sprintf(redir_url, "pwlock,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysconf->pwlock = (enum pwlock) pwlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("access_pw")) {
|
||||||
|
cgi_dbg("access_pw: %s", buff);
|
||||||
|
|
||||||
|
if (strlen(buff)) {
|
||||||
|
strcpy(buff2, buff);
|
||||||
|
if (!GET_ARG("access_pw2")) {
|
||||||
|
cgi_warn("Missing repeated access_pw %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "access_pw2,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!streq(buff, buff2)) {
|
||||||
|
cgi_warn("Bad repeated access_pw %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "access_pw2,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(buff) >= 64) {
|
||||||
|
cgi_warn("Too long access_pw %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "access_pw,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cgi_dbg("Changing access PW!");
|
||||||
|
strncpy(sysconf->access_pw, buff, 64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("access_name")) {
|
||||||
|
cgi_dbg("access_name: %s", buff);
|
||||||
|
|
||||||
|
if (!strlen(buff) || strlen(buff) >= 32) {
|
||||||
|
cgi_warn("Too long access_name %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "access_name,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(sysconf->access_name, buff, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("admin_pw")) {
|
||||||
|
cgi_dbg("admin_pw: %s", buff);
|
||||||
|
|
||||||
|
if (strlen(buff)) {
|
||||||
|
strcpy(buff2, buff);
|
||||||
|
if (!GET_ARG("admin_pw2")) {
|
||||||
|
cgi_warn("Missing repeated admin_pw %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "admin_pw2,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!streq(buff, buff2)) {
|
||||||
|
cgi_warn("Bad repeated admin_pw %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "admin_pw2,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(buff) >= 64) {
|
||||||
|
cgi_warn("Too long admin_pw %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "admin_pw,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cgi_dbg("Changing admin PW!");
|
||||||
|
strncpy(persist.admin.pw, buff, 64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
if (GET_ARG("overclock")) {
|
||||||
|
cgi_dbg("overclock = %s", buff);
|
||||||
|
int enable = atoi(buff);
|
||||||
|
if (sysconf->overclock != enable) {
|
||||||
|
sysconf->overclock = (bool)enable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("uart_parity")) {
|
(void)redir_url;
|
||||||
cgi_dbg("Parity: %s", buff);
|
|
||||||
int parity = atoi(buff);
|
|
||||||
if (parity >= 0 && parity <= 2) {
|
|
||||||
sysconf->uart_parity = (UartParityMode) parity;
|
|
||||||
} else {
|
|
||||||
cgi_warn("Bad parity %s", buff);
|
|
||||||
redir_url += sprintf(redir_url, "uart_parity,");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GET_ARG("uart_stopbits")) {
|
|
||||||
cgi_dbg("Stop bits: %s", buff);
|
|
||||||
int stopbits = atoi(buff);
|
|
||||||
if (stopbits >= 1 && stopbits <= 3) {
|
|
||||||
sysconf->uart_stopbits = (UartStopBitsNum) stopbits;
|
|
||||||
} else {
|
|
||||||
cgi_warn("Bad stopbits %s", buff);
|
|
||||||
redir_url += sprintf(redir_url, "uart_stopbits,");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
||||||
// All was OK
|
// All was OK
|
||||||
@@ -145,12 +205,20 @@ cgiSystemCfgSetParams(HttpdConnData *connData)
|
|||||||
sysconf_apply_settings();
|
sysconf_apply_settings();
|
||||||
persist_store();
|
persist_store();
|
||||||
|
|
||||||
httpdRedirect(connData, SET_REDIR_SUC);
|
httpdRedirect(connData, SET_REDIR_SUC "?msg=Settings%20saved%20and%20applied.");
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Some settings did not validate, asking for correction");
|
cgi_warn("Some settings did not validate, asking for correction");
|
||||||
|
|
||||||
|
// revert any possible changes
|
||||||
|
memcpy(&persist.admin, admin_backup, sizeof(AdminConfigBlock));
|
||||||
|
memcpy(sysconf, sysconf_backup, sizeof(SystemConfigBundle));
|
||||||
|
|
||||||
// Some errors, appended to the URL as ?err=
|
// Some errors, appended to the URL as ?err=
|
||||||
httpdRedirect(connData, redir_url_buf);
|
httpdRedirect(connData, redir_url_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(admin_backup);
|
||||||
|
free(sysconf_backup);
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,14 +236,23 @@ tplSystemCfg(HttpdConnData *connData, char *token, void **arg)
|
|||||||
|
|
||||||
strcpy(buff, ""); // fallback
|
strcpy(buff, ""); // fallback
|
||||||
|
|
||||||
if (streq(token, "uart_baud")) {
|
if (streq(token, "pwlock")) {
|
||||||
sprintf(buff, "%d", sysconf->uart_baudrate);
|
sprintf(buff, "%d", sysconf->pwlock);
|
||||||
}
|
}
|
||||||
else if (streq(token, "uart_parity")) {
|
else if (streq(token, "access_name")) {
|
||||||
sprintf(buff, "%d", sysconf->uart_parity);
|
sprintf(buff, "%s", sysconf->access_name);
|
||||||
}
|
}
|
||||||
else if (streq(token, "uart_stopbits")) {
|
else if (streq(token, "def_access_name")) {
|
||||||
sprintf(buff, "%d", sysconf->uart_stopbits);
|
sprintf(buff, "%s", DEF_ACCESS_NAME);
|
||||||
|
}
|
||||||
|
else if (streq(token, "def_access_pw")) {
|
||||||
|
sprintf(buff, "%s", DEF_ACCESS_PW);
|
||||||
|
}
|
||||||
|
else if (streq(token, "def_admin_pw")) {
|
||||||
|
sprintf(buff, "%s", DEFAULT_ADMIN_PW);
|
||||||
|
}
|
||||||
|
else if (streq(token, "overclock")) {
|
||||||
|
sprintf(buff, "%d", sysconf->overclock);
|
||||||
}
|
}
|
||||||
|
|
||||||
tplSend(connData, buff, -1);
|
tplSend(connData, buff, -1);
|
||||||
|
|||||||
+205
-61
@@ -9,10 +9,28 @@ Cgi/template routines for configuring non-wifi settings
|
|||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "cgi_logging.h"
|
#include "cgi_logging.h"
|
||||||
|
#include "uart_driver.h"
|
||||||
|
#include "serial.h"
|
||||||
|
|
||||||
#define SET_REDIR_SUC "/cfg/term"
|
#define SET_REDIR_SUC "/cfg/term"
|
||||||
#define SET_REDIR_ERR SET_REDIR_SUC"?err="
|
#define SET_REDIR_ERR SET_REDIR_SUC"?err="
|
||||||
|
|
||||||
|
/** convert hex number to int */
|
||||||
|
static ICACHE_FLASH_ATTR u32
|
||||||
|
decodehex(const char *buf) {
|
||||||
|
u32 n = 0;
|
||||||
|
char c;
|
||||||
|
while ((c = *buf++) != 0) {
|
||||||
|
if (c >= '0' && c <= '9') c -= '0';
|
||||||
|
else if (c >= 'a' && c <= 'f') c -= 'a'-10;
|
||||||
|
else if (c >= 'A' && c <= 'F') c -= 'A'-10;
|
||||||
|
else c = 0;
|
||||||
|
n *= 16;
|
||||||
|
n += c;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Universal CGI endpoint to set Terminal params.
|
* Universal CGI endpoint to set Terminal params.
|
||||||
*/
|
*/
|
||||||
@@ -22,14 +40,20 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
char buff[50];
|
char buff[50];
|
||||||
char redir_url_buf[100];
|
char redir_url_buf[100];
|
||||||
int32 n, w, h;
|
int32 n, w, h;
|
||||||
bool notify_screen_content = 0, notify_screen_labels = 0;
|
ScreenNotifyTopics topics = 0;
|
||||||
|
|
||||||
bool shall_clear_screen = false;
|
bool shall_clear_screen = false;
|
||||||
|
bool shall_init_uart = false;
|
||||||
|
|
||||||
char *redir_url = redir_url_buf;
|
char *redir_url = redir_url_buf;
|
||||||
redir_url += sprintf(redir_url, SET_REDIR_ERR);
|
redir_url += sprintf(redir_url, SET_REDIR_ERR);
|
||||||
// we'll test if anything was printed by looking for \0 in failed_keys_buf
|
// we'll test if anything was printed by looking for \0 in failed_keys_buf
|
||||||
|
|
||||||
|
SystemConfigBundle *sysconf_backup = malloc(sizeof(SystemConfigBundle));
|
||||||
|
TerminalConfigBundle *termconf_backup = malloc(sizeof(TerminalConfigBundle));
|
||||||
|
memcpy(sysconf_backup, sysconf, sizeof(SystemConfigBundle));
|
||||||
|
memcpy(termconf_backup, termconf, sizeof(TerminalConfigBundle));
|
||||||
|
|
||||||
if (connData->conn == NULL) {
|
if (connData->conn == NULL) {
|
||||||
//Connection aborted. Clean up.
|
//Connection aborted. Clean up.
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
@@ -37,63 +61,76 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
|
|
||||||
// width and height must always go together so we can do max size validation
|
// width and height must always go together so we can do max size validation
|
||||||
if (GET_ARG("term_width")) {
|
if (GET_ARG("term_width")) {
|
||||||
cgi_dbg("Default screen width: %s", buff);
|
do {
|
||||||
w = atoi(buff);
|
cgi_dbg("Default screen width: %s", buff);
|
||||||
if (w > 1) {
|
w = atoi(buff);
|
||||||
if (GET_ARG("term_height")) {
|
if (w < 1) {
|
||||||
cgi_dbg("Default screen height: %s", buff);
|
cgi_warn("Bad width: \"%s\"", buff);
|
||||||
h = atoi(buff);
|
redir_url += sprintf(redir_url, "term_width,");
|
||||||
if (h > 1) {
|
break;
|
||||||
if (w * h <= MAX_SCREEN_SIZE) {
|
}
|
||||||
if (termconf->width != w || termconf->height != h) {
|
|
||||||
termconf->width = w;
|
if (!GET_ARG("term_height")) {
|
||||||
termconf->height = h;
|
|
||||||
shall_clear_screen = true; // this causes a notify
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cgi_warn("Bad dimensions: %d x %d (total %d)", w, h, w*h);
|
|
||||||
redir_url += sprintf(redir_url, "term_width,term_height,");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cgi_warn("Bad height: \"%s\"", buff);
|
|
||||||
redir_url += sprintf(redir_url, "term_width,");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cgi_warn("Missing height arg!");
|
cgi_warn("Missing height arg!");
|
||||||
// this wont happen normally when the form is used
|
// this wont happen normally when the form is used
|
||||||
redir_url += sprintf(redir_url, "term_width,term_height,");
|
redir_url += sprintf(redir_url, "term_height,");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
cgi_warn("Bad width: \"%s\"", buff);
|
cgi_dbg("Default screen height: %s", buff);
|
||||||
redir_url += sprintf(redir_url, "term_width,");
|
h = atoi(buff);
|
||||||
}
|
if (h < 1) {
|
||||||
|
cgi_warn("Bad height: \"%s\"", buff);
|
||||||
|
redir_url += sprintf(redir_url, "term_height,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w * h > MAX_SCREEN_SIZE) {
|
||||||
|
cgi_warn("Bad dimensions: %d x %d (total %d)", w, h, w * h);
|
||||||
|
redir_url += sprintf(redir_url, "term_width,term_height,");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (termconf->width != w || termconf->height != h) {
|
||||||
|
termconf->width = w;
|
||||||
|
termconf->height = h;
|
||||||
|
shall_clear_screen = true;
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS | TOPIC_CHANGE_CONTENT_ALL;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("default_bg")) {
|
if (GET_ARG("default_bg")) {
|
||||||
cgi_dbg("Screen default BG: %s", buff);
|
cgi_dbg("Screen default BG: %s", buff);
|
||||||
n = atoi(buff);
|
|
||||||
if (n >= 0 && n < 16) {
|
if (buff[0] == '#') {
|
||||||
if (termconf->default_bg != n) {
|
// decode hex
|
||||||
termconf->default_bg = (u8) n;
|
n = decodehex(buff+1);
|
||||||
shall_clear_screen = true;
|
n += 256;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Bad color %s", buff);
|
n = atoi(buff);
|
||||||
redir_url += sprintf(redir_url, "default_bg,");
|
}
|
||||||
|
|
||||||
|
if (termconf->default_bg != n) {
|
||||||
|
termconf->default_bg = n; // this is current not sent through socket, no use to notify
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("default_fg")) {
|
if (GET_ARG("default_fg")) {
|
||||||
cgi_dbg("Screen default FG: %s", buff);
|
cgi_dbg("Screen default FG: %s", buff);
|
||||||
n = atoi(buff);
|
|
||||||
if (n >= 0 && n < 16) {
|
if (buff[0] == '#') {
|
||||||
if (termconf->default_fg != n) {
|
// decode hex
|
||||||
termconf->default_fg = (u8) n;
|
n = decodehex(buff+1);
|
||||||
shall_clear_screen = true;
|
n += 256;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Bad color %s", buff);
|
n = atoi(buff);
|
||||||
redir_url += sprintf(redir_url, "default_fg,");
|
}
|
||||||
|
|
||||||
|
if (termconf->default_fg != n) {
|
||||||
|
termconf->default_fg = n; // this is current not sent through socket, no use to notify
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +148,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
if (GET_ARG("display_tout_ms")) {
|
if (GET_ARG("display_tout_ms")) {
|
||||||
cgi_dbg("Display update idle timeout: %s ms", buff);
|
cgi_dbg("Display update idle timeout: %s ms", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
if (n > 0) {
|
if (n >= 0) {
|
||||||
termconf->display_tout_ms = n;
|
termconf->display_tout_ms = n;
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Bad update timeout %s", buff);
|
cgi_warn("Bad update timeout %s", buff);
|
||||||
@@ -134,51 +171,74 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
cgi_dbg("FN alt mode: %s", buff);
|
cgi_dbg("FN alt mode: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->fn_alt_mode = (bool)n;
|
termconf->fn_alt_mode = (bool)n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("want_all_fn")) {
|
if (GET_ARG("want_all_fn")) {
|
||||||
cgi_dbg("AllFN mode: %s", buff);
|
cgi_dbg("AllFN mode: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->want_all_fn = (bool)n;
|
termconf->want_all_fn = (bool)n;
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("crlf_mode")) {
|
if (GET_ARG("crlf_mode")) {
|
||||||
cgi_dbg("CRLF mode: %s", buff);
|
cgi_dbg("CRLF mode: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->crlf_mode = (bool)n;
|
termconf->crlf_mode = (bool)n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("show_buttons")) {
|
if (GET_ARG("show_buttons")) {
|
||||||
cgi_dbg("Show buttons: %s", buff);
|
cgi_dbg("Show buttons: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->show_buttons = (bool)n;
|
termconf->show_buttons = (bool)n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("show_config_links")) {
|
if (GET_ARG("show_config_links")) {
|
||||||
cgi_dbg("Show config links: %s", buff);
|
cgi_dbg("Show config links: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->show_config_links = (bool)n;
|
termconf->show_config_links = (bool)n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("loopback")) {
|
if (GET_ARG("loopback")) {
|
||||||
cgi_dbg("Loopback: %s", buff);
|
cgi_dbg("Loopback: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
termconf->loopback = (bool)n;
|
termconf->loopback = (bool)n;
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("debugbar")) {
|
||||||
|
cgi_dbg("Debugbar: %s", buff);
|
||||||
|
n = atoi(buff);
|
||||||
|
termconf->debugbar = (bool)n;
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("allow_decopt_12")) {
|
||||||
|
cgi_dbg("DECOPT 12: %s", buff);
|
||||||
|
n = atoi(buff);
|
||||||
|
termconf->allow_decopt_12 = (bool)n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("ascii_debug")) {
|
||||||
|
cgi_dbg("ascii_debug: %s", buff);
|
||||||
|
n = atoi(buff);
|
||||||
|
termconf->ascii_debug = (bool)n;
|
||||||
|
shall_clear_screen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GET_ARG("theme")) {
|
if (GET_ARG("theme")) {
|
||||||
cgi_dbg("Screen color theme: %s", buff);
|
cgi_dbg("Screen color theme: %s", buff);
|
||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
if (n >= 0 && n <= 5) { // ALWAYS ADJUST WHEN ADDING NEW THEME!
|
if (n >= 0) {
|
||||||
termconf->theme = (u8) n;
|
termconf->theme = (u8) n;
|
||||||
// this can't be notified, page must reload.
|
// this can't be notified, page must reload.
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Bad theme num: %s", buff);
|
cgi_warn("Bad theme num: %s", buff);
|
||||||
redir_url += sprintf(redir_url, "theme,");
|
redir_url += sprintf(redir_url, "theme,");
|
||||||
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +247,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
n = atoi(buff);
|
n = atoi(buff);
|
||||||
if (n >= 0 && n <= 6 && n != 1) {
|
if (n >= 0 && n <= 6 && n != 1) {
|
||||||
termconf->cursor_shape = (enum CursorShape) n;
|
termconf->cursor_shape = (enum CursorShape) n;
|
||||||
notify_screen_content = true;
|
topics |= TOPIC_CHANGE_SCREEN_OPTS;
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Bad cursor_shape num: %s", buff);
|
cgi_warn("Bad cursor_shape num: %s", buff);
|
||||||
redir_url += sprintf(redir_url, "cursor_shape,");
|
redir_url += sprintf(redir_url, "cursor_shape,");
|
||||||
@@ -197,7 +257,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
if (GET_ARG("term_title")) {
|
if (GET_ARG("term_title")) {
|
||||||
cgi_dbg("Terminal title default text: \"%s\"", buff);
|
cgi_dbg("Terminal title default text: \"%s\"", buff);
|
||||||
strncpy_safe(termconf->title, buff, 64); // ATTN those must match the values in
|
strncpy_safe(termconf->title, buff, 64); // ATTN those must match the values in
|
||||||
notify_screen_labels = true;
|
topics |= TOPIC_CHANGE_TITLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int btn_i = 1; btn_i <= TERM_BTN_COUNT; btn_i++) {
|
for (int btn_i = 1; btn_i <= TERM_BTN_COUNT; btn_i++) {
|
||||||
@@ -205,7 +265,7 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
if (GET_ARG(buff)) {
|
if (GET_ARG(buff)) {
|
||||||
cgi_dbg("Button%d default text: \"%s\"", btn_i, buff);
|
cgi_dbg("Button%d default text: \"%s\"", btn_i, buff);
|
||||||
strncpy_safe(termconf->btn[btn_i-1], buff, TERM_BTN_LEN);
|
strncpy_safe(termconf->btn[btn_i-1], buff, TERM_BTN_LEN);
|
||||||
notify_screen_labels = true;
|
topics |= TOPIC_CHANGE_BUTTONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(buff, "bm%d", btn_i);
|
sprintf(buff, "bm%d", btn_i);
|
||||||
@@ -265,6 +325,59 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("uart_baud")) {
|
||||||
|
cgi_dbg("Baud rate: %s", buff);
|
||||||
|
int baud = atoi(buff);
|
||||||
|
if (baud == BIT_RATE_300 ||
|
||||||
|
baud == BIT_RATE_600 ||
|
||||||
|
baud == BIT_RATE_1200 ||
|
||||||
|
baud == BIT_RATE_2400 ||
|
||||||
|
baud == BIT_RATE_4800 ||
|
||||||
|
baud == BIT_RATE_9600 ||
|
||||||
|
baud == BIT_RATE_19200 ||
|
||||||
|
baud == BIT_RATE_38400 ||
|
||||||
|
baud == BIT_RATE_57600 ||
|
||||||
|
baud == BIT_RATE_74880 ||
|
||||||
|
baud == BIT_RATE_115200 ||
|
||||||
|
baud == BIT_RATE_230400 ||
|
||||||
|
baud == BIT_RATE_460800 ||
|
||||||
|
baud == BIT_RATE_921600 ||
|
||||||
|
baud == BIT_RATE_1843200 ||
|
||||||
|
baud == BIT_RATE_3686400) {
|
||||||
|
sysconf->uart_baudrate = (u32) baud;
|
||||||
|
shall_init_uart = true;
|
||||||
|
} else {
|
||||||
|
cgi_warn("Bad baud rate %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "uart_baud,");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("uart_parity")) {
|
||||||
|
cgi_dbg("Parity: %s", buff);
|
||||||
|
int parity = atoi(buff);
|
||||||
|
if (parity >= 0 && parity <= 2) {
|
||||||
|
sysconf->uart_parity = (UartParityMode) parity;
|
||||||
|
shall_init_uart = true;
|
||||||
|
} else {
|
||||||
|
cgi_warn("Bad parity %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "uart_parity,");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GET_ARG("uart_stopbits")) {
|
||||||
|
cgi_dbg("Stop bits: %s", buff);
|
||||||
|
int stopbits = atoi(buff);
|
||||||
|
if (stopbits >= 1 && stopbits <= 3) {
|
||||||
|
sysconf->uart_stopbits = (UartStopBitsNum) stopbits;
|
||||||
|
shall_init_uart = true;
|
||||||
|
} else {
|
||||||
|
cgi_warn("Bad stopbits %s", buff);
|
||||||
|
redir_url += sprintf(redir_url, "uart_stopbits,");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)redir_url;
|
||||||
|
|
||||||
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
||||||
// All was OK
|
// All was OK
|
||||||
info("Set term params - success, saving...");
|
info("Set term params - success, saving...");
|
||||||
@@ -277,20 +390,25 @@ cgiTermCfgSetParams(HttpdConnData *connData)
|
|||||||
terminal_apply_settings_noclear();
|
terminal_apply_settings_noclear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notify_screen_content) {
|
if (shall_init_uart) {
|
||||||
screen_notifyChange(CHANGE_CONTENT);
|
serialInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notify_screen_labels) {
|
if (topics) screen_notifyChange(topics);
|
||||||
screen_notifyChange(CHANGE_LABELS);
|
|
||||||
}
|
|
||||||
|
|
||||||
httpdRedirect(connData, SET_REDIR_SUC);
|
httpdRedirect(connData, SET_REDIR_SUC "?msg=Settings%20saved%20and%20applied.");
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Some settings did not validate, asking for correction");
|
cgi_warn("Some settings did not validate, asking for correction");
|
||||||
|
|
||||||
|
memcpy(sysconf, sysconf_backup, sizeof(SystemConfigBundle));
|
||||||
|
memcpy(termconf, termconf_backup, sizeof(TerminalConfigBundle));
|
||||||
|
|
||||||
// Some errors, appended to the URL as ?err=
|
// Some errors, appended to the URL as ?err=
|
||||||
httpdRedirect(connData, redir_url_buf);
|
httpdRedirect(connData, redir_url_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(sysconf_backup);
|
||||||
|
free(termconf_backup);
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,17 +457,34 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
|
|||||||
else if (streq(token, "show_config_links")) {
|
else if (streq(token, "show_config_links")) {
|
||||||
sprintf(buff, "%d", (int)termconf->show_config_links);
|
sprintf(buff, "%d", (int)termconf->show_config_links);
|
||||||
}
|
}
|
||||||
|
else if (streq(token, "allow_decopt_12")) {
|
||||||
|
sprintf(buff, "%d", (int)termconf->allow_decopt_12);
|
||||||
|
}
|
||||||
|
else if (streq(token, "ascii_debug")) {
|
||||||
|
sprintf(buff, "%d", (int)termconf->ascii_debug);
|
||||||
|
}
|
||||||
else if (streq(token, "loopback")) {
|
else if (streq(token, "loopback")) {
|
||||||
sprintf(buff, "%d", (int)termconf->loopback);
|
sprintf(buff, "%d", (int)termconf->loopback);
|
||||||
}
|
}
|
||||||
|
else if (streq(token, "debugbar")) {
|
||||||
|
sprintf(buff, "%d", (int)termconf->debugbar);
|
||||||
|
}
|
||||||
else if (streq(token, "theme")) {
|
else if (streq(token, "theme")) {
|
||||||
sprintf(buff, "%d", termconf->theme);
|
sprintf(buff, "%d", termconf->theme);
|
||||||
}
|
}
|
||||||
else if (streq(token, "default_bg")) {
|
else if (streq(token, "default_bg")) {
|
||||||
sprintf(buff, "%d", termconf->default_bg);
|
if (termconf->default_bg < 256) {
|
||||||
|
sprintf(buff, "%d", termconf->default_bg);
|
||||||
|
} else {
|
||||||
|
sprintf(buff, "#%06X", termconf->default_bg - 256);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (streq(token, "default_fg")) {
|
else if (streq(token, "default_fg")) {
|
||||||
sprintf(buff, "%d", termconf->default_fg);
|
if (termconf->default_fg < 256) {
|
||||||
|
sprintf(buff, "%d", termconf->default_fg);
|
||||||
|
} else {
|
||||||
|
sprintf(buff, "#%06X", termconf->default_fg - 256);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (streq(token, "cursor_shape")) {
|
else if (streq(token, "cursor_shape")) {
|
||||||
sprintf(buff, "%d", termconf->cursor_shape);
|
sprintf(buff, "%d", termconf->cursor_shape);
|
||||||
@@ -357,6 +492,15 @@ tplTermCfg(HttpdConnData *connData, char *token, void **arg)
|
|||||||
else if (streq(token, "term_title")) {
|
else if (streq(token, "term_title")) {
|
||||||
strncpy_safe(buff, termconf->title, BUFLEN);
|
strncpy_safe(buff, termconf->title, BUFLEN);
|
||||||
}
|
}
|
||||||
|
else if (streq(token, "uart_baud")) {
|
||||||
|
sprintf(buff, "%d", sysconf->uart_baudrate);
|
||||||
|
}
|
||||||
|
else if (streq(token, "uart_parity")) {
|
||||||
|
sprintf(buff, "%d", sysconf->uart_parity);
|
||||||
|
}
|
||||||
|
else if (streq(token, "uart_stopbits")) {
|
||||||
|
sprintf(buff, "%d", sysconf->uart_stopbits);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
for (int btn_i = 1; btn_i <= TERM_BTN_COUNT; btn_i++) {
|
for (int btn_i = 1; btn_i <= TERM_BTN_COUNT; btn_i++) {
|
||||||
sprintf(buff2, "btn%d", btn_i);
|
sprintf(buff2, "btn%d", btn_i);
|
||||||
|
|||||||
+16
-17
@@ -355,6 +355,11 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData)
|
|||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WiFiConfigBundle *wificonf_backup = malloc(sizeof(WiFiConfigBundle));
|
||||||
|
WiFiConfChangeFlags *wcf_backup = malloc(sizeof(WiFiConfChangeFlags));
|
||||||
|
memcpy(wificonf_backup, wificonf, sizeof(WiFiConfigBundle));
|
||||||
|
memcpy(wcf_backup, &wifi_change_flags, sizeof(WiFiConfChangeFlags));
|
||||||
|
|
||||||
bool sta_turned_on = false;
|
bool sta_turned_on = false;
|
||||||
bool sta_ssid_pw_changed = false;
|
bool sta_ssid_pw_changed = false;
|
||||||
|
|
||||||
@@ -502,6 +507,8 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(void)redir_url;
|
||||||
|
|
||||||
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
if (redir_url_buf[strlen(SET_REDIR_ERR)] == 0) {
|
||||||
// All was OK
|
// All was OK
|
||||||
cgi_info("Set WiFi params - success, applying in 2000 ms");
|
cgi_info("Set WiFi params - success, applying in 2000 ms");
|
||||||
@@ -528,13 +535,20 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData)
|
|||||||
httpdRedirect(connData, "/cfg/wifi/connecting");
|
httpdRedirect(connData, "/cfg/wifi/connecting");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
httpdRedirect(connData, SET_REDIR_SUC);
|
httpdRedirect(connData, SET_REDIR_SUC "?msg=Settings%20saved%20and%20applied.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cgi_warn("Some WiFi settings did not validate, asking for correction");
|
cgi_warn("Some WiFi settings did not validate, asking for correction");
|
||||||
|
|
||||||
|
memcpy(wificonf, wificonf_backup, sizeof(WiFiConfigBundle));
|
||||||
|
memcpy(&wifi_change_flags, wcf_backup, sizeof(WiFiConfChangeFlags));
|
||||||
|
|
||||||
// Some errors, appended to the URL as ?err=
|
// Some errors, appended to the URL as ?err=
|
||||||
httpdRedirect(connData, redir_url_buf);
|
httpdRedirect(connData, redir_url_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(wificonf_backup);
|
||||||
|
free(wcf_backup);
|
||||||
return HTTPD_CGI_DONE;
|
return HTTPD_CGI_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,22 +617,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (streq(token, "sta_active_ip")) {
|
else if (streq(token, "sta_active_ip")) {
|
||||||
x = wifi_get_opmode();
|
getStaIpAsString(buff);
|
||||||
connectStatus = wifi_station_get_connect_status();
|
|
||||||
|
|
||||||
if (x == SOFTAP_MODE || connectStatus != STATION_GOT_IP || wificonf->opmode == SOFTAP_MODE) {
|
|
||||||
strcpy(buff, "");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
struct ip_info info;
|
|
||||||
wifi_get_ip_info(STATION_IF, &info);
|
|
||||||
sprintf(buff, IPSTR, GOOD_IP2STR(info.ip.addr));
|
|
||||||
|
|
||||||
// sprintf(buff, "ip: "IPSTR", mask: "IPSTR", gw: "IPSTR,
|
|
||||||
// GOOD_IP2STR(info.ip.addr),
|
|
||||||
// GOOD_IP2STR(info.netmask.addr),
|
|
||||||
// GOOD_IP2STR(info.gw.addr));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tplSend(connData, buff, -1);
|
tplSend(connData, buff, -1);
|
||||||
|
|||||||
+336
-127
@@ -19,143 +19,352 @@
|
|||||||
* Based on rxvt-unicode screen.C table.
|
* Based on rxvt-unicode screen.C table.
|
||||||
*/
|
*/
|
||||||
static const u16 codepage_0[] ESP_CONST_DATA =
|
static const u16 codepage_0[] ESP_CONST_DATA =
|
||||||
{// Unicode ASCII SYM
|
{ // Unicode ASCII SYM
|
||||||
// %%BEGIN:0%%
|
// %%BEGIN:0%%
|
||||||
0x2666, // 96 ` ♦
|
u'♦', // 0x2666 96 `
|
||||||
0x2592, // 97 a ▒
|
u'▒', // 0x2592 97 a
|
||||||
0x2409, // 98 b HT
|
u'␉', // 0x2409 98 b
|
||||||
0x240c, // 99 c FF
|
u'␌', // 0x240c 99 c FF
|
||||||
0x240d, // 100 d CR
|
u'␍', // 0x240d 100 d CR
|
||||||
0x240a, // 101 e LF
|
u'␊', // 0x240a 101 e LF
|
||||||
0x00b0, // 102 f °
|
u'°', // 0x00b0 102 f
|
||||||
0x00b1, // 103 g ±
|
u'±', // 0x00b1 103 g
|
||||||
0x2424, // 104 h NL
|
u'', // 0x2424 104 h NL
|
||||||
0x240b, // 105 i VT
|
u'␋', // 0x240b 105 i VT
|
||||||
0x2518, // 106 j ┘
|
u'┘', // 0x2518 106 j
|
||||||
0x2510, // 107 k ┐
|
u'┐', // 0x2510 107 k
|
||||||
0x250c, // 108 l ┌
|
u'┌', // 0x250c 108 l
|
||||||
0x2514, // 109 m └
|
u'└', // 0x2514 109 m
|
||||||
0x253c, // 110 n ┼
|
u'┼', // 0x253c 110 n
|
||||||
0x23ba, // 111 o ⎺
|
u'⎺', // 0x23ba 111 o
|
||||||
0x23bb, // 112 p ⎻
|
u'⎻', // 0x23bb 112 p
|
||||||
0x2500, // 113 q ─
|
u'─', // 0x2500 113 q
|
||||||
0x23bc, // 114 r ⎼
|
u'⎼', // 0x23bc 114 r
|
||||||
0x23bd, // 115 s ⎽
|
u'⎽', // 0x23bd 115 s
|
||||||
0x251c, // 116 t ├
|
u'├', // 0x251c 116 t
|
||||||
0x2524, // 117 u ┤
|
u'┤', // 0x2524 117 u
|
||||||
0x2534, // 118 v ┴
|
u'┴', // 0x2534 118 v
|
||||||
0x252c, // 119 w ┬
|
u'┬', // 0x252c 119 w
|
||||||
0x2502, // 120 x │
|
u'│', // 0x2502 120 x
|
||||||
0x2264, // 121 y ≤
|
u'≤', // 0x2264 121 y
|
||||||
0x2265, // 122 z ≥
|
u'≥', // 0x2265 122 z
|
||||||
0x03c0, // 123 { π
|
u'π', // 0x03c0 123 {
|
||||||
0x2260, // 124 | ≠
|
u'≠', // 0x2260 124 |
|
||||||
0x20a4, // 125 } £
|
u'£', // 0x20a4 125 }
|
||||||
0x00b7, // 126 ~ ·
|
u'·', // 0x00b7 126 ~
|
||||||
// %%END:0%%
|
// %%END:0%%
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CODEPAGE_1_BEGIN 33
|
#define CODEPAGE_1_BEGIN 33
|
||||||
#define CODEPAGE_1_END 126
|
#define CODEPAGE_1_END 126
|
||||||
|
|
||||||
|
// DOS, thin and double lines, arrows, angles, diagonals, thick border
|
||||||
static const u16 codepage_1[] ESP_CONST_DATA =
|
static const u16 codepage_1[] ESP_CONST_DATA =
|
||||||
{// Unicode ASCII SYM DOS
|
{// Unicode ASCII DOS
|
||||||
// %%BEGIN:1%%
|
// %%BEGIN:1%%
|
||||||
0x263A, // 33 ! ☺ (1) - low ASCII symbols from DOS, moved to +32
|
u'☺', // 0x263A, 33 ! (1) - low ASCII symbols from DOS, moved to +32
|
||||||
0x263B, // 34 " ☻ (2)
|
u'☻', // 0x263B, 34 " (2)
|
||||||
0x2665, // 35 # ♥ (3)
|
u'♥', // 0x2665, 35 # (3)
|
||||||
0x2666, // 36 $ ♦ (4)
|
u'♦', // 0x2666, 36 $ (4)
|
||||||
0x2663, // 37 % ♣ (5)
|
u'♣', // 0x2663, 37 % (5)
|
||||||
0x2660, // 38 & ♠ (6)
|
u'♠', // 0x2660, 38 & (6)
|
||||||
0x2022, // 39 ' • (7) - inverse dot and circle left out, can be done with SGR
|
u'•', // 0x2022, 39 ' (7) - inverse dot and circle left out, can be done with SGR
|
||||||
0x231B, // 40 ( ⌛ - hourglass (timer icon)
|
u'⌛', // 0x231B, 40 ( - hourglass (timer icon)
|
||||||
0x25CB, // 41 ) ○ (9)
|
u'○', // 0x25CB, 41 ) (9)
|
||||||
0x21AF, // 42 * ↯ - electricity (lightning monitor...)
|
u'↯', // 0x21AF, 42 * - electricity (lightning monitor...)
|
||||||
0x266A, // 43 + ♪ (13)
|
u'♪', // 0x266A, 43 + (13)
|
||||||
0x266B, // 44 , ♫ (14)
|
u'♫', // 0x266B, 44 , (14)
|
||||||
0x263C, // 45 - ☼ (15)
|
u'☼', // 0x263C, 45 - (15)
|
||||||
0x2302, // 46 . ⌂ (127)
|
u'⌂', // 0x2302, 46 . (127)
|
||||||
0x2622, // 47 / ☢ - radioactivity (geiger counter...)
|
u'☢', // 0x2622, 47 / - radioactivity (geiger counter...)
|
||||||
0x2591, // 48 0 ░ (176) - this block is kept aligned and ordered from DOS, moved -128
|
u'░', // 0x2591, 48 0 (176) - this block is kept aligned and ordered from DOS, moved -128
|
||||||
0x2592, // 49 1 ▒ (177)
|
u'▒', // 0x2592, 49 1 (177)
|
||||||
0x2593, // 50 2 ▓ (178)
|
u'▓', // 0x2593, 50 2 (178)
|
||||||
0x2502, // 51 3 │ (179)
|
u'│', // 0x2502, 51 3 (179)
|
||||||
0x2524, // 52 4 ┤ (180)
|
u'┤', // 0x2524, 52 4 (180)
|
||||||
0x2561, // 53 5 ╡ (181)
|
u'╡', // 0x2561, 53 5 (181)
|
||||||
0x2562, // 54 6 ╢ (182)
|
u'╢', // 0x2562, 54 6 (182)
|
||||||
0x2556, // 55 7 ╖ (183)
|
u'╖', // 0x2556, 55 7 (183)
|
||||||
0x2555, // 56 8 ╕ (184)
|
u'╕', // 0x2555, 56 8 (184)
|
||||||
0x2563, // 57 9 ╣ (185)
|
u'╣', // 0x2563, 57 9 (185)
|
||||||
0x2551, // 58 : ║ (186)
|
u'║', // 0x2551, 58 : (186)
|
||||||
0x2557, // 59 ; ╗ (187)
|
u'╗', // 0x2557, 59 ; (187)
|
||||||
0x255D, // 60 < ╝ (188)
|
u'╝', // 0x255D, 60 < (188)
|
||||||
0x255C, // 61 = ╜ (189)
|
u'╜', // 0x255C, 61 = (189)
|
||||||
0x255B, // 62 > ╛ (190)
|
u'╛', // 0x255B, 62 > (190)
|
||||||
0x2510, // 63 ? ┐ (191)
|
u'┐', // 0x2510, 63 ? (191)
|
||||||
0x2514, // 64 @ └ (192)
|
u'└', // 0x2514, 64 @ (192)
|
||||||
0x2534, // 65 A ┴ (193)
|
u'┴', // 0x2534, 65 A (193)
|
||||||
0x252C, // 66 B ┬ (194)
|
u'┬', // 0x252C, 66 B (194)
|
||||||
0x251C, // 67 C ├ (195)
|
u'├', // 0x251C, 67 C (195)
|
||||||
0x2500, // 68 D ─ (196)
|
u'─', // 0x2500, 68 D (196)
|
||||||
0x253C, // 69 E ┼ (197)
|
u'┼', // 0x253C, 69 E (197)
|
||||||
0x255E, // 70 F ╞ (198)
|
u'╞', // 0x255E, 70 F (198)
|
||||||
0x255F, // 71 G ╟ (199)
|
u'╟', // 0x255F, 71 G (199)
|
||||||
0x255A, // 72 H ╚ (200)
|
u'╚', // 0x255A, 72 H (200)
|
||||||
0x2554, // 73 I ╔ (201)
|
u'╔', // 0x2554, 73 I (201)
|
||||||
0x2569, // 74 J ╩ (202)
|
u'╩', // 0x2569, 74 J (202)
|
||||||
0x2566, // 75 K ╦ (203)
|
u'╦', // 0x2566, 75 K (203)
|
||||||
0x2560, // 76 L ╠ (204)
|
u'╠', // 0x2560, 76 L (204)
|
||||||
0x2550, // 77 M ═ (205)
|
u'═', // 0x2550, 77 M (205)
|
||||||
0x256C, // 78 N ╬ (206)
|
u'╬', // 0x256C, 78 N (206)
|
||||||
0x2567, // 79 O ╧ (207)
|
u'╧', // 0x2567, 79 O (207)
|
||||||
0x2568, // 80 P ╨ (208)
|
u'╨', // 0x2568, 80 P (208)
|
||||||
0x2564, // 81 Q ╤ (209)
|
u'╤', // 0x2564, 81 Q (209)
|
||||||
0x2565, // 82 R ╥ (210)
|
u'╥', // 0x2565, 82 R (210)
|
||||||
0x2559, // 83 S ╙ (211)
|
u'╙', // 0x2559, 83 S (211)
|
||||||
0x2558, // 84 T ╘ (212)
|
u'╘', // 0x2558, 84 T (212)
|
||||||
0x2552, // 85 U ╒ (213)
|
u'╒', // 0x2552, 85 U (213)
|
||||||
0x2553, // 86 V ╓ (214)
|
u'╓', // 0x2553, 86 V (214)
|
||||||
0x256B, // 87 W ╫ (215)
|
u'╫', // 0x256B, 87 W (215)
|
||||||
0x256A, // 88 X ╪ (216)
|
u'╪', // 0x256A, 88 X (216)
|
||||||
0x2518, // 89 Y ┘ (217)
|
u'┘', // 0x2518, 89 Y (217)
|
||||||
0x250C, // 90 Z ┌ (218)
|
u'┌', // 0x250C, 90 Z (218)
|
||||||
0x2588, // 91 [ █ (219)
|
u'█', // 0x2588, 91 [ (219)
|
||||||
0x2584, // 92 \ ▄ (220)
|
u'▄', // 0x2584, 92 \ (220)
|
||||||
0x258C, // 93 ] ▌ (221)
|
u'▌', // 0x258C, 93 ] (221)
|
||||||
0x2590, // 94 ^ ▐ (222)
|
u'▐', // 0x2590, 94 ^ (222)
|
||||||
0x2580, // 95 _ ▀ (223)
|
u'▀', // 0x2580, 95 _ (223)
|
||||||
0x2195, // 96 ` ↕ (18) - moved from low DOS ASCII
|
u'↕', // 0x2195, 96 ` (18) - moved from low DOS ASCII
|
||||||
0x2191, // 97 a ↑ (24)
|
u'↑', // 0x2191, 97 a (24)
|
||||||
0x2193, // 98 b ↓ (25)
|
u'↓', // 0x2193, 98 b (25)
|
||||||
0x2192, // 99 c → (26)
|
u'→', // 0x2192, 99 c (26)
|
||||||
0x2190, // 100 d ← (27)
|
u'←', // 0x2190, 100 d (27)
|
||||||
0x2194, // 101 e ↔ (29)
|
u'↔', // 0x2194, 101 e (29)
|
||||||
0x25B2, // 102 f ▲ (30)
|
u'▲', // 0x25B2, 102 f (30)
|
||||||
0x25BC, // 103 g ▼ (31)
|
u'▼', // 0x25BC, 103 g (31)
|
||||||
0x25BA, // 104 h ► (16)
|
u'►', // 0x25BA, 104 h (16)
|
||||||
0x25C4, // 105 i ◄ (17)
|
u'◄', // 0x25C4, 105 i (17)
|
||||||
0x25E2, // 106 j ◢ - added for slanted corners
|
u'◢', // 0x25E2, 106 j - added for slanted corners
|
||||||
0x25E3, // 107 k ◣
|
u'◣', // 0x25E3, 107 k
|
||||||
0x25E4, // 108 l ◤
|
u'◤', // 0x25E4, 108 l
|
||||||
0x25E5, // 109 m ◥
|
u'◥', // 0x25E5, 109 m
|
||||||
0x256D, // 110 n ╭ - rounded corners
|
u'╭', // 0x256D, 110 n - rounded corners
|
||||||
0x256E, // 111 o ╮
|
u'╮', // 0x256E, 111 o
|
||||||
0x256F, // 112 p ╯
|
u'╯', // 0x256F, 112 p
|
||||||
0x2570, // 113 q ╰
|
u'╰', // 0x2570, 113 q
|
||||||
0x0, // 114 r - free positions for future expansion
|
u'╱', // 0x0, 114 r - right up diagonal
|
||||||
0x0, // 115 s
|
u'╲', // 0x0, 115 s - right down diagonal
|
||||||
0x0, // 116 t
|
u'╳', // 0x0, 116 t
|
||||||
0x0, // 117 u
|
0, // 0x0, 117 u
|
||||||
0x0, // 118 v
|
0, // 0x0, 118 v
|
||||||
0x0, // 119 w
|
0, // 0x0, 119 w
|
||||||
0x0, // 120 x
|
0, // 0x0, 120 x
|
||||||
0x0, // 121 y
|
0xE0B0, // powerline right triangle (filled), 121 y
|
||||||
0x0, // 122 z
|
0xE0B1, // powerline right triangle (hollow), 122 z
|
||||||
0x0, // 123 {
|
0xE0B2, // powerline left triangle (filled), 123 {
|
||||||
0x0, // 124 |
|
0xE0B3, // powerline left triangle (hollow), 124 | - reserved
|
||||||
0x2714, // 125 } ✔ - checkboxes or checklist items
|
u'✔', // 0x2714, 125 } - checkboxes or checklist items
|
||||||
0x2718, // 126 ~ ✘
|
u'✘', // 0x2718, 126 ~
|
||||||
// %%END:1%%
|
// %%END:1%%
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CODEPAGE_2_BEGIN 33
|
||||||
|
#define CODEPAGE_2_END 126
|
||||||
|
|
||||||
|
// blocks, thick and split lines, line butts
|
||||||
|
static const u16 codepage_2[] ESP_CONST_DATA =
|
||||||
|
{// Unicode ASCII DOS
|
||||||
|
// %%BEGIN:2%%
|
||||||
|
u'▁', // 0x2581, 33 ! - those are ordered this way to allow easy calculating of the right code (for graphs)
|
||||||
|
u'▂', // 0x2582, 34 "
|
||||||
|
u'▃', // 0x2583, 35 #
|
||||||
|
u'▄', // 0x2584, 36 $
|
||||||
|
u'▅', // 0x2585, 37 %
|
||||||
|
u'▆', // 0x2586, 38 &
|
||||||
|
u'▇', // 0x2587, 39 ' - 7-eighths
|
||||||
|
u'█', // 0x2588, 40 ( - full block, shared by both sequences
|
||||||
|
u'▉', // 0x2589, 41 ) - those grow thinner, to re-use the full block
|
||||||
|
u'▊', // 0x258A, 42 *
|
||||||
|
u'▋', // 0x258B, 43 +
|
||||||
|
u'▌', // 0x258C, 44 ,
|
||||||
|
u'▍', // 0x258D, 45 -
|
||||||
|
u'▎', // 0x258E, 46 .
|
||||||
|
u'▏', // 0x258F, 47 /
|
||||||
|
u'▔', // 0x2594, 48 0 - complementary symbols
|
||||||
|
u'▕', // 0x2595, 49 1
|
||||||
|
u'▐', // 0x2590, 50 2
|
||||||
|
u'▀', // 0x2580, 51 3
|
||||||
|
u'▘', // 0x2598, 52 4 - top-left, top-right, bottom-right, bottom-left
|
||||||
|
u'▝', // 0x259D, 53 5
|
||||||
|
u'▗', // 0x2597, 54 6
|
||||||
|
u'▖', // 0x2596, 55 7
|
||||||
|
u'▟', // 0x259F, 56 8
|
||||||
|
u'▙', // 0x2599, 57 9
|
||||||
|
u'▛', // 0x259B, 58 :
|
||||||
|
u'▜', // 0x259C, 59 ;
|
||||||
|
u'▞', // 0x259E, 60 < - complementary diagonals
|
||||||
|
u'▚', // 0x259A, 61 =
|
||||||
|
u'━', // 0x, 62 > - here are thick and thin lines and their joins. it's really quite arbitrary, based on the unicode order, excluding single lines
|
||||||
|
u'┃', // 0x, 63 ?
|
||||||
|
u'┍', // 0x, 64 @
|
||||||
|
u'┎', // 0x, 65 A
|
||||||
|
u'┏', // 0x, 66 B
|
||||||
|
u'┑', // 0x, 67 C
|
||||||
|
u'┒', // 0x, 68 D
|
||||||
|
u'┓', // 0x, 69 E
|
||||||
|
u'┕', // 0x, 70 F
|
||||||
|
u'┖', // 0x, 71 G
|
||||||
|
u'┗', // 0x, 72 H
|
||||||
|
u'┙', // 0x, 73 I
|
||||||
|
u'┚', // 0x, 74 J
|
||||||
|
u'┛', // 0x, 75 K
|
||||||
|
u'┝', // 0x, 76 L
|
||||||
|
u'┞', // 0x, 77 M
|
||||||
|
u'┟', // 0x, 78 N
|
||||||
|
u'┠', // 0x, 79 O
|
||||||
|
u'┡', // 0x, 80 P
|
||||||
|
u'┢', // 0x, 81 Q
|
||||||
|
u'┣', // 0x, 82 R
|
||||||
|
u'┥', // 0x, 83 S
|
||||||
|
u'┦', // 0x, 84 T
|
||||||
|
u'┧', // 0x, 85 U
|
||||||
|
u'┨', // 0x, 86 V
|
||||||
|
u'┩', // 0x, 87 W
|
||||||
|
u'┪', // 0x, 88 X
|
||||||
|
u'┫', // 0x, 89 Y
|
||||||
|
u'┭', // 0x, 90 Z
|
||||||
|
u'┮', // 0x, 91 [
|
||||||
|
u'┯', // 0x, 92 \ .
|
||||||
|
u'┰', // 0x, 93 ]
|
||||||
|
u'┱', // 0x, 94 ^
|
||||||
|
u'┲', // 0x, 95 _
|
||||||
|
u'┳', // 0x, 96 `
|
||||||
|
u'┵', // 0x, 97 a
|
||||||
|
u'┶', // 0x, 98 b
|
||||||
|
u'┷', // 0x, 99 c
|
||||||
|
u'┸', // 0x, 100 d
|
||||||
|
u'┹', // 0x, 101 e
|
||||||
|
u'┺', // 0x, 102 f
|
||||||
|
u'┻', // 0x, 103 g
|
||||||
|
u'┽', // 0x, 104 h
|
||||||
|
u'┾', // 0x, 105 i
|
||||||
|
u'┿', // 0x, 106 j
|
||||||
|
u'╀', // 0x, 107 k
|
||||||
|
u'╁', // 0x, 108 l
|
||||||
|
u'╂', // 0x, 109 m
|
||||||
|
u'╃', // 0x, 110 n
|
||||||
|
u'╄', // 0x, 111 o
|
||||||
|
u'╅', // 0x, 112 p
|
||||||
|
u'╆', // 0x, 113 q
|
||||||
|
u'╇', // 0x, 114 r
|
||||||
|
u'╈', // 0x, 115 s
|
||||||
|
u'╉', // 0x, 116 t
|
||||||
|
u'╊', // 0x, 117 u
|
||||||
|
u'╋', // 0x, 118 v
|
||||||
|
u'╴', // 0x, 119 w - butts
|
||||||
|
u'╵', // 0x, 120 x
|
||||||
|
u'╶', // 0x, 121 y
|
||||||
|
u'╷', // 0x, 122 z
|
||||||
|
u'╸', // 0x, 123 {
|
||||||
|
u'╹', // 0x, 124 |
|
||||||
|
u'╺', // 0x, 125 }
|
||||||
|
u'╻', // 0x, 126 ~
|
||||||
|
// %%END:2%%
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CODEPAGE_3_BEGIN 33
|
||||||
|
#define CODEPAGE_3_END 48
|
||||||
|
|
||||||
|
// dashed lines, split straight lines
|
||||||
|
static const u16 codepage_3[] ESP_CONST_DATA =
|
||||||
|
{// Unicode ASCII DOS
|
||||||
|
// %%BEGIN:3%%
|
||||||
|
u'╌', // 0x, 33 !
|
||||||
|
u'┄', // 0x, 34 "
|
||||||
|
u'┈', // 0x, 35 #
|
||||||
|
u'╍', // 0x, 36 $
|
||||||
|
u'┅', // 0x, 37 %
|
||||||
|
u'┉', // 0x, 38 &
|
||||||
|
u'╎', // 0x, 39 '
|
||||||
|
u'┆', // 0x, 40 (
|
||||||
|
u'┊', // 0x, 41 )
|
||||||
|
u'╏', // 0x, 42 *
|
||||||
|
u'┇', // 0x, 43 +
|
||||||
|
u'┋', // 0x, 44 ,
|
||||||
|
u'╼', // 0x, 45 -
|
||||||
|
u'╽', // 0x, 46 .
|
||||||
|
u'╾', // 0x, 47 /
|
||||||
|
u'╿', // 0x, 48 0
|
||||||
|
// %%END:3%%
|
||||||
|
// u'\0', // 0x, 49 1
|
||||||
|
// u'\0', // 0x, 50 2
|
||||||
|
// u'\0', // 0x, 51 3
|
||||||
|
// u'\0', // 0x, 52 4
|
||||||
|
// u'\0', // 0x, 53 5
|
||||||
|
// u'\0', // 0x, 54 6
|
||||||
|
// u'\0', // 0x, 55 7
|
||||||
|
// u'\0', // 0x, 56 8
|
||||||
|
// u'\0', // 0x, 57 9
|
||||||
|
// u'\0', // 0x, 58 :
|
||||||
|
// u'\0', // 0x, 59 ;
|
||||||
|
// u'\0', // 0x, 60 <
|
||||||
|
// u'\0', // 0x, 61 =
|
||||||
|
// u'\0', // 0x, 62 >
|
||||||
|
// u'\0', // 0x, 63 ?
|
||||||
|
// u'\0', // 0x, 64 @
|
||||||
|
// u'\0', // 0x, 65 A
|
||||||
|
// u'\0', // 0x, 66 B
|
||||||
|
// u'\0', // 0x, 67 C
|
||||||
|
// u'\0', // 0x, 68 D
|
||||||
|
// u'\0', // 0x, 69 E
|
||||||
|
// u'\0', // 0x, 70 F
|
||||||
|
// u'\0', // 0x, 71 G
|
||||||
|
// u'\0', // 0x, 72 H
|
||||||
|
// u'\0', // 0x, 73 I
|
||||||
|
// u'\0', // 0x, 74 J
|
||||||
|
// u'\0', // 0x, 75 K
|
||||||
|
// u'\0', // 0x, 76 L
|
||||||
|
// u'\0', // 0x, 77 M
|
||||||
|
// u'\0', // 0x, 78 N
|
||||||
|
// u'\0', // 0x, 79 O
|
||||||
|
// u'\0', // 0x, 80 P
|
||||||
|
// u'\0', // 0x, 81 Q
|
||||||
|
// u'\0', // 0x, 82 R
|
||||||
|
// u'\0', // 0x, 83 S
|
||||||
|
// u'\0', // 0x, 84 T
|
||||||
|
// u'\0', // 0x, 85 U
|
||||||
|
// u'\0', // 0x, 86 V
|
||||||
|
// u'\0', // 0x, 87 W
|
||||||
|
// u'\0', // 0x, 88 X
|
||||||
|
// u'\0', // 0x, 89 Y
|
||||||
|
// u'\0', // 0x, 90 Z
|
||||||
|
// u'\0', // 0x, 91 [
|
||||||
|
// u'\0', // 0x, 92 \ .
|
||||||
|
// u'\0', // 0x, 93 ]
|
||||||
|
// u'\0', // 0x, 94 ^
|
||||||
|
// u'\0', // 0x, 95 _
|
||||||
|
// u'\0', // 0x, 96 `
|
||||||
|
// u'\0', // 0x, 97 a
|
||||||
|
// u'\0', // 0x, 98 b
|
||||||
|
// u'\0', // 0x, 99 c
|
||||||
|
// u'\0', // 0x, 100 d
|
||||||
|
// u'\0', // 0x, 101 e
|
||||||
|
// u'\0', // 0x, 102 f
|
||||||
|
// u'\0', // 0x, 103 g
|
||||||
|
// u'\0', // 0x, 104 h
|
||||||
|
// u'\0', // 0x, 105 i
|
||||||
|
// u'\0', // 0x, 106 j
|
||||||
|
// u'\0', // 0x, 107 k
|
||||||
|
// u'\0', // 0x, 108 l
|
||||||
|
// u'\0', // 0x, 109 m
|
||||||
|
// u'\0', // 0x, 110 n
|
||||||
|
// u'\0', // 0x, 111 o
|
||||||
|
// u'\0', // 0x, 112 p
|
||||||
|
// u'\0', // 0x, 113 q
|
||||||
|
// u'\0', // 0x, 114 r
|
||||||
|
// u'\0', // 0x, 115 s
|
||||||
|
// u'\0', // 0x, 116 t
|
||||||
|
// u'\0', // 0x, 117 u
|
||||||
|
// u'\0', // 0x, 118 v
|
||||||
|
// u'\0', // 0x, 119 w
|
||||||
|
// u'\0', // 0x, 120 x
|
||||||
|
// u'\0', // 0x, 121 y
|
||||||
|
// u'\0', // 0x, 122 z
|
||||||
|
// u'\0', // 0x, 123 {
|
||||||
|
// u'\0', // 0x, 124 |
|
||||||
|
// u'\0', // 0x, 125 }
|
||||||
|
// u'\0', // 0x, 126 ~
|
||||||
|
};
|
||||||
|
|
||||||
#endif //ESPTERM_CHARACTER_SETS_H_H
|
#endif //ESPTERM_CHARACTER_SETS_H_H
|
||||||
|
|||||||
+25
-7
@@ -97,19 +97,27 @@ compute_checksum(AppConfigBundle *bundle)
|
|||||||
return calculateCRC32((uint8_t *) bundle, sizeof(AppConfigBundle) - 4);
|
return calculateCRC32((uint8_t *) bundle, sizeof(AppConfigBundle) - 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR
|
||||||
|
set_admin_block_defaults(void)
|
||||||
|
{
|
||||||
|
persist_info("[Persist] Initing admin config block");
|
||||||
|
strcpy(persist.admin.pw, DEFAULT_ADMIN_PW);
|
||||||
|
persist.admin.version = ADMINCONF_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load, verify and apply persistent config
|
* Load, verify and apply persistent config
|
||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
persist_load(void)
|
persist_load(void)
|
||||||
{
|
{
|
||||||
persist_info("[Persist] Loading stored settings from FLASH...");
|
persist_info("[Persist] Loading settings from FLASH...");
|
||||||
|
|
||||||
persist_dbg("AppConfigBundle memory map:");
|
persist_dbg("Persist memory map:");
|
||||||
persist_dbg("> WiFiConfigBundle at %4d (error %2d)", wconf_at, wconf_at - 0);
|
persist_dbg("> wifi at %4d (error %2d)", wconf_at, wconf_at - 0);
|
||||||
persist_dbg("> SystemConfigBundle at %4d (error %2d)", sconf_at, sconf_at - WIFICONF_SIZE);
|
persist_dbg("> sys at %4d (error %2d)", sconf_at, sconf_at - WIFICONF_SIZE);
|
||||||
persist_dbg("> TerminalConfigBundle at %4d (error %2d)", tconf_at, tconf_at - WIFICONF_SIZE - SYSCONF_SIZE);
|
persist_dbg("> term at %4d (error %2d)", tconf_at, tconf_at - WIFICONF_SIZE - SYSCONF_SIZE);
|
||||||
persist_dbg("> Checksum at %4d (error %2d)", cksum_at, cksum_at - (APPCONF_SIZE - 4));
|
persist_dbg("> cksum at %4d (error %2d)", cksum_at, cksum_at - (APPCONF_SIZE - 4));
|
||||||
persist_dbg("> Total size = %d bytes (error %d)", sizeof(AppConfigBundle), APPCONF_SIZE - sizeof(AppConfigBundle));
|
persist_dbg("> Total size = %d bytes (error %d)", sizeof(AppConfigBundle), APPCONF_SIZE - sizeof(AppConfigBundle));
|
||||||
|
|
||||||
bool hard_reset = false;
|
bool hard_reset = false;
|
||||||
@@ -120,7 +128,8 @@ persist_load(void)
|
|||||||
// Verify checksums
|
// Verify checksums
|
||||||
if (hard_reset ||
|
if (hard_reset ||
|
||||||
(compute_checksum(&persist.defaults) != persist.defaults.checksum) ||
|
(compute_checksum(&persist.defaults) != persist.defaults.checksum) ||
|
||||||
(compute_checksum(&persist.current) != persist.current.checksum)) {
|
(compute_checksum(&persist.current) != persist.current.checksum) ||
|
||||||
|
(persist.admin.version != 0 && (calculateCRC32((uint8_t *) &persist.admin, sizeof(AdminConfigBlock) - 4) != persist.admin.checksum))) {
|
||||||
error("[Persist] Checksum verification: FAILED");
|
error("[Persist] Checksum verification: FAILED");
|
||||||
hard_reset = true;
|
hard_reset = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -135,10 +144,18 @@ persist_load(void)
|
|||||||
|
|
||||||
// write them also as defaults
|
// write them also as defaults
|
||||||
memcpy(&persist.defaults, &persist.current, sizeof(AppConfigBundle));
|
memcpy(&persist.defaults, &persist.current, sizeof(AppConfigBundle));
|
||||||
|
|
||||||
|
// reset admin pw
|
||||||
|
set_admin_block_defaults();
|
||||||
persist_store();
|
persist_store();
|
||||||
|
|
||||||
// this also stores them to flash and applies to modules
|
// this also stores them to flash and applies to modules
|
||||||
} else {
|
} else {
|
||||||
|
if (persist.admin.version == 0) {
|
||||||
|
set_admin_block_defaults();
|
||||||
|
persist_store();
|
||||||
|
}
|
||||||
|
|
||||||
apply_live_settings();
|
apply_live_settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,6 +170,7 @@ persist_store(void)
|
|||||||
// Update checksums before write
|
// Update checksums before write
|
||||||
persist.current.checksum = compute_checksum(&persist.current);
|
persist.current.checksum = compute_checksum(&persist.current);
|
||||||
persist.defaults.checksum = compute_checksum(&persist.defaults);
|
persist.defaults.checksum = compute_checksum(&persist.defaults);
|
||||||
|
persist.admin.checksum = calculateCRC32((uint8_t *) &persist.admin, sizeof(AdminConfigBlock) - 4);
|
||||||
|
|
||||||
if (!system_param_save_with_protect(PERSIST_SECTOR_ID, &persist, sizeof(PersistBlock))) {
|
if (!system_param_save_with_protect(PERSIST_SECTOR_ID, &persist, sizeof(PersistBlock))) {
|
||||||
error("[Persist] Store to flash failed!");
|
error("[Persist] Store to flash failed!");
|
||||||
|
|||||||
+16
-3
@@ -14,11 +14,13 @@
|
|||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "syscfg.h"
|
#include "syscfg.h"
|
||||||
|
|
||||||
|
#define DEFAULT_ADMIN_PW "adminpw"
|
||||||
|
|
||||||
// Changing this could be used to force-erase the config area
|
// Changing this could be used to force-erase the config area
|
||||||
// after a firmware upgrade
|
// after a firmware upgrade
|
||||||
#define CHECKSUM_SALT 3
|
#define CHECKSUM_SALT 6
|
||||||
|
|
||||||
#define APPCONF_SIZE 2048
|
#define APPCONF_SIZE 1900
|
||||||
|
|
||||||
/** Struct for current or default settings */
|
/** Struct for current or default settings */
|
||||||
typedef struct { // the entire block should be 1024 bytes long (for compatibility across upgrades)
|
typedef struct { // the entire block should be 1024 bytes long (for compatibility across upgrades)
|
||||||
@@ -41,7 +43,7 @@ typedef struct { // the entire block should be 1024 bytes long (for compatibilit
|
|||||||
// it grew to a different memory area.
|
// it grew to a different memory area.
|
||||||
uint8_t _filler_end[
|
uint8_t _filler_end[
|
||||||
APPCONF_SIZE
|
APPCONF_SIZE
|
||||||
- sizeof(uint32_t) // checksum
|
- 4 // checksum
|
||||||
- WIFICONF_SIZE
|
- WIFICONF_SIZE
|
||||||
- SYSCONF_SIZE
|
- SYSCONF_SIZE
|
||||||
- TERMCONF_SIZE
|
- TERMCONF_SIZE
|
||||||
@@ -50,10 +52,21 @@ typedef struct { // the entire block should be 1024 bytes long (for compatibilit
|
|||||||
uint32_t checksum; // computed before write and tested on load. If it doesn't match, values are reset to hard defaults.
|
uint32_t checksum; // computed before write and tested on load. If it doesn't match, values are reset to hard defaults.
|
||||||
} AppConfigBundle;
|
} AppConfigBundle;
|
||||||
|
|
||||||
|
#define ADMINCONF_VERSION 1
|
||||||
|
#define ADMINCONF_SIZE 256
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 version;
|
||||||
|
char pw[64];
|
||||||
|
uint8_t _filler[ADMINCONF_SIZE-64-4];
|
||||||
|
uint32_t checksum;
|
||||||
|
} AdminConfigBlock;
|
||||||
|
|
||||||
/** This is the entire data block stored in FLASH */
|
/** This is the entire data block stored in FLASH */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
AppConfigBundle defaults; // defaults are stored here
|
AppConfigBundle defaults; // defaults are stored here
|
||||||
AppConfigBundle current; // active settings adjusted by the user
|
AppConfigBundle current; // active settings adjusted by the user
|
||||||
|
AdminConfigBlock admin;
|
||||||
} PersistBlock;
|
} PersistBlock;
|
||||||
|
|
||||||
// Persist holds the data currently loaded from the flash
|
// Persist holds the data currently loaded from the flash
|
||||||
|
|||||||
+83
-25
@@ -12,12 +12,84 @@
|
|||||||
#include "cgi_network.h"
|
#include "cgi_network.h"
|
||||||
#include "cgi_term_cfg.h"
|
#include "cgi_term_cfg.h"
|
||||||
#include "cgi_persist.h"
|
#include "cgi_persist.h"
|
||||||
|
#include "syscfg.h"
|
||||||
|
#include "persist.h"
|
||||||
|
#include "api.h"
|
||||||
|
#include "cgi_d2d.h"
|
||||||
|
|
||||||
#define WIFI_PROTECT 0
|
/**
|
||||||
#define WIFI_AUTH_NAME "wifi"
|
* Password for WiFi config
|
||||||
#define WIFI_AUTH_PASS "nicitel"
|
*/
|
||||||
|
static int ICACHE_FLASH_ATTR wifiPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen)
|
||||||
|
{
|
||||||
|
if (no == 0) {
|
||||||
|
os_strcpy(user, sysconf->access_name);
|
||||||
|
os_strcpy(pass, sysconf->access_pw);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (no == 1) {
|
||||||
|
os_strcpy(user, "admin");
|
||||||
|
os_strcpy(pass, persist.admin.pw);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int wifiPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen);
|
httpd_cgi_state ICACHE_FLASH_ATTR cgiOptionalPwLock(HttpdConnData *connData)
|
||||||
|
{
|
||||||
|
bool protect = false;
|
||||||
|
|
||||||
|
http_dbg("Route, %s, pwlock=%d", connData->url, sysconf->pwlock);
|
||||||
|
|
||||||
|
switch (sysconf->pwlock) {
|
||||||
|
case PWLOCK_ALL:
|
||||||
|
protect = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PWLOCK_SETTINGS_NOTERM:
|
||||||
|
protect = strstarts(connData->url, "/cfg") &&
|
||||||
|
!strstarts(connData->url, "/cfg/term");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PWLOCK_SETTINGS_ALL:
|
||||||
|
protect = strstarts(connData->url, "/cfg");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PWLOCK_MENUS:
|
||||||
|
protect = strstarts(connData->url, "/cfg") ||
|
||||||
|
strstarts(connData->url, "/about") ||
|
||||||
|
strstarts(connData->url, "/help");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
case PWLOCK_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pages outside the normal scope
|
||||||
|
|
||||||
|
if (sysconf->pwlock > PWLOCK_NONE) {
|
||||||
|
if (strstarts(connData->url, "/api/v1/reboot")) protect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysconf->pwlock > PWLOCK_SETTINGS_NOTERM) {
|
||||||
|
if (strstarts(connData->url, "/api/v1/clear")) protect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sysconf->access_pw[0] == 0) {
|
||||||
|
http_dbg("Access PW is nil, no protection.");
|
||||||
|
protect = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protect) {
|
||||||
|
http_dbg("Page is protected!");
|
||||||
|
connData->cgiArg = wifiPassFn;
|
||||||
|
return authBasic(connData);
|
||||||
|
} else {
|
||||||
|
http_dbg("Not protected");
|
||||||
|
return HTTPD_CGI_NOTFOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application routes
|
* Application routes
|
||||||
@@ -25,6 +97,7 @@ static int wifiPassFn(HttpdConnData *connData, int no, char *user, int userLen,
|
|||||||
const HttpdBuiltInUrl routes[] ESP_CONST_DATA = {
|
const HttpdBuiltInUrl routes[] ESP_CONST_DATA = {
|
||||||
// redirect func for the captive portal
|
// redirect func for the captive portal
|
||||||
ROUTE_CGI_ARG("*", cgiRedirectApClientToHostname, "esp-terminal.ap"),
|
ROUTE_CGI_ARG("*", cgiRedirectApClientToHostname, "esp-terminal.ap"),
|
||||||
|
ROUTE_CGI("*", cgiOptionalPwLock),
|
||||||
|
|
||||||
// --- Web pages ---
|
// --- Web pages ---
|
||||||
ROUTE_TPL_FILE("/", tplScreen, "/term.tpl"),
|
ROUTE_TPL_FILE("/", tplScreen, "/term.tpl"),
|
||||||
@@ -35,14 +108,13 @@ const HttpdBuiltInUrl routes[] ESP_CONST_DATA = {
|
|||||||
ROUTE_WS(URL_WS_UPDATE, updateSockConnect),
|
ROUTE_WS(URL_WS_UPDATE, updateSockConnect),
|
||||||
|
|
||||||
// --- System control ---
|
// --- System control ---
|
||||||
ROUTE_CGI("/system/reset/?", cgiResetDevice),
|
|
||||||
ROUTE_CGI("/system/ping/?", cgiPing),
|
|
||||||
ROUTE_CGI("/system/cls/?", cgiResetScreen),
|
|
||||||
|
|
||||||
// --- WiFi config --- (TODO make this conditional and configurable)
|
// API endpoints
|
||||||
#if WIFI_PROTECT
|
ROUTE_CGI(API_REBOOT"/?", cgiResetDevice),
|
||||||
ROUTE_AUTH("/wifi*", wifiPassFn),
|
ROUTE_CGI(API_PING"/?", cgiPing),
|
||||||
#endif
|
ROUTE_CGI(API_CLEAR"/?", cgiResetScreen),
|
||||||
|
ROUTE_CGI(API_D2D_MSG"/?", cgiD2DMessage),
|
||||||
|
|
||||||
ROUTE_REDIRECT("/cfg/?", "/cfg/wifi"),
|
ROUTE_REDIRECT("/cfg/?", "/cfg/wifi"),
|
||||||
|
|
||||||
ROUTE_TPL_FILE("/cfg/wifi/?", tplWlan, "/cfg_wifi.tpl"),
|
ROUTE_TPL_FILE("/cfg/wifi/?", tplWlan, "/cfg_wifi.tpl"),
|
||||||
@@ -67,17 +139,3 @@ const HttpdBuiltInUrl routes[] ESP_CONST_DATA = {
|
|||||||
ROUTE_END(),
|
ROUTE_END(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Wifi password protection ---
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Password for WiFi config
|
|
||||||
*/
|
|
||||||
static int ICACHE_FLASH_ATTR wifiPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen)
|
|
||||||
{
|
|
||||||
if (no == 0) {
|
|
||||||
os_strcpy(user, WIFI_AUTH_NAME);
|
|
||||||
os_strcpy(pass, WIFI_AUTH_PASS);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,4 @@
|
|||||||
|
|
||||||
extern const HttpdBuiltInUrl routes[];
|
extern const HttpdBuiltInUrl routes[];
|
||||||
|
|
||||||
/** Broadcast screen state to sockets */
|
|
||||||
void screen_notifyChange();
|
|
||||||
|
|
||||||
#endif //ROUTES_H
|
#endif //ROUTES_H
|
||||||
|
|||||||
+836
-363
File diff suppressed because it is too large
Load Diff
+66
-32
@@ -34,11 +34,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Size designed for the terminal config structure
|
|
||||||
// Must be constant to avoid corrupting user config after upgrade
|
|
||||||
#define TERMCONF_SIZE 300
|
|
||||||
#define TERMCONF_VERSION 5
|
|
||||||
|
|
||||||
#define TERM_BTN_LEN 10
|
#define TERM_BTN_LEN 10
|
||||||
#define TERM_BTN_MSG_LEN 10
|
#define TERM_BTN_MSG_LEN 10
|
||||||
#define TERM_TITLE_LEN 64
|
#define TERM_TITLE_LEN 64
|
||||||
@@ -65,20 +60,28 @@ enum CursorShape {
|
|||||||
CURSOR_BAR = 6,
|
CURSOR_BAR = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SCR_DEF_SHOW_BUTTONS 0
|
#define SCR_DEF_SHOW_BUTTONS 1
|
||||||
#define SCR_DEF_SHOW_MENU 1
|
#define SCR_DEF_SHOW_MENU 1
|
||||||
#define SCR_DEF_CURSOR_SHAPE CURSOR_BLOCK_BL
|
#define SCR_DEF_CURSOR_SHAPE CURSOR_BLOCK_BL
|
||||||
#define SCR_DEF_CRLF 0
|
#define SCR_DEF_CRLF 0 // enter sends CRLF
|
||||||
#define SCR_DEF_ALLFN 0
|
#define SCR_DEF_ALLFN 0 // capture F5 etc
|
||||||
|
#define SCR_DEF_DEBUGBAR 0
|
||||||
|
#define SCR_DEF_DECOPT12 0
|
||||||
|
#define SCR_DEF_ASCIIDEBUG 0
|
||||||
|
|
||||||
// --- Persistent Settings ---
|
// --- Persistent Settings ---
|
||||||
#define CURSOR_BLINKS(shape) ((shape)==CURSOR_BLOCK_BL||(shape)==CURSOR_UNDERLINE_BL||(shape)==CURSOR_BAR_BL)
|
#define CURSOR_BLINKS(shape) ((shape)==CURSOR_BLOCK_BL||(shape)==CURSOR_UNDERLINE_BL||(shape)==CURSOR_BAR_BL)
|
||||||
|
|
||||||
|
// Size designed for the terminal config structure
|
||||||
|
// Must be constant to avoid corrupting user config after upgrade
|
||||||
|
#define TERMCONF_SIZE 300
|
||||||
|
#define TERMCONF_VERSION 3
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
u8 default_bg; // should be the Color typedef, but this way the size is more explicit
|
u32 default_bg; // 00-FFh - ANSI colors, (00:00:00-FF:FF:FF)+256 - True Color
|
||||||
u8 default_fg;
|
u32 default_fg;
|
||||||
char title[TERM_TITLE_LEN];
|
char title[TERM_TITLE_LEN];
|
||||||
char btn[TERM_BTN_COUNT][TERM_BTN_LEN];
|
char btn[TERM_BTN_COUNT][TERM_BTN_LEN];
|
||||||
u8 theme;
|
u8 theme;
|
||||||
@@ -94,6 +97,9 @@ typedef struct {
|
|||||||
enum CursorShape cursor_shape;
|
enum CursorShape cursor_shape;
|
||||||
bool crlf_mode;
|
bool crlf_mode;
|
||||||
bool want_all_fn;
|
bool want_all_fn;
|
||||||
|
bool debugbar;
|
||||||
|
bool allow_decopt_12;
|
||||||
|
bool ascii_debug;
|
||||||
} TerminalConfigBundle;
|
} TerminalConfigBundle;
|
||||||
|
|
||||||
// Live config
|
// Live config
|
||||||
@@ -150,11 +156,33 @@ typedef enum {
|
|||||||
CS_A_UKASCII = 'A',
|
CS_A_UKASCII = 'A',
|
||||||
CS_0_DEC_SUPPLEMENTAL = '0',
|
CS_0_DEC_SUPPLEMENTAL = '0',
|
||||||
CS_1_DOS_437 = '1',
|
CS_1_DOS_437 = '1',
|
||||||
|
CS_2_BLOCKS_LINES = '2',
|
||||||
|
CS_3_LINES_EXTRA = '3',
|
||||||
} CHARSET;
|
} CHARSET;
|
||||||
|
|
||||||
httpd_cgi_state screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
|
enum ScreenSerializeTopic {
|
||||||
|
TOPIC_CHANGE_SCREEN_OPTS = (1<<0),
|
||||||
|
TOPIC_CHANGE_CONTENT_ALL = (1<<1),
|
||||||
|
TOPIC_CHANGE_CONTENT_PART = (1<<2),
|
||||||
|
TOPIC_CHANGE_TITLE = (1<<3),
|
||||||
|
TOPIC_CHANGE_BUTTONS = (1<<4),
|
||||||
|
TOPIC_CHANGE_CURSOR = (1<<5),
|
||||||
|
TOPIC_INTERNAL = (1<<6), // debugging internal state
|
||||||
|
TOPIC_BELL = (1<<7), // beep
|
||||||
|
TOPIC_FLAG_NOCLEAN = (1<<15), // do not clean dirty extents
|
||||||
|
|
||||||
void screenSerializeLabelsToBuffer(char *buffer, size_t buf_len);
|
// combos
|
||||||
|
TOPIC_INITIAL =
|
||||||
|
TOPIC_CHANGE_SCREEN_OPTS |
|
||||||
|
TOPIC_CHANGE_CONTENT_ALL |
|
||||||
|
TOPIC_CHANGE_CURSOR |
|
||||||
|
TOPIC_CHANGE_TITLE |
|
||||||
|
TOPIC_CHANGE_BUTTONS,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef u16 ScreenNotifyTopics;
|
||||||
|
|
||||||
|
httpd_cgi_state screenSerializeToBuffer(char *buffer, size_t buf_len, ScreenNotifyTopics topics, void **data);
|
||||||
|
|
||||||
// --- Clearing ---
|
// --- Clearing ---
|
||||||
|
|
||||||
@@ -223,30 +251,40 @@ void screen_wrap_enable(bool enable);
|
|||||||
void screen_reverse_wrap_enable(bool enable);
|
void screen_reverse_wrap_enable(bool enable);
|
||||||
/** Set scrolling region */
|
/** Set scrolling region */
|
||||||
void screen_set_scrolling_region(int from, int to);
|
void screen_set_scrolling_region(int from, int to);
|
||||||
|
/* Report scrolling region */
|
||||||
|
void screen_region_get(int *pv0, int *pv1);
|
||||||
/** Enable or disable origin remap to top left of scrolling region */
|
/** Enable or disable origin remap to top left of scrolling region */
|
||||||
void screen_set_origin_mode(bool region_origin);
|
void screen_set_origin_mode(bool region_origin);
|
||||||
|
|
||||||
// --- Graphic rendition setting ---
|
// --- Graphic rendition setting ---
|
||||||
|
|
||||||
typedef uint8_t Color; // 0-16
|
typedef uint8_t Color;
|
||||||
|
typedef uint16_t CellAttrs;
|
||||||
|
|
||||||
#define ATTR_BOLD (1<<0)
|
enum SgrAttrBits {
|
||||||
#define ATTR_FAINT (1<<1)
|
ATTR_FG = (1<<0), //!< 1 if not using default background color (ignore cell bg) - color extension bit
|
||||||
#define ATTR_ITALIC (1<<2)
|
ATTR_BG = (1<<1), //!< 1 if not using default foreground color (ignore cell fg) - color extension bit
|
||||||
#define ATTR_UNDERLINE (1<<3)
|
ATTR_BOLD = (1<<2), //!< Bold font
|
||||||
#define ATTR_BLINK (1<<4)
|
ATTR_UNDERLINE = (1<<3), //!< Underline decoration
|
||||||
#define ATTR_FRAKTUR (1<<5)
|
ATTR_INVERSE = (1<<4), //!< Invert colors - this is useful so we can clear then with SGR manipulation commands
|
||||||
#define ATTR_STRIKE (1<<6)
|
ATTR_BLINK = (1<<5), //!< Blinking
|
||||||
#define ATTR_OVERLINE (1<<7)
|
ATTR_ITALIC = (1<<6), //!< Italic font
|
||||||
|
ATTR_STRIKE = (1<<7), //!< Strike-through decoration
|
||||||
|
ATTR_OVERLINE = (1<<8), //!< Over-line decoration
|
||||||
|
ATTR_FAINT = (1<<9), //!< Faint foreground color (reduced alpha)
|
||||||
|
ATTR_FRAKTUR = (1<<10), //!< Fraktur font (unicode substitution)
|
||||||
|
};
|
||||||
|
|
||||||
/** Set cursor foreground color */
|
/** Set cursor foreground color */
|
||||||
void screen_set_fg(Color color);
|
void screen_set_fg(Color color);
|
||||||
/** Set cursor background coloor */
|
/** Set cursor background coloor */
|
||||||
void screen_set_bg(Color color);
|
void screen_set_bg(Color color);
|
||||||
|
/** Set cursor foreground color to default */
|
||||||
|
void screen_set_default_fg(void);
|
||||||
|
/** Set cursor background color to default */
|
||||||
|
void screen_set_default_bg(void);
|
||||||
/** Enable/disable attrs by bitmask */
|
/** Enable/disable attrs by bitmask */
|
||||||
void screen_set_sgr(u8 attrs, bool ena);
|
void screen_set_sgr(CellAttrs attrs, bool ena);
|
||||||
/** Set the inverse attribute */
|
|
||||||
void screen_set_sgr_inverse(bool ena);
|
|
||||||
/** Conceal style */
|
/** Conceal style */
|
||||||
void screen_set_sgr_conceal(bool ena);
|
void screen_set_sgr_conceal(bool ena);
|
||||||
/** Reset cursor attribs */
|
/** Reset cursor attribs */
|
||||||
@@ -316,18 +354,14 @@ void screen_repeat_last_character(int count);
|
|||||||
/** Report current SGR as num;num;... for DAC query */
|
/** Report current SGR as num;num;... for DAC query */
|
||||||
void screen_report_sgr(char *buffer);
|
void screen_report_sgr(char *buffer);
|
||||||
|
|
||||||
// --- Notify ---
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CHANGE_CONTENT = 0,
|
|
||||||
CHANGE_LABELS = 1,
|
|
||||||
} ScreenNotifyChangeTopic;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the screen content or settings change
|
* Called when the screen content or settings change
|
||||||
* and the front-end should redraw / update.
|
* and the front-end should redraw / update.
|
||||||
* @param topic - what kind of change this is (chooses what message to send)
|
* @param topic - what kind of change this is (chooses what message to send)
|
||||||
*/
|
*/
|
||||||
extern void screen_notifyChange(ScreenNotifyChangeTopic topic);
|
extern void screen_notifyChange(ScreenNotifyTopics topics);
|
||||||
|
|
||||||
|
#define seri_dbg(...)
|
||||||
|
#define seri_warn(...) warn(__VA_ARGS__)
|
||||||
|
|
||||||
#endif // SCREEN_H
|
#endif // SCREEN_H
|
||||||
|
|||||||
+13
-10
@@ -4,8 +4,7 @@
|
|||||||
#include "ansi_parser.h"
|
#include "ansi_parser.h"
|
||||||
#include "syscfg.h"
|
#include "syscfg.h"
|
||||||
|
|
||||||
#define LOGBUF_SIZE 512
|
static char logbuf[DEBUG_LOGBUF_SIZE];
|
||||||
static char logbuf[LOGBUF_SIZE];
|
|
||||||
static u32 lb_nw = 1;
|
static u32 lb_nw = 1;
|
||||||
static u32 lb_ls = 0;
|
static u32 lb_ls = 0;
|
||||||
static ETSTimer flushLogTimer;
|
static ETSTimer flushLogTimer;
|
||||||
@@ -14,7 +13,7 @@ static void buf_putc(char c)
|
|||||||
{
|
{
|
||||||
if (lb_ls != lb_nw) {
|
if (lb_ls != lb_nw) {
|
||||||
logbuf[lb_nw++] = c;
|
logbuf[lb_nw++] = c;
|
||||||
if (lb_nw >= LOGBUF_SIZE) lb_nw = 0;
|
if (lb_nw >= DEBUG_LOGBUF_SIZE) lb_nw = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,11 +24,11 @@ buf_pop(void *unused)
|
|||||||
u32 old_ls;
|
u32 old_ls;
|
||||||
while (quantity > 0) {
|
while (quantity > 0) {
|
||||||
// stop when done
|
// stop when done
|
||||||
if ((lb_ls == lb_nw-1) || (lb_ls == LOGBUF_SIZE-1 && lb_nw == 0)) break;
|
if ((lb_ls == lb_nw-1) || (lb_ls == DEBUG_LOGBUF_SIZE-1 && lb_nw == 0)) break;
|
||||||
|
|
||||||
old_ls = lb_ls;
|
old_ls = lb_ls;
|
||||||
lb_ls++;
|
lb_ls++;
|
||||||
if (lb_ls >= LOGBUF_SIZE) lb_ls = 0;
|
if (lb_ls >= DEBUG_LOGBUF_SIZE) lb_ls = 0;
|
||||||
|
|
||||||
if (OK == UART_WriteCharCRLF(UART1, logbuf[lb_ls], 5)) {
|
if (OK == UART_WriteCharCRLF(UART1, logbuf[lb_ls], 5)) {
|
||||||
quantity--;
|
quantity--;
|
||||||
@@ -41,10 +40,10 @@ buf_pop(void *unused)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//LOCAL void my_putc(char c)
|
LOCAL void my_putc(char c)
|
||||||
//{
|
{
|
||||||
// UART_WriteCharCRLF(UART1, (u8) c, 10);
|
UART_WriteCharCRLF(UART1, (u8) c, 10);
|
||||||
//}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init the serial ports
|
* Init the serial ports
|
||||||
@@ -57,8 +56,11 @@ void ICACHE_FLASH_ATTR serialInitBase(void)
|
|||||||
UART_SetStopBits(UART1, ONE_STOP_BIT);
|
UART_SetStopBits(UART1, ONE_STOP_BIT);
|
||||||
UART_SetBaudrate(UART1, BIT_RATE_115200);
|
UART_SetBaudrate(UART1, BIT_RATE_115200);
|
||||||
UART_SetPrintPort(UART1);
|
UART_SetPrintPort(UART1);
|
||||||
|
#if ASYNC_LOG
|
||||||
os_install_putc1(buf_putc);
|
os_install_putc1(buf_putc);
|
||||||
//os_install_putc1(my_putc);
|
#else
|
||||||
|
os_install_putc1(my_putc);
|
||||||
|
#endif
|
||||||
UART_SetupAsyncReceiver();
|
UART_SetupAsyncReceiver();
|
||||||
|
|
||||||
// 1 ms timer
|
// 1 ms timer
|
||||||
@@ -93,4 +95,5 @@ void ICACHE_FLASH_ATTR serialInit(void)
|
|||||||
void ICACHE_FLASH_ATTR UART_HandleRxByte(char c)
|
void ICACHE_FLASH_ATTR UART_HandleRxByte(char c)
|
||||||
{
|
{
|
||||||
ansi_parser(c);
|
ansi_parser(c);
|
||||||
|
system_soft_wdt_feed(); // so we survive long torrents
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-1
@@ -12,9 +12,23 @@ SystemConfigBundle * const sysconf = &persist.current.sysconf;
|
|||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
sysconf_apply_settings(void)
|
sysconf_apply_settings(void)
|
||||||
{
|
{
|
||||||
// !!! Update to current version !!!
|
bool changed = false;
|
||||||
|
if (sysconf->config_version < 1) {
|
||||||
|
dbg("Upgrading syscfg to v 1");
|
||||||
|
sysconf->overclock = false;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysconf->config_version = SYSCONF_VERSION;
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
persist_store();
|
||||||
|
}
|
||||||
|
|
||||||
|
// uart settings live here, but the CGI handler + form has been moved to the Terminal config page
|
||||||
serialInit();
|
serialInit();
|
||||||
|
|
||||||
|
system_update_cpu_freq((uint8) (sysconf->overclock ? 160 : 80));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
@@ -23,4 +37,10 @@ sysconf_restore_defaults(void)
|
|||||||
sysconf->uart_parity = PARITY_NONE;
|
sysconf->uart_parity = PARITY_NONE;
|
||||||
sysconf->uart_baudrate = BIT_RATE_115200;
|
sysconf->uart_baudrate = BIT_RATE_115200;
|
||||||
sysconf->uart_stopbits = ONE_STOP_BIT;
|
sysconf->uart_stopbits = ONE_STOP_BIT;
|
||||||
|
sysconf->config_version = SYSCONF_VERSION;
|
||||||
|
sysconf->access_pw[0] = 0;
|
||||||
|
sysconf->pwlock = PWLOCK_NONE;
|
||||||
|
strcpy(sysconf->access_pw, DEF_ACCESS_PW);
|
||||||
|
strcpy(sysconf->access_name, DEF_ACCESS_NAME);
|
||||||
|
sysconf->overclock = false;
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-2
@@ -9,14 +9,30 @@
|
|||||||
|
|
||||||
// Size designed for the wifi config structure
|
// Size designed for the wifi config structure
|
||||||
// Must be constant to avoid corrupting user config after upgrade
|
// Must be constant to avoid corrupting user config after upgrade
|
||||||
#define SYSCONF_SIZE 200
|
#define SYSCONF_SIZE 300
|
||||||
#define SYSCONF_VERSION 0
|
#define SYSCONF_VERSION 1
|
||||||
|
|
||||||
|
#define DEF_ACCESS_PW "1234"
|
||||||
|
#define DEF_ACCESS_NAME "espterm"
|
||||||
|
|
||||||
|
enum pwlock {
|
||||||
|
PWLOCK_NONE = 0,
|
||||||
|
PWLOCK_SETTINGS_NOTERM = 1,
|
||||||
|
PWLOCK_SETTINGS_ALL = 2,
|
||||||
|
PWLOCK_MENUS = 3,
|
||||||
|
PWLOCK_ALL = 4,
|
||||||
|
PWLOCK_MAX = 5,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 uart_baudrate;
|
u32 uart_baudrate;
|
||||||
u8 uart_parity;
|
u8 uart_parity;
|
||||||
u8 uart_stopbits;
|
u8 uart_stopbits;
|
||||||
u8 config_version;
|
u8 config_version;
|
||||||
|
enum pwlock pwlock : 8; // page access lock
|
||||||
|
char access_pw[64]; // access password
|
||||||
|
char access_name[32]; // access name
|
||||||
|
bool overclock;
|
||||||
} SystemConfigBundle;
|
} SystemConfigBundle;
|
||||||
|
|
||||||
extern SystemConfigBundle * const sysconf;
|
extern SystemConfigBundle * const sysconf;
|
||||||
|
|||||||
+64
-47
@@ -8,8 +8,8 @@
|
|||||||
#include <esp8266.h>
|
#include <esp8266.h>
|
||||||
#include <uart_register.h>
|
#include <uart_register.h>
|
||||||
|
|
||||||
#define UART_TX_BUFFER_SIZE 512 //Ring buffer length of tx buffer
|
//#define buf_dbg(format, ...) printf(format "\r\n", ##__VA_ARGS__)
|
||||||
#define UART_RX_BUFFER_SIZE 512 //Ring buffer length of rx buffer
|
#define buf_dbg(format, ...) (void)format
|
||||||
|
|
||||||
struct UartBuffer {
|
struct UartBuffer {
|
||||||
uint32 UartBuffSize;
|
uint32 UartBuffSize;
|
||||||
@@ -22,12 +22,15 @@ struct UartBuffer {
|
|||||||
static struct UartBuffer *pTxBuffer = NULL;
|
static struct UartBuffer *pTxBuffer = NULL;
|
||||||
static struct UartBuffer *pRxBuffer = NULL;
|
static struct UartBuffer *pRxBuffer = NULL;
|
||||||
|
|
||||||
static struct UartBuffer *UART_AsyncBufferInit(uint32 buf_size);
|
static u8 rxArray[UART_RX_BUFFER_SIZE];
|
||||||
|
static u8 txArray[UART_TX_BUFFER_SIZE];
|
||||||
|
|
||||||
|
static struct UartBuffer *UART_AsyncBufferInit(uint32 buf_size, u8 *buffer);
|
||||||
|
|
||||||
void ICACHE_FLASH_ATTR UART_AllocBuffers(void)
|
void ICACHE_FLASH_ATTR UART_AllocBuffers(void)
|
||||||
{
|
{
|
||||||
pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE);
|
pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE, txArray);
|
||||||
pRxBuffer = UART_AsyncBufferInit(UART_RX_BUFFER_SIZE);
|
pRxBuffer = UART_AsyncBufferInit(UART_RX_BUFFER_SIZE, rxArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -37,7 +40,7 @@ void ICACHE_FLASH_ATTR UART_AllocBuffers(void)
|
|||||||
* Returns : NONE
|
* Returns : NONE
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
static struct UartBuffer *ICACHE_FLASH_ATTR
|
static struct UartBuffer *ICACHE_FLASH_ATTR
|
||||||
UART_AsyncBufferInit(uint32 buf_size)
|
UART_AsyncBufferInit(uint32 buf_size, u8 *buffer)
|
||||||
{
|
{
|
||||||
uint32 heap_size = system_get_free_heap_size();
|
uint32 heap_size = system_get_free_heap_size();
|
||||||
if (heap_size <= buf_size) {
|
if (heap_size <= buf_size) {
|
||||||
@@ -47,7 +50,7 @@ UART_AsyncBufferInit(uint32 buf_size)
|
|||||||
else {
|
else {
|
||||||
struct UartBuffer *pBuff = (struct UartBuffer *) malloc(sizeof(struct UartBuffer));
|
struct UartBuffer *pBuff = (struct UartBuffer *) malloc(sizeof(struct UartBuffer));
|
||||||
pBuff->UartBuffSize = buf_size;
|
pBuff->UartBuffSize = buf_size;
|
||||||
pBuff->pUartBuff = (uint8 *) malloc(pBuff->UartBuffSize);
|
pBuff->pUartBuff = buffer != NULL ? buffer : (uint8 *) malloc(pBuff->UartBuffSize);
|
||||||
pBuff->pInPos = pBuff->pUartBuff;
|
pBuff->pInPos = pBuff->pUartBuff;
|
||||||
pBuff->pOutPos = pBuff->pUartBuff;
|
pBuff->pOutPos = pBuff->pUartBuff;
|
||||||
pBuff->Space = (uint16) pBuff->UartBuffSize;
|
pBuff->Space = (uint16) pBuff->UartBuffSize;
|
||||||
@@ -55,6 +58,13 @@ UART_AsyncBufferInit(uint32 buf_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ICACHE_FLASH_ATTR
|
||||||
|
UART_AsyncBufferReset(struct UartBuffer *pBuff)
|
||||||
|
{
|
||||||
|
pBuff->pInPos = pBuff->pUartBuff;
|
||||||
|
pBuff->pOutPos = pBuff->pUartBuff;
|
||||||
|
pBuff->Space = (uint16) pBuff->UartBuffSize;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy data onto Buffer
|
* Copy data onto Buffer
|
||||||
@@ -67,23 +77,30 @@ UART_WriteToAsyncBuffer(struct UartBuffer *pCur, const char *pdata, uint16 data_
|
|||||||
{
|
{
|
||||||
if (data_len == 0) return;
|
if (data_len == 0) return;
|
||||||
|
|
||||||
|
buf_dbg("WTAB %d, space %d", data_len, pCur->Space);
|
||||||
|
|
||||||
uint16 tail_len = (uint16) (pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos);
|
uint16 tail_len = (uint16) (pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos);
|
||||||
if (tail_len >= data_len) { //do not need to loop back the queue
|
if (tail_len >= data_len) { //do not need to loop back the queue
|
||||||
|
buf_dbg("tail %d, no fold", tail_len);
|
||||||
memcpy(pCur->pInPos, pdata, data_len);
|
memcpy(pCur->pInPos, pdata, data_len);
|
||||||
pCur->pInPos += (data_len);
|
pCur->pInPos += (data_len);
|
||||||
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize);
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize);
|
||||||
pCur->Space -= data_len;
|
pCur->Space -= data_len;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
buf_dbg("tail only %d, folding", tail_len);
|
||||||
memcpy(pCur->pInPos, pdata, tail_len);
|
memcpy(pCur->pInPos, pdata, tail_len);
|
||||||
|
buf_dbg("chunk 1, %d", tail_len);
|
||||||
pCur->pInPos += (tail_len);
|
pCur->pInPos += (tail_len);
|
||||||
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize);
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize);
|
||||||
pCur->Space -= tail_len;
|
pCur->Space -= tail_len;
|
||||||
|
buf_dbg("chunk 2, %d", data_len - tail_len);
|
||||||
memcpy(pCur->pInPos, pdata + tail_len, data_len - tail_len);
|
memcpy(pCur->pInPos, pdata + tail_len, data_len - tail_len);
|
||||||
pCur->pInPos += (data_len - tail_len);
|
pCur->pInPos += (data_len - tail_len);
|
||||||
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize);
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize);
|
||||||
pCur->Space -= (data_len - tail_len);
|
pCur->Space -= (data_len - tail_len);
|
||||||
}
|
}
|
||||||
|
buf_dbg("new space %d", pCur->Space);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
@@ -158,24 +175,33 @@ void UART_RxFifoCollect(void)
|
|||||||
uint8 fifo_data;
|
uint8 fifo_data;
|
||||||
fifo_len = (uint8) ((READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT);
|
fifo_len = (uint8) ((READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT);
|
||||||
if (fifo_len >= pRxBuffer->Space) {
|
if (fifo_len >= pRxBuffer->Space) {
|
||||||
UART_WriteChar(UART1, '%', 100);
|
fifo_len = (uint8) (pRxBuffer->Space - 1);
|
||||||
}
|
UART_WriteChar(UART1, '#', 10);
|
||||||
else {
|
// discard contents of the FIFO - would loop forever
|
||||||
buf_idx = 0;
|
buf_idx = 0;
|
||||||
while (buf_idx < fifo_len) {
|
while (buf_idx < fifo_len) {
|
||||||
buf_idx++;
|
buf_idx++;
|
||||||
fifo_data = (uint8) (READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);
|
fifo_data = (uint8) (READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);
|
||||||
*(pRxBuffer->pInPos++) = fifo_data;
|
(void)fifo_data; // pretend we use it
|
||||||
if (pRxBuffer->pInPos == (pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize)) {
|
|
||||||
pRxBuffer->pInPos = pRxBuffer->pUartBuff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pRxBuffer->Space -= fifo_len;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (pRxBuffer->Space >= UART_FIFO_LEN) {
|
buf_idx = 0;
|
||||||
uart_rx_intr_enable(UART0);
|
while (buf_idx < fifo_len) {
|
||||||
|
buf_idx++;
|
||||||
|
fifo_data = (uint8) (READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);
|
||||||
|
*(pRxBuffer->pInPos++) = fifo_data;
|
||||||
|
if (pRxBuffer->pInPos == (pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize)) {
|
||||||
|
pRxBuffer->pInPos = pRxBuffer->pUartBuff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pRxBuffer->Space -= fifo_len;
|
||||||
|
//
|
||||||
|
// this is called by the processing routine, no need here
|
||||||
|
// if (pRxBuffer->Space >= UART_FIFO_LEN) {
|
||||||
|
// uart_rx_intr_enable(UART0);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 ICACHE_FLASH_ATTR UART_AsyncTxGetEmptySpace(void)
|
u16 ICACHE_FLASH_ATTR UART_AsyncTxGetEmptySpace(void)
|
||||||
@@ -183,35 +209,30 @@ u16 ICACHE_FLASH_ATTR UART_AsyncTxGetEmptySpace(void)
|
|||||||
return pTxBuffer->Space;
|
return pTxBuffer->Space;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u16 ICACHE_FLASH_ATTR UART_AsyncTxCount(void)
|
||||||
|
{
|
||||||
|
return (u16) (pTxBuffer->UartBuffSize - pTxBuffer->Space);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule data to be sent
|
* Schedule data to be sent
|
||||||
* @param pdata
|
* @param pdata
|
||||||
* @param data_len - can be -1 for strlen
|
* @param data_len - can be -1 for strlen
|
||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
UART_SendAsync(const char *pdata, int16_t data_len)
|
UART_SendAsync(const char *pdata, int data_len)
|
||||||
{
|
{
|
||||||
u16 real_len = (u16) data_len;
|
size_t real_len = (data_len) <= 0 ? strlen(pdata) : (size_t) data_len;
|
||||||
if (data_len <= 0) real_len = (u16) strlen(pdata);
|
|
||||||
|
|
||||||
// if (pTxBuffer == NULL) {
|
buf_dbg("Send Async %d", real_len);
|
||||||
// printf("init tx buf\n\r");
|
if (real_len <= pTxBuffer->Space) {
|
||||||
// pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE);
|
buf_dbg("accepted, space %d", pTxBuffer->Space);
|
||||||
// if (pTxBuffer != NULL) {
|
UART_WriteToAsyncBuffer(pTxBuffer, pdata, (uint16) real_len);
|
||||||
// UART_WriteToAsyncBuffer(pTxBuffer, pdata, real_len);
|
}
|
||||||
// }
|
else {
|
||||||
// else {
|
buf_dbg("FULL!");
|
||||||
// printf("tx alloc fail\r\n");
|
UART_WriteChar(UART1, '=', 10);
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
if (real_len <= pTxBuffer->Space) {
|
|
||||||
UART_WriteToAsyncBuffer(pTxBuffer, pdata, real_len);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
UART_WriteChar(UART1, '^', 100);
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Here we enable TX empty interrupt that will take care of sending the content
|
// Here we enable TX empty interrupt that will take care of sending the content
|
||||||
SET_PERI_REG_MASK(UART_CONF1(UART0), (UART_TX_EMPTY_THRESH_VAL & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
|
SET_PERI_REG_MASK(UART_CONF1(UART0), (UART_TX_EMPTY_THRESH_VAL & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
|
||||||
@@ -247,8 +268,8 @@ void UART_DispatchFromTxBuffer(uint8 uart_no)
|
|||||||
uint8 len_tmp;
|
uint8 len_tmp;
|
||||||
uint16 data_len;
|
uint16 data_len;
|
||||||
|
|
||||||
// if (pTxBuffer) {
|
data_len = (uint16) (pTxBuffer->UartBuffSize - pTxBuffer->Space);
|
||||||
data_len = (uint8) (pTxBuffer->UartBuffSize - pTxBuffer->Space);
|
buf_dbg("rem %d",data_len);
|
||||||
if (data_len > fifo_remain) {
|
if (data_len > fifo_remain) {
|
||||||
len_tmp = fifo_remain;
|
len_tmp = fifo_remain;
|
||||||
UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no);
|
UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no);
|
||||||
@@ -258,8 +279,9 @@ void UART_DispatchFromTxBuffer(uint8 uart_no)
|
|||||||
len_tmp = (uint8) data_len;
|
len_tmp = (uint8) data_len;
|
||||||
UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no);
|
UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no);
|
||||||
|
|
||||||
// we get one more IT after fifo ends even if we have 0 more bytes
|
// We get one more IT after fifo ends even if we have 0 more bytes,
|
||||||
// for notify
|
// for notify. Otherwise we would say we have space while the FIFO
|
||||||
|
// was still running
|
||||||
if (next_empty_it_only_for_notify) {
|
if (next_empty_it_only_for_notify) {
|
||||||
notify_empty_txbuf();
|
notify_empty_txbuf();
|
||||||
next_empty_it_only_for_notify = 0;
|
next_empty_it_only_for_notify = 0;
|
||||||
@@ -269,9 +291,4 @@ void UART_DispatchFromTxBuffer(uint8 uart_no)
|
|||||||
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
|
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// error("pTxBuff null \n\r");
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
#include <esp8266.h>
|
#include <esp8266.h>
|
||||||
|
|
||||||
|
#define UART_TX_BUFFER_SIZE 1000 //Ring buffer length of tx buffer
|
||||||
|
#define UART_RX_BUFFER_SIZE 600 //Ring buffer length of rx buffer
|
||||||
|
|
||||||
// the init func
|
// the init func
|
||||||
void UART_AllocBuffers(void);
|
void UART_AllocBuffers(void);
|
||||||
|
|
||||||
@@ -14,7 +17,7 @@ void UART_AllocBuffers(void);
|
|||||||
uint16 UART_ReadAsync(char *pdata, uint16 data_len);
|
uint16 UART_ReadAsync(char *pdata, uint16 data_len);
|
||||||
|
|
||||||
// write to tx buffer
|
// write to tx buffer
|
||||||
void UART_SendAsync(const char *pdata, int16_t data_len);
|
void UART_SendAsync(const char *pdata, int data_len);
|
||||||
|
|
||||||
//move data from uart fifo to rx buffer
|
//move data from uart fifo to rx buffer
|
||||||
void UART_RxFifoCollect(void);
|
void UART_RxFifoCollect(void);
|
||||||
@@ -22,6 +25,7 @@ void UART_RxFifoCollect(void);
|
|||||||
void UART_DispatchFromTxBuffer(uint8 uart_no);
|
void UART_DispatchFromTxBuffer(uint8 uart_no);
|
||||||
|
|
||||||
u16 UART_AsyncRxCount(void);
|
u16 UART_AsyncRxCount(void);
|
||||||
|
u16 UART_AsyncTxCount(void);
|
||||||
|
|
||||||
u16 UART_AsyncTxGetEmptySpace(void);
|
u16 UART_AsyncTxGetEmptySpace(void);
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -24,8 +24,8 @@ static void uart_recvTask(os_event_t *events);
|
|||||||
static void uart_processTask(os_event_t *events);
|
static void uart_processTask(os_event_t *events);
|
||||||
|
|
||||||
// Those heavily affect the byte loss ratio
|
// Those heavily affect the byte loss ratio
|
||||||
#define PROCESS_CHUNK_LEN 1
|
#define PROCESS_CHUNK_LEN 10
|
||||||
#define FIFO_FULL_THRES 4
|
#define RX_FIFO_FULL_THRES 40
|
||||||
|
|
||||||
#define uart_recvTaskPrio 1
|
#define uart_recvTaskPrio 1
|
||||||
#define uart_recvTaskQueueLen 25
|
#define uart_recvTaskQueueLen 25
|
||||||
@@ -52,6 +52,7 @@ void ICACHE_FLASH_ATTR UART_Init(void)
|
|||||||
|
|
||||||
// U0RXD
|
// U0RXD
|
||||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
|
||||||
|
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0RXD_U);
|
||||||
|
|
||||||
// U1TXD (GPIO2)
|
// U1TXD (GPIO2)
|
||||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
|
||||||
@@ -78,8 +79,8 @@ void ICACHE_FLASH_ATTR UART_SetupAsyncReceiver(void)
|
|||||||
ETS_UART_INTR_ATTACH((void *)uart0_rx_intr_handler, &(UartDev.rcv_buff)); // the buf will be used as an arg
|
ETS_UART_INTR_ATTACH((void *)uart0_rx_intr_handler, &(UartDev.rcv_buff)); // the buf will be used as an arg
|
||||||
|
|
||||||
// fifo threshold config (max: UART_RXFIFO_FULL_THRHD = 127)
|
// fifo threshold config (max: UART_RXFIFO_FULL_THRHD = 127)
|
||||||
uint32_t conf = ((FIFO_FULL_THRES & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
|
uint32_t conf = ((RX_FIFO_FULL_THRES & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
|
||||||
conf |= ((0x10 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
|
conf |= ((0x05 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
|
||||||
// timeout config
|
// timeout config
|
||||||
conf |= ((0x06 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S); // timeout threshold
|
conf |= ((0x06 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S); // timeout threshold
|
||||||
conf |= UART_RX_TOUT_EN; // enable timeout
|
conf |= UART_RX_TOUT_EN; // enable timeout
|
||||||
|
|||||||
+38
-17
@@ -28,6 +28,9 @@
|
|||||||
#include "ansi_parser_callbacks.h"
|
#include "ansi_parser_callbacks.h"
|
||||||
#include "wifimgr.h"
|
#include "wifimgr.h"
|
||||||
#include "persist.h"
|
#include "persist.h"
|
||||||
|
#include "ansi_parser.h"
|
||||||
|
#include "ascii.h"
|
||||||
|
#include "uart_buffer.h"
|
||||||
|
|
||||||
#ifdef ESPFS_POS
|
#ifdef ESPFS_POS
|
||||||
CgiUploadFlashDef uploadParams={
|
CgiUploadFlashDef uploadParams={
|
||||||
@@ -49,6 +52,7 @@ CgiUploadFlashDef uploadParams={
|
|||||||
#define INCLUDE_FLASH_FNS
|
#define INCLUDE_FLASH_FNS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define HEAP_TIMER_MS 1000
|
||||||
/** Periodically show heap usage */
|
/** Periodically show heap usage */
|
||||||
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg)
|
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg)
|
||||||
{
|
{
|
||||||
@@ -58,18 +62,24 @@ static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg)
|
|||||||
int heap = system_get_free_heap_size();
|
int heap = system_get_free_heap_size();
|
||||||
int diff = (heap-last);
|
int diff = (heap-last);
|
||||||
|
|
||||||
|
int rxc = UART_AsyncRxCount();
|
||||||
|
int txc = UART_AsyncTxCount();
|
||||||
|
|
||||||
|
int rxp = ((rxc*10000) / UART_RX_BUFFER_SIZE)/100;
|
||||||
|
int txp = ((txc*10000) / UART_TX_BUFFER_SIZE)/100;
|
||||||
|
|
||||||
const char *cc = "+";
|
const char *cc = "+";
|
||||||
if (diff<0) cc = "";
|
if (diff<0) cc = "";
|
||||||
|
|
||||||
if (diff == 0) {
|
if (diff == 0) {
|
||||||
if (cnt == 5) {
|
if (cnt == 5) {
|
||||||
// only every 5 secs if no change
|
// only every 5 secs if no change
|
||||||
dbg("FH: %d", heap);
|
dbg("Rx/Tx: %d/%d%c, Hp: %d", rxp, txp, '%', heap);
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// report change
|
// report change
|
||||||
dbg("FH: %d (%s%d)", heap, cc, diff);
|
dbg("Rx/Tx: %d/%d%c, Hp: %d (%s%d)", rxp, txp, '%', heap, cc, diff);
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +89,6 @@ static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg)
|
|||||||
|
|
||||||
// Deferred init
|
// Deferred init
|
||||||
static void user_start(void *unused);
|
static void user_start(void *unused);
|
||||||
static void user_start2(void *unused);
|
|
||||||
|
|
||||||
static ETSTimer userStartTimer;
|
static ETSTimer userStartTimer;
|
||||||
static ETSTimer prHeapTimer;
|
static ETSTimer prHeapTimer;
|
||||||
@@ -87,6 +96,7 @@ static ETSTimer prHeapTimer;
|
|||||||
//Main routine. Initialize stdout, the I/O, filesystem and the webserver and we're done.
|
//Main routine. Initialize stdout, the I/O, filesystem and the webserver and we're done.
|
||||||
void ICACHE_FLASH_ATTR user_init(void)
|
void ICACHE_FLASH_ATTR user_init(void)
|
||||||
{
|
{
|
||||||
|
ansi_parser_inhibit = true;
|
||||||
serialInitBase();
|
serialInitBase();
|
||||||
|
|
||||||
// Prevent WiFi starting and connecting by default
|
// Prevent WiFi starting and connecting by default
|
||||||
@@ -94,13 +104,22 @@ void ICACHE_FLASH_ATTR user_init(void)
|
|||||||
wifi_station_set_auto_connect(false);
|
wifi_station_set_auto_connect(false);
|
||||||
wifi_set_opmode(NULL_MODE); // saves to flash if changed - this might avoid the current spike on startup?
|
wifi_set_opmode(NULL_MODE); // saves to flash if changed - this might avoid the current spike on startup?
|
||||||
|
|
||||||
printf("\r\n");
|
u8 mac[6];
|
||||||
banner("====== ESPTerm ======");
|
wifi_get_macaddr(SOFTAP_IF, mac);
|
||||||
banner_info("Firmware (c) Ondrej Hruska, 2017");
|
|
||||||
banner_info(TERMINAL_GITHUB_REPO);
|
banner_gap();
|
||||||
banner_info("");
|
banner("================ ESPTerm ================");
|
||||||
banner_info("Version "FIRMWARE_VERSION", built " __DATE__ " at " __TIME__);
|
banner_info();
|
||||||
printf("\r\n");
|
banner_info("Project by Ondrej Hruska, 2017");
|
||||||
|
banner_info();
|
||||||
|
banner_info(TERMINAL_GITHUB_REPO_NOPROTO);
|
||||||
|
banner_info();
|
||||||
|
banner_info("Version "FW_VERSION" ("ESP_LANG"), code name "FW_CODENAME_QUOTED);
|
||||||
|
banner_info(" back-end #"GIT_HASH_BACKEND" front-end #"GIT_HASH_FRONTEND);
|
||||||
|
banner_info(" built "__DATE__" at "__TIME__" "__TIMEZONE__);
|
||||||
|
banner_info();
|
||||||
|
banner_info("Device ID: %02X%02X%02X", mac[3], mac[4], mac[5]);
|
||||||
|
banner_gap();
|
||||||
|
|
||||||
ioInit();
|
ioInit();
|
||||||
|
|
||||||
@@ -112,16 +131,10 @@ void ICACHE_FLASH_ATTR user_init(void)
|
|||||||
espFsInit((void *) (webpages_espfs_start));
|
espFsInit((void *) (webpages_espfs_start));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if DEBUG_HEAP
|
|
||||||
// Heap use timer & blink
|
|
||||||
TIMER_START(&prHeapTimer, prHeapTimerCb, 1000, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// do later (some functions do not work if called from user_init)
|
// do later (some functions do not work if called from user_init)
|
||||||
TIMER_START(&userStartTimer, user_start, 10, 0);
|
TIMER_START(&userStartTimer, user_start, 10, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ICACHE_FLASH_ATTR user_start(void *unused)
|
static void ICACHE_FLASH_ATTR user_start(void *unused)
|
||||||
{
|
{
|
||||||
// Load and apply stored settings, or defaults if stored settings are invalid
|
// Load and apply stored settings, or defaults if stored settings are invalid
|
||||||
@@ -129,10 +142,18 @@ static void ICACHE_FLASH_ATTR user_start(void *unused)
|
|||||||
|
|
||||||
captdnsInit();
|
captdnsInit();
|
||||||
httpdInit(routes, 80);
|
httpdInit(routes, 80);
|
||||||
|
httpdSetName("ESPTerm " VERSION_STRING);
|
||||||
|
|
||||||
|
ansi_parser_inhibit = false;
|
||||||
|
|
||||||
// Print the CANCEL character to indicate the module has restarted
|
// Print the CANCEL character to indicate the module has restarted
|
||||||
// Critically important for client application if any kind of screen persistence / content re-use is needed
|
// Critically important for client application if any kind of screen persistence / content re-use is needed
|
||||||
UART_WriteChar(UART0, 24, UART_TIMEOUT_US); // 0x18 - 24 - CAN
|
UART_WriteChar(UART0, CAN, UART_TIMEOUT_US); // 0x18 - 24 - CAN
|
||||||
|
|
||||||
|
#if DEBUG_HEAP
|
||||||
|
// Heap use timer & blink
|
||||||
|
TIMER_START(&prHeapTimer, prHeapTimerCb, HEAP_TIMER_MS, 1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- unused funcs removed from sdk to save space ---
|
// ---- unused funcs removed from sdk to save space ---
|
||||||
|
|||||||
+35
-5
@@ -20,7 +20,8 @@ static UnicodeCacheSlot cache[UNICODE_CACHE_SIZE];
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void ICACHE_FLASH_ATTR
|
void ICACHE_FLASH_ATTR
|
||||||
unicode_cache_clear(void) {
|
unicode_cache_clear(void)
|
||||||
|
{
|
||||||
utfc_dbg("utf8 cache clear!");
|
utfc_dbg("utf8 cache clear!");
|
||||||
for (int slot = 0; slot < UNICODE_CACHE_SIZE; slot++) {
|
for (int slot = 0; slot < UNICODE_CACHE_SIZE; slot++) {
|
||||||
cache[slot].count=0;
|
cache[slot].count=0;
|
||||||
@@ -35,7 +36,8 @@ unicode_cache_clear(void) {
|
|||||||
* @return the obtained look-up reference
|
* @return the obtained look-up reference
|
||||||
*/
|
*/
|
||||||
UnicodeCacheRef ICACHE_FLASH_ATTR
|
UnicodeCacheRef ICACHE_FLASH_ATTR
|
||||||
unicode_cache_add(const u8 *bytes) {
|
unicode_cache_add(const u8 *bytes)
|
||||||
|
{
|
||||||
if (bytes[0] < 32) {
|
if (bytes[0] < 32) {
|
||||||
utfc_warn("utf8 cache bad char '%c'", bytes[0]);
|
utfc_warn("utf8 cache bad char '%c'", bytes[0]);
|
||||||
return '?';
|
return '?';
|
||||||
@@ -69,6 +71,27 @@ unicode_cache_add(const u8 *bytes) {
|
|||||||
return ID_TO_REF(slot);
|
return ID_TO_REF(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment a reference
|
||||||
|
*
|
||||||
|
* @param ref - reference
|
||||||
|
* @return success
|
||||||
|
*/
|
||||||
|
bool ICACHE_FLASH_ATTR
|
||||||
|
unicode_cache_inc(UnicodeCacheRef ref)
|
||||||
|
{
|
||||||
|
if (!IS_UNICODE_CACHE_REF(ref)) return true; // ASCII
|
||||||
|
|
||||||
|
int slot = REF_TO_ID(ref);
|
||||||
|
if (cache[slot].count == 0) {
|
||||||
|
utfc_warn("utf8 cache inc-after-free ref @ %d", ref);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cache[slot].count++;
|
||||||
|
utfc_dbg("utf8 cache inc '%.4s' @ %d, %d uses", cache[slot].bytes, slot, cache[slot].count);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up a code point in the cache by reference. Do not change the use counter.
|
* Look up a code point in the cache by reference. Do not change the use counter.
|
||||||
*
|
*
|
||||||
@@ -77,7 +100,8 @@ unicode_cache_add(const u8 *bytes) {
|
|||||||
* @return true if the look-up succeeded
|
* @return true if the look-up succeeded
|
||||||
*/
|
*/
|
||||||
bool ICACHE_FLASH_ATTR
|
bool ICACHE_FLASH_ATTR
|
||||||
unicode_cache_retrieve(UnicodeCacheRef ref, u8 *target) {
|
unicode_cache_retrieve(UnicodeCacheRef ref, u8 *target)
|
||||||
|
{
|
||||||
if (!IS_UNICODE_CACHE_REF(ref)) {
|
if (!IS_UNICODE_CACHE_REF(ref)) {
|
||||||
// ASCII, bypass
|
// ASCII, bypass
|
||||||
target[0] = ref;
|
target[0] = ref;
|
||||||
@@ -107,7 +131,8 @@ unicode_cache_retrieve(UnicodeCacheRef ref, u8 *target) {
|
|||||||
* @return true if the code point was found in the cache
|
* @return true if the code point was found in the cache
|
||||||
*/
|
*/
|
||||||
bool ICACHE_FLASH_ATTR
|
bool ICACHE_FLASH_ATTR
|
||||||
unicode_cache_remove(UnicodeCacheRef ref) {
|
unicode_cache_remove(UnicodeCacheRef ref)
|
||||||
|
{
|
||||||
if (!IS_UNICODE_CACHE_REF(ref)) return true; // ASCII, bypass
|
if (!IS_UNICODE_CACHE_REF(ref)) return true; // ASCII, bypass
|
||||||
|
|
||||||
u8 slot = REF_TO_ID(ref);
|
u8 slot = REF_TO_ID(ref);
|
||||||
@@ -135,8 +160,13 @@ unicode_cache_remove(UnicodeCacheRef ref) {
|
|||||||
* @return number of bytes on success, 0 on failure (also produces U+FFFD, which uses 3 bytes)
|
* @return number of bytes on success, 0 on failure (also produces U+FFFD, which uses 3 bytes)
|
||||||
*/
|
*/
|
||||||
int ICACHE_FLASH_ATTR
|
int ICACHE_FLASH_ATTR
|
||||||
utf8_encode(char *out, uint32_t utf)
|
utf8_encode(char *out, uint32_t utf, bool surrogateFix)
|
||||||
{
|
{
|
||||||
|
// Skip the surrogate block (wtf, unicode???)
|
||||||
|
if (surrogateFix && utf >= 0xD800) {
|
||||||
|
utf += 0x800;
|
||||||
|
}
|
||||||
|
|
||||||
if (utf <= 0x7F) {
|
if (utf <= 0x7F) {
|
||||||
// Plain ASCII
|
// Plain ASCII
|
||||||
out[0] = (char) utf;
|
out[0] = (char) utf;
|
||||||
|
|||||||
+11
-2
@@ -8,7 +8,7 @@
|
|||||||
#include <c_types.h>
|
#include <c_types.h>
|
||||||
|
|
||||||
// 160 is maximum possible
|
// 160 is maximum possible
|
||||||
#define UNICODE_CACHE_SIZE 100
|
#define UNICODE_CACHE_SIZE 160
|
||||||
|
|
||||||
typedef u8 UnicodeCacheRef;
|
typedef u8 UnicodeCacheRef;
|
||||||
#define IS_UNICODE_CACHE_REF(c) ((c) < 32 || (c) >= 127)
|
#define IS_UNICODE_CACHE_REF(c) ((c) < 32 || (c) >= 127)
|
||||||
@@ -28,6 +28,14 @@ void unicode_cache_clear(void);
|
|||||||
*/
|
*/
|
||||||
UnicodeCacheRef unicode_cache_add(const u8 *bytes);
|
UnicodeCacheRef unicode_cache_add(const u8 *bytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment a reference
|
||||||
|
*
|
||||||
|
* @param ref - reference
|
||||||
|
* @return success
|
||||||
|
*/
|
||||||
|
bool unicode_cache_inc(UnicodeCacheRef ref);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up a code point in the cache by reference. Do not change the use counter.
|
* Look up a code point in the cache by reference. Do not change the use counter.
|
||||||
*
|
*
|
||||||
@@ -55,9 +63,10 @@ bool unicode_cache_remove(UnicodeCacheRef ref);
|
|||||||
*
|
*
|
||||||
* @param out - output buffer (min 4 characters), will be 0-terminated if shorten than 4
|
* @param out - output buffer (min 4 characters), will be 0-terminated if shorten than 4
|
||||||
* @param utf - code point 0-0x10FFFF
|
* @param utf - code point 0-0x10FFFF
|
||||||
|
* @param surrogateFix - add 0x800 to 0xD800-0xDFFF to avoid invalid code points
|
||||||
* @return number of bytes on success, 0 on failure (also produces U+FFFD, which uses 3 bytes)
|
* @return number of bytes on success, 0 on failure (also produces U+FFFD, which uses 3 bytes)
|
||||||
*/
|
*/
|
||||||
int utf8_encode(char *out, uint32_t utf);
|
int utf8_encode(char *out, uint32_t utf, bool surrogateFix);
|
||||||
|
|
||||||
#if DEBUG_UTFCACHE
|
#if DEBUG_UTFCACHE
|
||||||
#define utfc_warn warn
|
#define utfc_warn warn
|
||||||
|
|||||||
+15
-3
@@ -5,13 +5,25 @@
|
|||||||
#ifndef ESP_VT100_FIRMWARE_VERSION_H
|
#ifndef ESP_VT100_FIRMWARE_VERSION_H
|
||||||
#define ESP_VT100_FIRMWARE_VERSION_H
|
#define ESP_VT100_FIRMWARE_VERSION_H
|
||||||
|
|
||||||
#define FW_V_MAJOR 1
|
#define STR_HELPER(x) #x
|
||||||
|
#define STR(x) STR_HELPER(x)
|
||||||
|
|
||||||
|
#define FW_V_MAJOR 2
|
||||||
#define FW_V_MINOR 1
|
#define FW_V_MINOR 1
|
||||||
#define FW_V_PATCH 0
|
#define FW_V_PATCH 0
|
||||||
|
#define FW_V_SUFFIX ""
|
||||||
|
#define FW_CODENAME "Anthill" // 2.1.0
|
||||||
|
#define FW_CODENAME_QUOTED "\""FW_CODENAME"\""
|
||||||
|
|
||||||
|
#define FW_VERSION STR(FW_V_MAJOR) "." STR(FW_V_MINOR) "." STR(FW_V_PATCH) FW_V_SUFFIX
|
||||||
|
|
||||||
|
#define VERSION_STRING FW_VERSION " " FW_CODENAME_QUOTED
|
||||||
|
|
||||||
#define FIRMWARE_VERSION STR(FW_V_MAJOR) "." STR(FW_V_MINOR) "." STR(FW_V_PATCH)
|
|
||||||
#define FIRMWARE_VERSION_NUM (FW_V_MAJOR*1000 + FW_V_MINOR*10 + FW_V_PATCH) // this is used in ID queries
|
#define FIRMWARE_VERSION_NUM (FW_V_MAJOR*1000 + FW_V_MINOR*10 + FW_V_PATCH) // this is used in ID queries
|
||||||
#define TERMINAL_GITHUB_REPO "https://github.com/espterm/espterm-firmware"
|
|
||||||
|
#define TERMINAL_GITHUB_REPO_NOPROTO "github.com/espterm/espterm-firmware"
|
||||||
|
#define TERMINAL_GITHUB_REPO "https://"TERMINAL_GITHUB_REPO_NOPROTO
|
||||||
|
|
||||||
#define TERMINAL_GITHUB_REPO_FRONT "https://github.com/espterm/espterm-front-end"
|
#define TERMINAL_GITHUB_REPO_FRONT "https://github.com/espterm/espterm-front-end"
|
||||||
|
|
||||||
#endif //ESP_VT100_FIRMWARE_VERSION_H
|
#endif //ESP_VT100_FIRMWARE_VERSION_H
|
||||||
|
|||||||
@@ -8,6 +8,22 @@
|
|||||||
WiFiConfigBundle * const wificonf = &persist.current.wificonf;
|
WiFiConfigBundle * const wificonf = &persist.current.wificonf;
|
||||||
WiFiConfChangeFlags wifi_change_flags;
|
WiFiConfChangeFlags wifi_change_flags;
|
||||||
|
|
||||||
|
int ICACHE_FLASH_ATTR getStaIpAsString(char *buffer)
|
||||||
|
{
|
||||||
|
WIFI_MODE x = wifi_get_opmode();
|
||||||
|
STATION_STATUS connectStatus = wifi_station_get_connect_status();
|
||||||
|
|
||||||
|
if (x == SOFTAP_MODE || connectStatus != STATION_GOT_IP || wificonf->opmode == SOFTAP_MODE) {
|
||||||
|
strcpy(buffer, "");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct ip_info info;
|
||||||
|
wifi_get_ip_info(STATION_IF, &info);
|
||||||
|
return sprintf(buffer, IPSTR, GOOD_IP2STR(info.ip.addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore defaults in the WiFi config block.
|
* Restore defaults in the WiFi config block.
|
||||||
* This is to be called if the WiFi config is corrupted on startup,
|
* This is to be called if the WiFi config is corrupted on startup,
|
||||||
@@ -187,6 +203,10 @@ wifimgr_apply_settings(void)
|
|||||||
configure_ap();
|
configure_ap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tpw seems to be common - but info is scarce
|
||||||
|
// at any rate seems to do no harm to have it here
|
||||||
|
system_phy_set_max_tpw(wificonf->tpw);
|
||||||
|
|
||||||
wifi_change_flags.ap = false;
|
wifi_change_flags.ap = false;
|
||||||
wifi_change_flags.sta = false;
|
wifi_change_flags.sta = false;
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ void wifimgr_restore_defaults(void);
|
|||||||
|
|
||||||
void wifimgr_apply_settings(void);
|
void wifimgr_apply_settings(void);
|
||||||
|
|
||||||
|
int getStaIpAsString(char *buffer);
|
||||||
|
|
||||||
#if DEBUG_WIFI
|
#if DEBUG_WIFI
|
||||||
#define wifi_warn warn
|
#define wifi_warn warn
|
||||||
#define wifi_dbg dbg
|
#define wifi_dbg dbg
|
||||||
|
|||||||
Reference in New Issue
Block a user