diff --git a/Makefile b/Makefile index 13089b6..8be49f6 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ XTENSA_TOOLS_ROOT ?= $(abspath ../esp-open-sdk/xtensa-lx106-elf/bin)/ # Base directory of the ESP8266 SDK package, absolute # Typically you'll download from Espressif's BBS, http://bbs.espressif.com/viewforum.php?f=5 -SDK_BASE ?= $(abspath ../esp_iot_sdk_v1.4.1_pre7) +SDK_BASE ?= $(abspath ../esp_iot_sdk_v1.5.0) # Esptool.py path and port, only used for 1-time serial flashing # Typically you'll use https://github.com/themadinventor/esptool @@ -38,29 +38,11 @@ ESPTOOL ?= $(abspath ../esp-open-sdk/esptool/esptool.py) ESPPORT ?= /dev/ttyUSB0 ESPBAUD ?= 460800 -# --------------- chipset configuration --------------- - -# Pick your flash size: "512KB" or "4MB" -FLASH_SIZE ?= 4MB - -ifeq ("$(FLASH_SIZE)","512KB") -# Winbond 25Q40 512KB flash, typ for esp-01 thru esp-11 -ESP_SPI_SIZE ?= 0 # 0->512KB -ESP_FLASH_MODE ?= 0 # 0->QIO -ESP_FLASH_FREQ_DIV ?= 0 # 0->40Mhz -ESP_FLASH_MAX ?= 241664 # max bin file for 512KB flash: 236KB - -else -# Winbond 25Q32 4MB flash, typ for esp-12 -# Here we're using two partitions of approx 0.5MB because that's what's easily available in terms -# of linker scripts in the SDK. Ideally we'd use two partitions of approx 1MB, the remaining 2MB -# cannot be used for code. -ESP_SPI_SIZE ?= 4 # 6->4MB (1MB+1MB) or 4->4MB (512KB+512KB) -ESP_FLASH_MODE ?= 0 # 0->QIO, 2->DIO -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 -endif +# The Wifi station configuration can be hard-coded here, which makes esp-link come up in STA+AP +# mode trying to connect to the specified AP *only* if the flash wireless settings are empty! +# This happens on a full serial flash and avoids having to hunt for the AP... +# STA_SSID ?= +# STA_PASS ?= # hostname or IP address for wifi flashing ESP_HOSTNAME ?= esp-link @@ -120,6 +102,25 @@ YUI_COMPRESSOR ?= yuicompressor-2.4.8.jar # -------------- End of config options ------------- +ifeq ("$(FLASH_SIZE)","512KB") +# Winbond 25Q40 512KB flash, typ for esp-01 thru esp-11 +ESP_SPI_SIZE ?= 0 # 0->512KB +ESP_FLASH_MODE ?= 0 # 0->QIO +ESP_FLASH_FREQ_DIV ?= 0 # 0->40Mhz +ESP_FLASH_MAX ?= 241664 # max bin file for 512KB flash: 236KB + +else +# Winbond 25Q32 4MB flash, typ for esp-12 +# Here we're using two partitions of approx 0.5MB because that's what's easily available in terms +# of linker scripts in the SDK. Ideally we'd use two partitions of approx 1MB, the remaining 2MB +# cannot be used for code. +ESP_SPI_SIZE ?= 4 # 6->4MB (1MB+1MB) or 4->4MB (512KB+512KB) +ESP_FLASH_MODE ?= 0 # 0->QIO, 2->DIO +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 +endif + HTML_PATH = $(abspath ./html)/ WIFI_PATH = $(HTML_PATH)wifi/ @@ -215,7 +216,7 @@ MODULES += $(foreach sdir,$(LIBRARIES_DIR),$(wildcard $(sdir)/*)) EXTRA_INCDIR = include . # libraries used in this project, mainly provided by the SDK -LIBS = c gcc hal phy pp net80211 wpa main lwip +LIBS = c gcc hal phy pp net80211 wpa main lwip crypto # compiler flags using during compilation of source files CFLAGS += -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ @@ -330,7 +331,7 @@ $(FW_BASE)/user1.bin: $(USER1_OUT) $(FW_BASE) $(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 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) + $(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) mv eagle.app.flash.bin $@ @echo "** user1.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available" @@ -341,7 +342,7 @@ $(FW_BASE)/user2.bin: $(USER2_OUT) $(FW_BASE) $(Q) $(OBJCP) --only-section .data -O binary $(USER2_OUT) eagle.app.v6.data.bin $(Q) $(OBJCP) --only-section .rodata -O binary $(USER2_OUT) eagle.app.v6.rodata.bin $(Q) $(OBJCP) --only-section .irom0.text -O binary $(USER2_OUT) eagle.app.v6.irom0text.bin - $(Q) COMPILE=gcc PATH=$(XTENSA_TOOLS_ROOT):$(PATH) python $(APPGEN_TOOL) $(USER2_OUT) 2 $(ESP_FLASH_MODE) $(ESP_FLASH_FREQ_DIV) $(ESP_SPI_SIZE) + $(Q) COMPILE=gcc PATH=$(XTENSA_TOOLS_ROOT):$(PATH) python $(APPGEN_TOOL) $(USER2_OUT) 2 $(ESP_FLASH_MODE) $(ESP_FLASH_FREQ_DIV) $(ESP_SPI_SIZE) 0 $(Q) rm -f eagle.app.v6.*.bin $(Q) mv eagle.app.flash.bin $@ $(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; false; fi @@ -405,6 +406,10 @@ ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes") $(Q) for file in `find html_compressed -type f -name "*.css"`; do \ java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \ 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 ifeq (,$(findstring mqtt,$(MODULES))) $(Q) rm -rf html_compressed/mqtt.html diff --git a/WINDOWS.md b/WINDOWS.md new file mode 100644 index 0000000..08e7a03 --- /dev/null +++ b/WINDOWS.md @@ -0,0 +1,14 @@ +* Install [SourceTree](https://www.sourcetreeapp.com) and check CLI git or other git distribution to obtain git from CLI +* Install the latest Java JRE +* Install Python 2.7 to C:\Python27 +* Install link shell extension from [here](http://schinagl.priv.at/nt/hardlinkshellext/linkshellextension.html) +* Download and install the [Windows Unofficial Development Kit for Espressif ESP8266](http://programs74.ru/get.php?file=EspressifESP8266DevKit) to c:\espressif +* Create a symbolic link for java/bin and git/bin directories under C:\espressif\git-bin and C:\espressif\java-bin. You must do this because "make" doesn't work properly with paths like "program files(x86)". You can see all the expected paths in the [espmake.cmd](https://github.com/jeelabs/esp-link/blob/master/espmake.cmd) +* [Download](http://sourceforge.net/projects/mingw/files/Installer/) and install MinGW. Run mingw-get-setup.exe. During the installation process select without GUI. (uncheck "... also install support for the graphical user interface") +* [Download](http://programs74.ru/get.php?file=EspressifESP8266DevKitAddon) the scripts to automate the installation of additional modules for MinGW. +* Run install-mingw-package.bat. This will install the basic modules required for MinGW to build esp8266. +* Checkout esp-link from git to C:\espressif\esp-link +* When you're done open a command prompt and run: espmake.cmd "make all wiflash" +* For a new flash over serial use: espmake.cmd "make all flash" +* If you want to program with serial but not loose your config each time use: espmake.cmd "make all baseflash" +* You can open the esp-link.sln file in Visual Studio 2013. "Build Solution" will issue "make all wiflash". "Clean Solution" will issue "make clean". "Rebuild Solution" will issue "make clean all". This can be changed under solution properties -> Configuration Properties -> NMake \ No newline at end of file diff --git a/cmd/cmd.c b/cmd/cmd.c index e7ec63f..8f04faf 100644 --- a/cmd/cmd.c +++ b/cmd/cmd.c @@ -7,6 +7,19 @@ #include "crc16.h" #include "uart.h" +#ifdef CMD_DBG +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) +static const char *cmd_names[] = { + "NULL", "RESET", "IS_READY", "WIFI_CONNECT", + "MQTT_SETUP", "MQTT_CONNECT", "MQTT_DISCONNECT", + "MQTT_PUBLISH", "MQTT_SUBSCRIBE", "MQTT_LWT", "MQTT_EVENTS", + "REST_SETUP", "REST_REQUEST", "REST_SETHEADER", "REST_EVENTS", + "CB_ADD", "CB_EVENTS", +}; +#else +#define DBG(format, ...) do { } while(0) +#endif + extern const CmdList commands[]; //===== ESP -> Serial responses @@ -82,39 +95,25 @@ CMD_Exec(const CmdList *scp, CmdPacket *packet) { // Iterate through the command table and call the appropriate function while (scp->sc_function != NULL) { if(scp->sc_name == packet->cmd) { - //os_printf("CMD: Dispatching cmd=%d\n", packet->cmd); + DBG("CMD_Exec: Dispatching cmd=%s\n", cmd_names[packet->cmd]); // call command function uint32_t ret = scp->sc_function(packet); // if requestor asked for a response, send it if (packet->_return){ -#ifdef CMD_DBG - os_printf("CMD: Response: 0x%lx, cmd: %d\r\n", ret, packet->cmd); -#endif + DBG("CMD_Exec: Response: 0x%lx, cmd: %d\r\n", ret, packet->cmd); crc = CMD_ResponseStart(packet->cmd, 0, ret, 0); CMD_ResponseEnd(crc); } else { -#ifdef CMD_DBG - os_printf("CMD: no response (%lu)\n", packet->_return); -#endif + DBG("CMD_Exec: no response (%lu)\n", packet->_return); } return ret; } scp++; } -#ifdef CMD_DBG - os_printf("CMD: cmd=%d not found\n", packet->cmd); -#endif + DBG("CMD_Exec: cmd=%d not found\n", packet->cmd); return 0; } -char *cmd_names[] = { - "NULL", "RESET", "IS_READY", "WIFI_CONNECT", - "MQTT_SETUP", "MQTT_CONNECT", "MQTT_DISCONNECT", - "MQTT_PUBLISH", "MQTT_SUBSCRIBE", "MQTT_LWT", "MQTT_EVENTS", - "REST_SETUP", "REST_REQUEST", "REST_SETHEADER", "REST_EVENTS", - "CB_ADD", "CB_EVENTS", -}; - // Parse a packet and print info about it void ICACHE_FLASH_ATTR CMD_parse_packet(uint8_t *buf, short len) { @@ -125,18 +124,22 @@ CMD_parse_packet(uint8_t *buf, short len) { CmdPacket *packet = (CmdPacket*)buf; uint8_t *data_ptr = (uint8_t*)&packet->args; uint8_t *data_limit = data_ptr+len; -#ifdef CMD_DBG - uint16_t argn = 0; - os_printf("CMD: cmd=%d(%s) argc=%d cb=%p ret=%lu\n", - packet->cmd, cmd_names[packet->cmd], packet->argc, (void *)packet->callback, packet->_return); -#endif + + DBG("CMD_parse_packet: cmd=%d(%s) argc=%d cb=%p ret=%lu\n", + packet->cmd, + cmd_names[packet->cmd], + packet->argc, + (void *)packet->callback, + packet->_return + ); #if 0 - // print out arguments + // print out arguments + uint16_t argn = 0; uint16_t argc = packet->argc; while (data_ptr+2 < data_limit && argc--) { short l = *(uint16_t*)data_ptr; - os_printf("CMD: arg[%d] len=%d:", argn++, l); + os_printf("CMD_parse_packet: arg[%d] len=%d:", argn++, l); data_ptr += 2; while (data_ptr < data_limit && l--) { os_printf(" %02X", *data_ptr++); @@ -148,9 +151,7 @@ CMD_parse_packet(uint8_t *buf, short len) { if (data_ptr <= data_limit) { CMD_Exec(commands, packet); } else { -#ifdef CMD_DBG - os_printf("CMD: packet length overrun, parsing arg %d\n", argn-1); -#endif + DBG("CMD_parse_packet: packet length overrun, parsing arg %d\n", packet->argc); } } diff --git a/cmd/handlers.c b/cmd/handlers.c index 9642856..4d20e4d 100644 --- a/cmd/handlers.c +++ b/cmd/handlers.c @@ -12,6 +12,12 @@ #include #endif +#ifdef CMD_DBG +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) +#else +#define DBG(format, ...) do { } while(0) +#endif + static uint32_t CMD_Null(CmdPacket *cmd); static uint32_t CMD_IsReady(CmdPacket *cmd); static uint32_t CMD_Reset(CmdPacket *cmd); @@ -81,9 +87,7 @@ CMD_AddCb(char* name, uint32_t cb) { os_strncpy(callbacks[i].name, name, sizeof(callbacks[i].name)); callbacks[i].name[CMD_CBNLEN-1] = 0; // strncpy doesn't null terminate callbacks[i].callback = cb; -#ifdef CMD_DBG - os_printf("CMD_AddCb: cb %s added at index %d\n", callbacks[i].name, i); -#endif + DBG("CMD_AddCb: cb %s added at index %d\n", callbacks[i].name, i); return 1; } } @@ -97,9 +101,7 @@ CMD_GetCbByName(char* name) { // (void *)callbacks[i].callback); // if callback doesn't exist or it's null if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0) { -#ifdef CMD_DBG - os_printf("CMD_GetCbByName: cb %s found at index %d\n", name, i); -#endif + DBG("CMD_GetCbByName: cb %s found at index %d\n", name, i); return &callbacks[i]; } } @@ -111,9 +113,7 @@ CMD_GetCbByName(char* name) { static void ICACHE_FLASH_ATTR CMD_WifiCb(uint8_t wifiStatus) { if (wifiStatus != lastWifiStatus){ -#ifdef CMD_DBG - os_printf("CMD_WifiCb: wifiStatus=%d\n", wifiStatus); -#endif + DBG("CMD_WifiCb: wifiStatus=%d\n", wifiStatus); lastWifiStatus = wifiStatus; cmdCallback *wifiCb = CMD_GetCbByName("wifiCb"); if ((uint32_t)wifiCb->callback != -1) { @@ -160,9 +160,7 @@ CMD_AddCallback(CmdPacket *cmd) { if (len > 15) return 0; // max size of name is 15 characters if (CMD_PopArg(&req, (uint8_t *)name, len)) return 0; name[len] = 0; -#ifdef CMD_DBG - os_printf("CMD_AddCallback: name=%s\n", name); -#endif + DBG("CMD_AddCallback: name=%s\n", name); return CMD_AddCb(name, (uint32_t)cmd->callback); // save the sensor callback } diff --git a/esp-link.vcxproj b/esp-link.vcxproj index 57e3a8d..4a1ef3a 100644 --- a/esp-link.vcxproj +++ b/esp-link.vcxproj @@ -16,7 +16,9 @@ + + @@ -24,6 +26,7 @@ + @@ -43,6 +46,7 @@ + @@ -50,13 +54,17 @@ + + + + @@ -79,8 +87,11 @@ + + + @@ -93,6 +104,8 @@ + + @@ -100,6 +113,7 @@ + @@ -125,8 +139,8 @@ - __ets__;_STDINT_H;ICACHE_FLASH;__MINGW32__;__WIN32__ - .\rest;.\esp-link;.\mqtt;.\cmd;.\serial;.\user;.\espfs;.\httpd;.\include;..\esp_iot_sdk_v1.3.0\include;..\xtensa-lx106-elf\xtensa-lx106-elf\include;c:\tools\mingw64\x86_64-w64-mingw32\include;c:\tools\mingw64\lib\gcc\x86_64-w64-mingw32\4.8.3\include + __ets__;_STDINT_H;ICACHE_FLASH;__MINGW32__;__WIN32__;MQTT;REST;SYSLOG;FIRMWARE_SIZE + .\syslog;.\rest;.\esp-link;.\mqtt;.\cmd;.\serial;.\user;.\espfs;.\httpd;.\include;..\esp_iot_sdk_v1.5.0\include;..\xtensa-lx106-elf\xtensa-lx106-elf\include;c:\tools\mingw64\x86_64-w64-mingw32\include;c:\tools\mingw64\lib\gcc\x86_64-w64-mingw32\4.8.3\include diff --git a/esp-link/cgi.c b/esp-link/cgi.c index ba08c00..081ef49 100644 --- a/esp-link/cgi.c +++ b/esp-link/cgi.c @@ -13,40 +13,39 @@ Some random cgi routines. * ---------------------------------------------------------------------------- */ - #include #include "cgi.h" #include "config.h" -void ICACHE_FLASH_ATTR -noCacheHeaders(HttpdConnData *connData, int code) { +#ifdef CGI_DBG +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) +#else +#define DBG(format, ...) do { } while(0) +#endif + +void ICACHE_FLASH_ATTR noCacheHeaders(HttpdConnData *connData, int code) { httpdStartResponse(connData, code); httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate"); httpdHeader(connData, "Pragma", "no-cache"); httpdHeader(connData, "Expires", "0"); } -void ICACHE_FLASH_ATTR -jsonHeader(HttpdConnData *connData, int code) { +void ICACHE_FLASH_ATTR jsonHeader(HttpdConnData *connData, int code) { noCacheHeaders(connData, code); httpdHeader(connData, "Content-Type", "application/json"); httpdEndHeaders(connData); } -void ICACHE_FLASH_ATTR -errorResponse(HttpdConnData *connData, int code, char *message) { +void ICACHE_FLASH_ATTR errorResponse(HttpdConnData *connData, int code, char *message) { noCacheHeaders(connData, code); httpdEndHeaders(connData); httpdSend(connData, message, -1); -#ifdef CGI_DBG - os_printf("HTTP %d error response: \"%s\"\n", code, message); -#endif + DBG("HTTP %d error response: \"%s\"\n", code, message); } // look for the HTTP arg 'name' and store it at 'config' with max length 'max_len' (incl // terminating zero), returns -1 on error, 0 if not found, 1 if found and OK -int8_t ICACHE_FLASH_ATTR -getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) { +int8_t ICACHE_FLASH_ATTR getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) { char buff[128]; int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); if (len < 0) return 0; // not found, skip @@ -55,19 +54,50 @@ getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) { errorResponse(connData, 400, buff); return -1; } - strcpy(config, buff); + os_strcpy(config, buff); return 1; } // look for the HTTP arg 'name' and store it at 'config' as an 8-bit integer // returns -1 on error, 0 if not found, 1 if found and OK -int8_t ICACHE_FLASH_ATTR -getInt8Arg(HttpdConnData *connData, char *name, int8_t *config) { +int8_t ICACHE_FLASH_ATTR getInt8Arg(HttpdConnData *connData, char *name, int8_t *config) { + char buff[16]; + int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); + if (len < 0) return 0; // not found, skip + int m = atoi(buff); + if (len > 5 || m < -127 || m > 127) { + os_sprintf(buff, "Value for %s out of range", name); + errorResponse(connData, 400, buff); + return -1; + } + *config = m; + return 1; +} + +// look for the HTTP arg 'name' and store it at 'config' as an unsigned 8-bit integer +// returns -1 on error, 0 if not found, 1 if found and OK +int8_t ICACHE_FLASH_ATTR getUInt8Arg(HttpdConnData *connData, char *name, uint8_t *config) { + char buff[16]; + int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); + if (len < 0) return 0; // not found, skip + int m = atoi(buff); + if (len > 4 || m < 0 || m > 255) { + os_sprintf(buff, "Value for %s out of range", name); + errorResponse(connData, 400, buff); + return -1; + } + *config = m; + return 1; +} + +// look for the HTTP arg 'name' and store it at 'config' as an unsigned 16-bit integer +// returns -1 on error, 0 if not found, 1 if found and OK +int8_t ICACHE_FLASH_ATTR getUInt16Arg(HttpdConnData *connData, char *name, uint16_t *config) { char buff[16]; int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); if (len < 0) return 0; // not found, skip int m = atoi(buff); - if (len >= 6 || m < -128 || m > 255) { + if (len > 6 || m < 0 || m > 65535) { os_sprintf(buff, "Value for %s out of range", name); errorResponse(connData, 400, buff); return -1; @@ -76,27 +106,27 @@ getInt8Arg(HttpdConnData *connData, char *name, int8_t *config) { return 1; } -int8_t ICACHE_FLASH_ATTR -getBoolArg(HttpdConnData *connData, char *name, bool*config) { - char buff[64]; +int8_t ICACHE_FLASH_ATTR getBoolArg(HttpdConnData *connData, char *name, bool *config) { + char buff[16]; int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); if (len < 0) return 0; // not found, skip - if (strcmp(buff, "1") == 0 || strcmp(buff, "true") == 0) { + if (os_strcmp(buff, "1") == 0 || os_strcmp(buff, "true") == 0) { *config = true; return 1; - } - if (strcmp(buff, "0") == 0 || strcmp(buff, "false") == 0) { + } + + if (os_strcmp(buff, "0") == 0 || os_strcmp(buff, "false") == 0) { *config = false; return 1; - } + } + os_sprintf(buff, "Invalid value for %s", name); errorResponse(connData, 400, buff); return -1; } -uint8_t ICACHE_FLASH_ATTR -UTILS_StrToIP(const char* str, void *ip){ +uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const char* str, void *ip){ /* The count of the number of bytes processed. */ int i; /* A pointer to the next digit to process. */ @@ -133,8 +163,8 @@ UTILS_StrToIP(const char* str, void *ip){ return 1; } -#define TOKEN(x) (os_strcmp(token, x) == 0) #if 0 +#define TOKEN(x) (os_strcmp(token, x) == 0) // Handle system information variables and print their value, returns the number of // characters appended to buff int ICACHE_FLASH_ATTR printGlobalInfo(char *buff, int buflen, char *token) { @@ -172,16 +202,23 @@ int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) { os_strncpy(name, flashConfig.hostname, 12); name[12] = 0; // construct json response - os_sprintf(buff, - "{\"menu\": [\"Home\", \"/home.html\", " - "\"Wifi\", \"/wifi/wifi.html\"," - "\"\xC2\xB5" "C Console\", \"/console.html\", " + os_sprintf(buff, + "{ " + "\"menu\": [ " + "\"Home\", \"/home.html\", " + "\"WiFI\", \"/wifi/wifi.html\", " + "\"µC Console\", \"/console.html\", " + "\"Services\", \"/services.html\", " #ifdef MQTT - "\"REST/MQTT\", \"/mqtt.html\"," + "\"REST/MQTT\", \"/mqtt.html\", " #endif - "\"Debug log\", \"/log.html\" ],\n" - " \"version\": \"%s\"," - "\"name\":\"%s\"}", esp_link_version, name); + "\"Debug log\", \"/log.html\"" + " ], " + "\"version\": \"%s\", " + "\"name\": \"%s\"" + " }", + esp_link_version, name); + httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; } diff --git a/esp-link/cgi.h b/esp-link/cgi.h index e64b301..cb897b0 100644 --- a/esp-link/cgi.h +++ b/esp-link/cgi.h @@ -12,16 +12,24 @@ void errorResponse(HttpdConnData *connData, int code, char *message); // 'max_len' (incl terminating zero), returns -1 on error, 0 if not found, 1 if found int8_t getStringArg(HttpdConnData *connData, char *name, char *config, int max_len); -// Get the HTTP query-string param 'name' and store it as a int8 value at 'config', +// Get the HTTP query-string param 'name' and store it as a int8_t value at 'config', // supports signed and unsigned, returns -1 on error, 0 if not found, 1 if found int8_t getInt8Arg(HttpdConnData *connData, char *name, int8_t *config); +// Get the HTTP query-string param 'name' and store it as a uint8_t value at 'config', +// supports signed and unsigned, returns -1 on error, 0 if not found, 1 if found +int8_t getUInt8Arg(HttpdConnData *connData, char *name, uint8_t *config); + +// Get the HTTP query-string param 'name' and store it as a uint16_t value at 'config', +// supports signed and unsigned, returns -1 on error, 0 if not found, 1 if found +int8_t getUInt16Arg(HttpdConnData *connData, char *name, uint16_t *config); + // Get the HTTP query-string param 'name' and store it boolean value at 'config', // supports 1/true and 0/false, returns -1 on error, 0 if not found, 1 if found -int8_t getBoolArg(HttpdConnData *connData, char *name, bool*config); +int8_t getBoolArg(HttpdConnData *connData, char *name, bool *config); int cgiMenu(HttpdConnData *connData); -uint8_t UTILS_StrToIP(const char* str, void *ip); +uint8_t UTILS_StrToIP(const char *str, void *ip); #endif diff --git a/esp-link/cgiflash.c b/esp-link/cgiflash.c index 2758aec..8c39e36 100644 --- a/esp-link/cgiflash.c +++ b/esp-link/cgiflash.c @@ -18,20 +18,25 @@ Some flash handling cgi routines. Used for reading the existing flash and updati #include #include "cgi.h" #include "cgiflash.h" -#include "espfs.h" + +#ifdef CGIFLASH_DBG +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) +#else +#define DBG(format, ...) do { } while(0) +#endif // Check that the header of the firmware blob looks like actual firmware... static char* ICACHE_FLASH_ATTR check_header(void *buf) { - uint8_t *cd = (uint8_t *)buf; + uint8_t *cd = (uint8_t *)buf; #ifdef CGIFLASH_DBG - uint32_t *buf32 = buf; - os_printf("%p: %08lX %08lX %08lX %08lX\n", buf, buf32[0], buf32[1], buf32[2], buf32[3]); + uint32_t *buf32 = buf; + os_printf("%p: %08lX %08lX %08lX %08lX\n", buf, buf32[0], buf32[1], buf32[2], buf32[3]); #endif - if (cd[0] != 0xEA) return "IROM magic missing"; - if (cd[1] != 4 || cd[2] > 3 || (cd[3]>>4) > 6) return "bad flash header"; - if (((uint16_t *)buf)[3] != 0x4010) return "Invalid entry addr"; - if (((uint32_t *)buf)[2] != 0) return "Invalid start offset"; - return NULL; + if (cd[0] != 0xEA) return "IROM magic missing"; + if (cd[1] != 4 || cd[2] > 3 || (cd[3]>>4) > 6) return "bad flash header"; + if (((uint16_t *)buf)[3] != 0x4010) return "Invalid entry addr"; + if (((uint32_t *)buf)[2] != 0) return "Invalid start offset"; + return NULL; } // check whether the flash map/size we have allows for OTA upgrade @@ -44,149 +49,152 @@ static char *flash_too_small = "Flash too small for OTA update"; //===== Cgi to query which firmware needs to be uploaded next int ICACHE_FLASH_ATTR cgiGetFirmwareNext(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. if (!canOTA()) { errorResponse(connData, 400, flash_too_small); return HTTPD_CGI_DONE; } - uint8 id = system_upgrade_userbin_check(); - httpdStartResponse(connData, 200); - httpdHeader(connData, "Content-Type", "text/plain"); - httpdHeader(connData, "Content-Length", "9"); - httpdEndHeaders(connData); - char *next = id == 1 ? "user1.bin" : "user2.bin"; - httpdSend(connData, next, -1); -#ifdef CGIFLASH_DBG - os_printf("Next firmware: %s (got %d)\n", next, id); -#endif - - return HTTPD_CGI_DONE; + uint8 id = system_upgrade_userbin_check(); + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", "text/plain"); + httpdHeader(connData, "Content-Length", "9"); + httpdEndHeaders(connData); + char *next = id == 1 ? "user1.bin" : "user2.bin"; + httpdSend(connData, next, -1); + DBG("Next firmware: %s (got %d)\n", next, id); + return HTTPD_CGI_DONE; } //===== Cgi that allows the firmware to be replaced via http POST int ICACHE_FLASH_ATTR cgiUploadFirmware(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. if (!canOTA()) { errorResponse(connData, 400, flash_too_small); return HTTPD_CGI_DONE; } - int offset = connData->post->received - connData->post->buffLen; - if (offset == 0) { - connData->cgiPrivData = NULL; - } else if (connData->cgiPrivData != NULL) { - // we have an error condition, do nothing - return HTTPD_CGI_DONE; - } - - // assume no error yet... - char *err = NULL; - int code = 400; - - // check overall size - //os_printf("FW: %d (max %d)\n", connData->post->len, FIRMWARE_SIZE); - if (connData->post->len > FIRMWARE_SIZE) err = "Firmware image too large"; - if (connData->post->buff == NULL || connData->requestType != HTTPD_METHOD_POST || - connData->post->len < 1024) err = "Invalid request"; - - // check that data starts with an appropriate header - if (err == NULL && offset == 0) err = check_header(connData->post->buff); - - // make sure we're buffering in 1024 byte chunks - if (err == NULL && offset % 1024 != 0) { - err = "Buffering problem"; - code = 500; - } - - // return an error if there is one - if (err != NULL) { -#ifdef CGIFLASH_DBG - os_printf("Error %d: %s\n", code, err); -#endif - httpdStartResponse(connData, code); - httpdHeader(connData, "Content-Type", "text/plain"); - //httpdHeader(connData, "Content-Length", strlen(err)+2); - httpdEndHeaders(connData); - httpdSend(connData, err, -1); - httpdSend(connData, "\r\n", -1); - connData->cgiPrivData = (void *)1; - return HTTPD_CGI_DONE; - } - - // let's see which partition we need to flash and what flash address that puts us at - uint8 id = system_upgrade_userbin_check(); - int address = id == 1 ? 4*1024 // either start after 4KB boot partition - : 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; // 4KB boot, fw1, 16KB user param, 4KB reserved - address += offset; - - // erase next flash block if necessary - if (address % SPI_FLASH_SEC_SIZE == 0){ -#ifdef CGIFLASH_DBG - os_printf("Flashing 0x%05x (id=%d)\n", address, 2-id); -#endif - spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE); - } - - // Write the data - //os_printf("Writing %d bytes at 0x%05x (%d of %d)\n", connData->post->buffSize, address, - // connData->post->received, connData->post->len); - spi_flash_write(address, (uint32 *)connData->post->buff, connData->post->buffLen); - - if (connData->post->received == connData->post->len){ - httpdStartResponse(connData, 200); - httpdEndHeaders(connData); - return HTTPD_CGI_DONE; - } else { - return HTTPD_CGI_MORE; - } + int offset = connData->post->received - connData->post->buffLen; + if (offset == 0) { + connData->cgiPrivData = NULL; + } else if (connData->cgiPrivData != NULL) { + // we have an error condition, do nothing + return HTTPD_CGI_DONE; + } + + // assume no error yet... + char *err = NULL; + int code = 400; + + // check overall size + //os_printf("FW: %d (max %d)\n", connData->post->len, FIRMWARE_SIZE); + if (connData->post->len > FIRMWARE_SIZE) err = "Firmware image too large"; + if (connData->post->buff == NULL || connData->requestType != HTTPD_METHOD_POST || + connData->post->len < 1024) err = "Invalid request"; + + // check that data starts with an appropriate header + if (err == NULL && offset == 0) err = check_header(connData->post->buff); + + // make sure we're buffering in 1024 byte chunks + if (err == NULL && offset % 1024 != 0) { + err = "Buffering problem"; + code = 500; + } + + // return an error if there is one + if (err != NULL) { + DBG("Error %d: %s\n", code, err); + httpdStartResponse(connData, code); + httpdHeader(connData, "Content-Type", "text/plain"); + //httpdHeader(connData, "Content-Length", strlen(err)+2); + httpdEndHeaders(connData); + httpdSend(connData, err, -1); + httpdSend(connData, "\r\n", -1); + connData->cgiPrivData = (void *)1; + return HTTPD_CGI_DONE; + } + + // let's see which partition we need to flash and what flash address that puts us at + uint8 id = system_upgrade_userbin_check(); + int address = id == 1 ? 4*1024 // either start after 4KB boot partition + : 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; // 4KB boot, fw1, 16KB user param, 4KB reserved + address += offset; + + // erase next flash block if necessary + if (address % SPI_FLASH_SEC_SIZE == 0){ + DBG("Flashing 0x%05x (id=%d)\n", address, 2 - id); + spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE); + } + + // Write the data + //DBG("Writing %d bytes at 0x%05x (%d of %d)\n", connData->post->buffSize, address, + // connData->post->received, connData->post->len); + spi_flash_write(address, (uint32 *)connData->post->buff, connData->post->buffLen); + + if (connData->post->received == connData->post->len){ + httpdStartResponse(connData, 200); + httpdEndHeaders(connData); + return HTTPD_CGI_DONE; + } else { + return HTTPD_CGI_MORE; + } } static ETSTimer flash_reboot_timer; // Handle request to reboot into the new firmware int ICACHE_FLASH_ATTR cgiRebootFirmware(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. + + if (!canOTA()) { + errorResponse(connData, 400, flash_too_small); + return HTTPD_CGI_DONE; + } + + // sanity-check that the 'next' partition actually contains something that looks like + // valid firmware + uint8 id = system_upgrade_userbin_check(); + int address = id == 1 ? 4*1024 // either start after 4KB boot partition + : 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; // 4KB boot, fw1, 16KB user param, 4KB reserved + uint32 buf[8]; + DBG("Checking %p\n", (void *)address); + spi_flash_read(address, buf, sizeof(buf)); + char *err = check_header(buf); + if (err != NULL) { + DBG("Error %d: %s\n", 400, err); + httpdStartResponse(connData, 400); + httpdHeader(connData, "Content-Type", "text/plain"); + //httpdHeader(connData, "Content-Length", strlen(err)+2); + httpdEndHeaders(connData); + httpdSend(connData, err, -1); + httpdSend(connData, "\r\n", -1); + return HTTPD_CGI_DONE; + } + + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Length", "0"); + httpdEndHeaders(connData); + + // Schedule a reboot + system_upgrade_flag_set(UPGRADE_FLAG_FINISH); + os_timer_disarm(&flash_reboot_timer); + os_timer_setfn(&flash_reboot_timer, (os_timer_func_t *)system_upgrade_reboot, NULL); + os_timer_arm(&flash_reboot_timer, 2000, 1); + return HTTPD_CGI_DONE; +} - if (!canOTA()) { - errorResponse(connData, 400, flash_too_small); - return HTTPD_CGI_DONE; - } +int ICACHE_FLASH_ATTR cgiReset(HttpdConnData *connData) { + if (connData->conn == NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - // sanity-check that the 'next' partition actually contains something that looks like - // valid firmware - uint8 id = system_upgrade_userbin_check(); - int address = id == 1 ? 4*1024 // either start after 4KB boot partition - : 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; // 4KB boot, fw1, 16KB user param, 4KB reserved - uint32 buf[8]; -#ifdef CGIFLASH_DBG - os_printf("Checking %p\n", (void *)address); -#endif - spi_flash_read(address, buf, sizeof(buf)); - char *err = check_header(buf); - if (err != NULL) { -#ifdef CGIFLASH_DBG - os_printf("Error %d: %s\n", 400, err); -#endif - httpdStartResponse(connData, 400); - httpdHeader(connData, "Content-Type", "text/plain"); - //httpdHeader(connData, "Content-Length", strlen(err)+2); - httpdEndHeaders(connData); - httpdSend(connData, err, -1); - httpdSend(connData, "\r\n", -1); - return HTTPD_CGI_DONE; - } - - httpdStartResponse(connData, 200); - httpdHeader(connData, "Content-Length", "0"); - httpdEndHeaders(connData); - - // Schedule a reboot - system_upgrade_flag_set(UPGRADE_FLAG_FINISH); - os_timer_disarm(&flash_reboot_timer); - os_timer_setfn(&flash_reboot_timer, (os_timer_func_t *)system_upgrade_reboot, NULL); - os_timer_arm(&flash_reboot_timer, 2000, 1); - return HTTPD_CGI_DONE; -} + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Length", "0"); + httpdEndHeaders(connData); + + // Schedule a reboot + os_timer_disarm(&flash_reboot_timer); + os_timer_setfn(&flash_reboot_timer, (os_timer_func_t *)system_restart, NULL); + os_timer_arm(&flash_reboot_timer, 2000, 1); + return HTTPD_CGI_DONE; +} \ No newline at end of file diff --git a/esp-link/cgiflash.h b/esp-link/cgiflash.h index 15c60c2..f03b8e0 100644 --- a/esp-link/cgiflash.h +++ b/esp-link/cgiflash.h @@ -7,5 +7,6 @@ int cgiReadFlash(HttpdConnData *connData); int cgiGetFirmwareNext(HttpdConnData *connData); int cgiUploadFirmware(HttpdConnData *connData); int cgiRebootFirmware(HttpdConnData *connData); +int cgiReset(HttpdConnData *connData); #endif diff --git a/esp-link/cgimqtt.c b/esp-link/cgimqtt.c index 627d679..88aa6ed 100644 --- a/esp-link/cgimqtt.c +++ b/esp-link/cgimqtt.c @@ -1,5 +1,14 @@ // Copyright 2015 by Thorsten von Eicken, see LICENSE.txt -#ifdef MQTT + +static char *mqtt_states[] = { + "disconnected", "reconnecting", "connecting", "connected", "disabled" +}; + +#if !defined(MQTT) +char *mqttState(void) { + return mqtt_states[4]; +} +#else #include #include "cgi.h" #include "config.h" @@ -7,9 +16,11 @@ #include "mqtt_client.h" #include "cgimqtt.h" -static char *mqtt_states[] = { - "disconnected", "reconnecting", "connecting", "connected", -}; +#ifdef CGIMQTT_DBG +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) +#else +#define DBG(format, ...) do { } while(0) +#endif char *mqttState(void) { return mqtt_states[mqttClient.connState]; @@ -64,7 +75,6 @@ int ICACHE_FLASH_ATTR cgiMqttGet(HttpdConnData *connData) { return HTTPD_CGI_DONE; } -// Cgi to change choice of pin assignments int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; @@ -119,17 +129,14 @@ int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) { // if server setting changed, we need to "make it so" if (mqtt_server) { -#ifdef CGIMQTT_DBG - os_printf("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable); -#endif + DBG("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable); MQTT_Free(&mqttClient); // safe even if not connected mqtt_client_init(); // if just enable changed we just need to bounce the client - } else if (mqtt_en_chg > 0) { -#ifdef CGIMQTT_DBG - os_printf("MQTT server enable=%d changed\n", flashConfig.mqtt_enable); -#endif + } + else if (mqtt_en_chg > 0) { + DBG("MQTT server enable=%d changed\n", flashConfig.mqtt_enable); if (flashConfig.mqtt_enable && strlen(flashConfig.mqtt_host) > 0) MQTT_Reconnect(&mqttClient); else @@ -147,11 +154,11 @@ int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) { // if SLIP-enable is toggled it gets picked-up immediately by the parser int slip_update = getBoolArg(connData, "slip-enable", &flashConfig.slip_enable); if (slip_update < 0) return HTTPD_CGI_DONE; -#ifdef CGIMQTT_DBG - if (slip_update > 0) os_printf("SLIP-enable changed: %d\n", flashConfig.slip_enable); + if (slip_update > 0) + DBG("SLIP-enable changed: %d\n", flashConfig.slip_enable); + + DBG("Saving config\n"); - os_printf("Saving config\n"); -#endif if (configSave()) { httpdStartResponse(connData, 200); httpdEndHeaders(connData); @@ -173,4 +180,4 @@ int ICACHE_FLASH_ATTR cgiMqtt(HttpdConnData *connData) { return HTTPD_CGI_DONE; } } -#endif // MQTT +#endif diff --git a/esp-link/cgimqtt.h b/esp-link/cgimqtt.h index b720fac..b3e7809 100644 --- a/esp-link/cgimqtt.h +++ b/esp-link/cgimqtt.h @@ -1,10 +1,10 @@ +char *mqttState(void); #ifdef MQTT #ifndef CGIMQTT_H #define CGIMQTT_H #include "httpd.h" int cgiMqtt(HttpdConnData *connData); -char *mqttState(void); #endif // CGIMQTT_H #endif // MQTT diff --git a/esp-link/cgioptiboot.c b/esp-link/cgioptiboot.c index 47cdea2..6d8b71c 100644 --- a/esp-link/cgioptiboot.c +++ b/esp-link/cgioptiboot.c @@ -16,10 +16,8 @@ #define PGM_TIMEOUT 20000 // timeout when sync is achieved, in milliseconds #define PGM_INTERVAL 200 // send sync at this interval in ms when in programming mode -#define OPTIBOOT_DBG -#undef DBG #ifdef OPTIBOOT_DBG -#define DBG(format, ...) os_printf(format, ## __VA_ARGS__) +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) #else #define DBG(format, ...) do { } while(0) #endif diff --git a/esp-link/cgiservices.c b/esp-link/cgiservices.c new file mode 100644 index 0000000..81f7200 --- /dev/null +++ b/esp-link/cgiservices.c @@ -0,0 +1,216 @@ +#include +#include "cgiwifi.h" +#include "cgi.h" +#include "config.h" +#include "syslog.h" +#include "sntp.h" +#include "cgimqtt.h" + +#ifdef CGISERVICES_DBG +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) +#else +#define DBG(format, ...) do { } while(0) +#endif + +char* rst_codes[7] = { + "normal", "wdt reset", "exception", "soft wdt", "restart", "deep sleep", "external", +}; + +char* flash_maps[7] = { + "512KB:256/256", "256KB", "1MB:512/512", "2MB:512/512", "4MB:512/512", + "2MB:1024/1024", "4MB:1024/1024" +}; + +static ETSTimer reassTimer; + +// Cgi to update system info (name/description) +int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData) { + if (connData->conn == NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + int8_t n = getStringArg(connData, "name", flashConfig.hostname, sizeof(flashConfig.hostname)); + int8_t d = getStringArg(connData, "description", flashConfig.sys_descr, sizeof(flashConfig.sys_descr)); + + if (n < 0 || d < 0) return HTTPD_CGI_DONE; // getStringArg has produced an error response + + if (n > 0) { + // schedule hostname change-over + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, configWifiIP, NULL); + os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it + } + + if (configSave()) { + httpdStartResponse(connData, 204); + httpdEndHeaders(connData); + } + else { + httpdStartResponse(connData, 500); + httpdEndHeaders(connData); + httpdSend(connData, "Failed to save config", -1); + } + return HTTPD_CGI_DONE; +} + +// Cgi to return various System information +int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) { + char buff[1024]; + + if (connData->conn == NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + uint8 part_id = system_upgrade_userbin_check(); + uint32_t fid = spi_flash_get_id(); + struct rst_info *rst_info = system_get_rst_info(); + + os_sprintf(buff, + "{ " + "\"name\": \"%s\", " + "\"reset cause\": \"%d=%s\", " + "\"size\": \"%s\", " + "\"id\": \"0x%02lX 0x%04lX\", " + "\"partition\": \"%s\", " + "\"slip\": \"%s\", " + "\"mqtt\": \"%s/%s\", " + "\"baud\": \"%ld\", " + "\"description\": \"%s\"" + " }", + flashConfig.hostname, + rst_info->reason, + rst_codes[rst_info->reason], + flash_maps[system_get_flash_size_map()], + fid & 0xff, (fid & 0xff00) | ((fid >> 16) & 0xff), + part_id ? "user2.bin" : "user1.bin", + flashConfig.slip_enable ? "enabled" : "disabled", + flashConfig.mqtt_enable ? "enabled" : "disabled", + mqttState(), + flashConfig.baud_rate, + flashConfig.sys_descr + ); + + jsonHeader(connData, 200); + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; +} + +void ICACHE_FLASH_ATTR cgiServicesSNTPInit() { + if (flashConfig.sntp_server[0] != '\0') { + sntp_stop(); + if (true == sntp_set_timezone(flashConfig.timezone_offset)) { + sntp_setservername(0, flashConfig.sntp_server); + sntp_init(); + } + DBG("SNTP timesource set to %s with offset %d\n", flashConfig.sntp_server, flashConfig.timezone_offset); + } +} + +int ICACHE_FLASH_ATTR cgiServicesInfo(HttpdConnData *connData) { + char buff[1024]; + + if (connData->conn == NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + os_sprintf(buff, + "{ " + "\"syslog_host\": \"%s\", " + "\"syslog_minheap\": %d, " + "\"syslog_filter\": %d, " + "\"syslog_showtick\": \"%s\", " + "\"syslog_showdate\": \"%s\", " + "\"timezone_offset\": %d, " + "\"sntp_server\": \"%s\", " + "\"mdns_enable\": \"%s\", " + "\"mdns_servername\": \"%s\"" + " }", + flashConfig.syslog_host, + flashConfig.syslog_minheap, + flashConfig.syslog_filter, + flashConfig.syslog_showtick ? "enabled" : "disabled", + flashConfig.syslog_showdate ? "enabled" : "disabled", + flashConfig.timezone_offset, + flashConfig.sntp_server, + flashConfig.mdns_enable ? "enabled" : "disabled", + flashConfig.mdns_servername + ); + + jsonHeader(connData, 200); + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; +} + +int ICACHE_FLASH_ATTR cgiServicesSet(HttpdConnData *connData) { + if (connData->conn == NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + int8_t syslog = 0; + + syslog |= getStringArg(connData, "syslog_host", flashConfig.syslog_host, sizeof(flashConfig.syslog_host)); + if (syslog < 0) return HTTPD_CGI_DONE; + syslog |= getUInt16Arg(connData, "syslog_minheap", &flashConfig.syslog_minheap); + if (syslog < 0) return HTTPD_CGI_DONE; + syslog |= getUInt8Arg(connData, "syslog_filter", &flashConfig.syslog_filter); + if (syslog < 0) return HTTPD_CGI_DONE; + syslog |= getBoolArg(connData, "syslog_showtick", &flashConfig.syslog_showtick); + if (syslog < 0) return HTTPD_CGI_DONE; + syslog |= getBoolArg(connData, "syslog_showdate", &flashConfig.syslog_showdate); + if (syslog < 0) return HTTPD_CGI_DONE; + + if (syslog > 0) { + syslog_init(flashConfig.syslog_host); + } + + int8_t sntp = 0; + sntp |= getInt8Arg(connData, "timezone_offset", &flashConfig.timezone_offset); + if (sntp < 0) return HTTPD_CGI_DONE; + sntp |= getStringArg(connData, "sntp_server", flashConfig.sntp_server, sizeof(flashConfig.sntp_server)); + if (sntp < 0) return HTTPD_CGI_DONE; + + if (sntp > 0) { + cgiServicesSNTPInit(); + } + + int8_t mdns = 0; + mdns |= getBoolArg(connData, "mdns_enable", &flashConfig.mdns_enable); + if (mdns < 0) return HTTPD_CGI_DONE; + + if (mdns > 0) { + if (flashConfig.mdns_enable){ + DBG("Services: MDNS Enabled\n"); + struct ip_info ipconfig; + wifi_get_ip_info(STATION_IF, &ipconfig); + + if (wifiState == wifiGotIP && ipconfig.ip.addr != 0) { + wifiStartMDNS(ipconfig.ip); + } + } + else { + DBG("Services: MDNS Disabled\n"); + espconn_mdns_server_unregister(); + espconn_mdns_close(); + mdns_started = true; + } + } + else { + mdns |= getStringArg(connData, "mdns_servername", flashConfig.mdns_servername, sizeof(flashConfig.mdns_servername)); + if (mdns < 0) return HTTPD_CGI_DONE; + + if (mdns > 0 && mdns_started) { + DBG("Services: MDNS Servername Updated\n"); + espconn_mdns_server_unregister(); + espconn_mdns_close(); + struct ip_info ipconfig; + wifi_get_ip_info(STATION_IF, &ipconfig); + + if (wifiState == wifiGotIP && ipconfig.ip.addr != 0) { + wifiStartMDNS(ipconfig.ip); + } + } + } + + if (configSave()) { + httpdStartResponse(connData, 204); + httpdEndHeaders(connData); + } + else { + httpdStartResponse(connData, 500); + httpdEndHeaders(connData); + httpdSend(connData, "Failed to save config", -1); + } + return HTTPD_CGI_DONE; +} diff --git a/esp-link/cgiservices.h b/esp-link/cgiservices.h new file mode 100644 index 0000000..9c44242 --- /dev/null +++ b/esp-link/cgiservices.h @@ -0,0 +1,16 @@ +#ifndef CGISERVICES_H +#define CGISERVICES_H + +#include "httpd.h" + +int cgiSystemSet(HttpdConnData *connData); +int cgiSystemInfo(HttpdConnData *connData); + +void cgiServicesSNTPInit(); +int cgiServicesInfo(HttpdConnData *connData); +int cgiServicesSet(HttpdConnData *connData); + +extern char* rst_codes[7]; +extern char* flash_maps[7]; + +#endif // CGISERVICES_H diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 1af0051..b83a330 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -13,7 +13,6 @@ Cgi/template routines for the /wifi url. * ---------------------------------------------------------------------------- */ - #include #include "cgiwifi.h" #include "cgi.h" @@ -22,12 +21,12 @@ Cgi/template routines for the /wifi url. #include "log.h" #ifdef CGIWIFI_DBG -#define DBG(format, ...) os_printf(format, ## __VA_ARGS__) +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) #else #define DBG(format, ...) do { } while(0) #endif -static void wifiStartMDNS(struct ip_addr); +bool mdns_started = false; // ===== wifi status change callbacks static WifiStateChangeCb wifi_state_change_cb[4]; @@ -61,28 +60,29 @@ static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) { wifiState = wifiIsConnected; wifiReason = 0; DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, - evt->event_info.connected.channel); + evt->event_info.connected.channel); statusWifiUpdate(wifiState); break; case EVENT_STAMODE_DISCONNECTED: wifiState = wifiIsDisconnected; wifiReason = evt->event_info.disconnected.reason; DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", - evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); + evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); statusWifiUpdate(wifiState); break; case EVENT_STAMODE_AUTHMODE_CHANGE: DBG("Wifi auth mode: %d -> %d\n", - evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); + evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); break; case EVENT_STAMODE_GOT_IP: wifiState = wifiGotIP; wifiReason = 0; DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", - IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), - IP2STR(&evt->event_info.got_ip.gw)); + IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), + IP2STR(&evt->event_info.got_ip.gw)); statusWifiUpdate(wifiState); - wifiStartMDNS(evt->event_info.got_ip.ip); + if (!mdns_started) + wifiStartMDNS(evt->event_info.got_ip.ip); break; case EVENT_SOFTAPMODE_STACONNECTED: DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", @@ -101,8 +101,7 @@ static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) { } } -void ICACHE_FLASH_ATTR -wifiAddStateChangeCb(WifiStateChangeCb cb) { +void ICACHE_FLASH_ATTR wifiAddStateChangeCb(WifiStateChangeCb cb) { for (int i = 0; i < 4; i++) { if (wifi_state_change_cb[i] == cb) return; if (wifi_state_change_cb[i] == NULL) { @@ -113,21 +112,20 @@ wifiAddStateChangeCb(WifiStateChangeCb cb) { DBG("WIFI: max state change cb count exceeded\n"); } -static bool mdns_started = true; -static struct mdns_info mdns_info; - -// cannot allocate the info struct on the stack, it crashes! -static ICACHE_FLASH_ATTR -void wifiStartMDNS(struct ip_addr ip) { - if (!mdns_started) { - os_memset(&mdns_info, 0, sizeof(struct mdns_info)); - mdns_info.host_name = flashConfig.hostname; - mdns_info.server_name = "http", // service name - mdns_info.server_port = 80, // service port - mdns_info.ipAddr = ip.addr, - espconn_mdns_init(&mdns_info); - mdns_started = true; +void ICACHE_FLASH_ATTR wifiStartMDNS(struct ip_addr ip) { + if (flashConfig.mdns_enable) { + struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info)); + mdns_info->host_name = flashConfig.hostname; + mdns_info->server_name = flashConfig.mdns_servername; + mdns_info->server_port = 80; + mdns_info->ipAddr = ip.addr; + espconn_mdns_init(mdns_info); + } + else { + espconn_mdns_server_unregister(); + espconn_mdns_close(); } + mdns_started = true; } // ===== wifi scanning @@ -362,7 +360,7 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { return HTTPD_CGI_DONE; } -static bool parse_ip(char *buff, ip_addr_t *ip_ptr) { +static bool ICACHE_FLASH_ATTR parse_ip(char *buff, ip_addr_t *ip_ptr) { char *next = buff; // where to start parsing next integer int found = 0; // number of integers parsed uint32_t ip = 0; // the ip addres parsed @@ -621,6 +619,7 @@ int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { void ICACHE_FLASH_ATTR wifiInit() { // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky int x = wifi_get_opmode() & 0x3; + x = x; DBG("Wifi init, mode=%s\n", wifiMode[x]); configWifiIP(); diff --git a/esp-link/cgiwifi.h b/esp-link/cgiwifi.h index 37a02d6..e2e98bc 100644 --- a/esp-link/cgiwifi.h +++ b/esp-link/cgiwifi.h @@ -16,7 +16,9 @@ int cgiWiFiSpecial(HttpdConnData *connData); void configWifiIP(); void wifiInit(void); void wifiAddStateChangeCb(WifiStateChangeCb cb); +void wifiStartMDNS(struct ip_addr); extern uint8_t wifiState; +extern bool mdns_started; #endif diff --git a/esp-link/config.c b/esp-link/config.c index f962fdc..9b928cc 100644 --- a/esp-link/config.c +++ b/esp-link/config.c @@ -9,9 +9,9 @@ FlashConfig flashConfig; FlashConfig flashDefault = { - .seq=33, .magic=0, .crc=0, - .reset_pin = MCU_RESET_PIN, .isp_pin = MCU_ISP_PIN, - .conn_led_pin = LED_CONN_PIN, .ser_led_pin = LED_SERIAL_PIN, + .seq = 33, .magic = 0, .crc = 0, + .reset_pin = MCU_RESET_PIN, .isp_pin = MCU_ISP_PIN, + .conn_led_pin = LED_CONN_PIN, .ser_led_pin = LED_SERIAL_PIN, .baud_rate = 115200, .hostname = "esp-link\0", .staticip = 0, @@ -20,20 +20,17 @@ FlashConfig flashDefault = { .log_mode = 0, .swap_uart = 0, .tcp_enable = 1, .rssi_enable = 0, - .api_key = "\0", + .api_key = "", .slip_enable = 0, .mqtt_enable = 0, .mqtt_status_enable = 0, .mqtt_timeout = 2, .mqtt_clean_session = 1, .mqtt_port = 1883, .mqtt_keepalive = 60, - .mqtt_host = "\0", .mqtt_clientid = "\0", + .mqtt_host = "\0", .mqtt_clientid = "\0", .mqtt_username= "\0", .mqtt_password = "\0", .mqtt_status_topic = "\0", - .sys_descr = "\0", - .rx_pullup = 1, - .sntp_server = "\0", - .syslog_host = "\0", - .syslog_minheap= 8192, - .syslog_filter = 7, - .syslog_showtick= 1, - .syslog_showdate= 0, + .sys_descr = "\0", + .rx_pullup = 1, + .sntp_server = "us.pool.ntp.org\0", + .syslog_host = "\0", .syslog_minheap = 8192, .syslog_filter = 7, .syslog_showtick = 1, .syslog_showdate = 0, + .mdns_enable = 1, .mdns_servername = "http\0", .timezone_offset = 0 }; typedef union { diff --git a/esp-link/config.h b/esp-link/config.h index 4ad37b7..59d5f3d 100644 --- a/esp-link/config.h +++ b/esp-link/config.h @@ -21,16 +21,22 @@ typedef struct { mqtt_timeout, // MQTT send timeout mqtt_clean_session; // MQTT clean session uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer - char mqtt_host[32], mqtt_clientid[48], mqtt_username[32], mqtt_password[32]; - char mqtt_status_topic[32]; + char mqtt_host[32], + mqtt_clientid[48], + mqtt_username[32], + mqtt_password[32], + mqtt_status_topic[32]; char sys_descr[129]; // system description int8_t rx_pullup; // internal pull-up on RX pin char sntp_server[32]; char syslog_host[32]; uint16_t syslog_minheap; // min. heap to allow queuing - uint8_t syslog_filter; // min. severity - uint8_t syslog_showtick; // show system tick (µs) - uint8_t syslog_showdate; // populate SYSLOG date field + uint8_t syslog_filter, // min. severity + syslog_showtick, // show system tick (µs) + syslog_showdate; // populate SYSLOG date field + uint8_t mdns_enable; + char mdns_servername[32]; + int8_t timezone_offset; } FlashConfig; extern FlashConfig flashConfig; diff --git a/esp-link/log.c b/esp-link/log.c index d6c245b..821641f 100644 --- a/esp-link/log.c +++ b/esp-link/log.c @@ -7,7 +7,7 @@ #include "log.h" #ifdef LOG_DBG -#define DBG(format, ...) os_printf(format, ## __VA_ARGS__) +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0) #else #define DBG(format, ...) do { } while(0) #endif diff --git a/esp-link/main.c b/esp-link/main.c index 2dc1dfa..09904e1 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -9,7 +9,6 @@ * ---------------------------------------------------------------------------- */ - #include #include "httpd.h" #include "httpdespfs.h" @@ -29,19 +28,15 @@ #include "console.h" #include "config.h" #include "log.h" -#include +#include "gpio.h" #include "syslog.h" -#include "sntp.h" - -static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData); -static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData); +#include "cgiservices.h" -#define NOTICE(format, ...) do { \ +#define NOTICE(format, ...) do { \ LOG_NOTICE(format, ## __VA_ARGS__ ); \ os_printf(format "\n", ## __VA_ARGS__); \ } while ( 0 ) - /* This is the main url->function dispatching data struct. In short, it's a struct with various URLs plus their handlers. The handlers can @@ -62,6 +57,7 @@ HttpdBuiltInUrl builtInUrls[] = { { "/pgm/upload", cgiOptibootData, NULL }, { "/log/text", ajaxLog, NULL }, { "/log/dbg", ajaxLogDbg, NULL }, + { "/log/reset", cgiReset, NULL }, { "/console/reset", ajaxConsoleReset, NULL }, { "/console/baud", ajaxConsoleBaud, NULL }, { "/console/text", ajaxConsole, NULL }, @@ -78,11 +74,12 @@ HttpdBuiltInUrl builtInUrls[] = { { "/wifi/special", cgiWiFiSpecial, NULL }, { "/system/info", cgiSystemInfo, NULL }, { "/system/update", cgiSystemSet, NULL }, + { "/services/info", cgiServicesInfo, NULL }, + { "/services/update", cgiServicesSet, NULL }, { "/pins", cgiPins, NULL }, #ifdef MQTT { "/mqtt", cgiMqtt, NULL }, -#endif - +#endif { "*", cgiEspFsHook, NULL }, //Catch-all cgi function for the filesystem { NULL, NULL, NULL } }; @@ -102,105 +99,6 @@ char* esp_link_version = VERS_STR(VERSION); // address of espfs binary blob extern uint32_t _binary_espfs_img_start; -static char *rst_codes[] = { - "normal", "wdt reset", "exception", "soft wdt", "restart", "deep sleep", "external", -}; -static char *flash_maps[] = { - "512KB:256/256", "256KB", "1MB:512/512", "2MB:512/512", "4MB:512/512", - "2MB:1024/1024", "4MB:1024/1024" -}; - -// enable SNTP client... -static void ICACHE_FLASH_ATTR enableSNTP() { - if (flashConfig.sntp_server[0]) { - NOTICE("SNTP timesource set to %s", flashConfig.sntp_server); - sntp_stop(); - sntp_setservername(0, flashConfig.sntp_server); - // sntp_set_timezone(flashConfig.timezone); /* stay with GMT... */ - sntp_init(); - } -} - -// Cgi to return various System information -static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) { - char buff[1024]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - - uint8 part_id = system_upgrade_userbin_check(); - uint32_t fid = spi_flash_get_id(); - struct rst_info *rst_info = system_get_rst_info(); - - os_sprintf(buff, "{\"name\": \"%s\", \"reset cause\": \"%d=%s\", " - "\"size\": \"%s\"," "\"id\": \"0x%02lX 0x%04lX\"," "\"partition\": \"%s\"," - "\"slip\": \"%s\"," "\"mqtt\": \"%s/%s\"," "\"baud\": \"%ld\"," - "\"description\": \"%s\"," - "\"syslog\": \"%s\"," - "\"sntp\": \"%s\" " - "}", - flashConfig.hostname, rst_info->reason, rst_codes[rst_info->reason], - flash_maps[system_get_flash_size_map()], fid & 0xff, (fid&0xff00)|((fid>>16)&0xff), - part_id ? "user2.bin" : "user1.bin", - flashConfig.slip_enable ? "enabled" : "disabled", - flashConfig.mqtt_enable ? "enabled" : "disabled", - mqttState(), flashConfig.baud_rate, flashConfig.sys_descr, - flashConfig.syslog_host, - flashConfig.sntp_server - ); - - jsonHeader(connData, 200); - httpdSend(connData, buff, -1); - return HTTPD_CGI_DONE; -} - -static ETSTimer reassTimer; - -// Cgi to update system info (name/description) -static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - - int8_t n = getStringArg(connData, "name", flashConfig.hostname, sizeof(flashConfig.hostname)); - int8_t d = getStringArg(connData, "description", flashConfig.sys_descr, sizeof(flashConfig.sys_descr)); - int8_t t = getStringArg(connData, "sntp", flashConfig.sntp_server, sizeof(flashConfig.sntp_server)); - int8_t l = getStringArg(connData, "syslog", flashConfig.syslog_host, sizeof(flashConfig.syslog_host)); - if (n < 0 || d < 0 || t < 0 || l < 0) return HTTPD_CGI_DONE; // getStringArg has produced an error response - - // set defaults for syslog server - // we also should add a config or services web page... - if (l > 0) { - // set defaults for syslog server - syslog_init(flashConfig.syslog_host); - flashConfig.syslog_minheap= 8192; - flashConfig.syslog_filter = SYSLOG_PRIO_DEBUG; - flashConfig.syslog_showtick= 1; // show ESP µs Ticker in log message - flashConfig.syslog_showdate= 0; // Synology does a log rotate if timestamp is in the past, so we simply don't send it - os_printf("flashConfig: syslog: %s, minheap: %d, filter: %d, showtick: %d, showdate: %d\n", - flashConfig.syslog_host, flashConfig.syslog_minheap, flashConfig.syslog_filter, flashConfig.syslog_showtick, flashConfig.syslog_showdate); - } - - // (re)start SNTP client if server setting is changed - if (t > 0) { - enableSNTP(); - } - - if (n > 0) { - // schedule hostname change-over - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, configWifiIP, NULL); - os_timer_arm(&reassTimer, 1000, 0); // 1 second for the response of this request to make it - } - - if (configSave()) { - httpdStartResponse(connData, 204); - httpdEndHeaders(connData); - } else { - httpdStartResponse(connData, 500); - httpdEndHeaders(connData); - httpdSend(connData, "Failed to save config", -1); - } - return HTTPD_CGI_DONE; -} - extern void app_init(void); extern void mqtt_client_init(void); @@ -212,7 +110,7 @@ void user_rf_pre_init(void) { // Main routine to initialize esp-link. void user_init(void) { // get the flash config so we know how to init things - //configWipe(); // uncomment to reset the config for testing purposes +// configWipe(); // uncomment to reset the config for testing purposes bool restoreOk = configRestore(); // init gpio pin registers gpio_init(); @@ -278,7 +176,7 @@ void user_init(void) { fid & 0xff, (fid&0xff00)|((fid>>16)&0xff)); NOTICE("** esp-link ready"); - enableSNTP(); + cgiServicesSNTPInit(); #ifdef MQTT NOTICE("initializing MQTT"); diff --git a/esp-link/mqtt_client.c b/esp-link/mqtt_client.c index 3969530..12b9a8d 100644 --- a/esp-link/mqtt_client.c +++ b/esp-link/mqtt_client.c @@ -5,18 +5,13 @@ #include "mqtt.h" #ifdef MQTTCLIENT_DBG -#define DBG_MQTTCLIENT(format, ...) os_printf(format, ## __VA_ARGS__) +#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__) } while(0) #else -#define DBG_MQTTCLIENT(format, ...) do { } while(0) +#define DBG(format, ...) do { } while(0) #endif MQTT_Client mqttClient; // main mqtt client used by esp-link -#ifdef BRUNNELS -char* statusTopicStr; -static char* onlineMsgStr; -#endif - static MqttCallback connected_cb; static MqttCallback disconnected_cb; static MqttCallback published_cb; @@ -24,12 +19,9 @@ static MqttDataCallback data_cb; void ICACHE_FLASH_ATTR mqttConnectedCb(uint32_t *args) { - DBG_MQTTCLIENT("MQTT Client: Connected\n"); + DBG("MQTT Client: Connected\n"); //MQTT_Client* client = (MQTT_Client*)args; //MQTT_Subscribe(client, "system/time", 0); // handy for testing -#ifdef BRUNNELS - MQTT_Publish(client, "announce/all", onlineMsgStr, 0, 0); -#endif if (connected_cb) connected_cb(args); } @@ -37,7 +29,7 @@ mqttConnectedCb(uint32_t *args) { void ICACHE_FLASH_ATTR mqttDisconnectedCb(uint32_t *args) { // MQTT_Client* client = (MQTT_Client*)args; - DBG_MQTTCLIENT("MQTT Client: Disconnected\n"); + DBG("MQTT Client: Disconnected\n"); if (disconnected_cb) disconnected_cb(args); } @@ -45,7 +37,7 @@ mqttDisconnectedCb(uint32_t *args) { void ICACHE_FLASH_ATTR mqttPublishedCb(uint32_t *args) { // MQTT_Client* client = (MQTT_Client*)args; - DBG_MQTTCLIENT("MQTT Client: Published\n"); + DBG("MQTT Client: Published\n"); if (published_cb) published_cb(args); } @@ -93,29 +85,6 @@ mqtt_client_init() flashConfig.mqtt_clientid, flashConfig.mqtt_username, flashConfig.mqtt_password, flashConfig.mqtt_keepalive); -// removed client_id concat for now until a better solution is devised -// statusTopicStr = (char*)os_zalloc(strlen(flashConfig.mqtt_clientid) + strlen(flashConfig.mqtt_status_topic) + 2); -// os_strcpy(statusTopicStr, flashConfig.mqtt_clientid); -// os_strcat(statusTopicStr, "/"); - -#ifdef BRUNNELS - char* onlineMsg = " is online"; - onlineMsgStr = (char*)os_zalloc(strlen(flashConfig.mqtt_clientid) + strlen(onlineMsg) + 1); - os_strcpy(onlineMsgStr, flashConfig.mqtt_clientid); - os_strcat(onlineMsgStr, onlineMsg); - - char* offlineMsg = " is offline"; - char* offlineMsgStr = (char*)os_zalloc(strlen(flashConfig.mqtt_clientid) + strlen(offlineMsg) + 1); - os_strcpy(offlineMsgStr, flashConfig.mqtt_clientid); - os_strcat(offlineMsgStr, offlineMsg); - - char* lwt = "/lwt"; - char *lwtMsgStr = (char*)os_zalloc(strlen(flashConfig.mqtt_clientid) + strlen(lwt) + 1); - os_strcpy(lwtMsgStr, flashConfig.mqtt_clientid); - os_strcat(lwtMsgStr, lwt); - MQTT_InitLWT(&mqttClient, lwtMsgStr, offlineMsg, 0, 0); -#endif - MQTT_OnConnected(&mqttClient, mqttConnectedCb); MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); MQTT_OnPublished(&mqttClient, mqttPublishedCb); diff --git a/html/console.html b/html/console.html index e638af4..d84da72 100644 --- a/html/console.html +++ b/html/console.html @@ -5,8 +5,9 @@

- Reset µC -   Baud: + Reset µC +   Clear Log +   Baud: - -   Fmt: 8N1 +   Fmt: 8N1

Console
@@ -85,6 +73,12 @@ ); }); + $("#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); } diff --git a/html/console.js b/html/console.js index e85d6d7..58398ad 100644 --- a/html/console.js +++ b/html/console.js @@ -21,7 +21,7 @@ function updateText(resp) { var delay = 3000; if (resp != null && resp.len > 0) { - console.log("updateText got", resp.len, "chars at", resp.start); +// console.log("updateText got", resp.len, "chars at", resp.start); var isScrolledToBottom = el.scrollHeight - el.clientHeight <= el.scrollTop + 1; //console.log("isScrolledToBottom="+isScrolledToBottom, "scrollHeight="+el.scrollHeight, // "clientHeight="+el.clientHeight, "scrollTop="+el.scrollTop, diff --git a/html/home.html b/html/home.html index 1341903..2413566 100644 --- a/html/home.html +++ b/html/home.html @@ -22,31 +22,17 @@
Network SSID - Wifi status - Wifi address + WiFI status + WiFI address SLIP status MQTT status Serial baud - Syslog Server -
- - - -
- - SNTP Server -
- - - -
-

Info

The JeeLabs esp-link firmware bridges the ESP8266 - serial port to Wifi and can + serial port to WiFI and can program microcontrollers over the serial port, in particular Arduinos, AVRs, and NXP's LPC800 and other ARM processors. Typical avrdude command line to program an Arduino:

@@ -73,20 +59,21 @@