pull/205/merge
Alex 9 years ago committed by GitHub
commit 716f1d2793
  1. 49
      .travis.yml
  2. 64
      Makefile
  3. 2
      README.md
  4. 2
      esp-link/cgi.c
  5. 1
      esp-link/cgipins.c
  6. 120
      esp-link/cgitelnet.c
  7. 8
      esp-link/cgitelnet.h
  8. 17
      esp-link/config.c
  9. 9
      esp-link/config.h
  10. 9
      esp-link/main.c
  11. 3
      espmake.cmd
  12. 36
      html/home.html
  13. 19
      html/ui.js
  14. 69
      serial/serbridge.c
  15. 4
      serial/serbridge.h

@ -1,31 +1,28 @@
# Travis-CI file for Esp-Link
language: c language: c
before_install: before_install:
- curl -Ls http://s3.voneicken.com/xtensa-lx106-elf-20160330.tgx | tar Jxf - - curl -Ls http://s3.voneicken.com/xtensa-lx106-elf-20160330.tgx | tar Jxf -
- curl -Ls http://s3.voneicken.com/esp_iot_sdk_v2.0.0.p1.tgx | tar -C .. -Jxf - - curl -Ls http://s3.voneicken.com/esp_iot_sdk_v2.0.0.p1.tgx | tar -C .. -Jxf -
after_script:
# upload to an S3 bucket, requires S3_BUCKET, AWS_ACCESS_KEY_ID and AWS_SECRET_KEY to be set
# in environment using travis' repository settings
- "if [[ -n \"$S3_BUCKET\" && -n \"$AWS_ACCESS_KEY_ID\" ]]; then
echo Uploading *.tgz to $S3_BUCKET;
curl -Ls https://github.com/rlmcpherson/s3gof3r/releases/download/v0.5.0/gof3r_0.5.0_linux_amd64.tar.gz | tar zxf - gof3r_0.5.0_linux_amd64/gof3r;
mv gof3r*/gof3r .;
ls *.tgz | xargs -I {} ./gof3r put -b $S3_BUCKET -k esp-link/{} --acl public-read -p {};
ls *.tgz | xargs -I {} echo \"URL: http://$S3_BUCKET/esp-link/{}\";
fi"
compiler: gcc
env:
script: script:
- export XTENSA_TOOLS_ROOT=$PWD/xtensa-lx106-elf/bin/ - printenv
- export BRANCH=$TRAVIS_BRANCH - export XTENSA_TOOLS_ROOT=$PWD/xtensa-lx106-elf/bin/
#- export SDK_BASE=$PWD/esp_iot_sdk_v2.0.0.p1 - export BRANCH=$TRAVIS_BRANCH
- make release - echo "Travis Branch is $TRAVIS_BRANCH"
- echo "Travis Tag is $TRAVIS_TAG"
- echo "Travis COMMIT is $TRAVIS_COMMIT"
- echo "Travis COMMIT is $TRAVIS_COMMIT_RANGE"
- echo "Dont forget to set VARIABLES for S3 to function. SEE gof3r README"
- make release
notifications: notifications:
email: false email: false
deploy:
overwrite: true
skip_cleanup: true
provider: releases
api_key:
secure: unYyTCLpk1ixcNOyoUwroBqqx0yBhii56IXm57kjo5kl3umf1GRb3FUIE6la+B0njsNwAUNR/uLn6wF4FqYTUJzNQZskJDJfZjb53vwuoHaoa5j4K/bWB9zRlQ1XZBTkV48cxz8Ef2KyNduK2IciOHwsw3LQS0em3dpK7oG/20VzELt23Gx8uhBYa+OUzlr3Y+PYPynkwM30YwVQXpCy/GMgEbrcKheGbLTAIp7tms0KDAvbb98U0BI3tWBckE5GzAYYAmrXgyDXtEsU/poCMqUj/lpPl1s/5uxGVevTO7XuL4AYtF//AixsM20bPKtIZDHZS9b7JHtVhU655bY2aAfpMgf7xzkKbJkRzeAzT9HucFDjLY48yW4vztdJxBgkAL9d064gTHhThtn4hylZAYpHnqUiM0j4DKil5A0VG2F8EVEqZ7Q2tNzy6aqq37wzTuYXsYpz3mglpazaXXp/LoSurDHy1gz6aB/mdaeBoL3MX1q09LBE8lFGYBILQ8KUkrLyJathxAVvDBnl7nXFv2NWoZ2i7CfXdpCwmOVUN2WhudNfgbbaMung+voTFB+yLq9PBQP5gdP0MKU3zDTB/msmZo1pp/SbnNETCrKAdRtxNI+bxTQ98njAIkxI+7ZiVV8SMNEPyNcWq/6ViYDcIHJMR4Gq0DZunre1voEs1F4=
file_glob: true
file: esp-link-master-*.t*gz
on:
branch: master
repo: fuzzball03/esp-link
condition: "$TRAVIS_BRANCH = master"

@ -52,12 +52,15 @@ ESP_HOSTNAME ?= esp-link
# Base directory for the compiler. Needs a / at the end. # Base directory for the compiler. Needs a / at the end.
# Typically you'll install https://github.com/pfalcon/esp-open-sdk # Typically you'll install https://github.com/pfalcon/esp-open-sdk
# IMPORTANT: use esp-open-sdk `make STANDALONE=n`: the SDK bundled with esp-open-sdk will *not* work! # IMPORTANT: use esp-open-sdk `make STANDALONE=n`: the SDK bundled with esp-open-sdk will *not* work!
XTENSA_TOOLS_ROOT ?= $(abspath ../esp-open-sdk/xtensa-lx106-elf/bin)/ XTENSA_TOOLS_ROOT ?= $(abspath ../espressif/xtensa-lx106-elf/bin)/
$(warning Using XTENSA TOOLS from $(XTENSA_TOOLS_ROOT))
# Firmware version # Firmware version
# WARNING: if you change this expect to make code adjustments elsewhere, don't expect # WARNING: if you change this expect to make code adjustments elsewhere, don't expect
# that esp-link will magically work with a different version of the SDK!!! # that esp-link will magically work with a different version of the SDK!!!
SDK_VERS ?= esp_iot_sdk_v2.0.0.p1 SDK_VERS ?= esp_iot_sdk_v2.0.0.p1
# Uncomment this line if you're using windows to build with the C:\espressif structure
# SDK_VERS ?= ESP8266_SDK
# Try to find the firmware manually extracted, e.g. after downloading from Espressif's BBS, # Try to find the firmware manually extracted, e.g. after downloading from Espressif's BBS,
# http://bbs.espressif.com/viewforum.php?f=46 # http://bbs.espressif.com/viewforum.php?f=46
@ -66,16 +69,17 @@ SDK_BASE ?= $(wildcard ../$(SDK_VERS))
# If the firmware isn't there, see whether it got downloaded as part of esp-open-sdk # If the firmware isn't there, see whether it got downloaded as part of esp-open-sdk
# This used to work at some point, but is not supported, uncomment if you feel lucky ;-) # This used to work at some point, but is not supported, uncomment if you feel lucky ;-)
#ifeq ($(SDK_BASE),) ifeq ($(SDK_BASE),)
#SDK_BASE := $(wildcard $(XTENSA_TOOLS_ROOT)/../../$(SDK_VERS)) SDK_BASE := $(wildcard $(XTENSA_TOOLS_ROOT)/../../$(SDK_VERS))
#endif endif
# Clean up SDK path # Clean up SDK path
SDK_BASE := $(abspath $(SDK_BASE)) SDK_BASE := $(abspath $(SDK_BASE))
$(warning Using SDK from $(SDK_BASE)) $(warning Using SDK from $(SDK_BASE))
# Path to bootloader file # Path to bootloader file
BOOTFILE ?= $(SDK_BASE/bin/boot_v1.6.bin) BOOTFILE ?= $(SDK_BASE)/bin/boot_v1.6.bin
$(warning Using boot file-> $(BOOTFILE))
# Esptool.py path and port, only used for 1-time serial flashing # Esptool.py path and port, only used for 1-time serial flashing
# Typically you'll use https://github.com/themadinventor/esptool # Typically you'll use https://github.com/themadinventor/esptool
@ -127,8 +131,10 @@ GZIP_COMPRESSION ?= yes
# http://yui.github.io/yuicompressor/ # http://yui.github.io/yuicompressor/
# enabled by default. # enabled by default.
COMPRESS_W_HTMLCOMPRESSOR ?= yes COMPRESS_W_HTMLCOMPRESSOR ?= yes
HTML_COMPRESSOR ?= htmlcompressor-1.5.3.jar HTML_COMPRESSOR_VER ?= htmlcompressor-1.5.3.jar
YUI_COMPRESSOR ?= yuicompressor-2.4.8.jar HTML_COMPRESSOR = tools/$(HTML_COMPRESSOR_VER)
YUI_COMPRESSOR_VER ?= yuicompressor-2.4.8.jar
YUI_COMPRESSOR = tools/$(YUI_COMPRESSOR_VER)
# -------------- End of config options ------------- # -------------- End of config options -------------
@ -296,6 +302,13 @@ Q := @
vecho := @echo vecho := @echo
endif endif
#Fix for issues on some windows systems that call non GNU FIND
FIND ?= $(which FIND)
ifeq (,$(findstring system32,$(FIND)))
$(warning Non GNU 'find' called. Trying alternate path /usr/bin/find)
FIND = /usr/bin/find
endif
ifneq ($(strip $(STA_SSID)),) ifneq ($(strip $(STA_SSID)),)
CFLAGS += -DSTA_SSID="$(STA_SSID)" CFLAGS += -DSTA_SSID="$(STA_SSID)"
endif endif
@ -387,6 +400,7 @@ $(FW_BASE)/user2.bin: $(USER2_OUT) $(FW_BASE)
$(Q) COMPILE=gcc PATH=$(XTENSA_TOOLS_ROOT):$(PATH) python $(APPGEN_TOOL) $(USER2_OUT) 2 $(ESP_FLASH_MODE) $(ESP_FLASH_FREQ_DIV) $(ESP_SPI_SIZE) 1 >/dev/null $(Q) COMPILE=gcc PATH=$(XTENSA_TOOLS_ROOT):$(PATH) python $(APPGEN_TOOL) $(USER2_OUT) 2 $(ESP_FLASH_MODE) $(ESP_FLASH_FREQ_DIV) $(ESP_SPI_SIZE) 1 >/dev/null
$(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 "** user2.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available"
$(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
$(APP_AR): $(OBJ) $(APP_AR): $(OBJ)
@ -406,18 +420,18 @@ baseflash: all
flash: all flash: all
$(Q) $(ESPTOOL) --port $(ESPPORT) --baud $(ESPBAUD) write_flash -fs $(ET_FS) -ff $(ET_FF) \ $(Q) $(ESPTOOL) --port $(ESPPORT) --baud $(ESPBAUD) write_flash -fs $(ET_FS) -ff $(ET_FF) \
0x00000 "$(SDK_BASE)/bin/boot_v1.5.bin" 0x01000 $(FW_BASE)/user1.bin \ 0x00000 "$(BOOTFILE)" 0x01000 $(FW_BASE)/user1.bin \
$(ET_BLANK) $(SDK_BASE)/bin/blank.bin $(ET_BLANK) $(SDK_BASE)/bin/blank.bin
tools/$(HTML_COMPRESSOR): tools/$(HTML_COMPRESSOR):
$(Q) echo "The jar files in the tools dir are missing, they should be in the source repo" $(Q) echo "The jar files in the tools dir are missing, they should be in the source repo"
$(Q) echo "The following commands can be used to fetch them, but the URLs have changed..." $(Q) echo "The following commands can be used to fetch them, but the URLs have changed..."
$(Q) echo mkdir -p tools $(Q) echo mkdir -p tools
$(Q) echo "cd tools; wget --no-check-certificate https://github.com/yui/yuicompressor/releases/download/v2.4.8/$(YUI_COMPRESSOR) -O $(YUI_COMPRESSOR)" $(Q) echo "cd tools; wget --no-check-certificate https://github.com/yui/yuicompressor/releases/download/v2.4.8/$(YUI_COMPRESSOR_VER) -O $(YUI_COMPRESSOR_VER)"
$(Q) echo "cd tools; wget --no-check-certificate https://htmlcompressor.googlecode.com/files/$(HTML_COMPRESSOR) -O $(HTML_COMPRESSOR)" $(Q) echo "cd tools; wget --no-check-certificate https://htmlcompressor.googlecode.com/files/$(HTML_COMPRESSOR_VER) -O $(HTML_COMPRESSOR_VER)"
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes") ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(BUILD_BASE)/espfs_img.o: tools/$(HTML_COMPRESSOR) $(BUILD_BASE)/espfs_img.o: $(HTML_COMPRESSOR)
endif endif
$(BUILD_BASE)/espfs_img.o: html/ html/wifi/ espfs/mkespfsimage/mkespfsimage $(BUILD_BASE)/espfs_img.o: html/ html/wifi/ espfs/mkespfsimage/mkespfsimage
@ -428,38 +442,38 @@ $(BUILD_BASE)/espfs_img.o: html/ html/wifi/ espfs/mkespfsimage/mkespfsimage
$(Q) cp -r html/wifi/*.png html_compressed/wifi; $(Q) cp -r html/wifi/*.png html_compressed/wifi;
$(Q) cp -r html/wifi/*.js html_compressed/wifi; $(Q) cp -r html/wifi/*.js html_compressed/wifi;
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes") ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) echo "Compressing assets with htmlcompressor. This may take a while..." $(Q) echo "Compressing assets with htmlcompressor. This may take a while...";
$(Q) java -jar tools/$(HTML_COMPRESSOR) \ $(Q) java -jar $(HTML_COMPRESSOR) \
-t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \ -t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \
-o $(abspath ./html_compressed)/ \ -o $(abspath ./html_compressed)/ \
$(HTML_PATH)head- \ $(HTML_PATH)head- \
$(HTML_PATH)*.html $(HTML_PATH)*.html
$(Q) java -jar tools/$(HTML_COMPRESSOR) \ $(Q) java -jar $(HTML_COMPRESSOR) \
-t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \ -t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \
-o $(abspath ./html_compressed)/wifi/ \ -o $(abspath ./html_compressed)/wifi/ \
$(WIFI_PATH)*.html $(WIFI_PATH)*.html
$(Q) echo "Compressing assets with yui-compressor. This may take a while..." $(Q) echo "Compressing assets with yui-compressor. This may take a while..."
$(Q) for file in `find html_compressed -type f -name "*.js"`; do \ $(Q) java -jar $(YUI_COMPRESSOR) ./html_compressed/*.css -o '.css$:.css'
java -jar tools/$(YUI_COMPRESSOR) $$file --line-break 0 -o $$file; \ $(Q) java -jar $(YUI_COMPRESSOR) ./html_compressed/*.js -o '.js$:.js'
done $(Q) java -jar $(YUI_COMPRESSOR) ./html_compressed/wifi/*.js -o '.js$:.js'
$(Q) for file in `find html_compressed -type f -name "*.css"`; do \
java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \
done
else else
$(Q) cp -r html/head- html_compressed; $(Q) cp -r html/head- html_compressed;
$(Q) cp -r html/*.html html_compressed; $(Q) cp -r html/*.html html_compressed;
$(Q) cp -r html/wifi/*.html html_compressed/wifi; $(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) for file in `$(FIND) html_compressed -type f -name "*.htm*"`; do \
cat html_compressed/head- $$file >$${file}-; \ cat html_compressed/head- $$file >$${file}-; \
mv $$file- $$file; \ mv $$file- $$file; \
done done
$(Q) rm html_compressed/head- $(Q) rm html_compressed/head-
$(Q) cd html_compressed; find . \! -name \*- | ../espfs/mkespfsimage/mkespfsimage > ../build/espfs.img; cd ..; $(Q) echo "Compressing assets into espfs.img with Gzip. This may take a while..."
$(Q) cd html_compressed; $(FIND) . \! -name \*- | ../espfs/mkespfsimage/mkespfsimage > ../build/espfs.img; cd ..;
$(Q) ls -sl build/espfs.img $(Q) ls -sl build/espfs.img
$(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 ..
@ -483,7 +497,7 @@ release: all
$(Q) egrep -a 'esp-link [a-z0-9.]+ - 201' $(FW_BASE)/user1.bin | cut -b 1-80 $(Q) egrep -a 'esp-link [a-z0-9.]+ - 201' $(FW_BASE)/user1.bin | cut -b 1-80
$(Q) egrep -a 'esp-link [a-z0-9.]+ - 201' $(FW_BASE)/user2.bin | cut -b 1-80 $(Q) egrep -a 'esp-link [a-z0-9.]+ - 201' $(FW_BASE)/user2.bin | cut -b 1-80
$(Q) cp $(FW_BASE)/user1.bin $(FW_BASE)/user2.bin $(SDK_BASE)/bin/blank.bin \ $(Q) cp $(FW_BASE)/user1.bin $(FW_BASE)/user2.bin $(SDK_BASE)/bin/blank.bin \
"$(SDK_BASE)/bin/boot_v1.6.bin" "$(SDK_BASE)/bin/esp_init_data_default.bin" \ "$(BOOTFILE)" "$(SDK_BASE)/bin/esp_init_data_default.bin" \
wiflash avrflash release/esp-link-$(BRANCH) wiflash avrflash release/esp-link-$(BRANCH)
$(Q) tar zcf esp-link-$(BRANCH)-$(SHA).tgz -C release esp-link-$(BRANCH) $(Q) tar zcf esp-link-$(BRANCH)-$(SHA).tgz -C release esp-link-$(BRANCH)
$(Q) echo "Release file: esp-link-$(BRANCH)-$(SHA).tgz" $(Q) echo "Release file: esp-link-$(BRANCH)-$(SHA).tgz"
@ -494,7 +508,7 @@ docker:
clean: clean:
$(Q) rm -f $(APP_AR) $(Q) rm -f $(APP_AR)
$(Q) rm -f $(TARGET_OUT) $(Q) rm -f $(TARGET_OUT)
$(Q) find $(BUILD_BASE) -type f | xargs rm -f $(Q) $(FIND) $(BUILD_BASE) -type f | xargs rm -f
$(Q) make -C espfs/mkespfsimage/ clean $(Q) make -C espfs/mkespfsimage/ clean
$(Q) rm -rf $(FW_BASE) $(Q) rm -rf $(FW_BASE)
$(Q) rm -f webpages.espfs $(Q) rm -f webpages.espfs
@ -502,4 +516,4 @@ ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) rm -rf html_compressed $(Q) rm -rf html_compressed
endif endif
$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))

@ -149,6 +149,8 @@ From there, more advanced steps are:
### Serial bridge ### Serial bridge
Note that the default ports of 23 & 2323 may be changed via the webinterface.
In order to connect through the esp-link to a microcontroller use port 23. For example, In order to connect through the esp-link to a microcontroller use port 23. For example,
on linux you can use `nc esp-hostname 23` or `telnet esp-hostname 23`. on linux you can use `nc esp-hostname 23` or `telnet esp-hostname 23`.

@ -190,7 +190,7 @@ int ICACHE_FLASH_ATTR printGlobalInfo(char *buff, int buflen, char *token) {
extern char *esp_link_version; // in user_main.c extern char *esp_link_version; // in user_main.c
int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) { //This is where we can modify the navigation that is auto generated
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];
// don't use jsonHeader so the response does get cached // don't use jsonHeader so the response does get cached

@ -1,4 +1,3 @@
#include <esp8266.h> #include <esp8266.h>
#include "cgi.h" #include "cgi.h"
#include "espfs.h" #include "espfs.h"

@ -0,0 +1,120 @@
#include <esp8266.h>
#include "cgi.h"
#include "config.h"
#include "serbridge.h"
static char *portMode[] = { "open", "disabled", "secure" };
// Cgi to return choice of Telnet ports
int ICACHE_FLASH_ATTR cgiTelnetGet(HttpdConnData *connData) {
char buff[80];
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted
int len;
os_printf("Current telnet ports: port0=%d port1=%d\n",
flashConfig.telnet_port0, flashConfig.telnet_port1);
len = os_sprintf(buff,
"{ \"port0\": \"%d\", \"port1\": \"%d\" }",
flashConfig.telnet_port0, flashConfig.telnet_port1);
jsonHeader(connData, 200);
httpdSend(connData, buff, len);
return HTTPD_CGI_DONE;
}
// Cgi to change choice of Telnet ports
int ICACHE_FLASH_ATTR cgiTelnetSet(HttpdConnData *connData) {
char buf[80];
if (connData->conn==NULL) {
return HTTPD_CGI_DONE; // Connection aborted
}
int8_t ok = 0;
uint16_t port0, port1;
ok |= getUInt16Arg(connData, "port0", &port0);
ok |= getUInt16Arg(connData, "port1", &port1);
if (ok <= 0) { //If we get at least one good value, this should be >= 1
ets_sprintf(buf, "Unable to fetch telnet ports.\n Received: port0=%d port1=%d\n",
flashConfig.telnet_port0, flashConfig.telnet_port1);
os_printf(buf);
errorResponse(connData, 400, buf);
return HTTPD_CGI_DONE;
}
if (ok > 0) {
// fill both port variables from flash or ajax provided value
if (!port0) port0 = flashConfig.telnet_port0;
if (!port1) port1 = flashConfig.telnet_port1;
// check whether ports are different
if (port0 == port1) {
os_sprintf(buf, "Ports cannot be the same.\n Tried to set: port0=%d port1=%d\n",
flashConfig.telnet_port0, flashConfig.telnet_port1);
os_printf(buf);
errorResponse(connData, 400, buf);
return HTTPD_CGI_DONE;
}
// we're good, set flashconfig
flashConfig.telnet_port0 = port0;
flashConfig.telnet_port1 = port1;
os_printf("Telnet ports changed: port0=%d port1=%d\n",
flashConfig.telnet_port0, flashConfig.telnet_port1);
// save to flash
if (configSave()) {
httpdStartResponse(connData, 204);
httpdEndHeaders(connData);
} else {
httpdStartResponse(connData, 500);
httpdEndHeaders(connData);
httpdSend(connData, "Failed to save config", -1);
}
// apply the changes
serbridgeInit();
serbridgeStart(0, flashConfig.telnet_port0, flashDefault.telnet_port0mode);
serbridgeStart(1, flashConfig.telnet_port1, flashDefault.telnet_port1mode);
}
return HTTPD_CGI_DONE;
}
int ICACHE_FLASH_ATTR cgiTelnet(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
if (connData->requestType == HTTPD_METHOD_GET) {
return cgiTelnetGet(connData);
} else if (connData->requestType == HTTPD_METHOD_POST) {
return cgiTelnetSet(connData);
} else {
jsonHeader(connData, 404);
return HTTPD_CGI_DONE;
}
}
static char *portMode2string(int8_t m) { //Should we put this into flash?
if (m < 0 || m > 2) return "?";
return portMode[m];
}
// print various Telnet information into json buffer
int ICACHE_FLASH_ATTR printTelnetSecurity(char *buff) {
int len;
len = os_sprintf(buff,
"{ \"port0mode\": \"%s\", \"port0portnumber\": \"%d\", \"port0pwd\": \"%s\", "
"\"port1mode\": \"%s\", \"port1portnumber\": \"%d\", \"port1pwd\": \"%s\" }",
portMode2string(flashConfig.telnet_port0mode), flashConfig.telnet_port0, flashConfig.telnet_port0pass,
portMode2string(flashConfig.telnet_port1mode), flashConfig.telnet_port1, flashConfig.telnet_port1pass
);
return len;
}

@ -0,0 +1,8 @@
#ifndef CGITELNET_H
#define CGITELNET_H
#include "httpd.h"
int cgiTelnet(HttpdConnData *connData);
#endif // CGITELNET_H

@ -35,6 +35,12 @@ FlashConfig flashDefault = {
.data_bits = EIGHT_BITS, .data_bits = EIGHT_BITS,
.parity = NONE_BITS, .parity = NONE_BITS,
.stop_bits = ONE_STOP_BIT, .stop_bits = ONE_STOP_BIT,
.telnet_port0 = 23,
.telnet_port1 = 2323,
.telnet_port0mode = 0,
.telnet_port1mode = 0,
.telnet_port0pass = "\0",
.telnet_port1pass = "\0",
}; };
typedef union { typedef union {
@ -161,6 +167,17 @@ bool ICACHE_FLASH_ATTR configRestore(void) {
flashConfig.parity = flashDefault.parity; flashConfig.parity = flashDefault.parity;
flashConfig.stop_bits = flashDefault.stop_bits; flashConfig.stop_bits = flashDefault.stop_bits;
} }
if (flashConfig.telnet_port0 == 0) {
flashConfig.telnet_port0 = flashDefault.telnet_port0;
flashConfig.telnet_port0mode = flashDefault.telnet_port0mode;
os_memcpy(flashConfig.telnet_port0pass, flashDefault.telnet_port0pass, 32);
}
if (flashConfig.telnet_port1 == 0) {
flashConfig.telnet_port1 = flashDefault.telnet_port1;
flashConfig.telnet_port1mode = flashDefault.telnet_port1mode;
os_memcpy(flashConfig.telnet_port1pass, flashDefault.telnet_port1pass, 32);
}
return true; return true;
} }

@ -13,7 +13,7 @@ typedef struct {
char hostname[32]; // if using DHCP char hostname[32]; // if using DHCP
uint32_t staticip, netmask, gateway; // using DHCP if staticip==0 uint32_t staticip, netmask, gateway; // using DHCP if staticip==0
uint8_t log_mode; // UART log debug mode uint8_t log_mode; // UART log debug mode
uint8_t swap_uart; // swap uart0 to gpio 13&15 uint8_t swap_uart; // swap uart0 to gpio 13&15
uint8_t tcp_enable, rssi_enable; // TCP client settings uint8_t tcp_enable, rssi_enable; // TCP client settings
char api_key[48]; // RSSI submission API key (Grovestreams for now) char api_key[48]; // RSSI submission API key (Grovestreams for now)
uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client
@ -41,8 +41,15 @@ typedef struct {
int8_t data_bits; int8_t data_bits;
int8_t parity; int8_t parity;
int8_t stop_bits; int8_t stop_bits;
uint16_t telnet_port0, // Telnet port settings
telnet_port1;
int8_t telnet_port0mode,
telnet_port1mode;
char telnet_port0pass[32],
telnet_port1pass[32];
} FlashConfig; } FlashConfig;
extern FlashConfig flashConfig; extern FlashConfig flashConfig;
extern FlashConfig flashDefault;
bool configSave(void); bool configSave(void);
bool configRestore(void); bool configRestore(void);

@ -32,6 +32,7 @@
#include "gpio.h" #include "gpio.h"
#include "cgiservices.h" #include "cgiservices.h"
#include "web-server.h" #include "web-server.h"
#include "cgitelnet.h"
#ifdef SYSLOG #ifdef SYSLOG
#include "syslog.h" #include "syslog.h"
@ -96,6 +97,7 @@ HttpdBuiltInUrl builtInUrls[] = {
{ "/services/info", cgiServicesInfo, NULL }, { "/services/info", cgiServicesInfo, NULL },
{ "/services/update", cgiServicesSet, NULL }, { "/services/update", cgiServicesSet, NULL },
{ "/pins", cgiPins, NULL }, { "/pins", cgiPins, NULL },
{ "/telnet", cgiTelnet, NULL},
#ifdef MQTT #ifdef MQTT
{ "/mqtt", cgiMqtt, NULL }, { "/mqtt", cgiMqtt, NULL },
#endif #endif
@ -178,8 +180,11 @@ user_init(void) {
httpdInit(builtInUrls, 80); httpdInit(builtInUrls, 80);
WEB_Init(); WEB_Init();
// init the wifi-serial transparent bridge (port 23) // init the wifi-serial configurable transparent bridge (port defaults 23&2323)
serbridgeInit(23, 2323); serbridgeInit();
serbridgeStart(0, flashConfig.telnet_port0, flashDefault.telnet_port0mode);
serbridgeStart(1, flashConfig.telnet_port1, flashDefault.telnet_port1mode);
uart_add_recv_cb(&serbridgeUartCb); uart_add_recv_cb(&serbridgeUartCb);
#ifdef SHOW_HEAP_USE #ifdef SHOW_HEAP_USE
os_timer_disarm(&prHeapTimer); os_timer_disarm(&prHeapTimer);

@ -1,5 +1,6 @@
@echo off @echo off
SETLOCAL
REM LOCAL IS NEEDED ELSE WE KEEP ADDING TO WINDOW PATH EACH TIME SCRIPT IS CALLED.
REM remove automatic created obj folder REM remove automatic created obj folder
rd obj /S /Q >nul 2>&1 rd obj /S /Q >nul 2>&1

@ -50,6 +50,38 @@
<a href="https://github.com/jeelabs/esp-link/blob/master/README.md">the online README</a> <a href="https://github.com/jeelabs/esp-link/blob/master/README.md">the online README</a>
for up-to-date help.</p> for up-to-date help.</p>
</div> </div>
<div class="card">
<h1>Telnet Serial-Bridge</h1>
<p style="margin-bottom:0;">There are two ports available for telnet to use by default: 23 &amp; 2323 <br>
Note - this time, only port0 may be changed &amp; used sucessfully.</p>
<div id="telnet-spinner" class="spinner spinner-small"></div>
<table id="telnet-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>Current Telnet ports</td><td class="telnet-info"></td></tr>
<tr><td colspan=2 class="popup-target">Telnet port 1:<br>
<div class="click-to-edit telnet-port0">
<span class="edit-off" style="display:block; width:auto;"></span>
<input class="edit-on" maxlength=5 hidden> </input>
<div class="popup">Click to edit!<br>Default port: 23</div>
</div>
</td></tr>
<tr><td colspan=2 class="popup-target">Telnet port 2:<br>
<div class="click-to-edit telnet-port1">
<span class="edit-off" style="display:block; width:auto;"></span>
<input class="edit-on" maxlength=5 hidden> </input>
<div class="popup">Click to edit!<br>Default port: 2323</div>
</div>
</td></tr>
<tr><td colspan=2>Port0 Mode<br>
<div class="click-to-edit telnet-port0mode">
<span class="edit-off" style="display:block; width:auto;"></span>
<select class="edit-on" hidden>
<option value="0">open</option>
<option value="1">password</option>
</select>
</div>
</td></tr>
</tbody></table>
</div>
</div> </div>
<!-- RIGHT COLUMN --> <!-- RIGHT COLUMN -->
<div class="pure-u-1 pure-u-md-1-2"> <div class="pure-u-1 pure-u-md-1-2">
@ -152,9 +184,13 @@
onLoad(function() { onLoad(function() {
makeAjaxInput("system", "description"); makeAjaxInput("system", "description");
makeAjaxInput("system", "name"); makeAjaxInput("system", "name");
makeAjaxInput("telnet", "port0");
makeAjaxInput("telnet", "port1");
makeAjaxInput("telnet", "port0mode");
fetchPins(); fetchPins();
getWifiInfo(); getWifiInfo();
getSystemInfo(); getSystemInfo();
getTelnetInfo();
bnd($("#pinform"), "submit", setPins); bnd($("#pinform"), "submit", setPins);
}); });
</script> </script>

@ -302,6 +302,22 @@ function getWifiInfo() {
function(s, st) { window.setTimeout(getWifiInfo, 1000); }); function(s, st) { window.setTimeout(getWifiInfo, 1000); });
} }
//===== Telnet info
function showTelnetInfo(data) {
Object.keys(data).forEach(function(v) {
setEditToClick("telnet-"+v, data[v]);
});
$("#telnet-spinner").setAttribute("hidden", "");
$("#telnet-table").removeAttribute("hidden");
currAp = data.ssid;
}
function getTelnetInfo() {
ajaxJson('GET', "/telnet", showTelnetInfo,
function(s, st) { window.setTimeout(getTelnetInfo, 1000); });
}
//===== System info //===== System info
function showSystemInfo(data) { function showSystemInfo(data) {
@ -323,6 +339,8 @@ function makeAjaxInput(klass, field) {
var eon = $(".edit-on", div); var eon = $(".edit-on", div);
var eoff = $(".edit-off", div)[0]; var eoff = $(".edit-off", div)[0];
var url = "/"+klass+"/update?"+field; var url = "/"+klass+"/update?"+field;
//Dirty fix to avoid to seperate name spaces to GET or PUT telnet ports
if (klass == "telnet") { var url = "/"+klass+"?"+field; }
if (eoff === undefined || eon == undefined) return; if (eoff === undefined || eon == undefined) return;
@ -383,6 +401,7 @@ function showNotification(text) {
var el = $("#notification"); var el = $("#notification");
el.innerHTML = text; el.innerHTML = text;
el.removeAttribute('hidden'); el.removeAttribute('hidden');
window.scrollTo(0, 0); //Uncomment this line so window will scroll up on regular notifications
if (notifTimeout != null) clearTimeout(notifTimeout); if (notifTimeout != null) clearTimeout(notifTimeout);
notifTimout = setTimeout(function() { notifTimout = setTimeout(function() {
el.setAttribute('hidden', ''); el.setAttribute('hidden', '');

@ -16,14 +16,14 @@
#define syslog(X1...) #define syslog(X1...)
#endif #endif
static struct espconn serbridgeConn1; // plain bridging port static struct espconn serbridgeConn[2]; // 0 = plain bridging port, 1 = programming port
static struct espconn serbridgeConn2; // programming port static esp_tcp serbridgeTcp[2];
static esp_tcp serbridgeTcp1, serbridgeTcp2;
static int8_t mcu_reset_pin, mcu_isp_pin; static int8_t mcu_reset_pin, mcu_isp_pin;
uint8_t in_mcu_flashing; // for disabling slip during MCU flashing uint8_t in_mcu_flashing; // for disabling slip during MCU flashing
void (*programmingCB)(char *buffer, short length) = NULL; void (*programmingCB)(char *buffer, short length) = NULL;
void ICACHE_FLASH_ATTR serbridgeCleanup(int ix);
// Connection pool // Connection pool
serbridgeConnData connData[MAX_CONN]; serbridgeConnData connData[MAX_CONN];
@ -421,7 +421,7 @@ serbridgeConnectCb(void *arg)
connData[i].readytosend = true; connData[i].readytosend = true;
connData[i].conn_mode = cmInit; connData[i].conn_mode = cmInit;
// if it's the second port we start out in programming mode // if it's the second port we start out in programming mode
if (conn->proto.tcp->local_port == serbridgeConn2.proto.tcp->local_port) if (conn->proto.tcp->local_port == serbridgeConn[1].proto.tcp->local_port)
connData[i].conn_mode = cmPGMInit; connData[i].conn_mode = cmPGMInit;
espconn_regist_recvcb(conn, serbridgeRecvCb); espconn_regist_recvcb(conn, serbridgeRecvCb);
@ -470,35 +470,46 @@ serbridgeInitPins()
// Start transparent serial bridge TCP server on specified port (typ. 23) // Start transparent serial bridge TCP server on specified port (typ. 23)
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
serbridgeInit(int port1, int port2) serbridgeInit()
{ {
serbridgeInitPins(); serbridgeInitPins();
os_memset(connData, 0, sizeof(connData)); os_memset(connData, 0, sizeof(connData));
os_memset(&serbridgeTcp1, 0, sizeof(serbridgeTcp1)); os_memset(&serbridgeTcp[0], 0, sizeof(serbridgeTcp[0]));
os_memset(&serbridgeTcp2, 0, sizeof(serbridgeTcp2)); os_memset(&serbridgeTcp[1], 0, sizeof(serbridgeTcp[1]));
}
// set-up the primary port for plain bridging
serbridgeConn1.type = ESPCONN_TCP; // Start transparent serial bridge TCP server on specified port (typ. 23)
serbridgeConn1.state = ESPCONN_NONE; void ICACHE_FLASH_ATTR
serbridgeTcp1.local_port = port1; serbridgeStart(int ix, int port, int mode)
serbridgeConn1.proto.tcp = &serbridgeTcp1; {
espconn_regist_connectcb(&serbridgeConn1, serbridgeConnectCb); if (ix < 0 || ix > 2) // FIXME hardcoded limit
espconn_accept(&serbridgeConn1); return;
espconn_tcp_set_max_con_allow(&serbridgeConn1, MAX_CONN);
espconn_regist_time(&serbridgeConn1, SER_BRIDGE_TIMEOUT, 0); // If we are already initialized, let's clean it up.
if (serbridgeConn[ix].type != 0) {
// set-up the secondary port for programming serbridgeCleanup(ix);
serbridgeConn2.type = ESPCONN_TCP; }
serbridgeConn2.state = ESPCONN_NONE;
serbridgeTcp2.local_port = port2; if (0 < port && port < 65536 && port != 80) {
serbridgeConn2.proto.tcp = &serbridgeTcp2; serbridgeConn[ix].type = ESPCONN_TCP;
serbridgeConn[ix].state = ESPCONN_NONE;
espconn_regist_connectcb(&serbridgeConn2, serbridgeConnectCb); serbridgeTcp[ix].local_port = port;
espconn_accept(&serbridgeConn2); serbridgeConn[ix].proto.tcp = &serbridgeTcp[ix];
espconn_tcp_set_max_con_allow(&serbridgeConn2, MAX_CONN);
espconn_regist_time(&serbridgeConn2, SER_BRIDGE_TIMEOUT, 0); espconn_regist_connectcb(&serbridgeConn[ix], serbridgeConnectCb);
espconn_accept(&serbridgeConn[ix]);
espconn_tcp_set_max_con_allow(&serbridgeConn[ix], MAX_CONN);
espconn_regist_time(&serbridgeConn[ix], SER_BRIDGE_TIMEOUT, 0);
}
}
void ICACHE_FLASH_ATTR
serbridgeCleanup(int ix)
{
os_memset(&serbridgeTcp[ix], 0, sizeof(serbridgeTcp[ix]));
// Looks like none of the espconn_..() calls in serbridgeStart() needs cleanup here.
} }
int ICACHE_FLASH_ATTR serbridgeInMCUFlashing() int ICACHE_FLASH_ATTR serbridgeInMCUFlashing()

@ -31,11 +31,11 @@ typedef struct serbridgeConnData {
} serbridgeConnData; } serbridgeConnData;
// port1 is transparent&programming, second port is programming only // port1 is transparent&programming, second port is programming only
void ICACHE_FLASH_ATTR serbridgeInit(int port1, int port2); void ICACHE_FLASH_ATTR serbridgeInit();
void ICACHE_FLASH_ATTR serbridgeStart(int ix, int port, int mode);
void ICACHE_FLASH_ATTR serbridgeInitPins(void); void ICACHE_FLASH_ATTR serbridgeInitPins(void);
void ICACHE_FLASH_ATTR serbridgeUartCb(char *buf, short len); void ICACHE_FLASH_ATTR serbridgeUartCb(char *buf, short len);
void ICACHE_FLASH_ATTR serbridgeReset(); void ICACHE_FLASH_ATTR serbridgeReset();
int ICACHE_FLASH_ATTR serbridgeInMCUFlashing(); int ICACHE_FLASH_ATTR serbridgeInMCUFlashing();
// callback when receiving UART chars when in programming mode // callback when receiving UART chars when in programming mode

Loading…
Cancel
Save