Compare commits
7
Commits
1.0.0-beta
...
1.0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a20ec8a49e | ||
|
|
831ebe3b54 | ||
|
|
ea3c815a39 | ||
|
|
85f707401d | ||
|
|
0dbfbf707f | ||
|
|
a18b1d726e | ||
|
|
f8e3454250 |
@@ -1,4 +1,5 @@
|
|||||||
html/
|
html/
|
||||||
|
html_demo/
|
||||||
build/
|
build/
|
||||||
firmware/
|
firmware/
|
||||||
espfs/mkespfsimage/*.o
|
espfs/mkespfsimage/*.o
|
||||||
|
|||||||
@@ -1,92 +1,120 @@
|
|||||||
# ESPTerm
|
# ESPTerm
|
||||||
|
|
||||||
ESPTerm is a terminal emulator running on the ESP8266 WiFi chip.
|
**ESPTerm is a VT100-like terminal emulator running on the ESP8266 WiFi chip.**
|
||||||
The firmware emulates VT102 with some additional features based on `xterm` and later VT models, and the terminal screen can be accessed using any web browser, even on a phone or tablet. It works with ESP-01, ESP-01S, ESP-12 and likely many other modules (I use ESP-12 on a NodeMCU board for development).
|
|
||||||
|
|
||||||
ESPTerm can add remote access via WiFi to any embeded project, all you need is a serial port.
|
![Photo][photo-hw]<br>
|
||||||
|
*Fig 1: Breadboard adapter developed for ESPTerm*
|
||||||
|
|
||||||
## Screenshots, photos
|
Version 1.0.0 **passes most of VTTEST test cases** (from the main menu and some Xterm specific), making it
|
||||||
|
functionally comparable to eg. gnome-terminal, terminator, konsole, GtkTerm or PuTTY.
|
||||||
|
ESPTerm is **capable of running Midnight Commander** through agetty, **including full
|
||||||
|
mouse support**, provided agetty is made to believe it's Xterm, which shows ESPTerm is sufficiently well
|
||||||
|
implemented to work with ncurses.
|
||||||
|
|
||||||
- Look at the [GitHub releases page][releases], there are some pics.
|
To see what escape sequences are supported, check out this [annotated Xterm manual page][xterm-compare]
|
||||||
|
which was used for reference, or the built-in help page ([online demo][demo-help])
|
||||||
|
|
||||||
## ESPTerm features
|
The terminal screen can be accessed using any web browser, even on a phone or tablet.
|
||||||
|
It works with ESP-01, ESP-01S, ESP-12 and likely many other modules (I use an ESP-12
|
||||||
|
on a LoLin NodeMCU board from eBay for development).
|
||||||
|
|
||||||
- **Robust WiFi configuration interface**
|
With ESPTerm, you can add remote access via WiFi to any embeded project, all you need is
|
||||||
- static IP
|
a serial port and some imagination!
|
||||||
- DHCP
|
|
||||||
- AP channel and strength setting
|
## Try it online
|
||||||
- AP password
|
|
||||||
- SSID search for finding your existing network
|
You can try the web user interface here: [espterm.github.io][demo-term]
|
||||||
- **Almost complete VT102 emulation** with some extras
|
|
||||||
- *Sufficient to run most Linux console applications, including ncurses-based ones\**
|
The demo is almost identical to the real thing, except, of course, it doesn't do much without the
|
||||||
- All standard SGR (text style attributes) supported
|
emulator backend that runs on the ESP8266. The web version will be updated to match this repository
|
||||||
- Full UTF-8 support
|
after each minor release.
|
||||||
- Alternate character sets support
|
|
||||||
- 16 colors
|
## Main features
|
||||||
- Scrolling Region, Origin Mode
|
|
||||||
- Tab Stops
|
- **Almost complete VT102 emulation** with some extras from Xterm, eg.
|
||||||
- Cursor save/restore
|
|
||||||
- Character/Line insert, delete, clear operations
|
|
||||||
- Audible BEL (ASCII 7 beep)
|
|
||||||
- Most standard queries (get cursor position, get SGR, get screen size...)
|
|
||||||
- All DEC private options either implemented or safely consumed by the parser
|
|
||||||
- **Other features:**
|
|
||||||
- Screen size up to 80x25
|
- Screen size up to 80x25
|
||||||
|
- All standard text styles and 16 colors supported
|
||||||
|
- Full UTF-8 support, alternate character sets
|
||||||
|
- Standard mouse tracking modes
|
||||||
|
- You can dynamically set screen title, button labels...
|
||||||
|
- **Web Interface**
|
||||||
- Real-time screen update via WebSocket
|
- Real-time screen update via WebSocket
|
||||||
- Button to open Android software keyboard
|
- Button to open keyboard on Android
|
||||||
- 5 buttons under the screen for quick commands
|
- 5 buttons under the screen for quick commands
|
||||||
- Button labels can be changed (by OSC commands or via settings)
|
- Text file upload tool with configurable delays and line endings
|
||||||
- Screen title can be changed (by OSC commands or via settings)
|
- *Built-in help page* ([demo][demo-help]) with basic troubleshooting and command reference
|
||||||
- Built-in help page with basic troubleshooting and command reference
|
- **Robust WiFi configuration interface** (Demo: [WiFi][demo-wifi], [network][demo-network] config)
|
||||||
|
- Static IP, DHCP, channel selection, power
|
||||||
\*) Linux console applications run via agetty at ttyUSB0 were used for testing, obviously you'll be better off using SSH for remote shell
|
- SSID search utility for finding your existing network
|
||||||
|
|
||||||
ESPTerm firmware is written in C and is based on SpriteTM's `libesphttpd` http server library, forked by MightyPork to
|
|
||||||
[MightyPork/libesphttpd](https://github.com/MightyPork/libesphttpd) respectively. This fork includes various improvements and changes required by the project.
|
|
||||||
|
|
||||||
## Running ESPTerm
|
## Running ESPTerm
|
||||||
|
|
||||||
To run ESPTerm on your ESP8266, either build it yourself from source using `xtensa-lx106-elf-gcc` (and the included Makefile), or download pre-built binaries from the [GitHub releases section][releases]. Flash the binaries using [esptool](https://github.com/espressif/esptool).
|
To run ESPTerm on your ESP8266, either build it yourself from source using `xtensa-lx106-elf-gcc`
|
||||||
|
(and the included Makefile), or download pre-built binaries from the [GitHub releases section][releases].
|
||||||
|
Flash the binaries using [esptool][esptool].
|
||||||
|
|
||||||
### Pins
|
### Pins
|
||||||
|
|
||||||
- Pin GPIO2 is used for debug messages at 115200 baud, 8 bit, no parity.
|
- Pin GPIO2 is used for debug messages at 115200 baud, 8 bit, no parity.
|
||||||
- Pins Rx and Tx are used for the main communication UART. Connect your USB-serial dongle or application microcontroller here.
|
- Pins Rx and Tx are used for the main communication UART, parameters of which can be set on the system config page.
|
||||||
|
Connect your USB-serial dongle or application microcontroller here.
|
||||||
### Console commands - escape sequences
|
|
||||||
|
|
||||||
- A list of most supported commands can be found here: http://bits.ondrovo.com/espterm-xterm.html
|
|
||||||
- To set the screen title, use `OSC 0 ; title ST` (`OSC` = `ESC ]`, `ST` = `ESC \` or ASCII 7)
|
|
||||||
- To set buttons text, use `OSC 8 1 ; text ST` with 81 through 85.
|
|
||||||
- Mouse clicks (as of v0.6.9) generate `CSI row ; col M` at the Tx pin (`CSI` = `ESC [`)
|
|
||||||
- For more info, look eg. on Wikipedia or here: http://ascii-table.com/ansi-escape-sequences-vt-100.php
|
|
||||||
|
|
||||||
### Setup
|
### Setup
|
||||||
|
|
||||||
- When flashed for the first time, ESPTerm wipes any possible previous WiFi configuration, because it implements its own WiFi config manager with many additional features.
|
- When flashed for the first time, ESPTerm wipes any possible previous WiFi configuration, because it implements its own WiFi
|
||||||
- It should start in AP mode, the default SSID being `TERM-MACADR` with `MACADR` being three unique bytes from the MAC address / Device ID.
|
config manager with many additional features.
|
||||||
- Connect to it via a smartphone or laptop and configure WiFi as desired.
|
- It should start in AP mode, the default SSID being `TERM-MACADR` with `MACADR` being three unique bytes from the MAC
|
||||||
- To re-enable the built-in AP, hold the BOOT (GPIO0) button for about 1 s, until the blue LED starts slowly flashing. Then release the button!
|
address / Device ID as ASCII hex.
|
||||||
- To reset all settings to defaults, hold the BOOT (GPIO0) button until the blue LED flashes rapidly, then release the button.
|
- Connect to the AP via a smartphone or laptop and configure WiFi as desired. If a captive portal page does not open,
|
||||||
- When you accidentally make the blue LED flash, you can cancel the operation by pressing Reset or disconnecting its power supply. The wipe is done on the button's release.
|
try 192.168.4.1 in your web browser.
|
||||||
|
|
||||||
|
### Rescue from messed up config
|
||||||
|
|
||||||
|
It can happen that some changes to the WiFi or network config make the module inaccessible.
|
||||||
|
|
||||||
|
- To re-enable the built-in AP, hold the BOOT (GPIO0 -> GND) button for about 1 s, until the blue LED starts flashing.
|
||||||
|
Then quickly release the button.
|
||||||
|
- To reset all settings to defaults, hold the button a couple seconds until the LED flashes rapidly, then release it.
|
||||||
|
- You can cancel this wipe/reset operation (when triggered by accident) by pressing Reset or disconnecting the power supply.
|
||||||
|
|
||||||
### Config files
|
### Config files
|
||||||
|
|
||||||
ESPTerm has two config "files", one for defaults and one for the currently used settings. In the case of the terminal config, there is also a third, temporary file for changes done via ESC commands.
|
ESPTerm has two config "files", one for defaults and one for the currently used settings. In the case of the terminal
|
||||||
|
config, there is also a third, temporary file for changes done via ESC commands.
|
||||||
|
|
||||||
When you get your settings *just right*, you can store them as defaults, which can then be at any time restored by holding the BOOT (GPIO0) button. You can do this on the System Settings page. This asks for an "admin password", which you can define when building the firmware in the `esphttpdconfig.mk` file. The default password is `19738426`. This password can't presently be changed without re-flashing the firmware.
|
When you get your settings *just right*, you can store them as defaults, which can then be at any time restored
|
||||||
|
by holding the BOOT (GPIO0) button. You can do this on the System Settings page. This asks for an "admin password",
|
||||||
|
which you can define when building the firmware in the `esphttpdconfig.mk` file.
|
||||||
|
|
||||||
You can also restore everything (except the saved defaults) to "factory defaults", there is a button for this on the System Settings page. Those are the initial values in the config files.
|
The default password is `19738426`. This password can't presently be changed without re-flashing the firmware.
|
||||||
|
|
||||||
|
You can also restore everything (except the saved defaults) to "factory defaults", there is a button for this
|
||||||
|
on the System Settings page. Those are the initial values in the config files.
|
||||||
|
|
||||||
|
## Research resources
|
||||||
|
|
||||||
|
Developing ESPTerm wasn't an easy task, because the information is scattered across many places and the existing
|
||||||
|
terminal emulators I originally used for reference (terminator, Konsole) are not implemented correctly in some details.
|
||||||
|
|
||||||
|
A great tool for checking my implementation has proven to be [VTTTEST][vttest] and Xterm as a reference
|
||||||
|
implementation that is probably the most complete emulator available, although it's cumbersome to use and its age
|
||||||
|
really shows in the looks.
|
||||||
|
|
||||||
|
I've comnpiled a list of those I found most helpful here: [VT100 emulation resources][resources]
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
ESPTerm's firmware is written in C and is based on SpriteTM's `libesphttpd` http server library forked to
|
||||||
|
[MightyPork/libesphttpd][httpdlib]. This fork includes various improvements
|
||||||
|
and changes required by the project.
|
||||||
|
|
||||||
### Installation for development
|
### Installation for development
|
||||||
|
|
||||||
- Clone this project with `--recursive`, or afterwards run `git submodule init` and `git submodule update`.
|
- Clone this project with `--recursive`, or afterwards run `git submodule init` and `git submodule update`.
|
||||||
- Install [esp-open-sdk](https://github.com/pfalcon/esp-open-sdk/) and build it with
|
- Install [esp-open-sdk][opensdk] and build it with
|
||||||
`make toolchain esptool libhal STANDALONE=n`.
|
`make toolchain esptool libhal STANDALONE=n`.
|
||||||
Make sure the `xtensa-lx106-elf/bin` folder is on $PATH.
|
Make sure the `xtensa-lx106-elf/bin` folder is on $PATH.
|
||||||
- Install [esptool](https://github.com/espressif/esptool) (it's in the Arch community repo and on AUR, too)
|
- Install [esptool][esptool] (it's in the Arch community repo and on AUR, too)
|
||||||
- Set up udev rules so you have access to ttyUSB0 without root, eg:
|
- Set up udev rules so you have access to ttyUSB0 without root, eg:
|
||||||
```
|
```
|
||||||
KERNEL=="tty[A-Z]*[0-9]*", GROUP="uucp", MODE="0666"
|
KERNEL=="tty[A-Z]*[0-9]*", GROUP="uucp", MODE="0666"
|
||||||
@@ -123,3 +151,16 @@ build scripts manually, too.
|
|||||||
To flash, just run `make flash`.
|
To flash, just run `make flash`.
|
||||||
|
|
||||||
[releases]: https://github.com/MightyPork/esp-vt100-firmware/releases
|
[releases]: https://github.com/MightyPork/esp-vt100-firmware/releases
|
||||||
|
[httpdlib]: https://github.com/MightyPork/libesphttpd
|
||||||
|
[esptool]: https://github.com/espressif/esptool
|
||||||
|
[opensdk]: https://github.com/pfalcon/esp-open-sdk/
|
||||||
|
|
||||||
|
[demo-help]: https://espterm.github.io/help.html
|
||||||
|
[demo-wifi]: https://espterm.github.io/cfg_wifi.html
|
||||||
|
[demo-network]: https://espterm.github.io/cfg_network.html
|
||||||
|
[demo-term]: https://espterm.github.io/term.html
|
||||||
|
|
||||||
|
[xterm-compare]: https://espterm.github.io/docs/espterm-xterm.html
|
||||||
|
[photo-hw]: https://espterm.github.io/docs/espterm-hw-small.jpg
|
||||||
|
[resources]: https://espterm.github.io/docs/index.html
|
||||||
|
[vttest]: http://invisible-island.net/vttest/
|
||||||
|
|||||||
Executable
+26
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "-- Preparing WWW files --"
|
||||||
|
|
||||||
|
[[ -e html_demo ]] && rm -r html_demo
|
||||||
|
mkdir -p html_demo/img
|
||||||
|
mkdir -p html_demo/js
|
||||||
|
mkdir -p html_demo/css
|
||||||
|
|
||||||
|
cd html_orig
|
||||||
|
sh ./packjs.sh
|
||||||
|
ESP_DEMO=1 php ./build_html.php
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
cp html_orig/js/app.js html_demo/js/
|
||||||
|
|
||||||
|
sass html_orig/sass/app.scss html_demo/css/app.css
|
||||||
|
rm html_demo/css/app.css.map
|
||||||
|
|
||||||
|
cp html_orig/img/* html_demo/img/
|
||||||
|
cp html_orig/favicon.ico html_demo/favicon.ico
|
||||||
|
|
||||||
|
# cleanup
|
||||||
|
find html_demo/ -name "*.orig" -delete
|
||||||
|
find html_demo/ -name "*.xcf" -delete
|
||||||
|
find html_demo/ -name "*~" -delete
|
||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
./build_demo.sh
|
||||||
|
|
||||||
|
cp -r html_demo/* ../espterm.github.io/
|
||||||
|
|
||||||
|
cd ../espterm.github.io/
|
||||||
|
|
||||||
|
echo "Enter to deploy (^C to abort):"
|
||||||
|
read
|
||||||
|
|
||||||
|
git add --all
|
||||||
|
git commit -m "Deploy updates"
|
||||||
|
git push
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -5,15 +5,30 @@
|
|||||||
* without esphttpd. This is needed mainly for places where the replacements
|
* without esphttpd. This is needed mainly for places where the replacements
|
||||||
* are given to JavaScript, to avoid syntax errors with
|
* are given to JavaScript, to avoid syntax errors with
|
||||||
*/
|
*/
|
||||||
return [
|
|
||||||
'term_title' => 'ESPTerm local debug',
|
|
||||||
|
|
||||||
'btn1' => '1',
|
$vers = '???';
|
||||||
'btn2' => '2',
|
$f = file_get_contents(__DIR__ . '/../user/version.h');
|
||||||
'btn3' => '3',
|
preg_match_all('/#define FW_V_.*? (\d+)/', $f, $vm);
|
||||||
|
#define FW_V_MAJOR 1
|
||||||
|
#define FW_V_MINOR 0
|
||||||
|
#define FW_V_PATCH 0
|
||||||
|
|
||||||
|
$vers = $vm[1][0].'.'.$vm[1][1].'.'.$vm[1][2];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'term_title' => ESP_DEMO ? 'ESPTerm Web UI Demo' : 'ESPTerm local debug',
|
||||||
|
|
||||||
|
'btn1' => 'OK',
|
||||||
|
'btn2' => 'Cancel',
|
||||||
|
'btn3' => '',
|
||||||
'btn4' => '',
|
'btn4' => '',
|
||||||
'btn5' => '5',
|
'btn5' => 'Help',
|
||||||
'labels_seq' => 'TESPTerm local debug1235',
|
'bm1' => '01,'.ord('y'),
|
||||||
|
'bm2' => '01,'.ord('n'),
|
||||||
|
'bm3' => '',
|
||||||
|
'bm4' => '',
|
||||||
|
'bm5' => '05',
|
||||||
|
'labels_seq' => ESP_DEMO ? 'TESPTerm Web UI DemoOKCancelHelp' : 'TESPTerm local debugOKCancelHelp',
|
||||||
|
|
||||||
'parser_tout_ms' => 10,
|
'parser_tout_ms' => 10,
|
||||||
'display_tout_ms' => 15,
|
'display_tout_ms' => 15,
|
||||||
@@ -21,25 +36,25 @@ return [
|
|||||||
'fn_alt_mode' => '1',
|
'fn_alt_mode' => '1',
|
||||||
|
|
||||||
'opmode' => '2',
|
'opmode' => '2',
|
||||||
'sta_enable' => '0',
|
'sta_enable' => '1',
|
||||||
'ap_enable' => '1',
|
'ap_enable' => '1',
|
||||||
|
|
||||||
'tpw' => '60',
|
'tpw' => '60',
|
||||||
'ap_channel' => '7',
|
'ap_channel' => '7',
|
||||||
'ap_ssid' => 'ESP-123456',
|
'ap_ssid' => 'TERM-027451',
|
||||||
'ap_password' => 'Passw0rd!',
|
'ap_password' => '',
|
||||||
'ap_hidden' => '0',
|
'ap_hidden' => '0',
|
||||||
|
|
||||||
'sta_ssid' => 'Chlivek',
|
'sta_ssid' => 'Cisco',
|
||||||
'sta_password' => 'windows XP is The Best',
|
'sta_password' => 'Passw0rd!',
|
||||||
'sta_active_ip' => '1.2.3.4',
|
'sta_active_ip' => ESP_DEMO ? '192.168.82.66' : '192.168.0.19',
|
||||||
'sta_active_ssid' => 'Chlivek',
|
'sta_active_ssid' => 'Cisco',
|
||||||
|
|
||||||
'vers_fw' => '1.2.3',
|
'vers_fw' => $vers,
|
||||||
'date' => date('Y-m-d'),
|
'date' => date('Y-m-d'),
|
||||||
'time' => date('G:i'),
|
'time' => date('G:i'),
|
||||||
'vers_httpd' => '4.5.6',
|
'vers_httpd' => '0.4',
|
||||||
'vers_sdk' => '1.52',
|
'vers_sdk' => '010502',
|
||||||
'githubrepo' => 'https://github.com/MightyPork/esp-vt100-firmware',
|
'githubrepo' => 'https://github.com/MightyPork/esp-vt100-firmware',
|
||||||
|
|
||||||
'ap_dhcp_time' => '120',
|
'ap_dhcp_time' => '120',
|
||||||
@@ -53,11 +68,11 @@ return [
|
|||||||
'sta_addr_mask' => '255.255.255.0',
|
'sta_addr_mask' => '255.255.255.0',
|
||||||
'sta_addr_gw' => '192.168.0.1',
|
'sta_addr_gw' => '192.168.0.1',
|
||||||
|
|
||||||
'sta_mac' => 'ab:cd:ef:01:23:45',
|
'sta_mac' => '5c:cf:7f:02:74:51',
|
||||||
'ap_mac' => '01:23:45:ab:cd:ef',
|
'ap_mac' => '5e:cf:7f:02:74:51',
|
||||||
|
|
||||||
'term_width' => '26',
|
'term_width' => '80',
|
||||||
'term_height' => '10',
|
'term_height' => '25',
|
||||||
'default_bg' => '0',
|
'default_bg' => '0',
|
||||||
'default_fg' => '7',
|
'default_fg' => '7',
|
||||||
'show_buttons' => '1',
|
'show_buttons' => '1',
|
||||||
@@ -67,5 +82,5 @@ return [
|
|||||||
'uart_stopbits' => 1,
|
'uart_stopbits' => 1,
|
||||||
'uart_parity' => 2,
|
'uart_parity' => 2,
|
||||||
|
|
||||||
'theme' => 5,
|
'theme' => 0,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ pg('term', 'term', '', '/', 'title.term');
|
|||||||
|
|
||||||
pg('reset_screen', 'api', '', '/system/cls', 'title.term');
|
pg('reset_screen', 'api', '', '/system/cls', 'title.term');
|
||||||
|
|
||||||
|
pg('index', 'api', '', '/', '');
|
||||||
|
|
||||||
// ajax API
|
// ajax API
|
||||||
|
|
||||||
return $pages;
|
return $pages;
|
||||||
|
|||||||
@@ -23,6 +23,30 @@ define('DEBUG', !$prod);
|
|||||||
$root = DEBUG ? json_encode(ESP_IP) : 'location.host';
|
$root = DEBUG ? json_encode(ESP_IP) : 'location.host';
|
||||||
define('JS_WEB_ROOT', $root);
|
define('JS_WEB_ROOT', $root);
|
||||||
|
|
||||||
|
define('ESP_DEMO', (bool)getenv('ESP_DEMO'));
|
||||||
|
if (ESP_DEMO) {
|
||||||
|
define('DEMO_SCREEN', '"S\u0019\u0001Q\u0001\u0017\u0001K\u0001\u0015\u0004\u0003\b\u0001 \u0002P\u0001┌ESPTerm─Demo─\u0002\u0002\u0001\u0003\u0002\u000131\u0003\u0003\u000132\u0003\u0004\u00013\u0002\u0002\u0001\u0003\u0005\u000134\u0003\u0006\u000135\u0003\u0007\u000136\u0003\b\u000137\u0003\t\u000190\u0003\n\u000191\u0003\u000b\u000192\u0003\f\u000193\u0003\r\u000194\u0003\u000e\u000195\u0003\u000f\u000196\u0003\u0010\u000197\u0003\b\u0001─\u0002\r\u0001┐ \u0002\u0015\u0001│ \u00029\u0001│ \u0002\u0004\u0001│\u0002\t\u0001 \u0002\b\u0001│\u0004\u0002\u0001Bold \u0004\u0003\u0001F\u0004\u0003\u0001a\u0004\u0003\u0001i\u0004\u0003\u0001n\u0004\u0003\u0001t\u0004\u0003\u0001 \u0004\u0005\u0001I\u0004\u0005\u0001t\u0004\u0005\u0001a\u0004\u0005\u0001l\u0004\u0005\u0001i\u0004\u0005\u0001c\u0004\u0005\u0001 \u0004\t\u0001U\u0004\t\u0001n\u0004\t\u0001d\u0004\t\u0001e\u0004\t\u0001r\u0004\t\u0001l\u0004\t\u0001i\u0004\t\u0001n\u0004\t\u0001e\u0004\u0001\u0001 \u0004\u0011\u0001B\u0004\u0011\u0001l\u0004\u0011\u0001i\u0004\u0011\u0001n\u0004\u0011\u0001k\u0004\u0011\u0001 \u0001q\u0001\u0001Inverse\u0003\b\u0001 \u0004A\u0001S\u0004A\u0001t\u0004A\u0001r\u0004A\u0001i\u0004A\u0001k\u0004A\u0001e\u0004\u0001\u0001 \u0004!\u0001F\u0004!\u0001r\u0004!\u0001a\u0004!\u0001k\u0004!\u0001t\u0004!\u0001u\u0004!\u0001r\u0004\u0001\u0001 │ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0002\t\u0001\u0003\b\u0001─\u0002\u0002\u0001 \u0002\u0006\u0001│ \u00029\u0001│ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0003\u0002\u0002ESP826\u0002\u0002\u0001\u0003\n\u0002 \u0003\b\u0001─\u0002\u0002\u0001 \u0002\u0006\u0001└─\u00029\u0001┤ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0002\t\u0001\u0003\b\u0001─\u0002\u0002\u0001 \u0002@\u0001│ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0003\u0002\u0002(@)#\u0002\u0004\u0001\u0003\n\u0002 \u0003\b\u0001─\u0002\u0002\u0001 \u0002\u0007\u0001\u0003O\u0001 This is a static demo of the ESPTerm Web Interface \u0002\u0004\u0001\u0003\b\u0001 \u0002\u0002\u0001│ \u0002\u0002\u0001─\u0002\u0002\u0001\u0003\n\u0002 \u0002\t\u0001\u0003\b\u0001─\u0002\u0002\u0001 \u0002\u0007\u0001\u0003O\u0001 \u00027\u0001\u0003\b\u0001 \u0002\u0002\u0001│ \u0002\u0004\u0001│\u0002\t\u0001 \u0002\t\u0001\u0003O\u0001 Try the links beneath this scre\u0002\u0002\u0001n to browse the menu. \u0003\b\u0001 \u0002\u0002\u0001♦ \u0002\u0016\u0001\u0003O\u0001 \u00027\u0001\u0003\b\u0001 \u0002\u0019\u0001\u0003O\u0001 <°)\u0002\u0003\u0001>< ESPTerm ful\u0002\u0002\u0001y sup\u0002\u0002\u0001orts UTF-8 お は よ ー \u0002\u0002\u0001><(\u0002\u0003\u0001°> \u0003\b\u0001 \u0002\u0019\u0001\u0003O\u0001 \u00027\u0001\u0003\b\u0001 \u0002i\u0001\u0003\u000b\u0001Other interesting features:\u0003\b\u0001 \u0002\u0018\u0001↓ \u0002n\u0001\u0003\u0003\u0001- Almost ful\u0002\u0002\u0001 VT10\u0002\u0002\u0001 emulation \u0003\b\u0001 \u0003\u0006\u0001()\u0003\b\u0001 \u0003\u0006\u0001()\u0003\b\u0001 \u0002\b\u0001Funguje tu čeština! \u0002\u0011\u0001\u0003\u0005\u0001- Xterm-like mouse tracking\u0003\b\u0001 \u0002\u0003\u0001=\u0002\u0002\u0001\u0003\t\u0002°.°\u0003\b\u0001=\u0002\u0002\u0001 \u0003\u0006\u0001<-\u0002\u0003\u0001, \u0003\b\u0001 \u0002$\u0001\u0003\u0004\u0001- File upload utility\u0003\b\u0001 \u0002\n\u0001\'\u0002\u0002\u0001 \'\u0002\u0002\u0001 \u0002\u0002\u0001\u0003\u0006\u0001 \u0002\u0004\u0001mouse\u0003\b\u0001 \u0002!\u0001\u0003\u0002\u0001- User-friendly config interface\u0003\b\u0001 \u00020\u0001\u0003\u000e\u0001-\u0003\u0002\u0001 \u0003\u000e\u0001Advanced WiFi & network set\u0002\u0002\u0001ings\u0003\b\u0001 \u0002\u0011\u0001\u0003\f\u0001Try ESPTerm today!\u0003\b\u0001 \u0002\u000b\u0001- Built-in help page \u0002\u001a\u0001\u0003\u0007\u0001-\u0002\u0002\u0001>\u0003\b\u0001 \u0002\u0002\u0001\u0003\f\u0001Pre-built binaries\u0003\b\u0001 \u0003\f\u0001are\u0003\b\u0001 \u0002\"\u0001\u0003\u0007\u0001link on the About page \u0002\u0002\u0001\u0003\f\u0001available on GitHub! \u0003\b\u0001 \u0002U\u0001"');
|
||||||
|
define('DEMO_APS', <<<APS
|
||||||
|
{
|
||||||
|
"result": {
|
||||||
|
"inProgress": 0,
|
||||||
|
"APs": [
|
||||||
|
{"essid": "Cisco", "bssid": "88:f7:c7:52:b3:99", "rssi": 205, "rssi_perc": 100, "enc": 4, "channel": 7},
|
||||||
|
{"essid": "UPC Wi-Free", "bssid": "8a:f7:c7:52:b3:9b", "rssi": 203, "rssi_perc": 100, "enc": 5, "channel": 1},
|
||||||
|
{"essid": "UPC Wi-Free", "bssid": "0a:95:2a:0c:84:31", "rssi": 166, "rssi_perc": 32, "enc": 5, "channel": 1},
|
||||||
|
{"essid": "MujO2Internet_2EEB96", "bssid": "d0:60:8c:2e:eb:96", "rssi": 174, "rssi_perc": 48, "enc": 4, "channel": 4},
|
||||||
|
{"essid": "Internet", "bssid": "38:72:c0:32:bd:0d", "rssi": 164, "rssi_perc": 28, "enc": 2, "channel": 10},
|
||||||
|
{"essid": "MyO2Internet_08C850", "bssid": "78:c1:a7:08:c8:50", "rssi": 186, "rssi_perc": 72, "enc": 4, "channel": 11},
|
||||||
|
{"essid": "UPC Wi-Free", "bssid": "06:7c:34:9a:6f:7c", "rssi": 167, "rssi_perc": 34, "enc": 0, "channel": 11},
|
||||||
|
{"essid": "Internet_B0", "bssid": "5c:f4:ab:11:3b:b3", "rssi": 175, "rssi_perc": 50, "enc": 3, "channel": 13},
|
||||||
|
{"essid": "UPC5716805", "bssid": "08:95:2a:0c:84:3f", "rssi": 165, "rssi_perc": 30, "enc": 4, "channel": 1}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
APS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
define('LOCALE', isset($_GET['locale']) ? $_GET['locale'] : 'en');
|
define('LOCALE', isset($_GET['locale']) ? $_GET['locale'] : 'en');
|
||||||
|
|
||||||
$_messages = require(__DIR__ . '/lang/' . LOCALE . '.php');
|
$_messages = require(__DIR__ . '/lang/' . LOCALE . '.php');
|
||||||
@@ -37,6 +61,7 @@ function url($name, $relative = false)
|
|||||||
if ($relative) return $_pages[$name]->path;
|
if ($relative) return $_pages[$name]->path;
|
||||||
|
|
||||||
if (DEBUG) return "/index.php?page=$name";
|
if (DEBUG) return "/index.php?page=$name";
|
||||||
|
if (ESP_DEMO) return "$name.html";
|
||||||
else return $_pages[$name]->path;
|
else return $_pages[$name]->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,21 @@ function process_html($s) {
|
|||||||
|
|
||||||
$no_tpl_files = ['help', 'cfg_wifi_conn'];
|
$no_tpl_files = ['help', 'cfg_wifi_conn'];
|
||||||
|
|
||||||
|
$dest = ESP_DEMO ? __DIR__ . '/../html_demo/' : __DIR__ . '/../html/';
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
foreach($_pages as $_k => $p) {
|
foreach($_pages as $_k => $p) {
|
||||||
if ($p->bodyclass == 'api') continue;
|
if ($p->bodyclass == 'api') {
|
||||||
|
if (ESP_DEMO) {
|
||||||
|
$target = 'term.html';
|
||||||
|
echo "Generating: ~$_k.html -> $target\n";
|
||||||
|
$s = "<!DOCTYPE HTML><meta http-equiv=\"refresh\" content=\"0;url=$target\">";
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
echo "Generating: $_k ($p->title)\n";
|
echo "Generating: $_k ($p->title)\n";
|
||||||
|
|
||||||
$_GET['page'] = $_k;
|
$_GET['page'] = $_k;
|
||||||
ob_flush(); // print the message
|
ob_flush(); // print the message
|
||||||
ob_clean(); // clean up
|
ob_clean(); // clean up
|
||||||
@@ -30,9 +41,9 @@ foreach($_pages as $_k => $p) {
|
|||||||
// as tests have shown, it saves just a couple kilobytes,
|
// as tests have shown, it saves just a couple kilobytes,
|
||||||
// making it not a very big improvement at the expense of ugly html.
|
// making it not a very big improvement at the expense of ugly html.
|
||||||
// $s = process_html($s);
|
// $s = process_html($s);
|
||||||
|
ob_clean();
|
||||||
ob_clean(); // clean up
|
} // clean up
|
||||||
$of = __DIR__ . '/../html/' . $_k . (in_array($_k, $no_tpl_files) ? '.html' : '.tpl');
|
$of = $dest . $_k . ((in_array($_k, $no_tpl_files)||ESP_DEMO) ? '.html' : '.tpl');
|
||||||
file_put_contents($of, $s); // write to a file
|
file_put_contents($of, $s); // write to a file
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-4
@@ -7,9 +7,15 @@ if (!isset($_GET['page'])) $_GET['page'] = 'term';
|
|||||||
$_GET['PAGE_TITLE'] = $_pages[$_GET['page']]->title . ' :: ' . APP_NAME;
|
$_GET['PAGE_TITLE'] = $_pages[$_GET['page']]->title . ' :: ' . APP_NAME;
|
||||||
$_GET['BODYCLASS'] = $_pages[$_GET['page']]->bodyclass;
|
$_GET['BODYCLASS'] = $_pages[$_GET['page']]->bodyclass;
|
||||||
|
|
||||||
require __DIR__ . '/pages/_head.php';
|
|
||||||
$_pf = __DIR__ . '/pages/'.$_GET['page'].'.php';
|
$_pf = __DIR__ . '/pages/'.$_GET['page'].'.php';
|
||||||
|
|
||||||
|
if (!file_exists($_pf)) {
|
||||||
|
header("Location: /", true, 302);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
require __DIR__ . '/pages/_head.php';
|
||||||
|
|
||||||
$include_re = '/<\?php\s*(require|include)\s*\(?\s*?(?:__DIR__\s*\.)?\s*(["\'])(.*?)\2\s*\)?;\s*\?>/';
|
$include_re = '/<\?php\s*(require|include)\s*\(?\s*?(?:__DIR__\s*\.)?\s*(["\'])(.*?)\2\s*\)?;\s*\?>/';
|
||||||
|
|
||||||
if (file_exists($_pf)) {
|
if (file_exists($_pf)) {
|
||||||
@@ -25,7 +31,7 @@ if (file_exists($_pf)) {
|
|||||||
}
|
}
|
||||||
}, $f);
|
}, $f);
|
||||||
|
|
||||||
if (DEBUG)
|
if (DEBUG || ESP_DEMO)
|
||||||
$str = tplSubs($f, require(__DIR__ . '/_debug_replacements.php'));
|
$str = tplSubs($f, require(__DIR__ . '/_debug_replacements.php'));
|
||||||
else $str = $f;
|
else $str = $f;
|
||||||
|
|
||||||
@@ -39,8 +45,6 @@ if (file_exists($_pf)) {
|
|||||||
|
|
||||||
$str = preg_replace("/\s*(\\\\\\\\)[\n \t]+/", '<br>', $str);
|
$str = preg_replace("/\s*(\\\\\\\\)[\n \t]+/", '<br>', $str);
|
||||||
include_str($str);
|
include_str($str);
|
||||||
} else {
|
|
||||||
echo "404";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require __DIR__ . '/pages/_tail.php';
|
require __DIR__ . '/pages/_tail.php';
|
||||||
|
|||||||
+20
-6
@@ -1275,7 +1275,7 @@ $.ready(function () {
|
|||||||
$(h).on('click', hdl).on('keypress', cr(hdl));
|
$(h).on('click', hdl).on('keypress', cr(hdl));
|
||||||
});
|
});
|
||||||
|
|
||||||
qsa('form').forEach(function(x) {
|
$('form').forEach(function(x) {
|
||||||
$(x).on('keypress', function(e) {
|
$(x).on('keypress', function(e) {
|
||||||
if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey) {
|
if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey) {
|
||||||
x.submit();
|
x.submit();
|
||||||
@@ -1346,7 +1346,7 @@ $.ready(function () {
|
|||||||
|
|
||||||
// remove tabindixes from h2 if wide
|
// remove tabindixes from h2 if wide
|
||||||
if (window.innerWidth > 550) {
|
if (window.innerWidth > 550) {
|
||||||
qsa('.Box h2').forEach(function (x) {
|
$('.Box h2').forEach(function (x) {
|
||||||
x.removeAttribute('tabindex');
|
x.removeAttribute('tabindex');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1567,8 +1567,12 @@ function tr(key) { return _tr[key] || '?'+key+'?'; }
|
|||||||
|
|
||||||
/** Ask the CGI what APs are visible (async) */
|
/** Ask the CGI what APs are visible (async) */
|
||||||
function scanAPs() {
|
function scanAPs() {
|
||||||
|
if (_demo) {
|
||||||
|
onScan(_demo_aps, 200);
|
||||||
|
} else {
|
||||||
$.get('http://' + _root + '/cfg/wifi/scan', onScan);
|
$.get('http://' + _root + '/cfg/wifi/scan', onScan);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function rescan(time) {
|
function rescan(time) {
|
||||||
setTimeout(scanAPs, time);
|
setTimeout(scanAPs, time);
|
||||||
@@ -1658,7 +1662,10 @@ var Conn = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doSend(message) {
|
function doSend(message) {
|
||||||
//console.log("TX: ", message);
|
if (_demo) {
|
||||||
|
console.log("TX: ", message);
|
||||||
|
return true; // Simulate success
|
||||||
|
}
|
||||||
if (xoff) {
|
if (xoff) {
|
||||||
// TODO queue
|
// TODO queue
|
||||||
console.log("Can't send, flood control.");
|
console.log("Can't send, flood control.");
|
||||||
@@ -1678,6 +1685,12 @@ var Conn = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
if (_demo) {
|
||||||
|
console.log("Demo mode!");
|
||||||
|
Screen.load(_demo_screen);
|
||||||
|
showPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
heartbeat();
|
heartbeat();
|
||||||
|
|
||||||
ws = new WebSocket("ws://"+_root+"/term/update.ws");
|
ws = new WebSocket("ws://"+_root+"/term/update.ws");
|
||||||
@@ -1897,7 +1910,7 @@ var Input = (function() {
|
|||||||
_initKeys();
|
_initKeys();
|
||||||
|
|
||||||
// Button presses
|
// Button presses
|
||||||
qsa('#action-buttons button').forEach(function(s) {
|
$('#action-buttons button').forEach(function(s) {
|
||||||
s.addEventListener('click', function() {
|
s.addEventListener('click', function() {
|
||||||
sendBtnMsg(+this.dataset['n']);
|
sendBtnMsg(+this.dataset['n']);
|
||||||
});
|
});
|
||||||
@@ -2306,12 +2319,12 @@ var Screen = (function () {
|
|||||||
function _load_labels(str) {
|
function _load_labels(str) {
|
||||||
var pieces = str.split('\x01');
|
var pieces = str.split('\x01');
|
||||||
qs('h1').textContent = pieces[0];
|
qs('h1').textContent = pieces[0];
|
||||||
qsa('#action-buttons button').forEach(function(x, i) {
|
$('#action-buttons button').forEach(function(x, i) {
|
||||||
var s = pieces[i+1].trim();
|
var s = pieces[i+1].trim();
|
||||||
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
||||||
x.innerHTML = s.length > 0 ? e(s) : " ";
|
x.innerHTML = s.length > 0 ? e(s) : " ";
|
||||||
x.style.opacity = s.length > 0 ? 1 : 0.2;
|
x.style.opacity = s.length > 0 ? 1 : 0.2;
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Audible beep for ASCII 7 */
|
/** Audible beep for ASCII 7 */
|
||||||
@@ -2344,6 +2357,7 @@ var Screen = (function () {
|
|||||||
|
|
||||||
/** Load screen content from a binary sequence (new) */
|
/** Load screen content from a binary sequence (new) */
|
||||||
function load(str) {
|
function load(str) {
|
||||||
|
//console.log(JSON.stringify(str));
|
||||||
var content = str.substr(1);
|
var content = str.substr(1);
|
||||||
switch(str.charAt(0)) {
|
switch(str.charAt(0)) {
|
||||||
case 'S':
|
case 'S':
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ $.ready(function () {
|
|||||||
$(h).on('click', hdl).on('keypress', cr(hdl));
|
$(h).on('click', hdl).on('keypress', cr(hdl));
|
||||||
});
|
});
|
||||||
|
|
||||||
qsa('form').forEach(function(x) {
|
$('form').forEach(function(x) {
|
||||||
$(x).on('keypress', function(e) {
|
$(x).on('keypress', function(e) {
|
||||||
if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey) {
|
if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey) {
|
||||||
x.submit();
|
x.submit();
|
||||||
@@ -96,7 +96,7 @@ $.ready(function () {
|
|||||||
|
|
||||||
// remove tabindixes from h2 if wide
|
// remove tabindixes from h2 if wide
|
||||||
if (window.innerWidth > 550) {
|
if (window.innerWidth > 550) {
|
||||||
qsa('.Box h2').forEach(function (x) {
|
$('.Box h2').forEach(function (x) {
|
||||||
x.removeAttribute('tabindex');
|
x.removeAttribute('tabindex');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,10 @@ var Conn = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function doSend(message) {
|
function doSend(message) {
|
||||||
//console.log("TX: ", message);
|
if (_demo) {
|
||||||
|
console.log("TX: ", message);
|
||||||
|
return true; // Simulate success
|
||||||
|
}
|
||||||
if (xoff) {
|
if (xoff) {
|
||||||
// TODO queue
|
// TODO queue
|
||||||
console.log("Can't send, flood control.");
|
console.log("Can't send, flood control.");
|
||||||
@@ -72,6 +75,12 @@ var Conn = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
if (_demo) {
|
||||||
|
console.log("Demo mode!");
|
||||||
|
Screen.load(_demo_screen);
|
||||||
|
showPage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
heartbeat();
|
heartbeat();
|
||||||
|
|
||||||
ws = new WebSocket("ws://"+_root+"/term/update.ws");
|
ws = new WebSocket("ws://"+_root+"/term/update.ws");
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ var Input = (function() {
|
|||||||
_initKeys();
|
_initKeys();
|
||||||
|
|
||||||
// Button presses
|
// Button presses
|
||||||
qsa('#action-buttons button').forEach(function(s) {
|
$('#action-buttons button').forEach(function(s) {
|
||||||
s.addEventListener('click', function() {
|
s.addEventListener('click', function() {
|
||||||
sendBtnMsg(+this.dataset['n']);
|
sendBtnMsg(+this.dataset['n']);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -316,12 +316,12 @@ var Screen = (function () {
|
|||||||
function _load_labels(str) {
|
function _load_labels(str) {
|
||||||
var pieces = str.split('\x01');
|
var pieces = str.split('\x01');
|
||||||
qs('h1').textContent = pieces[0];
|
qs('h1').textContent = pieces[0];
|
||||||
qsa('#action-buttons button').forEach(function(x, i) {
|
$('#action-buttons button').forEach(function(x, i) {
|
||||||
var s = pieces[i+1].trim();
|
var s = pieces[i+1].trim();
|
||||||
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
// if empty string, use the "dim" effect and put nbsp instead to stretch the btn vertically
|
||||||
x.innerHTML = s.length > 0 ? e(s) : " ";
|
x.innerHTML = s.length > 0 ? e(s) : " ";
|
||||||
x.style.opacity = s.length > 0 ? 1 : 0.2;
|
x.style.opacity = s.length > 0 ? 1 : 0.2;
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Audible beep for ASCII 7 */
|
/** Audible beep for ASCII 7 */
|
||||||
@@ -354,6 +354,7 @@ var Screen = (function () {
|
|||||||
|
|
||||||
/** Load screen content from a binary sequence (new) */
|
/** Load screen content from a binary sequence (new) */
|
||||||
function load(str) {
|
function load(str) {
|
||||||
|
//console.log(JSON.stringify(str));
|
||||||
var content = str.substr(1);
|
var content = str.substr(1);
|
||||||
switch(str.charAt(0)) {
|
switch(str.charAt(0)) {
|
||||||
case 'S':
|
case 'S':
|
||||||
|
|||||||
@@ -120,8 +120,12 @@
|
|||||||
|
|
||||||
/** Ask the CGI what APs are visible (async) */
|
/** Ask the CGI what APs are visible (async) */
|
||||||
function scanAPs() {
|
function scanAPs() {
|
||||||
|
if (_demo) {
|
||||||
|
onScan(_demo_aps, 200);
|
||||||
|
} else {
|
||||||
$.get('http://' + _root + '/cfg/wifi/scan', onScan);
|
$.get('http://' + _root + '/cfg/wifi/scan', onScan);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function rescan(time) {
|
function rescan(time) {
|
||||||
setTimeout(scanAPs, time);
|
setTimeout(scanAPs, time);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'appname' => 'ESPTerm',
|
'appname' => 'ESPTerm',
|
||||||
|
'appname_demo' => 'ESPTerm<sup> DEMO</sup>',
|
||||||
|
|
||||||
'menu.cfg_wifi' => 'WiFi Settings',
|
'menu.cfg_wifi' => 'WiFi Settings',
|
||||||
'menu.cfg_network' => 'Network Settings',
|
'menu.cfg_network' => 'Network Settings',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<nav id="menu">
|
<nav id="menu">
|
||||||
<div id="brand" tabindex=0><?= tr('appname') ?></div>
|
<div id="brand" tabindex=0><?= tr('appname'.(ESP_DEMO?'_demo':'')) ?></div>
|
||||||
<a href="<?= e(url('term')) ?>" class="icn-back"><?= tr('menu.term') ?></a>
|
<a href="<?= e(url('term')) ?>" class="icn-back"><?= tr('menu.term') ?></a>
|
||||||
<?php
|
<?php
|
||||||
// generate the menu
|
// generate the menu
|
||||||
|
|||||||
@@ -7,7 +7,12 @@
|
|||||||
<title><?= $_GET['PAGE_TITLE'] ?></title>
|
<title><?= $_GET['PAGE_TITLE'] ?></title>
|
||||||
<link href="/css/app.css" rel="stylesheet">
|
<link href="/css/app.css" rel="stylesheet">
|
||||||
<script src="/js/app.js"></script>
|
<script src="/js/app.js"></script>
|
||||||
<script>var _root = <?= JS_WEB_ROOT ?>;</script>
|
<script>
|
||||||
|
var _root = <?= JS_WEB_ROOT ?>;
|
||||||
|
var _demo = <?= (int)ESP_DEMO ?>;
|
||||||
|
<?php if($_GET['page']=='term'): ?>var _demo_screen = <?= ESP_DEMO ? DEMO_SCREEN : 0 ?>;<?php endif; ?>
|
||||||
|
<?php if($_GET['page']=='cfg_wifi'): ?>var _demo_aps = <?= ESP_DEMO ? json_encode(DEMO_APS) : '' ?>;<?php endif; ?>
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body class="<?= $_GET['BODYCLASS'] ?>">
|
<body class="<?= $_GET['BODYCLASS'] ?>">
|
||||||
<div id="outer">
|
<div id="outer">
|
||||||
|
|||||||
+1
-1
@@ -1187,7 +1187,7 @@ utf8_remap(char *out, char g, char charset)
|
|||||||
|
|
||||||
case CS_1_DOS_437: /* ESPTerm Character Rom 1 */
|
case CS_1_DOS_437: /* ESPTerm Character Rom 1 */
|
||||||
if ((g >= CODEPAGE_1_BEGIN) && (g <= CODEPAGE_1_END)) {
|
if ((g >= CODEPAGE_1_BEGIN) && (g <= CODEPAGE_1_END)) {
|
||||||
n = codepage_1[g - CODEPAGE_1_END];
|
n = codepage_1[g - CODEPAGE_1_BEGIN];
|
||||||
if (n) utf = n;
|
if (n) utf = n;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+1
-1
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#define FW_V_MAJOR 1
|
#define FW_V_MAJOR 1
|
||||||
#define FW_V_MINOR 0
|
#define FW_V_MINOR 0
|
||||||
#define FW_V_PATCH 0
|
#define FW_V_PATCH 1
|
||||||
|
|
||||||
#define FIRMWARE_VERSION STR(FW_V_MAJOR) "." STR(FW_V_MINOR) "." STR(FW_V_PATCH) "+" GIT_HASH
|
#define FIRMWARE_VERSION STR(FW_V_MAJOR) "." STR(FW_V_MINOR) "." STR(FW_V_PATCH) "+" GIT_HASH
|
||||||
#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
|
||||||
|
|||||||
Reference in New Issue
Block a user