diff --git a/.travis.yml b/.travis.yml
index 008251c9..6ce3d58d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,31 +1,28 @@
-# Travis-CI file for Esp-Link
-
language: c
-
before_install:
- - 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 -
-
-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:
-
+- 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 -
script:
- - export XTENSA_TOOLS_ROOT=$PWD/xtensa-lx106-elf/bin/
- - export BRANCH=$TRAVIS_BRANCH
- #- export SDK_BASE=$PWD/esp_iot_sdk_v2.0.0.p1
- - make release
-
+- printenv
+- export XTENSA_TOOLS_ROOT=$PWD/xtensa-lx106-elf/bin/
+- export BRANCH=$TRAVIS_BRANCH
+- 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:
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"
diff --git a/Makefile b/Makefile
index 4172785d..5c22bd9e 100644
--- a/Makefile
+++ b/Makefile
@@ -52,12 +52,15 @@ ESP_HOSTNAME ?= esp-link
# Base directory for the compiler. Needs a / at the end.
# 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!
-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
# 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!!!
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,
# 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
# This used to work at some point, but is not supported, uncomment if you feel lucky ;-)
-#ifeq ($(SDK_BASE),)
-#SDK_BASE := $(wildcard $(XTENSA_TOOLS_ROOT)/../../$(SDK_VERS))
-#endif
+ifeq ($(SDK_BASE),)
+SDK_BASE := $(wildcard $(XTENSA_TOOLS_ROOT)/../../$(SDK_VERS))
+endif
# Clean up SDK path
SDK_BASE := $(abspath $(SDK_BASE))
$(warning Using SDK from $(SDK_BASE))
# 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
# Typically you'll use https://github.com/themadinventor/esptool
@@ -127,8 +131,10 @@ GZIP_COMPRESSION ?= yes
# http://yui.github.io/yuicompressor/
# enabled by default.
COMPRESS_W_HTMLCOMPRESSOR ?= yes
-HTML_COMPRESSOR ?= htmlcompressor-1.5.3.jar
-YUI_COMPRESSOR ?= yuicompressor-2.4.8.jar
+HTML_COMPRESSOR_VER ?= htmlcompressor-1.5.3.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 -------------
@@ -296,6 +302,13 @@ Q := @
vecho := @echo
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)),)
CFLAGS += -DSTA_SSID="$(STA_SSID)"
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) rm -f eagle.app.v6.*.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
$(APP_AR): $(OBJ)
@@ -406,18 +420,18 @@ baseflash: all
flash: all
$(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
tools/$(HTML_COMPRESSOR):
$(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 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://htmlcompressor.googlecode.com/files/$(HTML_COMPRESSOR) -O $(HTML_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_VER) -O $(HTML_COMPRESSOR_VER)"
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
-$(BUILD_BASE)/espfs_img.o: tools/$(HTML_COMPRESSOR)
+$(BUILD_BASE)/espfs_img.o: $(HTML_COMPRESSOR)
endif
$(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/*.js html_compressed/wifi;
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
- $(Q) echo "Compressing assets with htmlcompressor. This may take a while..."
- $(Q) java -jar tools/$(HTML_COMPRESSOR) \
+ $(Q) echo "Compressing assets with htmlcompressor. This may take a while...";
+ $(Q) java -jar $(HTML_COMPRESSOR) \
-t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \
-o $(abspath ./html_compressed)/ \
$(HTML_PATH)head- \
$(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 \
-o $(abspath ./html_compressed)/wifi/ \
$(WIFI_PATH)*.html
$(Q) echo "Compressing assets with yui-compressor. This may take a while..."
- $(Q) for file in `find html_compressed -type f -name "*.js"`; do \
- java -jar tools/$(YUI_COMPRESSOR) $$file --line-break 0 -o $$file; \
- done
- $(Q) for file in `find html_compressed -type f -name "*.css"`; do \
- java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \
- done
+ $(Q) java -jar $(YUI_COMPRESSOR) ./html_compressed/*.css -o '.css$:.css'
+ $(Q) java -jar $(YUI_COMPRESSOR) ./html_compressed/*.js -o '.js$:.js'
+ $(Q) java -jar $(YUI_COMPRESSOR) ./html_compressed/wifi/*.js -o '.js$:.js'
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
+
ifeq (,$(findstring mqtt,$(MODULES)))
$(Q) rm -rf html_compressed/mqtt.html
$(Q) rm -rf html_compressed/mqtt.js
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}-; \
mv $$file- $$file; \
done
$(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) cd build; $(OBJCP) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.espfs \
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)/user2.bin | cut -b 1-80
$(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)
$(Q) tar zcf esp-link-$(BRANCH)-$(SHA).tgz -C release esp-link-$(BRANCH)
$(Q) echo "Release file: esp-link-$(BRANCH)-$(SHA).tgz"
@@ -494,7 +508,7 @@ docker:
clean:
$(Q) rm -f $(APP_AR)
$(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) rm -rf $(FW_BASE)
$(Q) rm -f webpages.espfs
@@ -502,4 +516,4 @@ ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) rm -rf html_compressed
endif
-$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))
+$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))
\ No newline at end of file
diff --git a/README.md b/README.md
index 17ef3a0d..3bda6151 100644
--- a/README.md
+++ b/README.md
@@ -149,6 +149,8 @@ From there, more advanced steps are:
### 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,
on linux you can use `nc esp-hostname 23` or `telnet esp-hostname 23`.
diff --git a/esp-link/cgi.c b/esp-link/cgi.c
index d667be3f..6d0d79e6 100644
--- a/esp-link/cgi.c
+++ b/esp-link/cgi.c
@@ -190,7 +190,7 @@ int ICACHE_FLASH_ATTR printGlobalInfo(char *buff, int buflen, char *token) {
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.
char buff[1024];
// don't use jsonHeader so the response does get cached
diff --git a/esp-link/cgipins.c b/esp-link/cgipins.c
index b763d125..0f62212d 100644
--- a/esp-link/cgipins.c
+++ b/esp-link/cgipins.c
@@ -1,4 +1,3 @@
-
#include
#include "cgi.h"
#include "espfs.h"
diff --git a/esp-link/cgitelnet.c b/esp-link/cgitelnet.c
new file mode 100644
index 00000000..2791e34e
--- /dev/null
+++ b/esp-link/cgitelnet.c
@@ -0,0 +1,120 @@
+#include
+#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;
+ }
+
\ No newline at end of file
diff --git a/esp-link/cgitelnet.h b/esp-link/cgitelnet.h
new file mode 100644
index 00000000..516d5d9f
--- /dev/null
+++ b/esp-link/cgitelnet.h
@@ -0,0 +1,8 @@
+#ifndef CGITELNET_H
+#define CGITELNET_H
+
+#include "httpd.h"
+
+int cgiTelnet(HttpdConnData *connData);
+
+#endif // CGITELNET_H
diff --git a/esp-link/config.c b/esp-link/config.c
index d12f7a78..9ac57b9c 100644
--- a/esp-link/config.c
+++ b/esp-link/config.c
@@ -35,6 +35,12 @@ FlashConfig flashDefault = {
.data_bits = EIGHT_BITS,
.parity = NONE_BITS,
.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 {
@@ -161,6 +167,17 @@ bool ICACHE_FLASH_ATTR configRestore(void) {
flashConfig.parity = flashDefault.parity;
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;
}
diff --git a/esp-link/config.h b/esp-link/config.h
index 65195d29..59982154 100644
--- a/esp-link/config.h
+++ b/esp-link/config.h
@@ -13,7 +13,7 @@ typedef struct {
char hostname[32]; // if using DHCP
uint32_t staticip, netmask, gateway; // using DHCP if staticip==0
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
char api_key[48]; // RSSI submission API key (Grovestreams for now)
uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client
@@ -41,8 +41,15 @@ typedef struct {
int8_t data_bits;
int8_t parity;
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;
extern FlashConfig flashConfig;
+extern FlashConfig flashDefault;
bool configSave(void);
bool configRestore(void);
diff --git a/esp-link/main.c b/esp-link/main.c
index e775de9d..38a68177 100644
--- a/esp-link/main.c
+++ b/esp-link/main.c
@@ -32,6 +32,7 @@
#include "gpio.h"
#include "cgiservices.h"
#include "web-server.h"
+#include "cgitelnet.h"
#ifdef SYSLOG
#include "syslog.h"
@@ -96,6 +97,7 @@ HttpdBuiltInUrl builtInUrls[] = {
{ "/services/info", cgiServicesInfo, NULL },
{ "/services/update", cgiServicesSet, NULL },
{ "/pins", cgiPins, NULL },
+ { "/telnet", cgiTelnet, NULL},
#ifdef MQTT
{ "/mqtt", cgiMqtt, NULL },
#endif
@@ -178,8 +180,11 @@ user_init(void) {
httpdInit(builtInUrls, 80);
WEB_Init();
- // init the wifi-serial transparent bridge (port 23)
- serbridgeInit(23, 2323);
+ // init the wifi-serial configurable transparent bridge (port defaults 23&2323)
+ serbridgeInit();
+ serbridgeStart(0, flashConfig.telnet_port0, flashDefault.telnet_port0mode);
+ serbridgeStart(1, flashConfig.telnet_port1, flashDefault.telnet_port1mode);
+
uart_add_recv_cb(&serbridgeUartCb);
#ifdef SHOW_HEAP_USE
os_timer_disarm(&prHeapTimer);
diff --git a/espmake.cmd b/espmake.cmd
index 42e25a65..f475e01c 100644
--- a/espmake.cmd
+++ b/espmake.cmd
@@ -1,5 +1,6 @@
@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
rd obj /S /Q >nul 2>&1
diff --git a/html/home.html b/html/home.html
index de9862f2..62930263 100644
--- a/html/home.html
+++ b/html/home.html
@@ -50,6 +50,38 @@ Info
the online README
for up-to-date help.
+
+
Telnet Serial-Bridge
+
There are two ports available for telnet to use by default: 23 & 2323
+ Note - this time, only port0 may be changed & used sucessfully.
+
+
+ Current Telnet ports | |
+
+
+ Port0 Mode
+
+
+
+
+ |
+
+
@@ -152,9 +184,13 @@
System details
onLoad(function() {
makeAjaxInput("system", "description");
makeAjaxInput("system", "name");
+ makeAjaxInput("telnet", "port0");
+ makeAjaxInput("telnet", "port1");
+ makeAjaxInput("telnet", "port0mode");
fetchPins();
getWifiInfo();
getSystemInfo();
+ getTelnetInfo();
bnd($("#pinform"), "submit", setPins);
});
diff --git a/html/ui.js b/html/ui.js
index 67361c9b..3a00ef83 100644
--- a/html/ui.js
+++ b/html/ui.js
@@ -302,6 +302,22 @@ function getWifiInfo() {
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
function showSystemInfo(data) {
@@ -323,6 +339,8 @@ function makeAjaxInput(klass, field) {
var eon = $(".edit-on", div);
var eoff = $(".edit-off", div)[0];
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;
@@ -383,6 +401,7 @@ function showNotification(text) {
var el = $("#notification");
el.innerHTML = text;
el.removeAttribute('hidden');
+ window.scrollTo(0, 0); //Uncomment this line so window will scroll up on regular notifications
if (notifTimeout != null) clearTimeout(notifTimeout);
notifTimout = setTimeout(function() {
el.setAttribute('hidden', '');
diff --git a/serial/serbridge.c b/serial/serbridge.c
index cebc5615..8e9e0411 100644
--- a/serial/serbridge.c
+++ b/serial/serbridge.c
@@ -16,14 +16,14 @@
#define syslog(X1...)
#endif
-static struct espconn serbridgeConn1; // plain bridging port
-static struct espconn serbridgeConn2; // programming port
-static esp_tcp serbridgeTcp1, serbridgeTcp2;
+static struct espconn serbridgeConn[2]; // 0 = plain bridging port, 1 = programming port
+static esp_tcp serbridgeTcp[2];
static int8_t mcu_reset_pin, mcu_isp_pin;
uint8_t in_mcu_flashing; // for disabling slip during MCU flashing
void (*programmingCB)(char *buffer, short length) = NULL;
+void ICACHE_FLASH_ATTR serbridgeCleanup(int ix);
// Connection pool
serbridgeConnData connData[MAX_CONN];
@@ -421,7 +421,7 @@ serbridgeConnectCb(void *arg)
connData[i].readytosend = true;
connData[i].conn_mode = cmInit;
// 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;
espconn_regist_recvcb(conn, serbridgeRecvCb);
@@ -470,35 +470,46 @@ serbridgeInitPins()
// Start transparent serial bridge TCP server on specified port (typ. 23)
void ICACHE_FLASH_ATTR
-serbridgeInit(int port1, int port2)
+serbridgeInit()
{
serbridgeInitPins();
os_memset(connData, 0, sizeof(connData));
- os_memset(&serbridgeTcp1, 0, sizeof(serbridgeTcp1));
- os_memset(&serbridgeTcp2, 0, sizeof(serbridgeTcp2));
-
- // set-up the primary port for plain bridging
- serbridgeConn1.type = ESPCONN_TCP;
- serbridgeConn1.state = ESPCONN_NONE;
- serbridgeTcp1.local_port = port1;
- serbridgeConn1.proto.tcp = &serbridgeTcp1;
-
- espconn_regist_connectcb(&serbridgeConn1, serbridgeConnectCb);
- espconn_accept(&serbridgeConn1);
- espconn_tcp_set_max_con_allow(&serbridgeConn1, MAX_CONN);
- espconn_regist_time(&serbridgeConn1, SER_BRIDGE_TIMEOUT, 0);
-
- // set-up the secondary port for programming
- serbridgeConn2.type = ESPCONN_TCP;
- serbridgeConn2.state = ESPCONN_NONE;
- serbridgeTcp2.local_port = port2;
- serbridgeConn2.proto.tcp = &serbridgeTcp2;
-
- espconn_regist_connectcb(&serbridgeConn2, serbridgeConnectCb);
- espconn_accept(&serbridgeConn2);
- espconn_tcp_set_max_con_allow(&serbridgeConn2, MAX_CONN);
- espconn_regist_time(&serbridgeConn2, SER_BRIDGE_TIMEOUT, 0);
+ os_memset(&serbridgeTcp[0], 0, sizeof(serbridgeTcp[0]));
+ os_memset(&serbridgeTcp[1], 0, sizeof(serbridgeTcp[1]));
+}
+
+// Start transparent serial bridge TCP server on specified port (typ. 23)
+void ICACHE_FLASH_ATTR
+serbridgeStart(int ix, int port, int mode)
+{
+
+ if (ix < 0 || ix > 2) // FIXME hardcoded limit
+ return;
+
+ // If we are already initialized, let's clean it up.
+ if (serbridgeConn[ix].type != 0) {
+ serbridgeCleanup(ix);
+ }
+
+ if (0 < port && port < 65536 && port != 80) {
+ serbridgeConn[ix].type = ESPCONN_TCP;
+ serbridgeConn[ix].state = ESPCONN_NONE;
+ serbridgeTcp[ix].local_port = port;
+ serbridgeConn[ix].proto.tcp = &serbridgeTcp[ix];
+
+ 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()
diff --git a/serial/serbridge.h b/serial/serbridge.h
index ed661e1c..a1122ef7 100644
--- a/serial/serbridge.h
+++ b/serial/serbridge.h
@@ -31,11 +31,11 @@ typedef struct serbridgeConnData {
} serbridgeConnData;
// 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 serbridgeUartCb(char *buf, short len);
void ICACHE_FLASH_ATTR serbridgeReset();
-
int ICACHE_FLASH_ATTR serbridgeInMCUFlashing();
// callback when receiving UART chars when in programming mode