added auto-incrementing build number to the Makefile (available as "esp_link_build" in the C code)

converted the unconditional downloading of YUI compressor and HTML compressor to be conditional - only if they are not already present
moved all Javascript blocks from HTML files into separate JS files - otherwise HTML compressor does not compress the inlined Javascript code
changed the place of inclusion of JS files into HTML - it is now at the end of BODY instead of beginning (this speeds up the page loading a little)
added a page "Firmware" which allows for OTA upgrades - so the utility "wiflash" is no more needed
improved the Makefile to show firmware size as a percentage of the available ROM space
improved the Makefile to show the espFS size as a percentage of the raw uncompressed size of web assets
combined the 2 invokations of HTML compressor in Makefile (once for main folder and once for WIFI folder) into a single one
changed 4-5 CSS rules for better visual readability
fixed a bug in "cgiGetFirmwareNext" - it was not sending the No-Cache headers and so the browser shows wrong (older, cached) info
added "\n" in several DBG() statements
I had to rename "base64_decode" because there is same named function inside "ssl_crypto_misc" from the SSL library
pull/173/head
tmcdos 8 years ago
parent 65534229f2
commit 95d7e8e391
  1. 107
      Makefile
  2. 6
      esp-link/cgi.c
  3. 6
      esp-link/cgiflash.c
  4. 4
      esp-link/cgiwifi.c
  5. 22
      esp-link/main.c
  6. 81
      html/console.html
  7. 264
      html/home.html
  8. 50
      html/log.html
  9. 18
      html/mqtt.html
  10. 6
      html/mqtt.js
  11. 4
      html/pure.css
  12. 203
      html/services.html
  13. 7
      html/services.js
  14. 73
      html/style.css
  15. 18
      html/ui.js
  16. 143
      html/wifi/wifiAp.html
  17. 27
      html/wifi/wifiAp.js
  18. 89
      html/wifi/wifiSta.html
  19. 9
      html/wifi/wifiSta.js
  20. 4
      httpd/auth.c
  21. 2
      httpd/base64.c
  22. 2
      httpd/base64.h
  23. 2
      httpd/httpd.c
  24. 5
      include/user_config.h

@ -84,7 +84,7 @@ ESPBAUD ?= 460800
# --------------- chipset configuration --------------- # --------------- chipset configuration ---------------
# Pick your flash size: "512KB", "1MB", or "4MB" # Pick your flash size: "512KB", "1MB", "2MB" or "4MB"
FLASH_SIZE ?= 4MB FLASH_SIZE ?= 4MB
# The pin assignments below are used when the settings in flash are invalid, they # The pin assignments below are used when the settings in flash are invalid, they
@ -135,13 +135,12 @@ YUI_COMPRESSOR ?= yuicompressor-2.4.8.jar
HTML_PATH = $(abspath ./html)/ HTML_PATH = $(abspath ./html)/
WIFI_PATH = $(HTML_PATH)wifi/ WIFI_PATH = $(HTML_PATH)wifi/
ESP_FLASH_MAX ?= 503808 # max bin file
ifeq ("$(FLASH_SIZE)","512KB") ifeq ("$(FLASH_SIZE)","512KB")
# Winbond 25Q40 512KB flash, typ for esp-01 thru esp-11 # Winbond 25Q40 512KB flash, typ for esp-01 thru esp-11
ESP_SPI_SIZE ?= 0 # 0->512KB (256KB+256KB) ESP_SPI_SIZE ?= 0 # 0->512KB (256KB+256KB)
ESP_FLASH_MODE ?= 0 # 0->QIO ESP_FLASH_MODE ?= 0 # 0->QIO
ESP_FLASH_FREQ_DIV ?= 0 # 0->40Mhz ESP_FLASH_FREQ_DIV ?= 0 # 0->40Mhz
ESP_FLASH_MAX ?= 241664 # max bin file for 512KB flash: 236KB
ET_FS ?= 4m # 4Mbit flash size in esptool flash command ET_FS ?= 4m # 4Mbit flash size in esptool flash command
ET_FF ?= 40m # 40Mhz flash speed in esptool flash command ET_FF ?= 40m # 40Mhz flash speed in esptool flash command
ET_BLANK ?= 0x7E000 # where to flash blank.bin to erase wireless settings ET_BLANK ?= 0x7E000 # where to flash blank.bin to erase wireless settings
@ -151,6 +150,7 @@ else ifeq ("$(FLASH_SIZE)","1MB")
ESP_SPI_SIZE ?= 2 # 2->1MB (512KB+512KB) ESP_SPI_SIZE ?= 2 # 2->1MB (512KB+512KB)
ESP_FLASH_MODE ?= 0 # 0->QIO ESP_FLASH_MODE ?= 0 # 0->QIO
ESP_FLASH_FREQ_DIV ?= 15 # 15->80MHz ESP_FLASH_FREQ_DIV ?= 15 # 15->80MHz
ESP_FLASH_MAX ?= 503808 # max bin file for 1MB flash: 492KB
ET_FS ?= 8m # 8Mbit flash size in esptool flash command ET_FS ?= 8m # 8Mbit flash size in esptool flash command
ET_FF ?= 80m # 80Mhz flash speed in esptool flash command ET_FF ?= 80m # 80Mhz flash speed in esptool flash command
ET_BLANK ?= 0xFE000 # where to flash blank.bin to erase wireless settings ET_BLANK ?= 0xFE000 # where to flash blank.bin to erase wireless settings
@ -163,6 +163,7 @@ else ifeq ("$(FLASH_SIZE)","2MB")
ESP_SPI_SIZE ?= 4 # 6->4MB (1MB+1MB) or 4->4MB (512KB+512KB) ESP_SPI_SIZE ?= 4 # 6->4MB (1MB+1MB) or 4->4MB (512KB+512KB)
ESP_FLASH_MODE ?= 0 # 0->QIO, 2->DIO ESP_FLASH_MODE ?= 0 # 0->QIO, 2->DIO
ESP_FLASH_FREQ_DIV ?= 15 # 15->80Mhz ESP_FLASH_FREQ_DIV ?= 15 # 15->80Mhz
ESP_FLASH_MAX ?= 503808 # max bin file for 2MB flash: 492KB
ET_FS ?= 16m # 16Mbit flash size in esptool flash command ET_FS ?= 16m # 16Mbit flash size in esptool flash command
ET_FF ?= 80m # 80Mhz flash speed in esptool flash command ET_FF ?= 80m # 80Mhz flash speed in esptool flash command
ET_BLANK ?= 0x1FE000 # where to flash blank.bin to erase wireless settings ET_BLANK ?= 0x1FE000 # where to flash blank.bin to erase wireless settings
@ -175,6 +176,8 @@ else
ESP_SPI_SIZE ?= 4 # 6->4MB (1MB+1MB) or 4->4MB (512KB+512KB) ESP_SPI_SIZE ?= 4 # 6->4MB (1MB+1MB) or 4->4MB (512KB+512KB)
ESP_FLASH_MODE ?= 0 # 0->QIO, 2->DIO ESP_FLASH_MODE ?= 0 # 0->QIO, 2->DIO
ESP_FLASH_FREQ_DIV ?= 15 # 15->80Mhz ESP_FLASH_FREQ_DIV ?= 15 # 15->80Mhz
ESP_FLASH_MAX ?= 503808 # max bin file for 512KB flash partition: 492KB
#ESP_FLASH_MAX ?= 1028096 # max bin file for 1MB flash partition: 1004KB
ET_FS ?= 32m # 32Mbit flash size in esptool flash command ET_FS ?= 32m # 32Mbit flash size in esptool flash command
ET_FF ?= 80m # 80Mhz flash speed in esptool flash command ET_FF ?= 80m # 80Mhz flash speed in esptool flash command
ET_BLANK ?= 0x3FE000 # where to flash blank.bin to erase wireless settings ET_BLANK ?= 0x3FE000 # where to flash blank.bin to erase wireless settings
@ -187,12 +190,17 @@ endif
# Steps to release: create release on github, git pull, git describe --tags to verify you're # Steps to release: create release on github, git pull, git describe --tags to verify you're
# on the release tag, make release, upload esp-link.tgz into the release files # on the release tag, make release, upload esp-link.tgz into the release files
#VERSION ?= "esp-link custom version" #VERSION ?= "esp-link custom version"
DATE := $(shell date '+%F %T') DATE := $(shell date '+%F')
TIME := $(shell date '+%T')
BRANCH ?= $(shell if git diff --quiet HEAD; then git describe --tags; \ BRANCH ?= $(shell if git diff --quiet HEAD; then git describe --tags; \
else git symbolic-ref --short HEAD; fi) else git symbolic-ref --short HEAD; fi)
SHA := $(shell if git diff --quiet HEAD; then git rev-parse --short HEAD | cut -d"/" -f 3; \ SHA := $(shell if git diff --quiet HEAD; then git rev-parse --short HEAD | cut -d"/" -f 3; \
else echo "development"; fi) else echo "development"; fi)
VERSION ?=esp-link $(BRANCH) - $(DATE) - $(SHA) VERSION ?=esp-link $(BRANCH) - $(DATE) - $(TIME) - $(SHA)
BUILD_NUMBER_FILE = $(abspath ./build-number.txt)
BUILD_NUMBER_SRC = $(abspath ./user/buildnum.c)
BUILD_NUMBER := $(shell if ! test -f $(BUILD_NUMBER_FILE); then echo 1 > $(BUILD_NUMBER_FILE); fi; cat $(BUILD_NUMBER_FILE))
# Output directors to store intermediate compiled files # Output directors to store intermediate compiled files
# relative to the project directory # relative to the project directory
@ -227,15 +235,15 @@ MODULES += $(foreach sdir,$(LIBRARIES_DIR),$(wildcard $(sdir)/*))
EXTRA_INCDIR = include . EXTRA_INCDIR = include .
# libraries used in this project, mainly provided by the SDK # libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal phy pp net80211 wpa main lwip crypto LIBS = c gcc hal phy pp net80211 wpa main lwip crypto ssl
# compiler flags using during compilation of source files # compiler flags using during compilation of source files
CFLAGS += -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ CFLAGS += -Os -ggdb -std=c99 -Werror -Wno-unused-value -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \
-nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-sections \ -nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-sections \
-D__ets__ -DICACHE_FLASH -Wno-address -DFIRMWARE_SIZE=$(ESP_FLASH_MAX) \ -D__ets__ -DICACHE_FLASH -Wno-address -DFIRMWARE_SIZE=$(ESP_FLASH_MAX) \
-DMCU_RESET_PIN=$(MCU_RESET_PIN) -DMCU_ISP_PIN=$(MCU_ISP_PIN) \ -DMCU_RESET_PIN=$(MCU_RESET_PIN) -DMCU_ISP_PIN=$(MCU_ISP_PIN) \
-DLED_CONN_PIN=$(LED_CONN_PIN) -DLED_SERIAL_PIN=$(LED_SERIAL_PIN) \ -DLED_CONN_PIN=$(LED_CONN_PIN) -DLED_SERIAL_PIN=$(LED_SERIAL_PIN) \
-DVERSION="$(VERSION)" -DVERSION="$(VERSION)" -DBUILD_DATE="$(DATE)" -DBUILD_TIME="$(TIME)" -DBUILD_NUM="$(BUILD_NUMBER)"
# linker flags used to generate the main object file # linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--gc-sections LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--gc-sections
@ -343,13 +351,23 @@ all: echo_version checkdirs $(FW_BASE)/user1.bin $(FW_BASE)/user2.bin
echo_version: echo_version:
@echo VERSION: $(VERSION) @echo VERSION: $(VERSION)
# Create an auto-incrementing build number.
@echo "#define VER_STR2(V) #V" > $(BUILD_NUMBER_SRC)
@echo "#define VER_STR(V) VER_STR2(V)" >> $(BUILD_NUMBER_SRC)
@echo "char esp_link_version[] = VER_STR(VERSION);" >> $(BUILD_NUMBER_SRC)
@echo "char esp_link_date[] = VER_STR(BUILD_DATE);" >> $(BUILD_NUMBER_SRC)
@echo "char esp_link_time[] = VER_STR(BUILD_TIME);" >> $(BUILD_NUMBER_SRC)
@echo "char esp_link_build[] = VER_STR(BUILD_NUM);" >> $(BUILD_NUMBER_SRC)
# Build number file. Increment if firmware file changes
$(BUILD_NUMBER_FILE): $(USER1_OUT)
@if ! test -f $(BUILD_NUMBER_FILE); then echo 0 > $(BUILD_NUMBER_FILE); fi
@echo $$(($$(cat $(BUILD_NUMBER_FILE)) + 1)) > $(BUILD_NUMBER_FILE)
$(USER1_OUT): $(APP_AR) $(LD_SCRIPT1) $(USER1_OUT): $(APP_AR) $(LD_SCRIPT1)
$(vecho) "LD $@" $(vecho) "LD $@"
$(Q) $(LD) -L$(SDK_LIBDIR) -T$(LD_SCRIPT1) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@ $(Q) $(LD) -L$(SDK_LIBDIR) -T$(LD_SCRIPT1) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@
@echo Dump : $(OBJDP) -x $(USER1_OUT) $(Q) $(OBJDP) -S $(USER1_OUT) > $(addprefix $(BUILD_BASE)/,$(TARGET).dump)
@echo Disass: $(OBJDP) -d -l -x $(USER1_OUT)
# $(Q) $(OBJDP) -x $(TARGET_OUT) | egrep espfs_img
$(USER2_OUT): $(APP_AR) $(LD_SCRIPT2) $(USER2_OUT): $(APP_AR) $(LD_SCRIPT2)
$(vecho) "LD $@" $(vecho) "LD $@"
@ -360,16 +378,15 @@ $(FW_BASE):
$(vecho) "FW $@" $(vecho) "FW $@"
$(Q) mkdir -p $@ $(Q) mkdir -p $@
$(FW_BASE)/user1.bin: $(USER1_OUT) $(FW_BASE) $(FW_BASE)/user1.bin: $(USER1_OUT) $(FW_BASE) $(BUILD_NUMBER_FILE)
$(Q) $(OBJCP) --only-section .text -O binary $(USER1_OUT) eagle.app.v6.text.bin $(Q) $(OBJCP) --only-section .text -O binary $(USER1_OUT) eagle.app.v6.text.bin
$(Q) $(OBJCP) --only-section .data -O binary $(USER1_OUT) eagle.app.v6.data.bin $(Q) $(OBJCP) --only-section .data -O binary $(USER1_OUT) eagle.app.v6.data.bin
$(Q) $(OBJCP) --only-section .rodata -O binary $(USER1_OUT) eagle.app.v6.rodata.bin $(Q) $(OBJCP) --only-section .rodata -O binary $(USER1_OUT) eagle.app.v6.rodata.bin
$(Q) $(OBJCP) --only-section .irom0.text -O binary $(USER1_OUT) eagle.app.v6.irom0text.bin $(Q) $(OBJCP) --only-section .irom0.text -O binary $(USER1_OUT) eagle.app.v6.irom0text.bin
ls -ls eagle*bin
$(Q) COMPILE=gcc PATH=$(XTENSA_TOOLS_ROOT):$(PATH) python $(APPGEN_TOOL) $(USER1_OUT) 2 $(ESP_FLASH_MODE) $(ESP_FLASH_FREQ_DIV) $(ESP_SPI_SIZE) 0 $(Q) COMPILE=gcc PATH=$(XTENSA_TOOLS_ROOT):$(PATH) python $(APPGEN_TOOL) $(USER1_OUT) 2 $(ESP_FLASH_MODE) $(ESP_FLASH_FREQ_DIV) $(ESP_SPI_SIZE) 0
$(Q) rm -f eagle.app.v6.*.bin $(Q) rm -f eagle.app.v6.*.bin
$(Q) mv eagle.app.flash.bin $@ $(Q) mv eagle.app.flash.bin $@
@echo "** user1.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available" @echo "** user1.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available =" $(shell expr $$(stat -c '%s' $@) \* 100 / $(ESP_FLASH_MAX) ) "%"
$(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; false; fi $(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; false; fi
$(FW_BASE)/user2.bin: $(USER2_OUT) $(FW_BASE) $(FW_BASE)/user2.bin: $(USER2_OUT) $(FW_BASE)
@ -410,60 +427,55 @@ tools/$(HTML_COMPRESSOR):
else else
tools/$(HTML_COMPRESSOR): tools/$(HTML_COMPRESSOR):
$(Q) mkdir -p tools $(Q) mkdir -p tools
cd tools; wget https://github.com/yui/yuicompressor/releases/download/v2.4.8/$(YUI_COMPRESSOR) $(Q) if ! test -f tools/$(YUI_COMPRESSOR); then wget https://github.com/yui/yuicompressor/releases/download/v2.4.8/$(YUI_COMPRESSOR) -O tools/$(YUI_COMPRESSOR); fi
cd tools; wget https://htmlcompressor.googlecode.com/files/$(HTML_COMPRESSOR) $(Q) if ! test -f tools/$(HTML_COMPRESSOR); then wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/htmlcompressor/$(HTML_COMPRESSOR) -O tools/$(HTML_COMPRESSOR); fi
endif endif
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes") ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(BUILD_BASE)/espfs_img.o: tools/$(HTML_COMPRESSOR) $(BUILD_BASE)/espfs_img.o: tools/$(HTML_COMPRESSOR)
endif endif
$(BUILD_BASE)/espfs_img.o: html/ html/wifi/ espfs/mkespfsimage/mkespfsimage $(BUILD_BASE)/espfs_img.o: $(shell find html) espfs/mkespfsimage/mkespfsimage
$(Q) rm -rf html_compressed; mkdir html_compressed; mkdir html_compressed/wifi; $(Q) rm -rf html_compressed; mkdir -p html_compressed; cp -r html/* html_compressed;
$(Q) cp -r html/*.ico html_compressed;
$(Q) cp -r html/*.css html_compressed;
$(Q) cp -r html/*.js html_compressed;
$(Q) cp -r html/wifi/*.png html_compressed/wifi;
$(Q) cp -r html/wifi/*.js html_compressed/wifi;
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes") ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) echo "Compression assets with htmlcompressor. This may take a while..." $(Q) echo "Compression assets with htmlcompressor. This is fast..."
$(Q) java -jar tools/$(HTML_COMPRESSOR) \ $(Q) for file in `find html_compressed -type f -name "*.html"`; do \
-t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \ java -jar yui/$(HTML_COMPRESSOR) \
-o $(abspath ./html_compressed)/ \ -t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \
$(HTML_PATH)head- \ -o $$file $$file; \
$(HTML_PATH)*.html done
$(Q) java -jar tools/$(HTML_COMPRESSOR) \ $(Q) echo "Compressing JS/CSS with yui-compressor. This may take a while..."
-t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \
-o $(abspath ./html_compressed)/wifi/ \
$(WIFI_PATH)*.html
$(Q) echo "Compression assets with yui-compressor. This may take a while..."
$(Q) for file in `find html_compressed -type f -name "*.js"`; do \ $(Q) for file in `find html_compressed -type f -name "*.js"`; do \
java -jar tools/$(YUI_COMPRESSOR) $$file --line-break 0 -o $$file; \ java -jar yui/$(YUI_COMPRESSOR) $$file --line-break 0 -o $$file; \
done done
$(Q) for file in `find html_compressed -type f -name "*.css"`; do \ $(Q) for file in `find html_compressed -type f -name "*.css"`; do \
java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \ java -jar yui/$(YUI_COMPRESSOR) $$file -o $$file; \
done done
else
$(Q) cp -r html/head- html_compressed;
$(Q) cp -r html/*.html html_compressed;
$(Q) cp -r html/wifi/*.html html_compressed/wifi;
endif endif
ifeq (,$(findstring mqtt,$(MODULES))) ifeq (,$(findstring mqtt,$(MODULES)))
$(Q) rm -rf html_compressed/mqtt.html $(Q) rm -rf html_compressed/mqtt.html
$(Q) rm -rf html_compressed/mqtt.js $(Q) rm -rf html_compressed/mqtt.js
endif endif
$(Q) for file in `find html_compressed -type f -name "*.htm*"`; do \ $(Q) echo "Now building espFS ..."
cat html_compressed/head- $$file >$${file}-; \
mv $$file- $$file; \
done
$(Q) rm html_compressed/head-
$(Q) cd html_compressed; find . \! -name \*- | ../espfs/mkespfsimage/mkespfsimage > ../build/espfs.img; cd ..; $(Q) cd html_compressed; find . \! -name \*- | ../espfs/mkespfsimage/mkespfsimage > ../build/espfs.img; cd ..;
$(Q) ls -sl build/espfs.img @echo "espFS image is $$(stat -c '%s' build/espfs.img) bytes =" $(shell expr $$(stat -c '%s' build/espfs.img) \* 100 / $$(du -sb html_compressed | { read first _ ; echo $$first; })) "% of uncompressed originals"
$(Q) cd build; $(OBJCP) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.espfs \ $(Q) cd build; $(OBJCP) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.espfs \
espfs.img espfs_img.o; cd .. espfs.img espfs_img.o; cd ..
# edit the loader script to add the espfs section to the end of irom with a 4 byte alignment. # edit the loader script to add the espfs section to the end of irom with a 4 byte alignment.
# we also adjust the sizes of the segments 'cause we need more irom0 # we also adjust the sizes of the segments 'cause we need more irom0
# in the end the only thing that matters wrt size is that the whole shebang fits into the
# 236KB available (in a 512KB flash)
ifeq ("$(FLASH_SIZE)","512KB")
build/eagle.esphttpd1.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.512.app1.ld
$(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \
-e '/^ irom0_0_seg/ s/2B000/38000/' \
$(SDK_LDDIR)/eagle.app.v6.new.512.app1.ld >$@
build/eagle.esphttpd2.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.512.app2.ld
$(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \
-e '/^ irom0_0_seg/ s/2B000/38000/' \
$(SDK_LDDIR)/eagle.app.v6.new.512.app2.ld >$@
else
build/eagle.esphttpd1.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.1024.app1.ld build/eagle.esphttpd1.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.1024.app1.ld
$(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \ $(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \
-e '/^ irom0_0_seg/ s/6B000/7C000/' \ -e '/^ irom0_0_seg/ s/6B000/7C000/' \
@ -472,8 +484,9 @@ build/eagle.esphttpd2.v6.ld: $(SDK_LDDIR)/eagle.app.v6.new.1024.app2.ld
$(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \ $(Q) sed -e '/\.irom\.text/{' -e 'a . = ALIGN (4);' -e 'a *(.espfs)' -e '}' \
-e '/^ irom0_0_seg/ s/6B000/7C000/' \ -e '/^ irom0_0_seg/ s/6B000/7C000/' \
$(SDK_LDDIR)/eagle.app.v6.new.1024.app2.ld >$@ $(SDK_LDDIR)/eagle.app.v6.new.1024.app2.ld >$@
endif
espfs/mkespfsimage/mkespfsimage: espfs/mkespfsimage/ espfs/mkespfsimage/mkespfsimage: espfs/mkespfsimage/*.c
$(Q) $(MAKE) -C espfs/mkespfsimage GZIP_COMPRESSION="$(GZIP_COMPRESSION)" $(Q) $(MAKE) -C espfs/mkespfsimage GZIP_COMPRESSION="$(GZIP_COMPRESSION)"
release: all release: all

@ -27,10 +27,11 @@ void ICACHE_FLASH_ATTR noCacheHeaders(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code); httpdStartResponse(connData, code);
httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate"); httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate");
httpdHeader(connData, "Pragma", "no-cache"); httpdHeader(connData, "Pragma", "no-cache");
httpdHeader(connData, "Expires", "0"); httpdHeader(connData, "Expires", "Mon, 26 Jul 1997 05:00:00 GMT");
} }
void ICACHE_FLASH_ATTR jsonHeader(HttpdConnData *connData, int code) { void ICACHE_FLASH_ATTR jsonHeader(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code);
noCacheHeaders(connData, code); noCacheHeaders(connData, code);
httpdHeader(connData, "Content-Type", "application/json"); httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData); httpdEndHeaders(connData);
@ -187,8 +188,6 @@ int ICACHE_FLASH_ATTR printGlobalInfo(char *buff, int buflen, char *token) {
} }
#endif #endif
extern char *esp_link_version; // in user_main.c
int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
char buff[1024]; char buff[1024];
@ -214,6 +213,7 @@ int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) {
"\"REST/MQTT\", \"/mqtt.html\", " "\"REST/MQTT\", \"/mqtt.html\", "
#endif #endif
"\"Debug log\", \"/log.html\"" "\"Debug log\", \"/log.html\""
"\"Firmware\", \"/flash/flash.html\""
" ], " " ], "
"\"version\": \"%s\", " "\"version\": \"%s\", "
"\"name\": \"%s\"" "\"name\": \"%s\""

@ -57,11 +57,11 @@ int ICACHE_FLASH_ATTR cgiGetFirmwareNext(HttpdConnData *connData) {
} }
uint8 id = system_upgrade_userbin_check(); uint8 id = system_upgrade_userbin_check();
httpdStartResponse(connData, 200); noCacheHeaders(connData, 200);
httpdHeader(connData, "Content-Type", "text/plain"); httpdHeader(connData, "Content-Type", "text/plain");
httpdHeader(connData, "Content-Length", "9"); httpdHeader(connData, "Content-Length", "9");
httpdEndHeaders(connData); httpdEndHeaders(connData);
char *next = id == 1 ? "user1.bin" : "user2.bin"; char *next = (id == 1 ? "user1.bin" : "user2.bin");
httpdSend(connData, next, -1); httpdSend(connData, next, -1);
DBG("Next firmware: %s (got %d)\n", next, id); DBG("Next firmware: %s (got %d)\n", next, id);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
@ -124,7 +124,7 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
// erase next flash block if necessary // erase next flash block if necessary
if (address % SPI_FLASH_SEC_SIZE == 0){ if (address % SPI_FLASH_SEC_SIZE == 0){
DBG("Flashing 0x%05x (id=%d)\n", address, 2 - id); DBG("Flashing 0x%05X (id=%d)\n", address, 2 - id);
spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE); spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE);
} }

@ -732,8 +732,8 @@ int ICACHE_FLASH_ATTR printWifiInfo(char *buff) {
if (rssi > 0) rssi = 0; if (rssi > 0) rssi = 0;
uint8 mac_addr[6]; uint8 mac_addr[6];
uint8 apmac_addr[6]; uint8 apmac_addr[6];
wifi_get_macaddr(0, mac_addr); wifi_get_macaddr(STATION_IF, mac_addr);
wifi_get_macaddr(1, apmac_addr); wifi_get_macaddr(SOFTAP_IF, apmac_addr);
uint8_t chan = wifi_get_channel(); uint8_t chan = wifi_get_channel();
len = os_sprintf(buff, len = os_sprintf(buff,

@ -64,6 +64,8 @@ should be placed above the URLs they protect.
HttpdBuiltInUrl builtInUrls[] = { HttpdBuiltInUrl builtInUrls[] = {
{ "/", cgiRedirect, "/home.html" }, { "/", cgiRedirect, "/home.html" },
{ "/menu", cgiMenu, NULL }, { "/menu", cgiMenu, NULL },
{"/flash", cgiRedirect, "/flash/flash.html"},
{"/flash/", cgiRedirect, "/flash/flash.html"},
{ "/flash/next", cgiGetFirmwareNext, NULL }, { "/flash/next", cgiGetFirmwareNext, NULL },
{ "/flash/upload", cgiUploadFirmware, NULL }, { "/flash/upload", cgiUploadFirmware, NULL },
{ "/flash/reboot", cgiRebootFirmware, NULL }, { "/flash/reboot", cgiRebootFirmware, NULL },
@ -107,10 +109,6 @@ static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg) {
} }
#endif #endif
# define VERS_STR_STR(V) #V
# define VERS_STR(V) VERS_STR_STR(V)
char* esp_link_version = VERS_STR(VERSION);
// address of espfs binary blob // address of espfs binary blob
extern uint32_t _binary_espfs_img_start; extern uint32_t _binary_espfs_img_start;
@ -139,7 +137,7 @@ void user_init(void) {
logInit(); // must come after init of uart logInit(); // must come after init of uart
// Say hello (leave some time to cause break in TX after boot loader's msg // Say hello (leave some time to cause break in TX after boot loader's msg
os_delay_us(10000L); os_delay_us(10000L);
os_printf("\n\n** %s\n", esp_link_version); os_printf("\n\n** %s, build %s\n", esp_link_version, esp_link_build);
os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*"); os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*");
// Status LEDs // Status LEDs
statusInit(); statusInit();
@ -162,26 +160,26 @@ void user_init(void) {
#endif #endif
struct rst_info *rst_info = system_get_rst_info(); struct rst_info *rst_info = system_get_rst_info();
NOTICE("Reset cause: %d=%s", rst_info->reason, rst_codes[rst_info->reason]); NOTICE("Reset cause: %d=%s\n", rst_info->reason, rst_codes[rst_info->reason]);
NOTICE("exccause=%d epc1=0x%x epc2=0x%x epc3=0x%x excvaddr=0x%x depc=0x%x", NOTICE("exccause=%d epc1=0x%x epc2=0x%x epc3=0x%x excvaddr=0x%x depc=0x%x\n",
rst_info->exccause, rst_info->epc1, rst_info->epc2, rst_info->epc3, rst_info->exccause, rst_info->epc1, rst_info->epc2, rst_info->epc3,
rst_info->excvaddr, rst_info->depc); rst_info->excvaddr, rst_info->depc);
uint32_t fid = spi_flash_get_id(); uint32_t fid = spi_flash_get_id();
NOTICE("Flash map %s, manuf 0x%02X chip 0x%04X", flash_maps[system_get_flash_size_map()], NOTICE("Flash map %s, manuf 0x%02X chip 0x%04X\n", flash_maps[system_get_flash_size_map()],
fid & 0xff, (fid&0xff00)|((fid>>16)&0xff)); fid & 0xff, (fid&0xff00)|((fid>>16)&0xff));
NOTICE("** %s: ready, heap=%ld", esp_link_version, (unsigned long)system_get_free_heap_size()); NOTICE("** %s: ready, heap=%ld\n", esp_link_version, (unsigned long)system_get_free_heap_size());
// Init SNTP service // Init SNTP service
cgiServicesSNTPInit(); cgiServicesSNTPInit();
#ifdef MQTT #ifdef MQTT
if (flashConfig.mqtt_enable) { if (flashConfig.mqtt_enable) {
NOTICE("initializing MQTT"); NOTICE("initializing MQTT\n");
mqtt_client_init(); mqtt_client_init();
} }
#endif #endif
NOTICE("initializing user application"); NOTICE("initializing user application\n");
app_init(); app_init();
NOTICE("Waiting for work to do..."); NOTICE("Waiting for work to do...\n");
#ifdef MEMLEAK_DEBUG #ifdef MEMLEAK_DEBUG
system_show_malloc(); system_show_malloc();
#endif #endif

@ -1,25 +1,38 @@
<!doctype html>
<html><head>
<title>esp-link</title>
<link rel="stylesheet" href="pure.css">
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="layout">
<div id="main" class="flex-fill flex-vbox" style="max-height:100%"> <div id="main" class="flex-fill flex-vbox" style="max-height:100%">
<div class="header"> <div class="header">
<h1>Microcontroller Console</h1> <h1>Microcontroller Console</h1>
</div> </div>
<div class="content flex-fill flex-vbox"> <div class="content flex-fill flex-vbox">
<p> <p>The Microcontroller console shows the last 1024 characters
received from UART0, to which a microcontroller is typically attached.
The UART is configured for 8 bits, no parity, 1 stop bit (8N1).
</p>
<div>
<a id="reset-button" class="pure-button button-primary" href="#">Reset &#xb5;C</a> <a id="reset-button" class="pure-button button-primary" href="#">Reset &#xb5;C</a>
&nbsp; <a id="clear-button" class="pure-button button-primary" href="#">Clear Log</a> &nbsp; <a id="clear-button" class="pure-button button-primary" href="#">Clear Log</a>
&nbsp; Baud: &nbsp; Baud (8N1):
<select id="baud-sel" class="pure-button" href="#"> <select id="baud-sel" class="pure-button" href="#">
<option value="460800">460800</option> <option value="0"> </option>
<option value="250000">250000</option>
<option value="230400">230400</option>
<option value="115200">115200</option>
<option value="57600">57600</option>
<option value="38400">38400</option>
<option value="19200">19200</option>
<option value="9600">9600</option> <option value="9600">9600</option>
<option value="19200">19200</option>
<option value="38400">38400</option>
<option value="57600">57600</option>
<option value="115200">115200</option>
<option value="230400">230400</option>
<option value="250000">250000</option>
<option value="460800">460800</option>
</select> </select>
&nbsp; Fmt: 8N1 </div>
</p>
<div class="pure-g"> <div class="pure-g">
<div class="pure-u-1-4"><legend><b>Console</b></legend></div> <div class="pure-u-1-4"><legend><b>Console</b></legend></div>
<div class="pure-u-3-4"></div> <div class="pure-u-3-4"></div>
@ -56,49 +69,7 @@
</div> </div>
</div> </div>
</div> </div>
<script src="ui.js"></script>
<script type="text/javascript">console_url = "/console/text"</script>
<script src="console.js"></script> <script src="console.js"></script>
<script type="text/javascript"> <script src="console_main.js"></script>
onLoad(function() {
fetchText(100, true);
$("#reset-button").addEventListener("click", function(e) {
e.preventDefault();
var co = $("#console");
co.innerHTML = "";
ajaxSpin('POST', "/console/reset",
function(resp) { showNotification("uC reset"); co.textEnd = 0; },
function(s, st) { showWarning("Error resetting uC"); }
);
});
$("#clear-button").addEventListener("click", function(e) {
e.preventDefault();
var co = $("#console");
co.innerHTML = "";
});
ajaxJson('GET', "/console/baud",
function(data) { $("#baud-sel").value = data.rate; },
function(s, st) { showNotification(st); }
);
bnd($("#baud-sel"), "change", function(ev) {
ev.preventDefault();
var baud = $("#baud-sel").value;
ajaxSpin('POST', "/console/baud?rate="+baud,
function(resp) { showNotification("" + baud + " baud set"); },
function(s, st) { showWarning("Error setting baud rate: " + st); }
);
});
consoleSendInit();
addClass($('html')[0], "height100");
addClass($('body')[0], "height100");
addClass($('#layout'), "height100");
addClass($('#layout'), "flex-vbox");
});
</script>
</body></html> </body></html>

@ -1,3 +1,12 @@
<!doctype html>
<html><head>
<title>esp-link</title>
<link rel="stylesheet" href="pure.css">
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="layout">
<div id="main"> <div id="main">
<div class="header"> <div class="header">
<div><img src="favicon.ico" height="64"><span class="jl">JEELABS</span></div> <div><img src="favicon.ico" height="64"><span class="jl">JEELABS</span></div>
@ -6,150 +15,137 @@
</div> </div>
<div class="content"> <div class="content">
<div class="pure-g"> <div style="float:left; padding:2px">
<!-- LEFT COLUMN --> <div class="card">
<div class="pure-u-1 pure-u-md-1-2"> <h1>System overview</h1>
<div class="card"> <div id="wifi-spinner" class="spinner spinner-small"></div>
<h1>System overview</h1> <table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody>
<div id="wifi-spinner" class="spinner spinner-small"></div> <tr><td class="popup-target">Hostname</td><td>
<table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody> <div class="click-to-edit system-name">
<tr><td class="popup-target">Hostname</td><td> <span class="edit-off"></span>
<div class="click-to-edit system-name"> <input class="edit-on" maxlength=31 hidden></input>
<span class="edit-off"></span> <div class="popup">Click to edit!<br>Hostname displayed in menu bar
<input class="edit-on" maxlength=31 hidden></input> and used by DHCP and mDNS</div>
<div class="popup">Click to edit!<br>Hostname displayed in menu bar </div>
and used by DHCP and mDNS</div> </td></tr>
</div> <tr><td>Network SSID</td><td id="wifi-ssid"></td></tr>
</td></tr> <tr><td>WiFi status</td><td id="wifi-status"></td></tr>
<tr><td>Network SSID</td><td id="wifi-ssid"></td></tr> <tr><td>WiFi address</td><td id="wifi-ip"></td></tr>
<tr><td>WiFi status</td><td id="wifi-status"></td></tr> <tr><td>SLIP status</td><td class="system-slip"></td></tr>
<tr><td>WiFi address</td><td id="wifi-ip"></td></tr> <tr><td>MQTT status</td><td class="system-mqtt"></td></tr>
<tr><td>SLIP status</td><td class="system-slip"></td></tr> <tr><td>Serial baud</td><td class="system-baud"></td></tr>
<tr><td>MQTT status</td><td class="system-mqtt"></td></tr> </tbody></table>
<tr><td>Serial baud</td><td class="system-baud"></td></tr> </div>
</tbody></table> <div class="card">
</div> <h1>Info</h1>
<div class="card"> <p style="margin-bottom:0;">The JeeLabs esp-link firmware bridges the ESP8266
<h1>Info</h1> serial port to WiFi and can
<p style="margin-bottom:0;">The JeeLabs esp-link firmware bridges the ESP8266 program microcontrollers over the serial port, in particular Arduinos, AVRs, and
serial port to WiFi and can NXP's LPC800 and other ARM processors. Typical avrdude command line to
program microcontrollers over the serial port, in particular Arduinos, AVRs, and program an Arduino:</p>
NXP's LPC800 and other ARM processors. Typical avrdude command line to <div class="tt" style="font-size:100%;">
program an Arduino:</p> /home/arduino/hardware/tools/avrdude&nbsp;\<br>
<div class="tt" style="font-size:100%;"> &nbsp;&nbsp;-DV -patmega328p \<br>
/home/arduino/hardware/tools/avrdude&nbsp;\<br> &nbsp;&nbsp;-Pnet:esp-link.local:23 \<br>
&nbsp;&nbsp;-DV -patmega328p \<br> &nbsp;&nbsp;-carduino -b115200 \<br>
&nbsp;&nbsp;-Pnet:esp-link.local:23 \<br> &nbsp;&nbsp;-U flash:w:my_sketch.hex:i\<br>
&nbsp;&nbsp;-carduino -b115200 \<br> &nbsp;&nbsp;-C /home/arduino/hardware/tools/avrdude.conf
&nbsp;&nbsp;-U flash:w:my_sketch.hex:i\<br>
&nbsp;&nbsp;-C /home/arduino/hardware/tools/avrdude.conf
</div>
<p>where <tt>-Pnet:esp-link.local:23</tt> tells avrdude to connect to port 23 of esp-link.
You can substitute the IP address of your esp-link for esp-link.local if necessary.
Please refer to
<a href="https://github.com/jeelabs/esp-link/blob/master/README.md">the online README</a>
for up-to-date help.</p>
</div> </div>
<p>where <tt>-Pnet:esp-link.local:23</tt> tells avrdude to connect to port 23 of esp-link.
You can substitute the IP address of your esp-link for esp-link.local if necessary.
Please refer to
<a href="https://github.com/jeelabs/esp-link/blob/master/README.md">the online README</a>
for up-to-date help.</p>
</div> </div>
<!-- RIGHT COLUMN --> </div>
<div class="pure-u-1 pure-u-md-1-2"> <div style="float:left; padding:2px">
<div class="card"> <div class="card">
<h1>Pin assignment</h1> <h1>System details</h1>
<div id="pin-spinner" class="spinner spinner-small"></div> <div id="system-spinner" class="spinner spinner-small"></div>
<div id="pin-table" hidden> <table id="system-table" class="pure-table pure-table-horizontal" hidden><tbody>
<form action="#" id="pinform" class="pure-form pure-form-aligned form-narrow"> <tr><td>WiFi mode</td><td id="wifi-mode"></td></tr>
<div class="pure-control-group"> <tr><td>WiFi channel</td><td id="wifi-chan"></td></tr>
<label for="pin-preset">Presets</label> <tr><td>Flash chip ID</td><td>
<select id="pin-preset" class="pure-button"> <div>
<option value="" selected disabled></option> <span class="system-id"></span>
</select> <div class="popup pop-left">Common IDs: 4016=4MB, 4014=1MB, 4013=512KB</div>
</div>
<hr>
<div class="pure-control-group">
<label for="pin-reset">Reset</label>
<select id="pin-reset"></select>
<div class="popup">Connect to &#xb5;C reset pin for programming and reset-&#xb5;C function</div>
</div>
<div class="pure-control-group">
<label for="pin-isp">ISP/Flash</label>
<select id="pin-isp"></select>
<div class="popup">Second signal to program &#xb5;C.
AVR:not used, esp8266:gpio2, ARM:ISP</div>
</div>
<div class="pure-control-group">
<label for="pin-conn">Conn LED</label>
<select id="pin-conn"></select>
<div class="popup">LED to show WiFi connectivity</div>
</div>
<div class="pure-control-group">
<label for="pin-ser">Serial LED</label>
<select id="pin-ser"></select>
<div class="popup">LED to show serial activity</div>
</div>
<div class="pure-control-group">
<label for="pin-swap">UART pins</label>
<select id="pin-swap" class="pure-button">
<option value="0">normal</option>
<option value="1">swapped</option>
</select>
<div class="popup">Swap UART0 pins to avoid ROM boot message.<br>Normal is
TX on gpio1/TX0 and RX on gpio3/RX0, swapped is TX on gpio15 and RX on gpio13.
</div>
</div>
<div class="pure-control-group">
<label for="pin-rxpup" class="pure-checkbox">RX pull-up</label>
<input id="pin-rxpup" type="checkbox">
<div class="popup">Enable internal 40K pull-up on RX</div>
</div>
<button id="set-pins" type="submit" class="pure-button button-primary">Change!</button>
</form>
</div> </div>
</div> </td></tr>
<div class="card"> <tr><td>Flash size</td><td>
<h1>System details</h1> <div>
<div id="system-spinner" class="spinner spinner-small"></div> <span class="system-size"></span>
<table id="system-table" class="pure-table pure-table-horizontal" hidden><tbody> <div class="popup pop-left">Size configured into bootloader, must match chip size</div>
<tr><td>WiFi mode</td><td id="wifi-mode"></td></tr> </div>
<tr><td>WiFi channel</td><td id="wifi-chan"></td></tr> </td></tr>
<tr><td>Flash chip ID</td><td> <tr><td>Current partition</td><td class="system-partition"></td></tr>
<div> <tr><td colspan=2 class="popup-target">Description:<br>
<span class="system-id"></span> <div class="click-to-edit system-description">
<div class="popup pop-left">Common IDs: 4016=4MB, 4014=1MB, 4013=512KB</div> <span class="edit-off" style="display:block; width:auto;"></span>
<textarea class="edit-on" rows=3 maxlength=127 hidden> </textarea>
<div class="popup">Click to edit!<br>A short description or memo for this esp-link
module, 128 chars max</div>
</div> </div>
</td></tr> </td></tr>
<tr><td>Flash size</td><td> </tbody></table>
<div> </div>
<span class="system-size"></span> </div>
<div class="popup pop-left">Size configured into bootloader, must match chip size</div> <div style="float:left; padding:2px">
<div class="card">
<h1>Pin assignment</h1>
<div id="pin-spinner" class="spinner spinner-small"></div>
<div id="pin-table" hidden>
<form action="#" id="pinform" class="pure-form pure-form-aligned form-narrow">
<div class="pure-control-group">
<label for="pin-preset">Presets</label>
<select id="pin-preset" class="pure-button">
<option value="" selected disabled></option>
</select>
</div> </div>
</td></tr> <hr>
<tr><td>Current partition</td><td class="system-partition"></td></tr> <div class="pure-control-group">
<tr><td colspan=2 class="popup-target">Description:<br> <label for="pin-reset">Reset</label>
<div class="click-to-edit system-description"> <select id="pin-reset"></select>
<span class="edit-off" style="display:block; width:auto;"></span> <div class="popup">Connect to &#xb5;C reset pin for programming and reset-&#xb5;C function</div>
<textarea class="edit-on" rows=3 maxlength=127 hidden> </textarea> </div>
<div class="popup">Click to edit!<br>A short description or memo for this esp-link <div class="pure-control-group">
module, 128 chars max</div> <label for="pin-isp">ISP/Flash</label>
<select id="pin-isp"></select>
<div class="popup">Second signal to program &#xb5;C.
AVR:not used, esp8266:gpio2, ARM:ISP</div>
</div>
<div class="pure-control-group">
<label for="pin-conn">Conn LED</label>
<select id="pin-conn"></select>
<div class="popup">LED to show WiFi connectivity</div>
</div>
<div class="pure-control-group">
<label for="pin-ser">Serial LED</label>
<select id="pin-ser"></select>
<div class="popup">LED to show serial activity</div>
</div>
<div class="pure-control-group">
<label for="pin-swap">UART pins</label>
<select id="pin-swap" class="pure-button">
<option value="0">normal</option>
<option value="1">swapped</option>
</select>
<div class="popup">Swap UART0 pins to avoid ROM boot message.<br>Normal is
TX on gpio1/TX0 and RX on gpio3/RX0, swapped is TX on gpio15 and RX on gpio13.
</div> </div>
</td></tr> </div>
</tbody></table> <div class="pure-control-group">
<label for="pin-rxpup" class="pure-checkbox">RX pull-up</label>
<input id="pin-rxpup" type="checkbox">
<div class="popup">Enable internal 40K pull-up on RX</div>
</div>
<button id="set-pins" type="submit" class="pure-button button-primary">Change!</button>
</form>
</div> </div>
</div> </div>
</div> </div>
<div class="pure-g">
</div>
</div> </div>
</div> </div>
</div> </div>
<script src="ui.js"></script>
<script type="text/javascript"> <script src="home.js"></script>
onLoad(function() {
makeAjaxInput("system", "description");
makeAjaxInput("system", "name");
fetchPins();
getWifiInfo();
getSystemInfo();
bnd($("#pinform"), "submit", setPins);
});
</script>
</body></html> </body></html>

@ -1,11 +1,19 @@
<!doctype html>
<html><head>
<title>esp-link</title>
<link rel="stylesheet" href="pure.css">
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="layout">
<div id="main"> <div id="main">
<div class="header"> <div class="header">
<h1>Debug Log</h1> <h1>Debug Log</h1>
</div> </div>
<div class="content"> <div class="content">
<p>The debug log shows the most recent characters printed by the esp-link software itself to <p>The debug log shows the most recent characters printed by the ESP-LINK software itself to its own debug log.</p>
its own debug log.</p>
<div class="pure-g"> <div class="pure-g">
<p class="pure-u-1-4" style="vertical-align: baseline;width:40%"> <p class="pure-u-1-4" style="vertical-align: baseline;width:40%">
<a id="refresh-button" class="pure-button button-primary" href="#">Refresh</a> <a id="refresh-button" class="pure-button button-primary" href="#">Refresh</a>
@ -14,8 +22,11 @@
<p class="pure-u-3-4" style="vertical-align: baseline;width:60%"> <p class="pure-u-3-4" style="vertical-align: baseline;width:60%">
UART debug log: UART debug log:
<a id="dbg-auto" class="dbg-btn pure-button" href="#">auto</a> <a id="dbg-auto" class="dbg-btn pure-button" href="#">auto</a>
&nbsp;
<a id="dbg-off" class="dbg-btn pure-button" href="#">off</a> <a id="dbg-off" class="dbg-btn pure-button" href="#">off</a>
&nbsp;
<a id="dbg-on0" class="dbg-btn pure-button" href="#">on uart0</a> <a id="dbg-on0" class="dbg-btn pure-button" href="#">on uart0</a>
&nbsp;
<a id="dbg-on1" class="dbg-btn pure-button" href="#">on uart1</a> <a id="dbg-on1" class="dbg-btn pure-button" href="#">on uart1</a>
</p> </p>
</div> </div>
@ -23,38 +34,7 @@
</div> </div>
</div> </div>
</div> </div>
<script src="ui.js"></script>
<script type="text/javascript">console_url = "/log/text"</script>
<script src="console.js"></script> <script src="console.js"></script>
<script type="text/javascript"> <script src="log_main.js"></script>
onLoad(function() {
fetchText(100, false);
$("#refresh-button").addEventListener("click", function(e) {
e.preventDefault();
fetchText(100, false);
});
$("#reset-button").addEventListener("click", function (e) {
e.preventDefault();
var co = $("#console");
co.innerHTML = "";
ajaxSpin('POST', "/log/reset",
function (resp) { showNotification("Resetting esp-link"); co.textEnd = 0; fetchText(2000, false); },
function (s, st) { showWarning("Error resetting esp-link"); }
);
});
["auto", "off", "on0", "on1"].forEach(function(mode) {
bnd($('#dbg-'+mode), "click", function(el) {
ajaxJsonSpin('POST', "/log/dbg?mode="+mode,
function(data) { showNotification("UART mode " + data.mode); showDbgMode(data.mode); },
function(s, st) { showWarning("Error setting UART mode: " + st); }
);
});
});
ajaxJson('GET', "/log/dbg", function(data) { showDbgMode(data.mode); }, function() {});
});
</script>
</body></html> </body></html>

@ -1,3 +1,12 @@
<!doctype html>
<html><head>
<title>esp-link</title>
<link rel="stylesheet" href="pure.css">
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="layout">
<div id="main"> <div id="main">
<div class="header"> <div class="header">
<h1>REST &amp; MQTT</h1> <h1>REST &amp; MQTT</h1>
@ -92,13 +101,6 @@
</div> </div>
</div> </div>
</div> </div>
<script src="ui.js"></script>
<script src="mqtt.js"></script> <script src="mqtt.js"></script>
<script type="text/javascript">
onLoad(function() {
fetchMqtt();
bnd($("#mqtt-form"), "submit", changeMqtt);
bnd($("#mqtt-status-form"), "submit", changeMqttStatus);
});
</script>
</body></html> </body></html>

@ -1,3 +1,9 @@
onLoad(function() {
fetchMqtt();
bnd($("#mqtt-form"), "submit", changeMqtt);
bnd($("#mqtt-status-form"), "submit", changeMqttStatus);
});
//===== MQTT cards //===== MQTT cards
function changeMqtt(e) { function changeMqtt(e) {

@ -693,8 +693,8 @@ this the same font stack that Normalize.css sets for the `body`.
font-family: inherit; font-family: inherit;
font-size: 100%; font-size: 100%;
padding: 0.5em 1em; padding: 0.5em 1em;
color: #444; /* rgba not supported (IE 8) */ color: #fff; /* rgba not supported (IE 8) */
color: rgba(0, 0, 0, 0.80); /* rgba supported */ color: rgba(f, f, f, 0.80); /* rgba supported */
border: 1px solid #999; /*IE 6/7/8*/ border: 1px solid #999; /*IE 6/7/8*/
border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/ border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
background-color: #E6E6E6; background-color: #E6E6E6;

@ -1,120 +1,121 @@
<!doctype html>
<html><head>
<title>esp-link</title>
<link rel="stylesheet" href="pure.css">
<link rel="stylesheet" href="style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="layout">
<div id="main"> <div id="main">
<div class="header"> <div class="header">
<h1>Services</h1> <h1>Services</h1>
</div> </div>
<div class="content"> <div class="content">
<div class="pure-g"> <div style="float:left; padding:2px">
<div class="pure-u-1 pure-u-md-1-2"> <div class="card">
<div class="card"> <h1>
<h1> Syslog
Syslog <div id="syslog-spinner" class="spinner spinner-small"></div>
<div id="syslog-spinner" class="spinner spinner-small"></div> </h1>
</h1> <form action="#" id="Syslog-form" class="pure-form" hidden>
<form action="#" id="Syslog-form" class="pure-form" hidden> <div class="pure-form-stacked">
<div class="pure-form-stacked"> <label>Syslog Host</label>
<label>Syslog Host</label> <input type="text" name="syslog_host" />
<input type="text" name="syslog_host" /> <div class="popup">Esp-link sends event/debug info to this syslog host
<div class="popup">Esp-link sends event/debug info to this syslog host (hostname:port). Leave empty to disable syslog.</div>
(hostname:port). Leave empty to disable syslog.</div> </div>
</div> <div class="pure-form-stacked">
<div class="pure-form-stacked"> <label>Min Heap</label>
<label>Min Heap</label>
<div>
<input type="text" name="syslog_minheap" />
<div class="popup">Stop sending syslog if free heap drops below this many bytes</div>
</div>
<div>
<label>Filter</label>
<select name="syslog_filter" href="#">
<option value="0">EMERG</option>
<option value="1">ALERT</option>
<option value="2">CRIT</option>
<option value="3">ERR</option>
<option value="4">WARNING</option>
<option value="5">NOTICE</option>
<option value="6">INFO</option>
<option value="7">DEBUG</option>
</select>
<div class="popup">Minimum severity to send</div>
</div>
</div>
<div> <div>
<input type="checkbox" name="syslog_showtick" /> <input type="text" name="syslog_minheap" />
<label>Include esp-link millisecond ticker</label> <div class="popup">Stop sending syslog if free heap drops below this many bytes</div>
</div> </div>
<div> <div>
<input type="checkbox" name="syslog_showdate" /> <label>Filter</label>
<label>Include esp-link datetime</label> <select name="syslog_filter" href="#">
<div class="popup">Some syslog servers rotate log if timestamp is in the past so disable to prevent this</div> <option value="0">EMERG</option>
</div> <option value="1">ALERT</option>
<button id="Syslog-button" type="submit" class="pure-button button-primary"> <option value="2">CRIT</option>
Update Syslog settings! <option value="3">ERR</option>
</button> <option value="4">WARNING</option>
</form> <option value="5">NOTICE</option>
</div> <option value="6">INFO</option>
<div class="card"> <option value="7">DEBUG</option>
<h1> </select>
mDNS <div class="popup">Minimum severity to send</div>
<div id="mdns-spinner" class="spinner spinner-small"></div>
</h1>
<form action="#" id="mDNS-form" class="pure-form" hidden>
<div class="form-horizontal">
<input type="checkbox" name="mdns_enable"/>
<label>Enable mDNS</label>
<div class="popup">Esp-link can advertise its hostname and service name (both
with a .local suffix) via multicast DNS.</div>
</div> </div>
<br> </div>
<div class="pure-form-stacked"> <div>
<label>Service Name</label> <input type="checkbox" name="syslog_showtick" />
<input type="text" name="mdns_servername"/> <label>Include esp-link millisecond ticker</label>
<div class="popup">The default service is http. For the arduino IDE use arduino</div> </div>
</div> <div>
<button id="mDNS-button" type="submit" class="pure-button button-primary"> <input type="checkbox" name="syslog_showdate" />
Update mDNS settings! <label>Include esp-link datetime</label>
</button> <div class="popup">Some syslog servers rotate log if timestamp is in the past so disable to prevent this</div>
</form> </div>
</div> <button id="Syslog-button" type="submit" class="pure-button button-primary">
Update Syslog settings!
</button>
</form>
</div>
</div>
<div style="float:left; padding:2px">
<div class="card">
<h1>
mDNS
<div id="mdns-spinner" class="spinner spinner-small"></div>
</h1>
<form action="#" id="mDNS-form" class="pure-form" hidden>
<div class="form-horizontal">
<input type="checkbox" name="mdns_enable"/>
<label>Enable mDNS</label>
<div class="popup">Esp-link can advertise its hostname and service name (both
with a .local suffix) via multicast DNS.</div>
</div>
<br>
<div class="pure-form-stacked">
<label>Service Name</label>
<input type="text" name="mdns_servername"/>
<div class="popup">The default service is http. For the arduino IDE use arduino</div>
</div>
<button id="mDNS-button" type="submit" class="pure-button button-primary">
Update mDNS settings!
</button>
</form>
</div> </div>
<div class="pure-u-1 pure-u-md-1-2"> </div>
<div class="card"> <div style="float:left; padding:2px">
<h1> <div class="card">
SNTP <h1>
<div id="sntp-spinner" class="spinner spinner-small"></div> SNTP
</h1> <div id="sntp-spinner" class="spinner spinner-small"></div>
<form action="#" id="SNTP-form" class="pure-form" hidden> </h1>
<div class="pure-form-stacked"> <form action="#" id="SNTP-form" class="pure-form" hidden>
<div> <div class="pure-form-stacked">
<label>SNTP Server</label> <div>
<input type="text" name="sntp_server" /> <label>SNTP Server</label>
<div class="popup">Simple Network Time Protocol server to query. <input type="text" name="sntp_server" />
Leave empty to disable SNTP</div> <div class="popup">Simple Network Time Protocol server to query.
</div> Leave empty to disable SNTP</div>
<div>
<label>Timezone Offset</label>
<input type="text" name="timezone_offset" />
<div class="popup">Offset hours to apply (no daylight savings support)</div>
</div>
</div> </div>
<button id="SNTP-button" type="submit" class="pure-button button-primary"> <div>
Update SNTP settings! <label>Timezone Offset (+/- hours)</label>
</button> <input type="text" name="timezone_offset" />
</form> <div class="popup">Offset hours to apply (no daylight savings support)</div>
</div> </div>
</div>
<button id="SNTP-button" type="submit" class="pure-button button-primary">
Update SNTP settings!
</button>
</form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script src="ui.js"></script>
<script src="services.js"></script> <script src="services.js"></script>
<script type="text/javascript">
onLoad(function() {
fetchServices();
bnd($("#Syslog-form"), "submit", changeServices);
bnd($("#SNTP-form"), "submit", changeServices);
bnd($("#mDNS-form"), "submit", changeServices);
});
</script>
</body></html> </body></html>

@ -1,3 +1,10 @@
onLoad(function() {
fetchServices();
bnd($("#Syslog-form"), "submit", changeServices);
bnd($("#SNTP-form"), "submit", changeServices);
bnd($("#mDNS-form"), "submit", changeServices);
});
function changeServices(e) { function changeServices(e) {
e.preventDefault(); e.preventDefault();
var url = "services/update?1=1"; var url = "services/update?1=1";

@ -26,6 +26,8 @@ a:hover {
background-color: #eee; background-color: #eee;
padding: 1em; padding: 1em;
margin: 0.5em; margin: 0.5em;
-moz-border-radius: 0.5em;
-webkit-border-radius: 0.5em;
border-radius: 0.5em; border-radius: 0.5em;
border: 0px solid #000000; border: 0px solid #000000;
} }
@ -39,7 +41,7 @@ a:hover {
} }
.click-to-edit input, .click-to-edit textarea { .click-to-edit input, .click-to-edit textarea {
color: black; color: black;
background-color: #eee; background-color: #F0CAA6;
width: 100%; width: 100%;
} }
.click-to-edit span, .click-to-edit div { .click-to-edit span, .click-to-edit div {
@ -49,9 +51,9 @@ a:hover {
width: 100%; width: 100%;
color: #444; /* rgba not supported (IE 8) */ color: #444; /* rgba not supported (IE 8) */
color: rgba(0, 0, 0, 0.80); /* rgba supported */ color: rgba(0, 0, 0, 0.80); /* rgba supported */
border: 1px solid #999; /*IE 6/7/8*/ border: 1px solid #111; /*IE 6/7/8*/
border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/ border: none rgba(0, 0, 0, 0); /*IE9 + everything else*/
background-color: #E6E6E6; background-color: #CCCCCC;
text-decoration: none; text-decoration: none;
border-radius: 2px; border-radius: 2px;
} }
@ -155,6 +157,9 @@ fieldset fields {
/* Add transition to containers so they can push in and out */ /* Add transition to containers so they can push in and out */
#layout, #menu, .menu-link { #layout, #menu, .menu-link {
-webkit-transition: all 0.2s ease-out; -webkit-transition: all 0.2s ease-out;
-moz-transition: all 0.2s ease-out;
-ms-transition: all 0.2s ease-out;
-o-transition: all 0.2s ease-out;
transition: all 0.2s ease-out; transition: all 0.2s ease-out;
} }
@ -186,10 +191,10 @@ div.tt {
.content { .content {
margin: 0 auto; margin: 0 auto;
padding: 0 2em; padding: 0 2em;
max-width: 800px; /*max-width: 800px;*/
margin-bottom: 20px; margin-bottom: 20px;
line-height: 1.6em; line-height: 1.6em;
width: 100%; /*width: 100%;*/
box-sizing: border-box; box-sizing: border-box;
overflow: auto; overflow: auto;
} }
@ -198,12 +203,12 @@ div.tt {
margin: 0; margin: 0;
color: #333; color: #333;
text-align: center; text-align: center;
padding: 2.5em 2em 0; padding: 0.5em;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
background-color: #fc0; background-color: #fc0;
} }
.header h1 { .header h1 {
margin: 0.2em 0; margin: 0;
font-size: 3em; font-size: 3em;
font-weight: 300; font-weight: 300;
} }
@ -251,6 +256,8 @@ input.inline {
/* Text console */ /* Text console */
pre.console { pre.console {
background-color: #663300; background-color: #663300;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px; border-radius: 5px;
border: 0px solid #000000; border: 0px solid #000000;
color: #66ff66; color: #66ff66;
@ -495,6 +502,8 @@ pre.console a {
height: 50px; height: 50px;
width: 50px; width: 50px;
-webkit-animation: rotation 1s infinite linear; -webkit-animation: rotation 1s infinite linear;
-moz-animation: rotation 1s infinite linear;
-o-animation: rotation 1s infinite linear;
animation: rotation 1s infinite linear; animation: rotation 1s infinite linear;
border-left: 10px solid rgba(204, 51, 0, 0.15); border-left: 10px solid rgba(204, 51, 0, 0.15);
border-right: 10px solid rgba(204, 51, 0, 0.15); border-right: 10px solid rgba(204, 51, 0, 0.15);
@ -518,6 +527,23 @@ pre.console a {
} }
} }
@-moz-keyframes rotation {
from {
-moz-transform: rotate(0deg);
}
to {
-moz-transform: rotate(359deg);
}
}
@-o-keyframes rotation {
from {
-o-transform: rotate(0deg);
}
to {
-o-transform: rotate(359deg);
}
}
@keyframes rotation { @keyframes rotation {
from { from {
-webkit-transform: rotate(0deg); -webkit-transform: rotate(0deg);
@ -528,3 +554,36 @@ pre.console a {
transform: rotate(359deg); transform: rotate(359deg);
} }
} }
a
{
color: #5873DD;
font-family: Arial;
font-size: 10pt;
font-weight: bold;
text-decoration: none;
}
a.btn
{
white-space: nowrap;
text-align: center;
vertical-align: middle;
display: inline-block;
border-radius: 6px;
font-size: 16pt;
line-height: 1.33;
padding: 10px 10px;
}
a.btn-yes
{
background-color: #5CB85C;
color: white;
}
a.btn-no
{
background-color: #D9534F;
color: white;
}

@ -330,6 +330,15 @@ function makeAjaxInput(klass, field) {
eoff.setAttribute('hidden',''); eoff.setAttribute('hidden','');
domForEach(eon, function(el){ el.removeAttribute('hidden'); }); domForEach(eon, function(el){ el.removeAttribute('hidden'); });
eon[0].select(); eon[0].select();
old_hostname = eon[0].value;
return false;
}
var just_close = function()
{
domForEach(eon, function(el){ el.setAttribute('hidden',''); });
eoff.removeAttribute('hidden');
setEditToClick(klass+"-"+field, old_hostname);
return false; return false;
} }
@ -347,9 +356,10 @@ function makeAjaxInput(klass, field) {
} }
bnd(eoff, "click", function(){return enableEditToClick();}); bnd(eoff, "click", function(){return enableEditToClick();});
bnd(eon[0], "blur", function(){return submitEditToClick(eon[0].value);}); bnd(eon[0], "blur", function(){return just_close();});
bnd(eon[0], "keyup", function(ev){ bnd(eon[0], "keyup", function(ev){
if ((ev||window.event).keyCode==13) return submitEditToClick(eon[0].value); if ((ev||window.event).keyCode==13) return submitEditToClick(eon[0].value);
else if ((ev||window.event).keyCode==27) return just_close();
}); });
}); });
} }
@ -369,11 +379,17 @@ function setEditToClick(klass, value) {
//===== Notifications //===== Notifications
var notifTimeout = null;
function showWarning(text) { function showWarning(text) {
var el = $("#warning"); var el = $("#warning");
el.innerHTML = text; el.innerHTML = text;
el.removeAttribute('hidden'); el.removeAttribute('hidden');
window.scrollTo(0, 0); window.scrollTo(0, 0);
if (notifTimeout != null) clearTimeout(notifTimeout);
notifTimout = setTimeout(function() {
el.setAttribute('hidden', '');
notifTimout = null;
}, 6000);
} }
function hideWarning() { function hideWarning() {
el = $("#warning").setAttribute('hidden', ''); el = $("#warning").setAttribute('hidden', '');

@ -1,50 +1,74 @@
<!doctype html>
<html><head>
<title>esp-link</title>
<link rel="stylesheet" href="../pure.css">
<link rel="stylesheet" href="../style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="layout">
<div id="main"> <div id="main">
<div class="header"> <div class="header">
<h1>WiFi Soft-AP Configuration</h1> <h1>WiFi Soft-AP Configuration</h1>
</div> </div>
<div class="content"> <div class="content">
<div class="pure-g"> <div style="float:left; padding:2px">
<div class="pure-u-1 pure-u-md-1-2"> <div class="card">
<div class="card">
<h1>Soft-AP State</h1> <h1>Soft-AP State</h1>
<div id="wifi-spinner" class="spinner spinner-small"> <div id="wifi-spinner" class="spinner spinner-small"></div>
</div>
<table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody> <table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>WiFi mode</td><td id="wifi-mode"></td></tr> <tr><td>WiFi mode</td><td id="wifi-mode"></td></tr>
<tr><td>Soft-AP SSID</td><td id="wifi-apssid"></td></tr> <tr><td>Soft-AP SSID</td><td id="wifi-apssid"></td></tr>
<tr><td>Soft-AP Password</td><td id="wifi-appass"></td></tr> <tr><td>Soft-AP Password</td><td id="wifi-appass"></td></tr>
<tr><td>Soft-AP Channel</td><td id="wifi-apchan"></td></tr> <tr><td>Soft-AP Channel</td><td id="wifi-apchan"></td></tr>
<tr><td>Soft-AP Max Conn</td><td id="wifi-apmaxc"></td></tr> <tr><td>Soft-AP Max Conn</td><td id="wifi-apmaxc"></td></tr>
<tr><td>Soft-AP Hidden</td><td id="wifi-aphidd"></td></tr> <tr><td>Soft-AP Hidden</td><td id="wifi-aphidd"></td></tr>
<tr><td>Soft-AP Beacon Int</td><td id="wifi-apbeac"></td></tr> <tr><td>Soft-AP Beacon Interval</td><td id="wifi-apbeac"></td></tr>
<tr><td>Soft-AP Auth Mode</td><td id="wifi-apauth"></td></tr> <tr><td>Soft-AP Auth Mode</td><td id="wifi-apauth"></td></tr>
<tr><td>Soft-AP MAC</td><td id="wifi-apmac"></td></tr> <tr><td>Soft-AP MAC</td><td id="wifi-apmac"></td></tr>
<tr><td colspan="2" id="wifi-apwarn"></td></tr> <tr><td colspan="2" id="wifi-apwarn"></td></tr>
</tbody> </table> </tbody> </table>
</div><!-- card--> </div>
</div><!-- pure-u-1 --> </div>
<div class="pure-u-1 pure-u-md-1-2"> <div style="float:left; padding:2px">
<div class="card"> <div class="card">
<h1>Soft-AP Settings</h1> <h1>Soft-AP Settings</h1>
<div id="AP_Settings-spinner" class="spinner spinner-small"></div> <div id="AP_Settings-spinner" class="spinner spinner-small"></div>
<form action="#" name="ap_form" id="AP_Settings-form" class="pure-form" hidden>
<form action="#" id="AP_Settings-form" class="pure-form" hidden> <legend>Soft-AP main settings, use with care!</legend>
<legend>Soft-AP main settings, use with care!</legend> <div class="pure-form-stacked">
<label>Soft-AP SSID</label>
<input type="text" name="ap_ssid" />
<div class="popup">Change the name of your AP!</div>
</div>
<div class="pure-form-stacked">
<label>Soft-AP Password</label>
<input type="text" name="ap_password" />
<div class="popup">Password must be at least 8 chars long!</div>
</div>
<div class="pure-form-stacked">
<legend>Soft-AP Advanced Settings</legend>
</div>
<div class="form-horizontal">
<label for="AP_Settings-ron" style="margin-right:1em">
<input type="radio" name="ap" value="on" id="AP_Settings-ron"/> Show
</label>
<label for="AP_Settings-roff" style="margin-right:1em">
<input type="radio" name="ap" value="off" id="AP_Settings-roff"/> Hide
</label>
</div>
<div id="AP_Settings-off" class="pure-form-stacked"></div>
<div id="AP_Settings-on" class="pure-form-stacked">
<div class="pure-form-stacked"> <div class="pure-form-stacked">
<label>Soft-AP SSID</label> <label>Soft-AP Max Connections</label>
<input type="text" name="ap_ssid" /> <input type="text" name="ap_maxconn" />
<div class="popup">Change the name of your AP!</div> <div class="popup">Max 4 ( default 4 )</div>
</div> </div>
<div class="pure-form-stacked"> <div class="pure-form-stacked">
<label>Soft-AP Password</label> <label>Soft-AP Beacon Interval (ms)</label>
<input type="text" name="ap_password" /> <input type="text" name="ap_beacon" />
<div class="popup">Password must be at least 8 chars long!</div> <div class="popup">Between 100 - 60000 ms ( default 100ms )</div>
</div> </div>
<div class="pure-form-stacked"> <div class="pure-form-stacked">
<label>Soft-AP Auth Mode</label> <label>Soft-AP Auth Mode</label>
<select name="ap_authmode" href="#"> <select name="ap_authmode" href="#">
@ -56,47 +80,20 @@
</select> </select>
<div class="popup">Default WPA_WPA2_PSK</div> <div class="popup">Default WPA_WPA2_PSK</div>
</div> </div>
<div class="pure-form-stacked">
<label>Soft-AP Max Connections</label>
<input type="text" name="ap_maxconn" />
<div class="popup">Max 4 ( default 4 )</div>
</div>
<div class="pure-form-stacked">
<label>Soft-AP Beacon Interval</label>
<input type="text" name="ap_beacon" />
<div class="popup">Between 100 - 60000 ms ( default 100ms )</div>
</div>
<div class="form-horizontal"> <div class="form-horizontal">
<label><input type="checkbox" name="ap_hidden" />Soft-AP SSID hidden</label> <label><input type="checkbox" name="ap_hidden" />Soft-AP SSID hidden</label>
<div class="popup">Check this box to hide you Soft-AP SSID ( default Not Hidden )</div> <div class="popup">Check this box to hide your Soft-AP SSID ( default Not Hidden )</div>
</div> </div>
</div>
<button id="AP_Settings-button" type="submit" class="pure-button button-primary"> <button id="AP_Settings-button" type="submit" class="pure-button button-primary">
Change Soft-AP settings! Change Soft-AP settings
</button> </button>
</form>
</form> </div>
</div> </div>
</div><!-- pure-u-1 --> </div>
</div><!-- pure-g --> </div>
</div><!-- content --> </div>
</div><!-- main --> <script src="../ui.js"></script>
</div><!-- layout -->
<script type="text/javascript">
</script>
<script src="wifiAp.js"></script> <script src="wifiAp.js"></script>
<script type="text/javascript">
onLoad(function() {
// Show info about AP
getWifiInfo();
// Fetch actual settings
fetchApSettings();
// Wire-up form
bnd($("#AP_Settings-form"), "submit", changeApSettings);
});
</script>
</body></html> </body></html>

@ -7,7 +7,7 @@ specials["ap_beacon"] = "Beacon Interval";
function changeWifiMode(m) { function changeWifiMode(m) {
blockScan = 1; blockScan = 1;
hideWarning(); hideWarning();
ajaxSpin("POST", "setmode?mode=" + m, function(resp) { ajaxSpin("POST", "/wifi/setmode?mode=" + m, function(resp) {
showNotification("Mode changed"); showNotification("Mode changed");
window.setTimeout(getWifiInfo, 100); window.setTimeout(getWifiInfo, 100);
blockScan = 0; blockScan = 0;
@ -83,3 +83,28 @@ function fetchApSettings() {
window.setTimeout(fetchApSettings, 1000); window.setTimeout(fetchApSettings, 1000);
}); });
} }
function doApAdvanced() {
$('#AP_Settings-on').removeAttribute('hidden');
$("#AP_Settings-off").setAttribute("hidden", "");
$("#AP_Settings-roff").removeAttribute("checked");
}
function undoApAdvanced(){
$("#AP_Settings-on").setAttribute("hidden", "");
$("#AP_Settings-off").removeAttribute("hidden");
$("#AP_Settings-roff").setAttribute("checked", "");
}
onLoad(function() {
// Show info about AP
getWifiInfo();
// Fetch actual settings
fetchApSettings();
// Hide advanced settings
undoApAdvanced();
document.ap_form.ap.value='off';
bnd($("#AP_Settings-ron"), "click", doApAdvanced);
bnd($("#AP_Settings-roff"), "click", undoApAdvanced);
bnd($("#AP_Settings-form"), "submit", changeApSettings);
});

@ -1,47 +1,37 @@
<!doctype html>
<html><head>
<title>esp-link</title>
<link rel="stylesheet" href="../pure.css">
<link rel="stylesheet" href="../style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="layout">
<div id="main"> <div id="main">
<div class="header"> <div class="header">
<h1>WiFi Station Configuration</h1> <h1>WiFi Station Configuration</h1>
</div> </div>
<div class="content"> <div class="content">
<div class="pure-g"> <div style="float:left; padding:2px">
<div class="pure-u-1 pure-u-md-1-2"><div class="card"> <div class="card">
<h1>WiFi State</h1> <h1>WiFi State</h1>
<div id="wifi-spinner" class="spinner spinner-small"></div> <div id="wifi-spinner" class="spinner spinner-small"></div>
<table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody> <table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>WiFi mode</td><td id="wifi-mode"></td></tr> <tr><td>WiFi mode</td><td id="wifi-mode"></td></tr>
<tr><td>WiFi channel</td><td id="wifi-chan"></td></tr> <tr><td>WiFi channel</td><td id="wifi-chan"></td></tr>
<tr><td>Configured network</td><td id="wifi-ssid"></td></tr> <tr><td>Configured network</td><td id="wifi-ssid"></td></tr>
<tr><td>WiFi status</td><td id="wifi-status"></td></tr> <tr><td>WiFi status</td><td id="wifi-status"></td></tr>
<tr><td>WiFi address</td><td id="wifi-ip"></td></tr> <tr><td>WiFi address</td><td id="wifi-ip"></td></tr>
<tr><td>WiFi rssi</td><td id="wifi-rssi"></td></tr> <tr><td>WiFi rssi</td><td id="wifi-rssi"></td></tr>
<tr><td>WiFi phy</td><td id="wifi-phy"></td></tr> <tr><td>WiFi phy</td><td id="wifi-phy"></td></tr>
<tr><td>WiFi MAC</td><td id="wifi-mac"></td></tr> <tr><td>WiFi MAC</td><td id="wifi-mac"></td></tr>
<tr><td colspan="2" id="wifi-warn"></td></tr> <tr><td colspan="2" id="wifi-warn"></td></tr>
</tbody> </table> </tbody> </table>
</div> </div>
</div>
<div class="pure-u-1 pure-u-md-1-2"><div class="card">
<h1>WiFi Association</h1>
<p id="reconnect" style="color: #600" hidden></p>
<form action="#" id="wifiform" class="pure-form pure-form-stacked">
<legend>To connect to a WiFi network, please select one of the detected networks,
enter the password, and hit the connect button...</legend>
<label>Network SSID</label>
<div id="aps">Scanning... <div class="spinner spinner-small"></div></div>
<label for="opt-hiddenssid">
<input type="radio" name="essid" value="_hidden_ssid_" id="opt-hiddenssid">
<input type="text" id="hidden-ssid" value="" style="width:auto; display:inline-block; margin-left: 0.7em">
</label>
<label>WiFi password, if applicable:</label>
<input id="wifi-passwd" type="password" name="passwd" placeholder="password">
<button id="connect-button" type="submit" class="pure-button button-primary">Connect!</button>
</form>
</div></div>
</div> </div>
<div class="pure-g"> <div style="float:left; padding:2px">
<div class="pure-u-1 pure-u-md-1-2"><div class="card"> <div class="card">
<h1>Special Settings</h1> <h1>Special Settings</h1>
<form action="#" id="specform" class="pure-form"> <form action="#" id="specform" class="pure-form">
<legend>Special settings, use with care!</legend> <legend>Special settings, use with care!</legend>
@ -64,23 +54,30 @@
</div> </div>
<button id="special-button" type="submit" class="pure-button button-primary">Change!</button> <button id="special-button" type="submit" class="pure-button button-primary">Change!</button>
</form> </form>
</div></div> </div>
</div>
<div style="float:left; padding:2px">
<div class="card">
<h1>WiFi Association</h1>
<p id="reconnect" style="color: #600" hidden></p>
<form action="#" id="wifiform" class="pure-form pure-form-stacked">
<legend>To connect to a WiFi network - choose one of detected networks (or enter a SSID),<br>
enter the password, and hit the CONNECT button...</legend>
<label>Network SSID</label>
<div id="aps">Scanning... <div class="spinner spinner-small"></div></div>
<label for="opt-hiddenssid">
<input type="radio" name="essid" value="_hidden_ssid_" id="opt-hiddenssid" />
<input type="text" id="hidden-ssid" value="" style="width:auto; display:inline-block; margin-left: 0.7em" />
</label>
<label>WiFi password, if applicable:</label>
<input id="wifi-passwd" type="password" name="passwd" placeholder="password" />
<button id="connect-button" type="submit" class="pure-button button-primary">Connect</button>
</form>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script src="../ui.js"></script>
<script type="text/javascript">
</script>
<script src="wifiSta.js"></script> <script src="wifiSta.js"></script>
<script type="text/javascript">
onLoad(function() {
getWifiInfo();
bnd($("#wifiform"), "submit", changeWifiAp);
bnd($("#specform"), "submit", changeSpecial);
bnd($("#dhcp-ron"), "click", doDhcp);
bnd($("#dhcp-roff"), "click", doStatic);
scanTimeout = window.setTimeout(scanAPs, 500);
});
</script>
</body></html> </body></html>

@ -201,3 +201,12 @@ function doStatic() {
$('#dhcp-off').removeAttribute('hidden'); $('#dhcp-off').removeAttribute('hidden');
$('#dhcp-on').setAttribute('hidden', ''); $('#dhcp-on').setAttribute('hidden', '');
} }
onLoad(function() {
getWifiInfo();
bnd($("#wifiform"), "submit", changeWifiAp);
bnd($("#specform"), "submit", changeSpecial);
bnd($("#dhcp-ron"), "click", doDhcp);
bnd($("#dhcp-roff"), "click", doStatic);
scanTimeout = window.setTimeout(scanAPs, 500);
});

@ -31,10 +31,10 @@ int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData) {
r=httpdGetHeader(connData, "Authorization", hdr, sizeof(hdr)); r=httpdGetHeader(connData, "Authorization", hdr, sizeof(hdr));
if (r && strncmp(hdr, "Basic", 5)==0) { if (r && strncmp(hdr, "Basic", 5)==0) {
r=base64_decode(strlen(hdr)-6, hdr+6, sizeof(userpass), (unsigned char *)userpass); r=ubase64_decode(strlen(hdr)-6, hdr+6, sizeof(userpass), (unsigned char *)userpass);
if (r<0) r=0; //just clean out string on decode error if (r<0) r=0; //just clean out string on decode error
userpass[r]=0; //zero-terminate user:pass string userpass[r]=0; //zero-terminate user:pass string
// os_printf("Auth: %s\n", userpass); // DBG("Auth: %s\n", userpass);
while (((AuthGetUserPw)(connData->cgiArg))(connData, no, while (((AuthGetUserPw)(connData->cgiArg))(connData, no,
user, AUTH_MAX_USER_LEN, pass, AUTH_MAX_PASS_LEN)) { user, AUTH_MAX_USER_LEN, pass, AUTH_MAX_PASS_LEN)) {
//Check user/pass against auth header //Check user/pass against auth header

@ -39,7 +39,7 @@ static int ICACHE_FLASH_ATTR base64decode(const char in[4], char out[3]) {
#endif #endif
/* decode a base64 string in one shot */ /* decode a base64 string in one shot */
int ICACHE_FLASH_ATTR base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out) { int ICACHE_FLASH_ATTR ubase64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out) {
unsigned int ii, io; unsigned int ii, io;
uint32_t v; uint32_t v;
unsigned int rem; unsigned int rem;

@ -1,6 +1,6 @@
#ifndef BASE64_H #ifndef BASE64_H
#define BASE64_H #define BASE64_H
int base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out); int ubase64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out);
#endif #endif

@ -396,7 +396,7 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) {
return; return;
} }
else { else {
if (!(r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED)) { if (r == HTTPD_CGI_NOTFOUND) {
os_printf("%shandler for %s returned invalid result %d\n", connStr, conn->url, r); os_printf("%shandler for %s returned invalid result %d\n", connStr, conn->url, r);
} }
//URL doesn't want to handle the request: either the data isn't found or there's no //URL doesn't want to handle the request: either the data isn't found or there's no

@ -37,7 +37,10 @@
// If defined, the default hostname for DHCP will include the chip ID to make it unique // If defined, the default hostname for DHCP will include the chip ID to make it unique
#undef CHIP_IN_HOSTNAME #undef CHIP_IN_HOSTNAME
extern char* esp_link_version; extern char esp_link_version[];
extern char esp_link_date[];
extern char esp_link_time[];
extern char esp_link_build[];
extern uint8_t UTILS_StrToIP(const char* str, void *ip); extern uint8_t UTILS_StrToIP(const char* str, void *ip);
#endif #endif

Loading…
Cancel
Save