Merge pull request #72 from brunnels/master

Thank you!
pull/91/head
Thorsten von Eicken 9 years ago
commit 60d3dbfa33
  1. 59
      Makefile
  2. 14
      WINDOWS.md
  3. 55
      cmd/cmd.c
  4. 22
      cmd/handlers.c
  5. 18
      esp-link.vcxproj
  6. 103
      esp-link/cgi.c
  7. 14
      esp-link/cgi.h
  8. 268
      esp-link/cgiflash.c
  9. 1
      esp-link/cgiflash.h
  10. 41
      esp-link/cgimqtt.c
  11. 2
      esp-link/cgimqtt.h
  12. 4
      esp-link/cgioptiboot.c
  13. 216
      esp-link/cgiservices.c
  14. 16
      esp-link/cgiservices.h
  15. 51
      esp-link/cgiwifi.c
  16. 2
      esp-link/cgiwifi.h
  17. 23
      esp-link/config.c
  18. 16
      esp-link/config.h
  19. 2
      esp-link/log.c
  20. 118
      esp-link/main.c
  21. 41
      esp-link/mqtt_client.c
  22. 26
      html/console.html
  23. 2
      html/console.js
  24. 35
      html/home.html
  25. 15
      html/log.html
  26. 2
      html/mqtt.html
  27. 2
      html/mqtt.js
  28. 106
      html/services.html
  29. 77
      html/services.js
  30. 12
      html/ui.js
  31. 24
      html/wifi/wifi.html
  32. 2
      html/wifi/wifi.js
  33. 61
      httpd/httpd.c
  34. 6
      include/user_config.h
  35. 38
      mqtt/mqtt_cmd.c
  36. 24
      mqtt/pktbuf.c
  37. 24
      serial/slip.c
  38. 80
      syslog/syslog.c
  39. 2
      syslog/syslog.h

@ -29,7 +29,7 @@ XTENSA_TOOLS_ROOT ?= $(abspath ../esp-open-sdk/xtensa-lx106-elf/bin)/
# Base directory of the ESP8266 SDK package, absolute # Base directory of the ESP8266 SDK package, absolute
# Typically you'll download from Espressif's BBS, http://bbs.espressif.com/viewforum.php?f=5 # 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 # 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
@ -38,29 +38,11 @@ ESPTOOL ?= $(abspath ../esp-open-sdk/esptool/esptool.py)
ESPPORT ?= /dev/ttyUSB0 ESPPORT ?= /dev/ttyUSB0
ESPBAUD ?= 460800 ESPBAUD ?= 460800
# --------------- chipset configuration --------------- # 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!
# Pick your flash size: "512KB" or "4MB" # This happens on a full serial flash and avoids having to hunt for the AP...
FLASH_SIZE ?= 4MB # STA_SSID ?=
# STA_PASS ?=
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
# hostname or IP address for wifi flashing # hostname or IP address for wifi flashing
ESP_HOSTNAME ?= esp-link ESP_HOSTNAME ?= esp-link
@ -120,6 +102,25 @@ YUI_COMPRESSOR ?= yuicompressor-2.4.8.jar
# -------------- End of config options ------------- # -------------- 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)/ HTML_PATH = $(abspath ./html)/
WIFI_PATH = $(HTML_PATH)wifi/ WIFI_PATH = $(HTML_PATH)wifi/
@ -215,7 +216,7 @@ MODULES += $(foreach sdir,$(LIBRARIES_DIR),$(wildcard $(sdir)/*))
EXTRA_INCDIR = include . EXTRA_INCDIR = include .
# libraries used in this project, mainly provided by the SDK # libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal phy pp net80211 wpa main lwip LIBS = c gcc hal phy pp net80211 wpa main lwip crypto
# compiler flags using during compilation of source files # compiler flags using during compilation of source files
CFLAGS += -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ CFLAGS += -Os -ggdb -std=c99 -Werror -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 .rodata -O binary $(USER1_OUT) eagle.app.v6.rodata.bin
$(Q) $(OBJCP) --only-section .irom0.text -O binary $(USER1_OUT) eagle.app.v6.irom0text.bin $(Q) $(OBJCP) --only-section .irom0.text -O binary $(USER1_OUT) eagle.app.v6.irom0text.bin
ls -ls eagle*bin 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) rm -f eagle.app.v6.*.bin
$(Q) mv eagle.app.flash.bin $@ $(Q) mv eagle.app.flash.bin $@
@echo "** user1.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available" @echo "** user1.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available"
@ -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 .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 .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) $(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) rm -f eagle.app.v6.*.bin
$(Q) mv eagle.app.flash.bin $@ $(Q) mv eagle.app.flash.bin $@
$(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
@ -405,6 +406,10 @@ ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) for file in `find html_compressed -type f -name "*.css"`; do \ $(Q) for file in `find html_compressed -type f -name "*.css"`; do \
java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \ java -jar tools/$(YUI_COMPRESSOR) $$file -o $$file; \
done done
else
$(Q) cp -r html/head- html_compressed;
$(Q) cp -r html/*.html html_compressed;
$(Q) cp -r html/wifi/*.html html_compressed/wifi;
endif endif
ifeq (,$(findstring mqtt,$(MODULES))) ifeq (,$(findstring mqtt,$(MODULES)))
$(Q) rm -rf html_compressed/mqtt.html $(Q) rm -rf html_compressed/mqtt.html

@ -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

@ -7,6 +7,19 @@
#include "crc16.h" #include "crc16.h"
#include "uart.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[]; extern const CmdList commands[];
//===== ESP -> Serial responses //===== ESP -> Serial responses
@ -82,39 +95,25 @@ CMD_Exec(const CmdList *scp, CmdPacket *packet) {
// Iterate through the command table and call the appropriate function // Iterate through the command table and call the appropriate function
while (scp->sc_function != NULL) { while (scp->sc_function != NULL) {
if(scp->sc_name == packet->cmd) { 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 // call command function
uint32_t ret = scp->sc_function(packet); uint32_t ret = scp->sc_function(packet);
// if requestor asked for a response, send it // if requestor asked for a response, send it
if (packet->_return){ if (packet->_return){
#ifdef CMD_DBG DBG("CMD_Exec: Response: 0x%lx, cmd: %d\r\n", ret, packet->cmd);
os_printf("CMD: Response: 0x%lx, cmd: %d\r\n", ret, packet->cmd);
#endif
crc = CMD_ResponseStart(packet->cmd, 0, ret, 0); crc = CMD_ResponseStart(packet->cmd, 0, ret, 0);
CMD_ResponseEnd(crc); CMD_ResponseEnd(crc);
} else { } else {
#ifdef CMD_DBG DBG("CMD_Exec: no response (%lu)\n", packet->_return);
os_printf("CMD: no response (%lu)\n", packet->_return);
#endif
} }
return ret; return ret;
} }
scp++; scp++;
} }
#ifdef CMD_DBG DBG("CMD_Exec: cmd=%d not found\n", packet->cmd);
os_printf("CMD: cmd=%d not found\n", packet->cmd);
#endif
return 0; 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 // Parse a packet and print info about it
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
CMD_parse_packet(uint8_t *buf, short len) { CMD_parse_packet(uint8_t *buf, short len) {
@ -125,18 +124,22 @@ CMD_parse_packet(uint8_t *buf, short len) {
CmdPacket *packet = (CmdPacket*)buf; CmdPacket *packet = (CmdPacket*)buf;
uint8_t *data_ptr = (uint8_t*)&packet->args; uint8_t *data_ptr = (uint8_t*)&packet->args;
uint8_t *data_limit = data_ptr+len; uint8_t *data_limit = data_ptr+len;
#ifdef CMD_DBG
uint16_t argn = 0; DBG("CMD_parse_packet: cmd=%d(%s) argc=%d cb=%p ret=%lu\n",
os_printf("CMD: cmd=%d(%s) argc=%d cb=%p ret=%lu\n", packet->cmd,
packet->cmd, cmd_names[packet->cmd], packet->argc, (void *)packet->callback, packet->_return); cmd_names[packet->cmd],
#endif packet->argc,
(void *)packet->callback,
packet->_return
);
#if 0 #if 0
// print out arguments // print out arguments
uint16_t argn = 0;
uint16_t argc = packet->argc; uint16_t argc = packet->argc;
while (data_ptr+2 < data_limit && argc--) { while (data_ptr+2 < data_limit && argc--) {
short l = *(uint16_t*)data_ptr; 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; data_ptr += 2;
while (data_ptr < data_limit && l--) { while (data_ptr < data_limit && l--) {
os_printf(" %02X", *data_ptr++); os_printf(" %02X", *data_ptr++);
@ -148,9 +151,7 @@ CMD_parse_packet(uint8_t *buf, short len) {
if (data_ptr <= data_limit) { if (data_ptr <= data_limit) {
CMD_Exec(commands, packet); CMD_Exec(commands, packet);
} else { } else {
#ifdef CMD_DBG DBG("CMD_parse_packet: packet length overrun, parsing arg %d\n", packet->argc);
os_printf("CMD: packet length overrun, parsing arg %d\n", argn-1);
#endif
} }
} }

@ -12,6 +12,12 @@
#include <rest.h> #include <rest.h>
#endif #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_Null(CmdPacket *cmd);
static uint32_t CMD_IsReady(CmdPacket *cmd); static uint32_t CMD_IsReady(CmdPacket *cmd);
static uint32_t CMD_Reset(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)); os_strncpy(callbacks[i].name, name, sizeof(callbacks[i].name));
callbacks[i].name[CMD_CBNLEN-1] = 0; // strncpy doesn't null terminate callbacks[i].name[CMD_CBNLEN-1] = 0; // strncpy doesn't null terminate
callbacks[i].callback = cb; callbacks[i].callback = cb;
#ifdef CMD_DBG DBG("CMD_AddCb: cb %s added at index %d\n", callbacks[i].name, i);
os_printf("CMD_AddCb: cb %s added at index %d\n", callbacks[i].name, i);
#endif
return 1; return 1;
} }
} }
@ -97,9 +101,7 @@ CMD_GetCbByName(char* name) {
// (void *)callbacks[i].callback); // (void *)callbacks[i].callback);
// if callback doesn't exist or it's null // if callback doesn't exist or it's null
if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0) { if (os_strncmp(callbacks[i].name, name, CMD_CBNLEN) == 0) {
#ifdef CMD_DBG DBG("CMD_GetCbByName: cb %s found at index %d\n", name, i);
os_printf("CMD_GetCbByName: cb %s found at index %d\n", name, i);
#endif
return &callbacks[i]; return &callbacks[i];
} }
} }
@ -111,9 +113,7 @@ CMD_GetCbByName(char* name) {
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
CMD_WifiCb(uint8_t wifiStatus) { CMD_WifiCb(uint8_t wifiStatus) {
if (wifiStatus != lastWifiStatus){ if (wifiStatus != lastWifiStatus){
#ifdef CMD_DBG DBG("CMD_WifiCb: wifiStatus=%d\n", wifiStatus);
os_printf("CMD_WifiCb: wifiStatus=%d\n", wifiStatus);
#endif
lastWifiStatus = wifiStatus; lastWifiStatus = wifiStatus;
cmdCallback *wifiCb = CMD_GetCbByName("wifiCb"); cmdCallback *wifiCb = CMD_GetCbByName("wifiCb");
if ((uint32_t)wifiCb->callback != -1) { 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 (len > 15) return 0; // max size of name is 15 characters
if (CMD_PopArg(&req, (uint8_t *)name, len)) return 0; if (CMD_PopArg(&req, (uint8_t *)name, len)) return 0;
name[len] = 0; name[len] = 0;
#ifdef CMD_DBG DBG("CMD_AddCallback: name=%s\n", name);
os_printf("CMD_AddCallback: name=%s\n", name);
#endif
return CMD_AddCb(name, (uint32_t)cmd->callback); // save the sensor callback return CMD_AddCb(name, (uint32_t)cmd->callback); // save the sensor callback
} }

@ -16,7 +16,9 @@
<ClCompile Include="esp-link\cgi.c" /> <ClCompile Include="esp-link\cgi.c" />
<ClCompile Include="esp-link\cgiflash.c" /> <ClCompile Include="esp-link\cgiflash.c" />
<ClCompile Include="esp-link\cgimqtt.c" /> <ClCompile Include="esp-link\cgimqtt.c" />
<ClCompile Include="esp-link\cgioptiboot.c" />
<ClCompile Include="esp-link\cgipins.c" /> <ClCompile Include="esp-link\cgipins.c" />
<ClCompile Include="esp-link\cgiservices.c" />
<ClCompile Include="esp-link\cgitcp.c" /> <ClCompile Include="esp-link\cgitcp.c" />
<ClCompile Include="esp-link\cgiwifi.c" /> <ClCompile Include="esp-link\cgiwifi.c" />
<ClCompile Include="esp-link\config.c" /> <ClCompile Include="esp-link\config.c" />
@ -24,6 +26,7 @@
<ClCompile Include="esp-link\main.c" /> <ClCompile Include="esp-link\main.c" />
<ClCompile Include="esp-link\mqtt_client.c" /> <ClCompile Include="esp-link\mqtt_client.c" />
<ClCompile Include="esp-link\status.c" /> <ClCompile Include="esp-link\status.c" />
<ClCompile Include="esp-link\task.c" />
<ClCompile Include="espfs\espfs.c" /> <ClCompile Include="espfs\espfs.c" />
<ClCompile Include="espfs\mkespfsimage\main.c" /> <ClCompile Include="espfs\mkespfsimage\main.c" />
<ClCompile Include="espfs\mkespfsimage\mman-win32\mman.c" /> <ClCompile Include="espfs\mkespfsimage\mman-win32\mman.c" />
@ -43,6 +46,7 @@
<ClCompile Include="serial\serled.c" /> <ClCompile Include="serial\serled.c" />
<ClCompile Include="serial\slip.c" /> <ClCompile Include="serial\slip.c" />
<ClCompile Include="serial\uart.c" /> <ClCompile Include="serial\uart.c" />
<ClCompile Include="syslog\syslog.c" />
<ClCompile Include="user\user_main.c" /> <ClCompile Include="user\user_main.c" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -50,13 +54,17 @@
<ClInclude Include="esp-link\cgi.h" /> <ClInclude Include="esp-link\cgi.h" />
<ClInclude Include="esp-link\cgiflash.h" /> <ClInclude Include="esp-link\cgiflash.h" />
<ClInclude Include="esp-link\cgimqtt.h" /> <ClInclude Include="esp-link\cgimqtt.h" />
<ClInclude Include="esp-link\cgioptiboot.h" />
<ClInclude Include="esp-link\cgipins.h" /> <ClInclude Include="esp-link\cgipins.h" />
<ClInclude Include="esp-link\cgiservices.h" />
<ClInclude Include="esp-link\cgitcp.h" /> <ClInclude Include="esp-link\cgitcp.h" />
<ClInclude Include="esp-link\cgiwifi.h" /> <ClInclude Include="esp-link\cgiwifi.h" />
<ClInclude Include="esp-link\config.h" /> <ClInclude Include="esp-link\config.h" />
<ClInclude Include="esp-link\log.h" /> <ClInclude Include="esp-link\log.h" />
<ClInclude Include="esp-link\mqtt_client.h" /> <ClInclude Include="esp-link\mqtt_client.h" />
<ClInclude Include="esp-link\status.h" /> <ClInclude Include="esp-link\status.h" />
<ClInclude Include="esp-link\stk500.h" />
<ClInclude Include="esp-link\task.h" />
<ClInclude Include="espfs\espfs.h" /> <ClInclude Include="espfs\espfs.h" />
<ClInclude Include="espfs\espfsformat.h" /> <ClInclude Include="espfs\espfsformat.h" />
<ClInclude Include="espfs\mkespfsimage\mman-win32\mman.h" /> <ClInclude Include="espfs\mkespfsimage\mman-win32\mman.h" />
@ -79,8 +87,11 @@
<ClInclude Include="serial\serled.h" /> <ClInclude Include="serial\serled.h" />
<ClInclude Include="serial\slip.h" /> <ClInclude Include="serial\slip.h" />
<ClInclude Include="serial\uart.h" /> <ClInclude Include="serial\uart.h" />
<ClInclude Include="syslog\syslog.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include=".gitignore" />
<None Include="avrflash" />
<None Include="BOARDS.md" /> <None Include="BOARDS.md" />
<None Include="espmake.cmd" /> <None Include="espmake.cmd" />
<None Include="FLASH.md" /> <None Include="FLASH.md" />
@ -93,6 +104,8 @@
<None Include="html\mqtt.html" /> <None Include="html\mqtt.html" />
<None Include="html\mqtt.js" /> <None Include="html\mqtt.js" />
<None Include="html\pure.css" /> <None Include="html\pure.css" />
<None Include="html\services.html" />
<None Include="html\services.js" />
<None Include="html\style.css" /> <None Include="html\style.css" />
<None Include="html\ui.js" /> <None Include="html\ui.js" />
<None Include="html\wifi\wifi.html" /> <None Include="html\wifi\wifi.html" />
@ -100,6 +113,7 @@
<None Include="Makefile" /> <None Include="Makefile" />
<None Include="README.md" /> <None Include="README.md" />
<None Include="wiflash" /> <None Include="wiflash" />
<None Include="WINDOWS.md" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Text Include="esp-link.log" /> <Text Include="esp-link.log" />
@ -125,8 +139,8 @@
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup> <PropertyGroup>
<NMakeOutput /> <NMakeOutput />
<NMakePreprocessorDefinitions>__ets__;_STDINT_H;ICACHE_FLASH;__MINGW32__;__WIN32__</NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>__ets__;_STDINT_H;ICACHE_FLASH;__MINGW32__;__WIN32__;MQTT;REST;SYSLOG;FIRMWARE_SIZE</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>.\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</NMakeIncludeSearchPath> <NMakeIncludeSearchPath>.\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</NMakeIncludeSearchPath>
<ExecutablePath /> <ExecutablePath />
<ReferencePath /> <ReferencePath />
<LibraryPath /> <LibraryPath />

@ -13,40 +13,39 @@ Some random cgi routines.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#include <esp8266.h> #include <esp8266.h>
#include "cgi.h" #include "cgi.h"
#include "config.h" #include "config.h"
void ICACHE_FLASH_ATTR #ifdef CGI_DBG
noCacheHeaders(HttpdConnData *connData, int code) { #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); httpdStartResponse(connData, code);
httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate"); httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate");
httpdHeader(connData, "Pragma", "no-cache"); httpdHeader(connData, "Pragma", "no-cache");
httpdHeader(connData, "Expires", "0"); httpdHeader(connData, "Expires", "0");
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR jsonHeader(HttpdConnData *connData, int code) {
jsonHeader(HttpdConnData *connData, int code) {
noCacheHeaders(connData, code); noCacheHeaders(connData, code);
httpdHeader(connData, "Content-Type", "application/json"); httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData); httpdEndHeaders(connData);
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR errorResponse(HttpdConnData *connData, int code, char *message) {
errorResponse(HttpdConnData *connData, int code, char *message) {
noCacheHeaders(connData, code); noCacheHeaders(connData, code);
httpdEndHeaders(connData); httpdEndHeaders(connData);
httpdSend(connData, message, -1); httpdSend(connData, message, -1);
#ifdef CGI_DBG DBG("HTTP %d error response: \"%s\"\n", code, message);
os_printf("HTTP %d error response: \"%s\"\n", code, message);
#endif
} }
// look for the HTTP arg 'name' and store it at 'config' with max length 'max_len' (incl // 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 // terminating zero), returns -1 on error, 0 if not found, 1 if found and OK
int8_t ICACHE_FLASH_ATTR int8_t ICACHE_FLASH_ATTR getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) {
getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) {
char buff[128]; char buff[128];
int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff));
if (len < 0) return 0; // not found, skip 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); errorResponse(connData, 400, buff);
return -1; return -1;
} }
strcpy(config, buff); os_strcpy(config, buff);
return 1; return 1;
} }
// look for the HTTP arg 'name' and store it at 'config' as an 8-bit integer // 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 // returns -1 on error, 0 if not found, 1 if found and OK
int8_t ICACHE_FLASH_ATTR int8_t ICACHE_FLASH_ATTR getInt8Arg(HttpdConnData *connData, char *name, int8_t *config) {
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]; char buff[16];
int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff));
if (len < 0) return 0; // not found, skip if (len < 0) return 0; // not found, skip
int m = atoi(buff); 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); os_sprintf(buff, "Value for %s out of range", name);
errorResponse(connData, 400, buff); errorResponse(connData, 400, buff);
return -1; return -1;
@ -76,27 +106,27 @@ getInt8Arg(HttpdConnData *connData, char *name, int8_t *config) {
return 1; return 1;
} }
int8_t ICACHE_FLASH_ATTR int8_t ICACHE_FLASH_ATTR getBoolArg(HttpdConnData *connData, char *name, bool *config) {
getBoolArg(HttpdConnData *connData, char *name, bool*config) { char buff[16];
char buff[64];
int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff));
if (len < 0) return 0; // not found, skip 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; *config = true;
return 1; return 1;
} }
if (strcmp(buff, "0") == 0 || strcmp(buff, "false") == 0) {
if (os_strcmp(buff, "0") == 0 || os_strcmp(buff, "false") == 0) {
*config = false; *config = false;
return 1; return 1;
} }
os_sprintf(buff, "Invalid value for %s", name); os_sprintf(buff, "Invalid value for %s", name);
errorResponse(connData, 400, buff); errorResponse(connData, 400, buff);
return -1; return -1;
} }
uint8_t ICACHE_FLASH_ATTR uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const char* str, void *ip){
UTILS_StrToIP(const char* str, void *ip){
/* The count of the number of bytes processed. */ /* The count of the number of bytes processed. */
int i; int i;
/* A pointer to the next digit to process. */ /* A pointer to the next digit to process. */
@ -133,8 +163,8 @@ UTILS_StrToIP(const char* str, void *ip){
return 1; return 1;
} }
#define TOKEN(x) (os_strcmp(token, x) == 0)
#if 0 #if 0
#define TOKEN(x) (os_strcmp(token, x) == 0)
// Handle system information variables and print their value, returns the number of // Handle system information variables and print their value, returns the number of
// characters appended to buff // characters appended to buff
int ICACHE_FLASH_ATTR printGlobalInfo(char *buff, int buflen, char *token) { int ICACHE_FLASH_ATTR printGlobalInfo(char *buff, int buflen, char *token) {
@ -173,15 +203,22 @@ int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) {
name[12] = 0; name[12] = 0;
// construct json response // construct json response
os_sprintf(buff, os_sprintf(buff,
"{\"menu\": [\"Home\", \"/home.html\", " "{ "
"\"Wifi\", \"/wifi/wifi.html\"," "\"menu\": [ "
"\"\xC2\xB5" "C Console\", \"/console.html\", " "\"Home\", \"/home.html\", "
"\"WiFI\", \"/wifi/wifi.html\", "
"\"&#xb5;C Console\", \"/console.html\", "
"\"Services\", \"/services.html\", "
#ifdef MQTT #ifdef MQTT
"\"REST/MQTT\", \"/mqtt.html\"," "\"REST/MQTT\", \"/mqtt.html\", "
#endif #endif
"\"Debug log\", \"/log.html\" ],\n" "\"Debug log\", \"/log.html\""
" \"version\": \"%s\"," " ], "
"\"name\":\"%s\"}", esp_link_version, name); "\"version\": \"%s\", "
"\"name\": \"%s\""
" }",
esp_link_version, name);
httpdSend(connData, buff, -1); httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }

@ -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 // '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); 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 // 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); 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', // 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 // 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); int cgiMenu(HttpdConnData *connData);
uint8_t UTILS_StrToIP(const char* str, void *ip); uint8_t UTILS_StrToIP(const char *str, void *ip);
#endif #endif

@ -18,20 +18,25 @@ Some flash handling cgi routines. Used for reading the existing flash and updati
#include <osapi.h> #include <osapi.h>
#include "cgi.h" #include "cgi.h"
#include "cgiflash.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... // Check that the header of the firmware blob looks like actual firmware...
static char* ICACHE_FLASH_ATTR check_header(void *buf) { static char* ICACHE_FLASH_ATTR check_header(void *buf) {
uint8_t *cd = (uint8_t *)buf; uint8_t *cd = (uint8_t *)buf;
#ifdef CGIFLASH_DBG #ifdef CGIFLASH_DBG
uint32_t *buf32 = buf; uint32_t *buf32 = buf;
os_printf("%p: %08lX %08lX %08lX %08lX\n", buf, buf32[0], buf32[1], buf32[2], buf32[3]); os_printf("%p: %08lX %08lX %08lX %08lX\n", buf, buf32[0], buf32[1], buf32[2], buf32[3]);
#endif #endif
if (cd[0] != 0xEA) return "IROM magic missing"; if (cd[0] != 0xEA) return "IROM magic missing";
if (cd[1] != 4 || cd[2] > 3 || (cd[3]>>4) > 6) return "bad flash header"; 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 (((uint16_t *)buf)[3] != 0x4010) return "Invalid entry addr";
if (((uint32_t *)buf)[2] != 0) return "Invalid start offset"; if (((uint32_t *)buf)[2] != 0) return "Invalid start offset";
return NULL; return NULL;
} }
// check whether the flash map/size we have allows for OTA upgrade // 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 //===== Cgi to query which firmware needs to be uploaded next
int ICACHE_FLASH_ATTR cgiGetFirmwareNext(HttpdConnData *connData) { 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()) { if (!canOTA()) {
errorResponse(connData, 400, flash_too_small); errorResponse(connData, 400, flash_too_small);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
uint8 id = system_upgrade_userbin_check(); uint8 id = system_upgrade_userbin_check();
httpdStartResponse(connData, 200); httpdStartResponse(connData, 200);
httpdHeader(connData, "Content-Type", "text/plain"); httpdHeader(connData, "Content-Type", "text/plain");
httpdHeader(connData, "Content-Length", "9"); httpdHeader(connData, "Content-Length", "9");
httpdEndHeaders(connData); httpdEndHeaders(connData);
char *next = id == 1 ? "user1.bin" : "user2.bin"; char *next = id == 1 ? "user1.bin" : "user2.bin";
httpdSend(connData, next, -1); httpdSend(connData, next, -1);
#ifdef CGIFLASH_DBG DBG("Next firmware: %s (got %d)\n", next, id);
os_printf("Next firmware: %s (got %d)\n", next, id); return HTTPD_CGI_DONE;
#endif
return HTTPD_CGI_DONE;
} }
//===== Cgi that allows the firmware to be replaced via http POST //===== Cgi that allows the firmware to be replaced via http POST
int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) { 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()) { if (!canOTA()) {
errorResponse(connData, 400, flash_too_small); errorResponse(connData, 400, flash_too_small);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
int offset = connData->post->received - connData->post->buffLen; int offset = connData->post->received - connData->post->buffLen;
if (offset == 0) { if (offset == 0) {
connData->cgiPrivData = NULL; connData->cgiPrivData = NULL;
} else if (connData->cgiPrivData != NULL) { } else if (connData->cgiPrivData != NULL) {
// we have an error condition, do nothing // we have an error condition, do nothing
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
// assume no error yet... // assume no error yet...
char *err = NULL; char *err = NULL;
int code = 400; int code = 400;
// check overall size // check overall size
//os_printf("FW: %d (max %d)\n", connData->post->len, FIRMWARE_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->len > FIRMWARE_SIZE) err = "Firmware image too large";
if (connData->post->buff == NULL || connData->requestType != HTTPD_METHOD_POST || if (connData->post->buff == NULL || connData->requestType != HTTPD_METHOD_POST ||
connData->post->len < 1024) err = "Invalid request"; connData->post->len < 1024) err = "Invalid request";
// check that data starts with an appropriate header // check that data starts with an appropriate header
if (err == NULL && offset == 0) err = check_header(connData->post->buff); if (err == NULL && offset == 0) err = check_header(connData->post->buff);
// make sure we're buffering in 1024 byte chunks // make sure we're buffering in 1024 byte chunks
if (err == NULL && offset % 1024 != 0) { if (err == NULL && offset % 1024 != 0) {
err = "Buffering problem"; err = "Buffering problem";
code = 500; code = 500;
} }
// return an error if there is one // return an error if there is one
if (err != NULL) { if (err != NULL) {
#ifdef CGIFLASH_DBG DBG("Error %d: %s\n", code, err);
os_printf("Error %d: %s\n", code, err); httpdStartResponse(connData, code);
#endif httpdHeader(connData, "Content-Type", "text/plain");
httpdStartResponse(connData, code); //httpdHeader(connData, "Content-Length", strlen(err)+2);
httpdHeader(connData, "Content-Type", "text/plain"); httpdEndHeaders(connData);
//httpdHeader(connData, "Content-Length", strlen(err)+2); httpdSend(connData, err, -1);
httpdEndHeaders(connData); httpdSend(connData, "\r\n", -1);
httpdSend(connData, err, -1); connData->cgiPrivData = (void *)1;
httpdSend(connData, "\r\n", -1); return HTTPD_CGI_DONE;
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();
// let's see which partition we need to flash and what flash address that puts us at int address = id == 1 ? 4*1024 // either start after 4KB boot partition
uint8 id = system_upgrade_userbin_check(); : 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; // 4KB boot, fw1, 16KB user param, 4KB reserved
int address = id == 1 ? 4*1024 // either start after 4KB boot partition address += offset;
: 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){
// erase next flash block if necessary DBG("Flashing 0x%05x (id=%d)\n", address, 2 - id);
if (address % SPI_FLASH_SEC_SIZE == 0){ spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE);
#ifdef CGIFLASH_DBG }
os_printf("Flashing 0x%05x (id=%d)\n", address, 2-id);
#endif // Write the data
spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE); //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);
// Write the data
//os_printf("Writing %d bytes at 0x%05x (%d of %d)\n", connData->post->buffSize, address, if (connData->post->received == connData->post->len){
// connData->post->received, connData->post->len); httpdStartResponse(connData, 200);
spi_flash_write(address, (uint32 *)connData->post->buff, connData->post->buffLen); httpdEndHeaders(connData);
return HTTPD_CGI_DONE;
if (connData->post->received == connData->post->len){ } else {
httpdStartResponse(connData, 200); return HTTPD_CGI_MORE;
httpdEndHeaders(connData); }
return HTTPD_CGI_DONE;
} else {
return HTTPD_CGI_MORE;
}
} }
static ETSTimer flash_reboot_timer; static ETSTimer flash_reboot_timer;
// Handle request to reboot into the new firmware // Handle request to reboot into the new firmware
int ICACHE_FLASH_ATTR cgiRebootFirmware(HttpdConnData *connData) { 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()) { int ICACHE_FLASH_ATTR cgiReset(HttpdConnData *connData) {
errorResponse(connData, 400, flash_too_small); if (connData->conn == NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
// sanity-check that the 'next' partition actually contains something that looks like httpdStartResponse(connData, 200);
// valid firmware httpdHeader(connData, "Content-Length", "0");
uint8 id = system_upgrade_userbin_check(); httpdEndHeaders(connData);
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 // Schedule a reboot
uint32 buf[8]; os_timer_disarm(&flash_reboot_timer);
#ifdef CGIFLASH_DBG os_timer_setfn(&flash_reboot_timer, (os_timer_func_t *)system_restart, NULL);
os_printf("Checking %p\n", (void *)address); os_timer_arm(&flash_reboot_timer, 2000, 1);
#endif return HTTPD_CGI_DONE;
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;
} }

@ -7,5 +7,6 @@ int cgiReadFlash(HttpdConnData *connData);
int cgiGetFirmwareNext(HttpdConnData *connData); int cgiGetFirmwareNext(HttpdConnData *connData);
int cgiUploadFirmware(HttpdConnData *connData); int cgiUploadFirmware(HttpdConnData *connData);
int cgiRebootFirmware(HttpdConnData *connData); int cgiRebootFirmware(HttpdConnData *connData);
int cgiReset(HttpdConnData *connData);
#endif #endif

@ -1,5 +1,14 @@
// Copyright 2015 by Thorsten von Eicken, see LICENSE.txt // 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 <esp8266.h> #include <esp8266.h>
#include "cgi.h" #include "cgi.h"
#include "config.h" #include "config.h"
@ -7,9 +16,11 @@
#include "mqtt_client.h" #include "mqtt_client.h"
#include "cgimqtt.h" #include "cgimqtt.h"
static char *mqtt_states[] = { #ifdef CGIMQTT_DBG
"disconnected", "reconnecting", "connecting", "connected", #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
}; #else
#define DBG(format, ...) do { } while(0)
#endif
char *mqttState(void) { char *mqttState(void) {
return mqtt_states[mqttClient.connState]; return mqtt_states[mqttClient.connState];
@ -64,7 +75,6 @@ int ICACHE_FLASH_ATTR cgiMqttGet(HttpdConnData *connData) {
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
// Cgi to change choice of pin assignments
int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE; 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 server setting changed, we need to "make it so"
if (mqtt_server) { if (mqtt_server) {
#ifdef CGIMQTT_DBG DBG("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable);
os_printf("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable);
#endif
MQTT_Free(&mqttClient); // safe even if not connected MQTT_Free(&mqttClient); // safe even if not connected
mqtt_client_init(); mqtt_client_init();
// if just enable changed we just need to bounce the client // if just enable changed we just need to bounce the client
} else if (mqtt_en_chg > 0) { }
#ifdef CGIMQTT_DBG else if (mqtt_en_chg > 0) {
os_printf("MQTT server enable=%d changed\n", flashConfig.mqtt_enable); DBG("MQTT server enable=%d changed\n", flashConfig.mqtt_enable);
#endif
if (flashConfig.mqtt_enable && strlen(flashConfig.mqtt_host) > 0) if (flashConfig.mqtt_enable && strlen(flashConfig.mqtt_host) > 0)
MQTT_Reconnect(&mqttClient); MQTT_Reconnect(&mqttClient);
else 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 // if SLIP-enable is toggled it gets picked-up immediately by the parser
int slip_update = getBoolArg(connData, "slip-enable", &flashConfig.slip_enable); int slip_update = getBoolArg(connData, "slip-enable", &flashConfig.slip_enable);
if (slip_update < 0) return HTTPD_CGI_DONE; if (slip_update < 0) return HTTPD_CGI_DONE;
#ifdef CGIMQTT_DBG if (slip_update > 0)
if (slip_update > 0) os_printf("SLIP-enable changed: %d\n", flashConfig.slip_enable); DBG("SLIP-enable changed: %d\n", flashConfig.slip_enable);
DBG("Saving config\n");
os_printf("Saving config\n");
#endif
if (configSave()) { if (configSave()) {
httpdStartResponse(connData, 200); httpdStartResponse(connData, 200);
httpdEndHeaders(connData); httpdEndHeaders(connData);
@ -173,4 +180,4 @@ int ICACHE_FLASH_ATTR cgiMqtt(HttpdConnData *connData) {
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
} }
#endif // MQTT #endif

@ -1,10 +1,10 @@
char *mqttState(void);
#ifdef MQTT #ifdef MQTT
#ifndef CGIMQTT_H #ifndef CGIMQTT_H
#define CGIMQTT_H #define CGIMQTT_H
#include "httpd.h" #include "httpd.h"
int cgiMqtt(HttpdConnData *connData); int cgiMqtt(HttpdConnData *connData);
char *mqttState(void);
#endif // CGIMQTT_H #endif // CGIMQTT_H
#endif // MQTT #endif // MQTT

@ -16,10 +16,8 @@
#define PGM_TIMEOUT 20000 // timeout when sync is achieved, in milliseconds #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 PGM_INTERVAL 200 // send sync at this interval in ms when in programming mode
#define OPTIBOOT_DBG
#undef DBG
#ifdef OPTIBOOT_DBG #ifdef OPTIBOOT_DBG
#define DBG(format, ...) os_printf(format, ## __VA_ARGS__) #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
#else #else
#define DBG(format, ...) do { } while(0) #define DBG(format, ...) do { } while(0)
#endif #endif

@ -0,0 +1,216 @@
#include <esp8266.h>
#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;
}

@ -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

@ -13,7 +13,6 @@ Cgi/template routines for the /wifi url.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#include <esp8266.h> #include <esp8266.h>
#include "cgiwifi.h" #include "cgiwifi.h"
#include "cgi.h" #include "cgi.h"
@ -22,12 +21,12 @@ Cgi/template routines for the /wifi url.
#include "log.h" #include "log.h"
#ifdef CGIWIFI_DBG #ifdef CGIWIFI_DBG
#define DBG(format, ...) os_printf(format, ## __VA_ARGS__) #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
#else #else
#define DBG(format, ...) do { } while(0) #define DBG(format, ...) do { } while(0)
#endif #endif
static void wifiStartMDNS(struct ip_addr); bool mdns_started = false;
// ===== wifi status change callbacks // ===== wifi status change callbacks
static WifiStateChangeCb wifi_state_change_cb[4]; static WifiStateChangeCb wifi_state_change_cb[4];
@ -61,28 +60,29 @@ static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) {
wifiState = wifiIsConnected; wifiState = wifiIsConnected;
wifiReason = 0; wifiReason = 0;
DBG("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, 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); statusWifiUpdate(wifiState);
break; break;
case EVENT_STAMODE_DISCONNECTED: case EVENT_STAMODE_DISCONNECTED:
wifiState = wifiIsDisconnected; wifiState = wifiIsDisconnected;
wifiReason = evt->event_info.disconnected.reason; wifiReason = evt->event_info.disconnected.reason;
DBG("Wifi disconnected from ssid %s, reason %s (%d)\n", 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); statusWifiUpdate(wifiState);
break; break;
case EVENT_STAMODE_AUTHMODE_CHANGE: case EVENT_STAMODE_AUTHMODE_CHANGE:
DBG("Wifi auth mode: %d -> %d\n", 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; break;
case EVENT_STAMODE_GOT_IP: case EVENT_STAMODE_GOT_IP:
wifiState = wifiGotIP; wifiState = wifiGotIP;
wifiReason = 0; wifiReason = 0;
DBG("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", 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.ip), IP2STR(&evt->event_info.got_ip.mask),
IP2STR(&evt->event_info.got_ip.gw)); IP2STR(&evt->event_info.got_ip.gw));
statusWifiUpdate(wifiState); statusWifiUpdate(wifiState);
wifiStartMDNS(evt->event_info.got_ip.ip); if (!mdns_started)
wifiStartMDNS(evt->event_info.got_ip.ip);
break; break;
case EVENT_SOFTAPMODE_STACONNECTED: case EVENT_SOFTAPMODE_STACONNECTED:
DBG("Wifi AP: station " MACSTR " joined, AID = %d\n", 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 void ICACHE_FLASH_ATTR wifiAddStateChangeCb(WifiStateChangeCb cb) {
wifiAddStateChangeCb(WifiStateChangeCb cb) {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (wifi_state_change_cb[i] == cb) return; if (wifi_state_change_cb[i] == cb) return;
if (wifi_state_change_cb[i] == NULL) { if (wifi_state_change_cb[i] == NULL) {
@ -113,21 +112,20 @@ wifiAddStateChangeCb(WifiStateChangeCb cb) {
DBG("WIFI: max state change cb count exceeded\n"); DBG("WIFI: max state change cb count exceeded\n");
} }
static bool mdns_started = true; void ICACHE_FLASH_ATTR wifiStartMDNS(struct ip_addr ip) {
static struct mdns_info mdns_info; if (flashConfig.mdns_enable) {
struct mdns_info *mdns_info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info));
// cannot allocate the info struct on the stack, it crashes! mdns_info->host_name = flashConfig.hostname;
static ICACHE_FLASH_ATTR mdns_info->server_name = flashConfig.mdns_servername;
void wifiStartMDNS(struct ip_addr ip) { mdns_info->server_port = 80;
if (!mdns_started) { mdns_info->ipAddr = ip.addr;
os_memset(&mdns_info, 0, sizeof(struct mdns_info)); espconn_mdns_init(mdns_info);
mdns_info.host_name = flashConfig.hostname; }
mdns_info.server_name = "http", // service name else {
mdns_info.server_port = 80, // service port espconn_mdns_server_unregister();
mdns_info.ipAddr = ip.addr, espconn_mdns_close();
espconn_mdns_init(&mdns_info);
mdns_started = true;
} }
mdns_started = true;
} }
// ===== wifi scanning // ===== wifi scanning
@ -362,7 +360,7 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
return HTTPD_CGI_DONE; 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 char *next = buff; // where to start parsing next integer
int found = 0; // number of integers parsed int found = 0; // number of integers parsed
uint32_t ip = 0; // the ip addres 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() { void ICACHE_FLASH_ATTR wifiInit() {
// wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky // wifi_set_phy_mode(2); // limit to 802.11b/g 'cause n is flaky
int x = wifi_get_opmode() & 0x3; int x = wifi_get_opmode() & 0x3;
x = x;
DBG("Wifi init, mode=%s\n", wifiMode[x]); DBG("Wifi init, mode=%s\n", wifiMode[x]);
configWifiIP(); configWifiIP();

@ -16,7 +16,9 @@ int cgiWiFiSpecial(HttpdConnData *connData);
void configWifiIP(); void configWifiIP();
void wifiInit(void); void wifiInit(void);
void wifiAddStateChangeCb(WifiStateChangeCb cb); void wifiAddStateChangeCb(WifiStateChangeCb cb);
void wifiStartMDNS(struct ip_addr);
extern uint8_t wifiState; extern uint8_t wifiState;
extern bool mdns_started;
#endif #endif

@ -9,9 +9,9 @@
FlashConfig flashConfig; FlashConfig flashConfig;
FlashConfig flashDefault = { FlashConfig flashDefault = {
.seq=33, .magic=0, .crc=0, .seq = 33, .magic = 0, .crc = 0,
.reset_pin = MCU_RESET_PIN, .isp_pin = MCU_ISP_PIN, .reset_pin = MCU_RESET_PIN, .isp_pin = MCU_ISP_PIN,
.conn_led_pin = LED_CONN_PIN, .ser_led_pin = LED_SERIAL_PIN, .conn_led_pin = LED_CONN_PIN, .ser_led_pin = LED_SERIAL_PIN,
.baud_rate = 115200, .baud_rate = 115200,
.hostname = "esp-link\0", .hostname = "esp-link\0",
.staticip = 0, .staticip = 0,
@ -20,20 +20,17 @@ FlashConfig flashDefault = {
.log_mode = 0, .log_mode = 0,
.swap_uart = 0, .swap_uart = 0,
.tcp_enable = 1, .rssi_enable = 0, .tcp_enable = 1, .rssi_enable = 0,
.api_key = "\0", .api_key = "",
.slip_enable = 0, .mqtt_enable = 0, .mqtt_status_enable = 0, .slip_enable = 0, .mqtt_enable = 0, .mqtt_status_enable = 0,
.mqtt_timeout = 2, .mqtt_clean_session = 1, .mqtt_timeout = 2, .mqtt_clean_session = 1,
.mqtt_port = 1883, .mqtt_keepalive = 60, .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", .mqtt_username= "\0", .mqtt_password = "\0", .mqtt_status_topic = "\0",
.sys_descr = "\0", .sys_descr = "\0",
.rx_pullup = 1, .rx_pullup = 1,
.sntp_server = "\0", .sntp_server = "us.pool.ntp.org\0",
.syslog_host = "\0", .syslog_host = "\0", .syslog_minheap = 8192, .syslog_filter = 7, .syslog_showtick = 1, .syslog_showdate = 0,
.syslog_minheap= 8192, .mdns_enable = 1, .mdns_servername = "http\0", .timezone_offset = 0
.syslog_filter = 7,
.syslog_showtick= 1,
.syslog_showdate= 0,
}; };
typedef union { typedef union {

@ -21,16 +21,22 @@ typedef struct {
mqtt_timeout, // MQTT send timeout mqtt_timeout, // MQTT send timeout
mqtt_clean_session; // MQTT clean session mqtt_clean_session; // MQTT clean session
uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer 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_host[32],
char mqtt_status_topic[32]; mqtt_clientid[48],
mqtt_username[32],
mqtt_password[32],
mqtt_status_topic[32];
char sys_descr[129]; // system description char sys_descr[129]; // system description
int8_t rx_pullup; // internal pull-up on RX pin int8_t rx_pullup; // internal pull-up on RX pin
char sntp_server[32]; char sntp_server[32];
char syslog_host[32]; char syslog_host[32];
uint16_t syslog_minheap; // min. heap to allow queuing uint16_t syslog_minheap; // min. heap to allow queuing
uint8_t syslog_filter; // min. severity uint8_t syslog_filter, // min. severity
uint8_t syslog_showtick; // show system tick (µs) syslog_showtick, // show system tick (µs)
uint8_t syslog_showdate; // populate SYSLOG date field syslog_showdate; // populate SYSLOG date field
uint8_t mdns_enable;
char mdns_servername[32];
int8_t timezone_offset;
} FlashConfig; } FlashConfig;
extern FlashConfig flashConfig; extern FlashConfig flashConfig;

@ -7,7 +7,7 @@
#include "log.h" #include "log.h"
#ifdef LOG_DBG #ifdef LOG_DBG
#define DBG(format, ...) os_printf(format, ## __VA_ARGS__) #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
#else #else
#define DBG(format, ...) do { } while(0) #define DBG(format, ...) do { } while(0)
#endif #endif

@ -9,7 +9,6 @@
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#include <esp8266.h> #include <esp8266.h>
#include "httpd.h" #include "httpd.h"
#include "httpdespfs.h" #include "httpdespfs.h"
@ -29,19 +28,15 @@
#include "console.h" #include "console.h"
#include "config.h" #include "config.h"
#include "log.h" #include "log.h"
#include <gpio.h> #include "gpio.h"
#include "syslog.h" #include "syslog.h"
#include "sntp.h" #include "cgiservices.h"
static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData);
static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData);
#define NOTICE(format, ...) do { \ #define NOTICE(format, ...) do { \
LOG_NOTICE(format, ## __VA_ARGS__ ); \ LOG_NOTICE(format, ## __VA_ARGS__ ); \
os_printf(format "\n", ## __VA_ARGS__); \ os_printf(format "\n", ## __VA_ARGS__); \
} while ( 0 ) } while ( 0 )
/* /*
This is the main url->function dispatching data struct. This is the main url->function dispatching data struct.
In short, it's a struct with various URLs plus their handlers. The handlers can 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 }, { "/pgm/upload", cgiOptibootData, NULL },
{ "/log/text", ajaxLog, NULL }, { "/log/text", ajaxLog, NULL },
{ "/log/dbg", ajaxLogDbg, NULL }, { "/log/dbg", ajaxLogDbg, NULL },
{ "/log/reset", cgiReset, NULL },
{ "/console/reset", ajaxConsoleReset, NULL }, { "/console/reset", ajaxConsoleReset, NULL },
{ "/console/baud", ajaxConsoleBaud, NULL }, { "/console/baud", ajaxConsoleBaud, NULL },
{ "/console/text", ajaxConsole, NULL }, { "/console/text", ajaxConsole, NULL },
@ -78,11 +74,12 @@ HttpdBuiltInUrl builtInUrls[] = {
{ "/wifi/special", cgiWiFiSpecial, NULL }, { "/wifi/special", cgiWiFiSpecial, NULL },
{ "/system/info", cgiSystemInfo, NULL }, { "/system/info", cgiSystemInfo, NULL },
{ "/system/update", cgiSystemSet, NULL }, { "/system/update", cgiSystemSet, NULL },
{ "/services/info", cgiServicesInfo, NULL },
{ "/services/update", cgiServicesSet, NULL },
{ "/pins", cgiPins, NULL }, { "/pins", cgiPins, NULL },
#ifdef MQTT #ifdef MQTT
{ "/mqtt", cgiMqtt, NULL }, { "/mqtt", cgiMqtt, NULL },
#endif #endif
{ "*", cgiEspFsHook, NULL }, //Catch-all cgi function for the filesystem { "*", cgiEspFsHook, NULL }, //Catch-all cgi function for the filesystem
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
@ -102,105 +99,6 @@ char* esp_link_version = VERS_STR(VERSION);
// address of espfs binary blob // address of espfs binary blob
extern uint32_t _binary_espfs_img_start; extern uint32_t _binary_espfs_img_start;
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 app_init(void);
extern void mqtt_client_init(void); extern void mqtt_client_init(void);
@ -212,7 +110,7 @@ void user_rf_pre_init(void) {
// Main routine to initialize esp-link. // Main routine to initialize esp-link.
void user_init(void) { void user_init(void) {
// get the flash config so we know how to init things // 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(); bool restoreOk = configRestore();
// init gpio pin registers // init gpio pin registers
gpio_init(); gpio_init();
@ -278,7 +176,7 @@ void user_init(void) {
fid & 0xff, (fid&0xff00)|((fid>>16)&0xff)); fid & 0xff, (fid&0xff00)|((fid>>16)&0xff));
NOTICE("** esp-link ready"); NOTICE("** esp-link ready");
enableSNTP(); cgiServicesSNTPInit();
#ifdef MQTT #ifdef MQTT
NOTICE("initializing MQTT"); NOTICE("initializing MQTT");

@ -5,18 +5,13 @@
#include "mqtt.h" #include "mqtt.h"
#ifdef MQTTCLIENT_DBG #ifdef MQTTCLIENT_DBG
#define DBG_MQTTCLIENT(format, ...) os_printf(format, ## __VA_ARGS__) #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__) } while(0)
#else #else
#define DBG_MQTTCLIENT(format, ...) do { } while(0) #define DBG(format, ...) do { } while(0)
#endif #endif
MQTT_Client mqttClient; // main mqtt client used by esp-link MQTT_Client mqttClient; // main mqtt client used by esp-link
#ifdef BRUNNELS
char* statusTopicStr;
static char* onlineMsgStr;
#endif
static MqttCallback connected_cb; static MqttCallback connected_cb;
static MqttCallback disconnected_cb; static MqttCallback disconnected_cb;
static MqttCallback published_cb; static MqttCallback published_cb;
@ -24,12 +19,9 @@ static MqttDataCallback data_cb;
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
mqttConnectedCb(uint32_t *args) { mqttConnectedCb(uint32_t *args) {
DBG_MQTTCLIENT("MQTT Client: Connected\n"); DBG("MQTT Client: Connected\n");
//MQTT_Client* client = (MQTT_Client*)args; //MQTT_Client* client = (MQTT_Client*)args;
//MQTT_Subscribe(client, "system/time", 0); // handy for testing //MQTT_Subscribe(client, "system/time", 0); // handy for testing
#ifdef BRUNNELS
MQTT_Publish(client, "announce/all", onlineMsgStr, 0, 0);
#endif
if (connected_cb) if (connected_cb)
connected_cb(args); connected_cb(args);
} }
@ -37,7 +29,7 @@ mqttConnectedCb(uint32_t *args) {
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
mqttDisconnectedCb(uint32_t *args) { mqttDisconnectedCb(uint32_t *args) {
// MQTT_Client* client = (MQTT_Client*)args; // MQTT_Client* client = (MQTT_Client*)args;
DBG_MQTTCLIENT("MQTT Client: Disconnected\n"); DBG("MQTT Client: Disconnected\n");
if (disconnected_cb) if (disconnected_cb)
disconnected_cb(args); disconnected_cb(args);
} }
@ -45,7 +37,7 @@ mqttDisconnectedCb(uint32_t *args) {
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
mqttPublishedCb(uint32_t *args) { mqttPublishedCb(uint32_t *args) {
// MQTT_Client* client = (MQTT_Client*)args; // MQTT_Client* client = (MQTT_Client*)args;
DBG_MQTTCLIENT("MQTT Client: Published\n"); DBG("MQTT Client: Published\n");
if (published_cb) if (published_cb)
published_cb(args); published_cb(args);
} }
@ -93,29 +85,6 @@ mqtt_client_init()
flashConfig.mqtt_clientid, flashConfig.mqtt_username, flashConfig.mqtt_password, flashConfig.mqtt_clientid, flashConfig.mqtt_username, flashConfig.mqtt_password,
flashConfig.mqtt_keepalive); 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_OnConnected(&mqttClient, mqttConnectedCb);
MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb); MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
MQTT_OnPublished(&mqttClient, mqttPublishedCb); MQTT_OnPublished(&mqttClient, mqttPublishedCb);

@ -5,8 +5,9 @@
<div class="content flex-fill flex-vbox"> <div class="content flex-fill flex-vbox">
<p> <p>
<a id="reset-button" class="pure-button button-primary" href="#">Reset µC</a> <a id="reset-button" class="pure-button button-primary" href="#">Reset &#xb5;C</a>
&nbsp;&nbsp;Baud: &nbsp; <a id="clear-button" class="pure-button button-primary" href="#">Clear Log</a>
&nbsp; Baud:
<select id="baud-sel" class="pure-button" href="#"> <select id="baud-sel" class="pure-button" href="#">
<option value="460800">460800</option> <option value="460800">460800</option>
<option value="250000">250000</option> <option value="250000">250000</option>
@ -17,20 +18,7 @@
<option value="19200">19200</option> <option value="19200">19200</option>
<option value="9600">9600</option> <option value="9600">9600</option>
</select> </select>
<!-- &nbsp; Fmt: 8N1
&nbsp;&nbsp;Pgm baud:
<select id="baud-pgm" class="pure-button">
<option value="same">same</option>
<option value="460800">460800</option>
<option value="250000">250000</option>
<option value="230400">230400</option>
<option value="115200">115200</option>
<option value="57600">57600</option>
<option value="38400">38400</option>
<option value="19200">19200</option>
<option value="9600">9600</option>
</select> -->
&nbsp;&nbsp;Fmt: 8N1
</p> </p>
<div class="pure-g"> <div class="pure-g">
<div class="pure-u-1-4"><legend><b>Console</b></legend></div> <div class="pure-u-1-4"><legend><b>Console</b></legend></div>
@ -85,6 +73,12 @@
); );
}); });
$("#clear-button").addEventListener("click", function(e) {
e.preventDefault();
var co = $("#console");
co.innerHTML = "";
});
ajaxJson('GET', "/console/baud", ajaxJson('GET', "/console/baud",
function(data) { $("#baud-sel").value = data.rate; }, function(data) { $("#baud-sel").value = data.rate; },
function(s, st) { showNotification(st); } function(s, st) { showNotification(st); }

@ -21,7 +21,7 @@ function updateText(resp) {
var delay = 3000; var delay = 3000;
if (resp != null && resp.len > 0) { 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; var isScrolledToBottom = el.scrollHeight - el.clientHeight <= el.scrollTop + 1;
//console.log("isScrolledToBottom="+isScrolledToBottom, "scrollHeight="+el.scrollHeight, //console.log("isScrolledToBottom="+isScrolledToBottom, "scrollHeight="+el.scrollHeight,
// "clientHeight="+el.clientHeight, "scrollTop="+el.scrollTop, // "clientHeight="+el.clientHeight, "scrollTop="+el.scrollTop,

@ -22,31 +22,17 @@
</div> </div>
</td></tr> </td></tr>
<tr><td>Network SSID</td><td id="wifi-ssid"></td></tr> <tr><td>Network SSID</td><td id="wifi-ssid"></td></tr>
<tr><td>Wifi status</td><td id="wifi-status"></td></tr> <tr><td>WiFI status</td><td id="wifi-status"></td></tr>
<tr><td>Wifi address</td><td id="wifi-ip"></td></tr> <tr><td>WiFI address</td><td id="wifi-ip"></td></tr>
<tr><td>SLIP status</td><td class="system-slip"></td></tr> <tr><td>SLIP status</td><td class="system-slip"></td></tr>
<tr><td>MQTT status</td><td class="system-mqtt"></td></tr> <tr><td>MQTT status</td><td class="system-mqtt"></td></tr>
<tr><td>Serial baud</td><td class="system-baud"></td></tr> <tr><td>Serial baud</td><td class="system-baud"></td></tr>
<tr><td class="popup-target">Syslog Server</td><td>
<div class="click-to-edit system-syslog">
<span class="edit-off"></span>
<input class="edit-on" maxlength=31 hidden></input>
<div class="popup">Click to edit!<br>Use server [hostname:port] as UDP Syslog server</div>
</div>
</td></tr>
<tr><td class="popup-target">SNTP Server</td><td>
<div class="click-to-edit system-sntp">
<span class="edit-off"></span>
<input class="edit-on" maxlength=31 hidden></input>
<div class="popup">Click to edit!<br>Use server (f.e. 0.europe.pool.ntp.org) as NTP timesource</div>
</div>
</td></tr>
</tbody></table> </tbody></table>
</div> </div>
<div class="card"> <div class="card">
<h1>Info</h1> <h1>Info</h1>
<p style="margin-bottom:0;">The JeeLabs esp-link firmware bridges the ESP8266 <p style="margin-bottom:0;">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 program microcontrollers over the serial port, in particular Arduinos, AVRs, and
NXP's LPC800 and other ARM processors. Typical avrdude command line to NXP's LPC800 and other ARM processors. Typical avrdude command line to
program an Arduino:</p> program an Arduino:</p>
@ -73,20 +59,21 @@
<div id="pin-table" hidden> <div id="pin-table" hidden>
<form action="#" id="pinform" class="pure-form pure-form-aligned form-narrow"> <form action="#" id="pinform" class="pure-form pure-form-aligned form-narrow">
<div class="pure-control-group"> <div class="pure-control-group">
<label for="pin-preset">Presets</label><select id="pin-preset" class="pure-button"> <label for="pin-preset">Presets</label>
<select id="pin-preset" class="pure-button">
<option value="" selected disabled></option> <option value="" selected disabled></option>
</select></label> </select>
</div> </div>
<hr> <hr>
<div class="pure-control-group"> <div class="pure-control-group">
<label for="pin-reset">Reset</label> <label for="pin-reset">Reset</label>
<select id="pin-reset"></select> <select id="pin-reset"></select>
<div class="popup">Connect to uC reset pin for programming and reset-uC function</div> <div class="popup">Connect to &#xb5;C reset pin for programming and reset-&#xb5;C function</div>
</div> </div>
<div class="pure-control-group"> <div class="pure-control-group">
<label for="pin-isp">ISP/Flash</label> <label for="pin-isp">ISP/Flash</label>
<select id="pin-isp"></select> <select id="pin-isp"></select>
<div class="popup">Second signal to program uC. <div class="popup">Second signal to program &#xb5;C.
AVR:not used, esp8266:gpio2, ARM:ISP</div> AVR:not used, esp8266:gpio2, ARM:ISP</div>
</div> </div>
<div class="pure-control-group"> <div class="pure-control-group">
@ -122,8 +109,8 @@
<h1>System details</h1> <h1>System details</h1>
<div id="system-spinner" class="spinner spinner-small"></div> <div id="system-spinner" class="spinner spinner-small"></div>
<table id="system-table" class="pure-table pure-table-horizontal" hidden><tbody> <table id="system-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>WiFi mode</td><td id="wifi-mode"></td></tr> <tr><td>WiFI mode</td><td id="wifi-mode"></td></tr>
<tr><td>Wifi channel</td><td id="wifi-chan"></td></tr> <tr><td>WiFI channel</td><td id="wifi-chan"></td></tr>
<tr><td>Flash chip ID</td><td> <tr><td>Flash chip ID</td><td>
<div> <div>
<span class="system-id"></span> <span class="system-id"></span>
@ -159,8 +146,6 @@
onLoad(function() { onLoad(function() {
makeAjaxInput("system", "description"); makeAjaxInput("system", "description");
makeAjaxInput("system", "name"); makeAjaxInput("system", "name");
makeAjaxInput("system", "sntp");
makeAjaxInput("system", "syslog");
fetchPins(); fetchPins();
getWifiInfo(); getWifiInfo();
getSystemInfo(); getSystemInfo();

@ -7,10 +7,11 @@
<p>The debug log shows the most recent characters printed by the esp-link software itself to <p>The debug log shows the most recent characters printed by the esp-link software itself to
its own debug log.</p> its own debug log.</p>
<div class="pure-g"> <div class="pure-g">
<p class="pure-u-1-4"> <p class="pure-u-1-4" style="vertical-align: baseline;width:40%">
<a id="refresh-button" class="pure-button button-primary" href="#">Refresh</a> <a id="refresh-button" class="pure-button button-primary" href="#">Refresh</a>
&nbsp;<a id="reset-button" class="dbg-btn pure-button button-primary" href="#">Reset esp-link</a>
</p> </p>
<p class="pure-u-3-4" style="vertical-align: baseline"> <p class="pure-u-3-4" style="vertical-align: baseline;width:60%">
UART debug log: UART debug log:
<a id="dbg-auto" class="dbg-btn pure-button" href="#">auto</a> <a id="dbg-auto" class="dbg-btn pure-button" href="#">auto</a>
<a id="dbg-off" class="dbg-btn pure-button" href="#">off</a> <a id="dbg-off" class="dbg-btn pure-button" href="#">off</a>
@ -34,6 +35,16 @@
fetchText(100, false); fetchText(100, false);
}); });
$("#reset-button").addEventListener("click", function (e) {
e.preventDefault();
var co = $("#console");
co.innerHTML = "";
ajaxSpin('POST', "/log/reset",
function (resp) { showNotification("Resetting esp-link"); co.textEnd = 0; fetchText(2000, false); },
function (s, st) { showWarning("Error resetting esp-link"); }
);
});
["auto", "off", "on0", "on1"].forEach(function(mode) { ["auto", "off", "on0", "on1"].forEach(function(mode) {
bnd($('#dbg-'+mode), "click", function(el) { bnd($('#dbg-'+mode), "click", function(el) {
ajaxJsonSpin('POST', "/log/dbg?mode="+mode, ajaxJsonSpin('POST', "/log/dbg?mode="+mode,

@ -14,7 +14,7 @@
using parameters set below and stored in esp-link's flash settings. This allows using parameters set below and stored in esp-link's flash settings. This allows
esp-link to take care of connection parameters and disconnect/reconnect operations.</p> esp-link to take care of connection parameters and disconnect/reconnect operations.</p>
<p>The MQTT client also supports sending periodic status messages about esp-link itself, <p>The MQTT client also supports sending periodic status messages about esp-link itself,
including Wifi RSSI, and free heap memory.</p> including WiFI RSSI, and free heap memory.</p>
<div class="form-horizontal"> <div class="form-horizontal">
<input type="checkbox" name="slip-enable"/> <input type="checkbox" name="slip-enable"/>
<label>Enable SLIP on serial port</label> <label>Enable SLIP on serial port</label>

@ -44,7 +44,7 @@ function displayMqtt(data) {
var i, inputs = $("input"); var i, inputs = $("input");
for (i = 0; i < inputs.length; i++) { for (i = 0; i < inputs.length; i++) {
if (inputs[i].type == "checkbox") if (inputs[i].type == "checkbox")
inputs[i].onclick = function () { console.log(this); setMqtt(this.name, this.checked) }; inputs[i].onclick = function () { setMqtt(this.name, this.checked) };
} }
} }

@ -0,0 +1,106 @@
<div id="main">
<div class="header">
<h1>Services</h1>
</div>
<div class="content">
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2">
<div class="card">
<h1>
Syslog
<div id="syslog-spinner" class="spinner spinner-small"></div>
</h1>
<form action="#" id="Syslog-form" class="pure-form" hidden>
<legend>Syslog settings</legend>
<div class="pure-form-stacked">
<label>Syslog Host</label>
<input type="text" name="syslog_host" />
<div class="popup">Use server [hostname:port] as UDP Syslog server</div>
</div>
<div class="pure-form-stacked">
<label>Min Heap</label>
<input type="text" name="syslog_minheap" />
<label>Filter</label>
<select name="syslog_filter" href="#">
<option value="0">EMERG</option>
<option value="1">ALERT</option>
<option value="2">CRIT</option>
<option value="3">ERR</option>
<option value="4">WARNING</option>
<option value="5">NOTICE</option>
<option value="6">INFO</option>
<option value="7">DEBUG</option>
</select>
</div>
<div class="form-horizontal">
<label>Show ESP &#xb5;C Ticker in log message</label>
<input type="checkbox" name="syslog_showtick" />
</div>
<div class="form-horizontal">
<label>Show date in log message</label>
<input type="checkbox" name="syslog_showdate" />
<div class="popup">Synology does a log rotate if timestamp is in the past so disable to prevent this</div>
</div>
<button id="Syslog-button" type="submit" class="pure-button button-primary">
Update Syslog settings!
</button>
</form>
</div>
<div class="card">
<h1>
mDNS
<div id="mdns-spinner" class="spinner spinner-small"></div>
</h1>
<form action="#" id="mDNS-form" class="pure-form" hidden>
<div class="form-horizontal">
<input type="checkbox" name="mdns_enable"/>
<label>Enable mDNS</label>
</div>
<br>
<legend>mDNS server settings</legend>
<div class="pure-form-stacked">
<label>Server Name</label>
<input type="text" name="mdns_servername"/>
</div>
<button id="mDNS-button" type="submit" class="pure-button button-primary">
Update mDNS settings!
</button>
</form>
</div>
</div>
<div class="pure-u-1 pure-u-md-1-2">
<div class="card">
<h1>
SNTP
<div id="sntp-spinner" class="spinner spinner-small"></div>
</h1>
<form action="#" id="SNTP-form" class="pure-form" hidden>
<legend>SNTP server settings</legend>
<div class="pure-form-stacked">
<label>Timezone Offset</label>
<input type="text" name="timezone_offset" />
<label>SNTP Server</label>
<input type="text" name="sntp_server" />
</div>
<button id="SNTP-button" type="submit" class="pure-button button-primary">
Update SNTP settings!
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="services.js"></script>
<script type="text/javascript">
onLoad(function() {
fetchServices();
bnd($("#Syslog-form"), "submit", changeServices);
bnd($("#SNTP-form"), "submit", changeServices);
bnd($("#mDNS-form"), "submit", changeServices);
});
</script>
</body></html>

@ -0,0 +1,77 @@
function changeServices(e) {
e.preventDefault();
var url = "services/update?1=1";
var i, inputs = document.querySelectorAll("#" + e.target.id + " input,select");
for (i = 0; i < inputs.length; i++) {
if (inputs[i].type == "checkbox") {
if (inputs[i].name.slice(-6) == "enable")
continue;
var val = (inputs[i].checked) ? 1 : 0;
url += "&" + inputs[i].name + "=" + val;
}
else
url += "&" + inputs[i].name + "=" + inputs[i].value;
};
hideWarning();
var n = e.target.id.replace("-form", "");
var cb = $("#" + n + "-button");
addClass(cb, "pure-button-disabled");
ajaxSpin("POST", url, function (resp) {
showNotification(n + " updated");
removeClass(cb, "pure-button-disabled");
}, function (s, st) {
showWarning("Error: " + st);
removeClass(cb, "pure-button-disabled");
window.setTimeout(fetchServices, 100);
});
}
function displayServices(data) {
Object.keys(data).forEach(function (v) {
el = $("#" + v);
if (el != null) {
if (el.nodeName === "INPUT") el.value = data[v];
else el.innerHTML = data[v];
return;
}
el = document.querySelector('input[name="' + v + '"]');
if (el == null)
el = document.querySelector('select[name="' + v + '"]');
if (el != null) {
if (el.type == "checkbox") {
el.checked = data[v] == "enabled";
} else el.value = data[v];
}
});
$("#syslog-spinner").setAttribute("hidden", "");
$("#sntp-spinner").setAttribute("hidden", "");
$("#mdns-spinner").setAttribute("hidden", "");
$("#Syslog-form").removeAttribute("hidden");
$("#SNTP-form").removeAttribute("hidden");
$("#mDNS-form").removeAttribute("hidden");
var i, inputs = $("input");
for (i = 0; i < inputs.length; i++) {
if (inputs[i].name == "mdns_enable") inputs[i].onclick = function () { setMDNS(this.checked) };
}
}
function setMDNS(v) {
ajaxSpin("POST", "/services/update?mdns_enable=" + (v ? 1 : 0), function () {
showNotification("mDNS is now " + (v ? "enabled" : "disabled"));
}, function () {
showWarning("Enable/disable failed");
window.setTimeout(fetchServices, 100);
});
}
function fetchServices() {
ajaxJson("GET", "/services/info", displayServices, function () {
window.setTimeout(fetchServices, 1000);
});
}

@ -164,14 +164,14 @@ function ajaxReq(method, url, ok_cb, err_cb) {
if (xhr.readyState != 4) { return; } if (xhr.readyState != 4) { return; }
clearTimeout(timeout); clearTimeout(timeout);
if (xhr.status >= 200 && xhr.status < 300) { if (xhr.status >= 200 && xhr.status < 300) {
console.log("XHR done:", method, url, "->", xhr.status); // console.log("XHR done:", method, url, "->", xhr.status);
ok_cb(xhr.responseText); ok_cb(xhr.responseText);
} else { } else {
console.log("XHR ERR :", method, url, "->", xhr.status, xhr.responseText, xhr); console.log("XHR ERR :", method, url, "->", xhr.status, xhr.responseText, xhr);
err_cb(xhr.status, xhr.responseText); err_cb(xhr.status, xhr.responseText);
} }
} }
console.log("XHR send:", method, url); // console.log("XHR send:", method, url);
try { try {
xhr.send(); xhr.send();
} catch(err) { } catch(err) {
@ -244,7 +244,7 @@ onLoad(function() {
// make hamburger button pull out menu // make hamburger button pull out menu
var ml = $('#menuLink'), mm = $('#menu'); var ml = $('#menuLink'), mm = $('#menu');
bnd(ml, 'click', function (e) { bnd(ml, 'click', function (e) {
console.log("hamburger time"); // console.log("hamburger time");
var active = 'active'; var active = 'active';
e.preventDefault(); e.preventDefault();
toggleClass(l, active); toggleClass(l, active);
@ -346,7 +346,7 @@ function makeAjaxInput(klass, field) {
} }
var submitEditToClick = function(v) { var submitEditToClick = function(v) {
console.log("Submit POST "+url+"="+v); // console.log("Submit POST "+url+"="+v);
ajaxSpin("POST", url+"="+v, function() { ajaxSpin("POST", url+"="+v, function() {
domForEach(eon, function(el){ el.setAttribute('hidden',''); }); domForEach(eon, function(el){ el.setAttribute('hidden',''); });
eoff.removeAttribute('hidden'); eoff.removeAttribute('hidden');
@ -410,7 +410,7 @@ function createPresets(sel) {
function applyPreset(v) { function applyPreset(v) {
var pp = pinPresets[v]; var pp = pinPresets[v];
if (pp === undefined) return pp; if (pp === undefined) return pp;
console.log("apply preset:", v, pp); // console.log("apply preset:", v, pp);
function setPP(k, v) { $("#pin-"+k).value = v; }; function setPP(k, v) { $("#pin-"+k).value = v; };
setPP("reset", pp[0]); setPP("reset", pp[0]);
setPP("isp", pp[1]); setPP("isp", pp[1]);
@ -474,7 +474,7 @@ function setPins(ev) {
sep = "&"; sep = "&";
}); });
url += "&rxpup=" + ($("#pin-rxpup").selected ? "1" : "0"); url += "&rxpup=" + ($("#pin-rxpup").selected ? "1" : "0");
console.log("set pins: " + url); // console.log("set pins: " + url);
ajaxSpin("POST", url, function() { ajaxSpin("POST", url, function() {
showNotification("Pin assignment changed"); showNotification("Pin assignment changed");
}, function(status, errMsg) { }, function(status, errMsg) {

@ -1,27 +1,27 @@
<div id="main"> <div id="main">
<div class="header"> <div class="header">
<h1>Wifi Configuration</h1> <h1>WiFi Configuration</h1>
</div> </div>
<div class="content"> <div class="content">
<div class="pure-g"> <div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2"><div class="card"> <div class="pure-u-1 pure-u-md-1-2"><div class="card">
<h1>Wifi State</h1> <h1>WiFi State</h1>
<div id="wifi-spinner" class="spinner spinner-small"></div> <div id="wifi-spinner" class="spinner spinner-small"></div>
<table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody> <table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>WiFi mode</td><td id="wifi-mode"></td></tr> <tr><td>WiFi mode</td><td id="wifi-mode"></td></tr>
<tr><td>Wifi channel</td><td id="wifi-chan"></td></tr> <tr><td>WiFi channel</td><td id="wifi-chan"></td></tr>
<tr><td>Configured network</td><td id="wifi-ssid"></td></tr> <tr><td>Configured network</td><td id="wifi-ssid"></td></tr>
<tr><td>Wifi status</td><td id="wifi-status"></td></tr> <tr><td>WiFi status</td><td id="wifi-status"></td></tr>
<tr><td>Wifi address</td><td id="wifi-ip"></td></tr> <tr><td>WiFi address</td><td id="wifi-ip"></td></tr>
<tr><td>Wifi rssi</td><td id="wifi-rssi"></td></tr> <tr><td>WiFi rssi</td><td id="wifi-rssi"></td></tr>
<tr><td>Wifi phy</td><td id="wifi-phy"></td></tr> <tr><td>WiFi phy</td><td id="wifi-phy"></td></tr>
<tr><td>Wifi MAC</td><td id="wifi-mac"></td></tr> <tr><td>WiFi MAC</td><td id="wifi-mac"></td></tr>
<tr><td colspan="2" id="wifi-warn"></td></tr> <tr><td colspan="2" id="wifi-warn"></td></tr>
</tbody> </table> </tbody> </table>
</div></div> </div></div>
<div class="pure-u-1 pure-u-md-1-2"><div class="card"> <div class="pure-u-1 pure-u-md-1-2"><div class="card">
<h1>Wifi Association</h1> <h1>WiFi Association</h1>
<p id="reconnect" style="color: #600" hidden></p> <p id="reconnect" style="color: #600" hidden></p>
<form action="#" id="wifiform" class="pure-form pure-form-stacked"> <form action="#" id="wifiform" class="pure-form pure-form-stacked">
<legend>To connect to a WiFi network, please select one of the detected networks, <legend>To connect to a WiFi network, please select one of the detected networks,
@ -30,8 +30,7 @@
<div id="aps">Scanning... <div class="spinner spinner-small"></div></div> <div id="aps">Scanning... <div class="spinner spinner-small"></div></div>
<label for="opt-hiddenssid"> <label for="opt-hiddenssid">
<input type="radio" name="essid" value="_hidden_ssid_" id="opt-hiddenssid"> <input type="radio" name="essid" value="_hidden_ssid_" id="opt-hiddenssid">
<input type="text" id="hidden-ssid" value="" <input type="text" id="hidden-ssid" value="" style="width:auto; display:inline-block; margin-left: 0.7em">
style="width:auto; display:inline-block; margin-left: 0.7em">
</label> </label>
<label>WiFi password, if applicable:</label> <label>WiFi password, if applicable:</label>
<input id="wifi-passwd" type="password" name="passwd" placeholder="password"> <input id="wifi-passwd" type="password" name="passwd" placeholder="password">
@ -61,8 +60,7 @@
<label>Gateway (for static IP)</label> <label>Gateway (for static IP)</label>
<input id="wifi-gateway" type="text" name="gateway"/> <input id="wifi-gateway" type="text" name="gateway"/>
</div> </div>
<button id="special-button" type="submit" <button id="special-button" type="submit" class="pure-button button-primary">Change!</button>
class="pure-button button-primary">Change!</button>
</form> </form>
</div></div> </div></div>
</div> </div>

@ -82,7 +82,7 @@ function scanResult() {
} }
function scanAPs() { function scanAPs() {
console.log("scanning now"); // console.log("scanning now");
if (blockScan) { if (blockScan) {
scanTimeout = window.setTimeout(scanAPs, 1000); scanTimeout = window.setTimeout(scanAPs, 1000);
return; return;

@ -17,7 +17,11 @@ Esp8266 http server - core routines
#include <esp8266.h> #include <esp8266.h>
#include "httpd.h" #include "httpd.h"
//#define HTTPD_DBG #ifdef HTTPD_DBG
#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
#else
#define DBG(format, ...) do { } while(0)
#endif
//Max length of request head //Max length of request head
@ -97,7 +101,7 @@ static void debugConn(void *arg, char *what) {
os_sprintf(connStr, "%d.%d.%d.%d:%d ", os_sprintf(connStr, "%d.%d.%d.%d:%d ",
tcp->remote_ip[0], tcp->remote_ip[1], tcp->remote_ip[2], tcp->remote_ip[3], tcp->remote_ip[0], tcp->remote_ip[1], tcp->remote_ip[2], tcp->remote_ip[3],
tcp->remote_port); tcp->remote_port);
os_printf("%s %s\n", connStr, what); DBG("%s %s\n", connStr, what);
#else #else
connStr[0] = 0; connStr[0] = 0;
#endif #endif
@ -108,20 +112,18 @@ static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
if (conn->conn && conn->conn->reverse == conn) if (conn->conn && conn->conn->reverse == conn)
conn->conn->reverse = NULL; // break reverse link conn->conn->reverse = NULL; // break reverse link
#ifdef HTTPD_DBG
// log information about the request we handled // log information about the request we handled
uint32 dt = conn->startTime; uint32 dt = conn->startTime;
if (dt > 0) dt = (system_get_time() - dt) / 1000; if (dt > 0) dt = (system_get_time() - dt) / 1000;
if (conn->conn && conn->url) if (conn->conn && conn->url)
#if 0 #if 0
os_printf("HTTP %s %s from %s -> %d in %ums, heap=%ld\n", DBG("HTTP %s %s from %s -> %d in %ums, heap=%ld\n",
conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, conn->priv->from, conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, conn->priv->from,
conn->priv->code, dt, (unsigned long)system_get_free_heap_size()); conn->priv->code, dt, (unsigned long)system_get_free_heap_size());
#else #else
os_printf("HTTP %s %s: %d, %ums, h=%ld\n", DBG("HTTP %s %s: %d, %ums, h=%ld\n",
conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url,
conn->priv->code, dt, (unsigned long)system_get_free_heap_size()); conn->priv->code, dt, (unsigned long)system_get_free_heap_size());
#endif
#endif #endif
conn->conn = NULL; // don't try to send anything, the SDK crashes... conn->conn = NULL; // don't try to send anything, the SDK crashes...
@ -276,10 +278,8 @@ int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData) {
int ICACHE_FLASH_ATTR httpdSend(HttpdConnData *conn, const char *data, int len) { int ICACHE_FLASH_ATTR httpdSend(HttpdConnData *conn, const char *data, int len) {
if (len<0) len = strlen(data); if (len<0) len = strlen(data);
if (conn->priv->sendBuffLen + len>MAX_SENDBUFF_LEN) { if (conn->priv->sendBuffLen + len>MAX_SENDBUFF_LEN) {
#ifdef HTTPD_DBG DBG("%sERROR! httpdSend full (%d of %d)\n",
os_printf("%sERROR! httpdSend full (%d of %d)\n",
connStr, conn->priv->sendBuffLen, MAX_SENDBUFF_LEN); connStr, conn->priv->sendBuffLen, MAX_SENDBUFF_LEN);
#endif
return 0; return 0;
} }
os_memcpy(conn->priv->sendBuff + conn->priv->sendBuffLen, data, len); os_memcpy(conn->priv->sendBuff + conn->priv->sendBuffLen, data, len);
@ -292,10 +292,8 @@ static void ICACHE_FLASH_ATTR xmitSendBuff(HttpdConnData *conn) {
if (conn->priv->sendBuffLen != 0) { if (conn->priv->sendBuffLen != 0) {
sint8 status = espconn_sent(conn->conn, (uint8_t*)conn->priv->sendBuff, conn->priv->sendBuffLen); sint8 status = espconn_sent(conn->conn, (uint8_t*)conn->priv->sendBuff, conn->priv->sendBuffLen);
if (status != 0) { if (status != 0) {
#ifdef HTTPD_DBG DBG("%sERROR! espconn_sent returned %d, trying to send %d to %s\n",
os_printf("%sERROR! espconn_sent returned %d, trying to send %d to %s\n",
connStr, status, conn->priv->sendBuffLen, conn->url); connStr, status, conn->priv->sendBuffLen, conn->url);
#endif
} }
conn->priv->sendBuffLen = 0; conn->priv->sendBuffLen = 0;
} }
@ -323,9 +321,7 @@ static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) {
conn->cgi = NULL; //mark for destruction. conn->cgi = NULL; //mark for destruction.
} }
if (r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED) { if (r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED) {
#ifdef HTTPD_DBG DBG("%sERROR! Bad CGI code %d\n", connStr, r);
os_printf("%sERROR! Bad CGI code %d\n", connStr, r);
#endif
conn->cgi = NULL; //mark for destruction. conn->cgi = NULL; //mark for destruction.
} }
xmitSendBuff(conn); xmitSendBuff(conn);
@ -342,9 +338,7 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) {
int r; int r;
int i = 0; int i = 0;
if (conn->url == NULL) { if (conn->url == NULL) {
#ifdef HTTPD_DBG DBG("%sWtF? url = NULL\n", connStr);
os_printf("%sWtF? url = NULL\n", connStr);
#endif
return; //Shouldn't happen return; //Shouldn't happen
} }
//See if we can find a CGI that's happy to handle the request. //See if we can find a CGI that's happy to handle the request.
@ -370,9 +364,7 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) {
if (builtInUrls[i].url == NULL) { if (builtInUrls[i].url == NULL) {
//Drat, we're at the end of the URL table. This usually shouldn't happen. Well, just //Drat, we're at the end of the URL table. This usually shouldn't happen. Well, just
//generate a built-in 404 to handle this. //generate a built-in 404 to handle this.
#ifdef HTTPD_DBG DBG("%s%s not found. 404!\n", connStr, conn->url);
os_printf("%s%s not found. 404!\n", connStr, conn->url);
#endif
httpdSend(conn, httpNotFoundHeader, -1); httpdSend(conn, httpNotFoundHeader, -1);
xmitSendBuff(conn); xmitSendBuff(conn);
conn->cgi = NULL; //mark for destruction. conn->cgi = NULL; //mark for destruction.
@ -436,19 +428,15 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
*e = 0; //terminate url part *e = 0; //terminate url part
// Count number of open connections // Count number of open connections
#ifdef HTTPD_DBG
//esp_tcp *tcp = conn->conn->proto.tcp; //esp_tcp *tcp = conn->conn->proto.tcp;
//os_printf("%sHTTP %s %s from %s\n", connStr, //DBG("%sHTTP %s %s from %s\n", connStr,
// conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, conn->priv->from); // conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, conn->priv->from);
#endif
//Parse out the URL part before the GET parameters. //Parse out the URL part before the GET parameters.
conn->getArgs = (char*)os_strstr(conn->url, "?"); conn->getArgs = (char*)os_strstr(conn->url, "?");
if (conn->getArgs != 0) { if (conn->getArgs != 0) {
*conn->getArgs = 0; *conn->getArgs = 0;
conn->getArgs++; conn->getArgs++;
#ifdef HTTPD_DBG //DBG("%sargs = %s\n", connStr, conn->getArgs);
//os_printf("%sargs = %s\n", connStr, conn->getArgs);
#endif
} }
else { else {
conn->getArgs = NULL; conn->getArgs = NULL;
@ -470,7 +458,7 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
else { else {
conn->post->buffSize = conn->post->len; conn->post->buffSize = conn->post->len;
} }
//os_printf("Mallocced buffer for %d + 1 bytes of post data.\n", conn->post->buffSize); //DBG("Mallocced buffer for %d + 1 bytes of post data.\n", conn->post->buffSize);
conn->post->buff = (char*)os_malloc(conn->post->buffSize + 1); conn->post->buff = (char*)os_malloc(conn->post->buffSize + 1);
conn->post->buffLen = 0; conn->post->buffLen = 0;
} }
@ -482,7 +470,7 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
conn->post->multipartBoundary = b + 7; // move the pointer 2 chars before boundary then fill them with dashes conn->post->multipartBoundary = b + 7; // move the pointer 2 chars before boundary then fill them with dashes
conn->post->multipartBoundary[0] = '-'; conn->post->multipartBoundary[0] = '-';
conn->post->multipartBoundary[1] = '-'; conn->post->multipartBoundary[1] = '-';
//os_printf("boundary = %s\n", conn->post->multipartBoundary); //DBG("boundary = %s\n", conn->post->multipartBoundary);
} }
} }
} }
@ -562,10 +550,7 @@ static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) {
struct espconn* pCon = (struct espconn *)arg; struct espconn* pCon = (struct espconn *)arg;
HttpdConnData *conn = (HttpdConnData *)pCon->reverse; HttpdConnData *conn = (HttpdConnData *)pCon->reverse;
if (conn == NULL) return; // aborted connection if (conn == NULL) return; // aborted connection
DBG("%s***** reset, err=%d\n", connStr, err);
#ifdef HTTPD_DBG
os_printf("%s***** reset, err=%d\n", connStr, err);
#endif
httpdRetireConn(conn); httpdRetireConn(conn);
} }
@ -577,7 +562,7 @@ static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) {
// Find empty conndata in pool // Find empty conndata in pool
int i; int i;
for (i = 0; i<MAX_CONN; i++) if (connData[i].conn == NULL) break; for (i = 0; i<MAX_CONN; i++) if (connData[i].conn == NULL) break;
//os_printf("Con req, conn=%p, pool slot %d\n", conn, i); //DBG("Con req, conn=%p, pool slot %d\n", conn, i);
if (i == MAX_CONN) { if (i == MAX_CONN) {
os_printf("%sHTTP: conn pool overflow!\n", connStr); os_printf("%sHTTP: conn pool overflow!\n", connStr);
espconn_disconnect(conn); espconn_disconnect(conn);
@ -587,9 +572,7 @@ static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) {
#if 0 #if 0
int num = 0; int num = 0;
for (int j = 0; j<MAX_CONN; j++) if (connData[j].conn != NULL) num++; for (int j = 0; j<MAX_CONN; j++) if (connData[j].conn != NULL) num++;
#ifdef HTTPD_DBG DBG("%sConnect (%d open)\n", connStr, num + 1);
os_printf("%sConnect (%d open)\n", connStr, num + 1);
#endif
#endif #endif
connData[i].priv = &connPrivData[i]; connData[i].priv = &connPrivData[i];
@ -627,9 +610,7 @@ void ICACHE_FLASH_ATTR httpdInit(HttpdBuiltInUrl *fixedUrls, int port) {
httpdTcp.local_port = port; httpdTcp.local_port = port;
httpdConn.proto.tcp = &httpdTcp; httpdConn.proto.tcp = &httpdTcp;
builtInUrls = fixedUrls; builtInUrls = fixedUrls;
#ifdef HTTPD_DBG DBG("Httpd init, conn=%p\n", &httpdConn);
os_printf("Httpd init, conn=%p\n", &httpdConn);
#endif
espconn_regist_connectcb(&httpdConn, httpdConnectCb); espconn_regist_connectcb(&httpdConn, httpdConnectCb);
espconn_accept(&httpdConn); espconn_accept(&httpdConn);
espconn_tcp_set_max_con_allow(&httpdConn, MAX_CONN); espconn_tcp_set_max_con_allow(&httpdConn, MAX_CONN);

@ -19,7 +19,7 @@
#define CONFIG_DBG #define CONFIG_DBG
#define LOG_DBG #define LOG_DBG
#define STATUS_DBG #define STATUS_DBG
#define HTTPD_DBG #undef HTTPD_DBG
#define MQTT_DBG #define MQTT_DBG
#define MQTTCMD_DBG #define MQTTCMD_DBG
#undef PKTBUF_DBG #undef PKTBUF_DBG
@ -29,6 +29,10 @@
#define SERLED_DBG #define SERLED_DBG
#undef SLIP_DBG #undef SLIP_DBG
#define UART_DBG #define UART_DBG
#define MDNS_DBG
#define OPTIBOOT_DBG
#define SYSLOG_DBG
#define CGISERVICES_DBG
// If defined, the default hostname for DHCP will include the chip ID to make it unique // If defined, the default hostname for DHCP will include the chip ID to make it unique
#undef CHIP_IN_HOSTNAME #undef CHIP_IN_HOSTNAME

@ -8,9 +8,9 @@
#include "mqtt_cmd.h" #include "mqtt_cmd.h"
#ifdef MQTTCMD_DBG #ifdef MQTTCMD_DBG
#define DBG_MQTTCMD(format, ...) os_printf(format, ## __VA_ARGS__) #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
#else #else
#define DBG_MQTTCMD(format, ...) do { } while(0) #define DBG(format, ...) do { } while(0)
#endif #endif
// if MQTT_1_CLIENT is defined we only support the one client that is built into esp-link. // if MQTT_1_CLIENT is defined we only support the one client that is built into esp-link.
@ -25,7 +25,7 @@ void ICACHE_FLASH_ATTR
cmdMqttConnectedCb(uint32_t* args) { cmdMqttConnectedCb(uint32_t* args) {
MQTT_Client* client = (MQTT_Client*)args; MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data; MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
DBG_MQTTCMD("MQTT: Connected connectedCb=%p, disconnectedCb=%p, publishedCb=%p, dataCb=%p\n", DBG("MQTT: Connected connectedCb=%p, disconnectedCb=%p, publishedCb=%p, dataCb=%p\n",
(void*)cb->connectedCb, (void*)cb->connectedCb,
(void*)cb->disconnectedCb, (void*)cb->disconnectedCb,
(void*)cb->publishedCb, (void*)cb->publishedCb,
@ -38,7 +38,7 @@ void ICACHE_FLASH_ATTR
cmdMqttDisconnectedCb(uint32_t* args) { cmdMqttDisconnectedCb(uint32_t* args) {
MQTT_Client* client = (MQTT_Client*)args; MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data; MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
DBG_MQTTCMD("MQTT: Disconnected\n"); DBG("MQTT: Disconnected\n");
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->disconnectedCb, 0, 0); uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->disconnectedCb, 0, 0);
CMD_ResponseEnd(crc); CMD_ResponseEnd(crc);
} }
@ -47,7 +47,7 @@ void ICACHE_FLASH_ATTR
cmdMqttPublishedCb(uint32_t* args) { cmdMqttPublishedCb(uint32_t* args) {
MQTT_Client* client = (MQTT_Client*)args; MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data; MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
DBG_MQTTCMD("MQTT: Published\n"); DBG("MQTT: Published\n");
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->publishedCb, 0, 0); uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->publishedCb, 0, 0);
CMD_ResponseEnd(crc); CMD_ResponseEnd(crc);
} }
@ -79,7 +79,7 @@ MQTTCMD_Lwt(CmdPacket *cmd) {
MQTT_Client* client = &mqttClient; MQTT_Client* client = &mqttClient;
#else #else
MQTT_Client* client = (MQTT_Client*)client_ptr; MQTT_Client* client = (MQTT_Client*)client_ptr;
DBG_MQTTCMD("MQTT: MQTTCMD_Lwt client ptr=%p\n", (void*)client_ptr); DBG("MQTT: MQTTCMD_Lwt client ptr=%p\n", (void*)client_ptr);
#endif #endif
// free old topic & message // free old topic & message
@ -110,7 +110,7 @@ MQTTCMD_Lwt(CmdPacket *cmd) {
// get retain // get retain
CMD_PopArg(&req, (uint8_t*)&client->connect_info.will_retain, 4); CMD_PopArg(&req, (uint8_t*)&client->connect_info.will_retain, 4);
DBG_MQTTCMD("MQTT: MQTTCMD_Lwt topic=%s, message=%s, qos=%d, retain=%d\n", DBG("MQTT: MQTTCMD_Lwt topic=%s, message=%s, qos=%d, retain=%d\n",
client->connect_info.will_topic, client->connect_info.will_topic,
client->connect_info.will_message, client->connect_info.will_message,
client->connect_info.will_qos, client->connect_info.will_qos,
@ -136,7 +136,7 @@ MQTTCMD_Publish(CmdPacket *cmd) {
MQTT_Client* client = &mqttClient; MQTT_Client* client = &mqttClient;
#else #else
MQTT_Client* client = (MQTT_Client*)client_ptr; MQTT_Client* client = (MQTT_Client*)client_ptr;
DBG_MQTTCMD("MQTT: MQTTCMD_Publish client ptr=%p\n", (void*)client_ptr); DBG("MQTT: MQTTCMD_Publish client ptr=%p\n", (void*)client_ptr);
#endif #endif
uint16_t len; uint16_t len;
@ -170,7 +170,7 @@ MQTTCMD_Publish(CmdPacket *cmd) {
// get retain // get retain
CMD_PopArg(&req, (uint8_t*)&retain, 4); CMD_PopArg(&req, (uint8_t*)&retain, 4);
DBG_MQTTCMD("MQTT: MQTTCMD_Publish topic=%s, data_len=%d, qos=%ld, retain=%ld\n", DBG("MQTT: MQTTCMD_Publish topic=%s, data_len=%d, qos=%ld, retain=%ld\n",
topic, topic,
os_strlen((char*)data), os_strlen((char*)data),
qos, qos,
@ -197,7 +197,7 @@ MQTTCMD_Subscribe(CmdPacket *cmd) {
MQTT_Client* client = &mqttClient; MQTT_Client* client = &mqttClient;
#else #else
MQTT_Client* client = (MQTT_Client*)client_ptr; MQTT_Client* client = (MQTT_Client*)client_ptr;
DBG_MQTTCMD("MQTT: MQTTCMD_Subscribe client ptr=%p\n", (void*)client_ptr); DBG("MQTT: MQTTCMD_Subscribe client ptr=%p\n", (void*)client_ptr);
#endif #endif
uint16_t len; uint16_t len;
@ -213,7 +213,7 @@ MQTTCMD_Subscribe(CmdPacket *cmd) {
uint32_t qos = 0; uint32_t qos = 0;
CMD_PopArg(&req, (uint8_t*)&qos, 4); CMD_PopArg(&req, (uint8_t*)&qos, 4);
DBG_MQTTCMD("MQTT: MQTTCMD_Subscribe topic=%s, qos=%ld\n", topic, qos); DBG("MQTT: MQTTCMD_Subscribe topic=%s, qos=%ld\n", topic, qos);
MQTT_Subscribe(client, (char*)topic, (uint8_t)qos); MQTT_Subscribe(client, (char*)topic, (uint8_t)qos);
os_free(topic); os_free(topic);
@ -273,7 +273,7 @@ MQTTCMD_Setup(CmdPacket *cmd) {
// get clean session // get clean session
CMD_PopArg(&req, (uint8_t*)&clean_session, 4); CMD_PopArg(&req, (uint8_t*)&clean_session, 4);
#ifdef MQTTCMD_DBG #ifdef MQTTCMD_DBG
DBG_MQTTCMD("MQTT: MQTTCMD_Setup clientid=%s, user=%s, pw=%s, keepalive=%ld, clean_session=%ld\n", client_id, user_data, pass_data, keepalive, clean_session); DBG("MQTT: MQTTCMD_Setup clientid=%s, user=%s, pw=%s, keepalive=%ld, clean_session=%ld\n", client_id, user_data, pass_data, keepalive, clean_session);
#endif #endif
// init client // init client
@ -314,6 +314,14 @@ MQTTCMD_Connect(CmdPacket *cmd) {
CMD_Request(&req, cmd); CMD_Request(&req, cmd);
#ifdef MQTT_1_CLIENT #ifdef MQTT_1_CLIENT
if (mqttClient.connState == MQTT_CONNECTED && mqttClient.cmdConnectedCb) {
mqttClient.cmdConnectedCb((uint32_t*)&mqttClient);
}
else if (mqttClient.connState == MQTT_DISCONNECTED && mqttClient.cmdDisconnectedCb) {
mqttClient.cmdDisconnectedCb((uint32_t*)&mqttClient);
}
return 1; return 1;
#else #else
@ -324,7 +332,7 @@ MQTTCMD_Connect(CmdPacket *cmd) {
uint32_t client_ptr; uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4); CMD_PopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr; MQTT_Client* client = (MQTT_Client*)client_ptr;
DBG_MQTTCMD("MQTT: MQTTCMD_Connect client ptr=%p\n", (void*)client_ptr); DBG("MQTT: MQTTCMD_Connect client ptr=%p\n", (void*)client_ptr);
uint16_t len; uint16_t len;
@ -342,7 +350,7 @@ MQTTCMD_Connect(CmdPacket *cmd) {
// get security // get security
CMD_PopArg(&req, (uint8_t*)&client->security, 4); CMD_PopArg(&req, (uint8_t*)&client->security, 4);
DBG_MQTTCMD("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n", DBG("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n",
client->host, client->host,
client->port, client->port,
client->security); client->security);
@ -368,7 +376,7 @@ MQTTCMD_Disconnect(CmdPacket *cmd) {
uint32_t client_ptr; uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4); CMD_PopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr; MQTT_Client* client = (MQTT_Client*)client_ptr;
DBG_MQTTCMD("MQTT: MQTTCMD_Disconnect client ptr=%p\n", (void*)client_ptr); DBG("MQTT: MQTTCMD_Disconnect client ptr=%p\n", (void*)client_ptr);
// disconnect // disconnect
MQTT_Disconnect(client); MQTT_Disconnect(client);

@ -4,18 +4,18 @@
#include "pktbuf.h" #include "pktbuf.h"
#ifdef PKTBUF_DBG #ifdef PKTBUF_DBG
static void ICACHE_FLASH_ATTR //static void ICACHE_FLASH_ATTR
PktBuf_Print(PktBuf *buf) { //PktBuf_Print(PktBuf *buf) {
os_printf("PktBuf:"); // os_printf("PktBuf:");
for (int i=-16; i<0; i++) // for (int i=-16; i<0; i++)
os_printf(" %02X", ((uint8_t*)buf)[i]); // os_printf(" %02X", ((uint8_t*)buf)[i]);
os_printf(" %p", buf); // os_printf(" %p", buf);
for (int i=0; i<16; i++) // for (int i=0; i<16; i++)
os_printf(" %02X", ((uint8_t*)buf)[i]); // os_printf(" %02X", ((uint8_t*)buf)[i]);
os_printf("\n"); // os_printf("\n");
os_printf("PktBuf: next=%p len=0x%04x\n", // os_printf("PktBuf: next=%p len=0x%04x\n",
((void**)buf)[-4], ((uint16_t*)buf)[-6]); // ((void**)buf)[-4], ((uint16_t*)buf)[-6]);
} //}
#endif #endif

@ -7,6 +7,12 @@
#include "console.h" #include "console.h"
#include "cmd.h" #include "cmd.h"
#ifdef SLIP_DBG
#define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
#else
#define DBG(format, ...) do { } while(0)
#endif
uint8_t slip_disabled; // temporarily disable slip to allow flashing of attached MCU uint8_t slip_disabled; // temporarily disable slip to allow flashing of attached MCU
extern void ICACHE_FLASH_ATTR console_process(char *buf, short len); extern void ICACHE_FLASH_ATTR console_process(char *buf, short len);
@ -48,15 +54,15 @@ slip_process() {
} else { } else {
os_printf("SLIP: bad CRC, crc=%x rcv=%x\n", crc, rcv); os_printf("SLIP: bad CRC, crc=%x rcv=%x\n", crc, rcv);
#ifdef SLIP_DBG
for (short i=0; i<slip_len; i++) { for (short i=0; i<slip_len; i++) {
if (slip_buf[i] >= ' ' && slip_buf[i] <= '~') if (slip_buf[i] >= ' ' && slip_buf[i] <= '~') {
os_printf("%c", slip_buf[i]); DBG("%c", slip_buf[i]);
else }
os_printf("\\%02X", slip_buf[i]); else {
DBG("\\%02X", slip_buf[i]);
}
} }
os_printf("\n"); DBG("\n");
#endif
} }
} }
} }
@ -86,9 +92,7 @@ slip_parse_char(char c) {
if (slip_len > 0) console_process(slip_buf, slip_len); if (slip_len > 0) console_process(slip_buf, slip_len);
slip_reset(); slip_reset();
slip_inpkt = true; slip_inpkt = true;
#ifdef SLIP_DBG DBG("SLIP: start\n");
os_printf("SLIP: start\n");
#endif
return; return;
} }
} else if (slip_escaped) { } else if (slip_escaped) {

@ -10,36 +10,35 @@
#include <esp8266.h> #include <esp8266.h>
#include "config.h" #include "config.h"
#include <syslog.h> #include "syslog.h"
#include <time.h> #include "time.h"
#include "task.h" #include "task.h"
extern void * mem_trim(void *m, size_t s); // not well documented... extern void * mem_trim(void *m, size_t s); // not well documented...
#define SYSLOG_DBG
#ifdef SYSLOG_DBG #ifdef SYSLOG_DBG
#define DBG_SYSLOG(format, ...) os_printf(format, ## __VA_ARGS__) #define DBG(format, ...) do { os_printf(format, ## __VA_ARGS__); } while(0)
#else #else
#define DBG_SYSLOG(format, ...) do { } while(0) #define DBG(format, ...) do { } while(0)
#endif #endif
#define WIFI_CHK_INTERVAL 1000 // ms to check Wifi statis #define WIFI_CHK_INTERVAL 1000 // ms to check Wifi statis
LOCAL os_timer_t wifi_chk_timer; static os_timer_t wifi_chk_timer;
LOCAL struct espconn syslog_espconn; static struct espconn syslog_espconn;
LOCAL uint32_t syslog_msgid = 1; static uint32_t syslog_msgid = 1;
LOCAL uint8_t syslog_task = 0; static uint8_t syslog_task = 0;
LOCAL syslog_host_t syslogHost; static syslog_host_t syslogHost;
LOCAL syslog_entry_t *syslogQueue = NULL; static syslog_entry_t *syslogQueue = NULL;
static enum syslog_state syslogState = SYSLOG_NONE; static enum syslog_state syslogState = SYSLOG_NONE;
LOCAL void ICACHE_FLASH_ATTR syslog_add_entry(syslog_entry_t *entry); static void ICACHE_FLASH_ATTR syslog_add_entry(syslog_entry_t *entry);
LOCAL void ICACHE_FLASH_ATTR syslog_chk_wifi_stat(void); static void ICACHE_FLASH_ATTR syslog_chk_wifi_stat(void);
LOCAL void ICACHE_FLASH_ATTR syslog_udp_sent_cb(void *arg); static void ICACHE_FLASH_ATTR syslog_udp_sent_cb(void *arg);
#ifdef SYSLOG_UDP_RECV #ifdef SYSLOG_UDP_RECV
LOCAL void ICACHE_FLASH_ATTR syslog_udp_recv_cb(void *arg, char *pusrdata, unsigned short length); static void ICACHE_FLASH_ATTR syslog_udp_recv_cb(void *arg, char *pusrdata, unsigned short length);
#endif #endif
#define syslog_send_udp() post_usr_task(syslog_task,0) #define syslog_send_udp() post_usr_task(syslog_task,0)
@ -50,11 +49,10 @@ LOCAL void ICACHE_FLASH_ATTR syslog_udp_recv_cb(void *arg, char *pusrdata, unsig
* Parameters : none * Parameters : none
* Returns : none * Returns : none
*******************************************************************************/ *******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR syslog_chk_wifi_stat(void)
syslog_chk_wifi_stat(void)
{ {
struct ip_info ipconfig; struct ip_info ipconfig;
DBG_SYSLOG("syslog_chk_wifi_stat: state: %d ", syslogState); DBG("syslog_chk_wifi_stat: state: %d ", syslogState);
//disarm timer first //disarm timer first
os_timer_disarm(&wifi_chk_timer); os_timer_disarm(&wifi_chk_timer);
@ -65,7 +63,7 @@ syslog_chk_wifi_stat(void)
if (wifi_status == STATION_GOT_IP && ipconfig.ip.addr != 0) if (wifi_status == STATION_GOT_IP && ipconfig.ip.addr != 0)
{ {
if (syslogState == SYSLOG_WAIT) { // waiting for initialization if (syslogState == SYSLOG_WAIT) { // waiting for initialization
DBG_SYSLOG("connected, initializing UDP socket\n"); DBG("connected, initializing UDP socket\n");
syslog_init(flashConfig.syslog_host); syslog_init(flashConfig.syslog_host);
} }
} else { } else {
@ -75,15 +73,14 @@ syslog_chk_wifi_stat(void)
syslogState = SYSLOG_ERROR; syslogState = SYSLOG_ERROR;
os_printf("*** connect failure!!!\n"); os_printf("*** connect failure!!!\n");
} else { } else {
DBG_SYSLOG("re-arming timer...\n"); DBG("re-arming timer...\n");
os_timer_setfn(&wifi_chk_timer, (os_timer_func_t *)syslog_chk_wifi_stat, NULL); os_timer_setfn(&wifi_chk_timer, (os_timer_func_t *)syslog_chk_wifi_stat, NULL);
os_timer_arm(&wifi_chk_timer, WIFI_CHK_INTERVAL, 0); os_timer_arm(&wifi_chk_timer, WIFI_CHK_INTERVAL, 0);
} }
} }
} }
LOCAL void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR syslog_udp_send_event(os_event_t *events) {
syslog_udp_send_event(os_event_t *events) {
if (syslogQueue == NULL) if (syslogQueue == NULL)
syslogState = SYSLOG_READY; syslogState = SYSLOG_READY;
else { else {
@ -103,8 +100,7 @@ syslog_udp_send_event(os_event_t *events) {
* Parameters : va_args * Parameters : va_args
* Returns : the malloced syslog_entry_t * Returns : the malloced syslog_entry_t
******************************************************************************/ ******************************************************************************/
LOCAL syslog_entry_t ICACHE_FLASH_ATTR * static syslog_entry_t* ICACHE_FLASH_ATTR syslog_compose(uint8_t facility, uint8_t severity, const char *tag, const char *fmt, ...)
syslog_compose(uint8_t facility, uint8_t severity, const char *tag, const char *fmt, ...)
{ {
syslog_entry_t *se = os_zalloc(sizeof (syslog_entry_t) + 1024); // allow up to 1k datagram syslog_entry_t *se = os_zalloc(sizeof (syslog_entry_t) + 1024); // allow up to 1k datagram
char *p = se->datagram; char *p = se->datagram;
@ -155,8 +151,7 @@ syslog_compose(uint8_t facility, uint8_t severity, const char *tag, const char *
* Parameters : entry: the syslog_entry_t * Parameters : entry: the syslog_entry_t
* Returns : none * Returns : none
******************************************************************************/ ******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR syslog_add_entry(syslog_entry_t *entry)
syslog_add_entry(syslog_entry_t *entry)
{ {
syslog_entry_t *pse = syslogQueue; syslog_entry_t *pse = syslogQueue;
@ -188,8 +183,7 @@ syslog_add_entry(syslog_entry_t *entry)
* Parameters : arg -- Additional argument to pass to the callback function * Parameters : arg -- Additional argument to pass to the callback function
* Returns : none * Returns : none
******************************************************************************/ ******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR syslog_udp_sent_cb(void *arg)
syslog_udp_sent_cb(void *arg)
{ {
struct espconn *pespconn = arg; struct espconn *pespconn = arg;
(void) pespconn; (void) pespconn;
@ -214,18 +208,16 @@ syslog_udp_sent_cb(void *arg)
* Returns : none * Returns : none
******************************************************************************/ ******************************************************************************/
#ifdef SYSLOG_UDP_RECV #ifdef SYSLOG_UDP_RECV
LOCAL void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR syslog_udp_recv_cb(void *arg, char *pusrdata, unsigned short length)
syslog_udp_recv_cb(void *arg, char *pusrdata, unsigned short length)
{ {
DBG_SYSLOG("syslog_udp_recv_cb: %p, %p, %d\n", arg, pusrdata, length); DBG("syslog_udp_recv_cb: %p, %p, %d\n", arg, pusrdata, length);
} }
#endif #endif
/****************************************************************************** /******************************************************************************
* *
******************************************************************************/ ******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR syslog_gethostbyname_cb(const char *name, ip_addr_t *ipaddr, void *arg)
syslog_gethostbyname_cb(const char *name, ip_addr_t *ipaddr, void *arg)
{ {
struct espconn *pespconn = (struct espconn *)arg; struct espconn *pespconn = (struct espconn *)arg;
(void) pespconn; (void) pespconn;
@ -235,20 +227,23 @@ syslog_gethostbyname_cb(const char *name, ip_addr_t *ipaddr, void *arg)
syslog_send_udp(); syslog_send_udp();
} else { } else {
syslogState = SYSLOG_ERROR; syslogState = SYSLOG_ERROR;
DBG_SYSLOG("syslog_gethostbyname_cb: state=SYSLOG_ERROR\n"); DBG("syslog_gethostbyname_cb: state=SYSLOG_ERROR\n");
} }
} }
/****************************************************************************** /******************************************************************************
* FunctionName : initSyslog * FunctionName : initSyslog
* Description : Initialize the syslog library * Description : Initialize the syslog library
* Parameters : hostname -- the syslog server (host:port) * Parameters : syslog_host -- the syslog host (host:port)
* host: IP-Addr | hostname * host: IP-Addr | hostname
* Returns : none * Returns : none
*******************************************************************************/ *******************************************************************************/
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR syslog_init(char *syslog_host)
syslog_init(char *syslog_server)
{ {
if (!*syslog_host) {
syslogState = SYSLOG_HALTED;
return;
}
char host[32], *port = &host[0]; char host[32], *port = &host[0];
syslog_task = register_usr_task(syslog_udp_send_event); syslog_task = register_usr_task(syslog_udp_send_event);
@ -256,7 +251,7 @@ syslog_init(char *syslog_server)
syslogHost.port = 514; syslogHost.port = 514;
syslogState = SYSLOG_WAIT; syslogState = SYSLOG_WAIT;
os_strncpy(host, syslog_server, 32); os_strncpy(host, syslog_host, 32);
while (*port && *port != ':') // find port delimiter while (*port && *port != ':') // find port delimiter
port++; port++;
if (*port) { if (*port) {
@ -283,11 +278,11 @@ syslog_init(char *syslog_server)
// syslog_send_udp is called by syslog_gethostbyname_cb() // syslog_send_udp is called by syslog_gethostbyname_cb()
} }
#ifdef SYSLOG_UDP_RECV #ifdef SYSLOG_UDP_RECV
DBG_SYSLOG("syslog_init: host: %s, port: %d, lport: %d, recvcb: %p, sentcb: %p, state: %d\n", DBG("syslog_init: host: %s, port: %d, lport: %d, recvcb: %p, sentcb: %p, state: %d\n",
host, syslogHost.port, syslog_espconn.proto.udp->local_port, host, syslogHost.port, syslog_espconn.proto.udp->local_port,
syslog_udp_recv_cb, syslog_udp_sent_cb, syslogState ); syslog_udp_recv_cb, syslog_udp_sent_cb, syslogState );
#else #else
DBG_SYSLOG("syslog_init: host: %s, port: %d, lport: %d, rsentcb: %p, state: %d\n", DBG("syslog_init: host: %s, port: %d, lport: %d, rsentcb: %p, state: %d\n",
host, syslogHost.port, syslog_espconn.proto.udp->local_port, host, syslogHost.port, syslog_espconn.proto.udp->local_port,
syslog_udp_sent_cb, syslogState ); syslog_udp_sent_cb, syslogState );
#endif #endif
@ -364,10 +359,9 @@ syslog_init(char *syslog_server)
* *
* Returns : none * Returns : none
*******************************************************************************/ *******************************************************************************/
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR syslog(uint8_t facility, uint8_t severity, const char *tag, const char *fmt, ...)
syslog(uint8_t facility, uint8_t severity, const char *tag, const char *fmt, ...)
{ {
DBG_SYSLOG("syslog: state=%d ", syslogState); DBG("syslog: state=%d ", syslogState);
if (syslogState == SYSLOG_ERROR || if (syslogState == SYSLOG_ERROR ||
syslogState == SYSLOG_HALTED) syslogState == SYSLOG_HALTED)
return; return;

@ -84,7 +84,7 @@ struct syslog_entry_t {
syslog_host_t syslogserver; syslog_host_t syslogserver;
void ICACHE_FLASH_ATTR syslog_init(char *syslog_server); void ICACHE_FLASH_ATTR syslog_init(char *syslog_host);
void ICACHE_FLASH_ATTR syslog(uint8_t facility, uint8_t severity, const char tag[], const char message[], ...); void ICACHE_FLASH_ATTR syslog(uint8_t facility, uint8_t severity, const char tag[], const char message[], ...);
// some convenience macros // some convenience macros

Loading…
Cancel
Save