merged in ifdefs for debug and mqtt webpage additions

pull/47/head
Benjamin Runnels 9 years ago
commit 3337cc1508
  1. 1
      .gitignore
  2. 72
      Makefile
  3. 25
      cmd/cmd.c
  4. 22
      cmd/handlers.c
  5. 16
      esp-link.vcxproj
  6. 40
      esp-link/cgi.c
  7. 12
      esp-link/cgiflash.c
  8. 50
      esp-link/cgimqtt.c
  9. 3
      esp-link/cgipins.c
  10. 48
      esp-link/cgiwifi.c
  11. 50
      esp-link/config.c
  12. 9
      esp-link/config.h
  13. 4
      esp-link/log.c
  14. 21
      esp-link/main.c
  15. 4
      esp-link/mqtt_client.c
  16. 2
      esp-link/status.c
  17. 8
      espfs/espfs.c
  18. BIN
      html/favicon.ico
  19. 15
      html/mqtt.html
  20. 5
      html/style.css
  21. BIN
      html/wifi/icons.png
  22. 382
      httpd/httpd.c
  23. 42
      include/user_config.h
  24. 79
      mqtt/mqtt.c
  25. 33
      mqtt/mqtt_cmd.c
  26. 2
      mqtt/mqtt_msg.h
  27. 4
      mqtt/pktbuf.c
  28. 2
      mqtt/pktbuf.h
  29. 58
      rest/rest.c
  30. 41
      serial/serbridge.c
  31. 2
      serial/serled.c
  32. 5
      serial/slip.c
  33. 14
      serial/uart.c

1
.gitignore vendored

@ -15,3 +15,4 @@ esp-link.opensdf
esp-link.sdf esp-link.sdf
espfs/mkespfsimage/mman-win32/libmman.a espfs/mkespfsimage/mman-win32/libmman.a
.localhistory/ .localhistory/
tools/

@ -136,15 +136,20 @@ CHANGE_TO_STA ?= yes
#Static gzipping is disabled by default. #Static gzipping is disabled by default.
GZIP_COMPRESSION ?= yes GZIP_COMPRESSION ?= yes
# If COMPRESS_W_YUI is set to "yes" then the static css and js files will be compressed with # If COMPRESS_W_HTMLCOMPRESSOR is set to "yes" then the static css and js files will be compressed with
# yui-compressor. This option works only when GZIP_COMPRESSION is set to "yes". # htmlcompressor and yui-compressor. This option works only when GZIP_COMPRESSION is set to "yes".
# https://code.google.com/p/htmlcompressor/#For_Non-Java_Projects
# http://yui.github.io/yuicompressor/ # http://yui.github.io/yuicompressor/
#Disabled by default. # enabled by default.
COMPRESS_W_YUI ?= yes COMPRESS_W_HTMLCOMPRESSOR ?= yes
HTML-COMPRESSOR ?= htmlcompressor-1.5.3.jar
YUI-COMPRESSOR ?= yuicompressor-2.4.8.jar YUI-COMPRESSOR ?= yuicompressor-2.4.8.jar
HTML_PATH = $(abspath ./html)/
WIFI_PATH = $(HTML_PATH)wifi/
# Optional Modules # Optional Modules
MODULES ?= rest MODULES ?= mqtt rest
# -------------- End of config options ------------- # -------------- End of config options -------------
@ -170,19 +175,23 @@ ifneq (,$(findstring rest,$(MODULES)))
CFLAGS += -DREST CFLAGS += -DREST
endif endif
ifneq (,$(findstring tcpclient,$(MODULES)))
CFLAGS += -DTCPCLIENT
endif
# which modules (subdirectories) of the project to include in compiling # which modules (subdirectories) of the project to include in compiling
LIBRARIES_DIR = libraries LIBRARIES_DIR = libraries
MODULES += espfs httpd user serial cmd esp-link MODULES += espfs httpd user serial cmd esp-link
MODULES += $(foreach sdir,$(LIBRARIES_DIR),$(wildcard $(sdir)/*)) MODULES += $(foreach sdir,$(LIBRARIES_DIR),$(wildcard $(sdir)/*))
EXTRA_INCDIR =include .
EXTRA_INCDIR = include . EXTRA_INCDIR = include .
# libraries used in this project, mainly provided by the SDK # libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal phy pp net80211 wpa main lwip # crypto ssl LIBS = c gcc hal phy pp net80211 wpa main lwip
# 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 \
-nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-sections \ -nostdlib -mlongcalls -mtext-section-literals -ffunction-sections -fdata-sections \
-Wno-unused-function -Wno-unused-variable \
-D__ets__ -DICACHE_FLASH -D_STDINT_H -Wno-address -DFIRMWARE_SIZE=$(ESP_FLASH_MAX) \ -D__ets__ -DICACHE_FLASH -D_STDINT_H -Wno-address -DFIRMWARE_SIZE=$(ESP_FLASH_MAX) \
-DMCU_RESET_PIN=$(MCU_RESET_PIN) -DMCU_ISP_PIN=$(MCU_ISP_PIN) \ -DMCU_RESET_PIN=$(MCU_RESET_PIN) -DMCU_ISP_PIN=$(MCU_ISP_PIN) \
-DLED_CONN_PIN=$(LED_CONN_PIN) -DLED_SERIAL_PIN=$(LED_SERIAL_PIN) \ -DLED_CONN_PIN=$(LED_CONN_PIN) -DLED_SERIAL_PIN=$(LED_SERIAL_PIN) \
@ -321,34 +330,51 @@ flash: all
0x00000 "$(SDK_BASE)/bin/boot_v1.4(b1).bin" 0x01000 $(FW_BASE)/user1.bin \ 0x00000 "$(SDK_BASE)/bin/boot_v1.4(b1).bin" 0x01000 $(FW_BASE)/user1.bin \
$(ET_BLANK) $(SDK_BASE)/bin/blank.bin $(ET_BLANK) $(SDK_BASE)/bin/blank.bin
yui/$(YUI-COMPRESSOR): tools/$(HTML-COMPRESSOR):
$(Q) mkdir -p yui $(Q) mkdir -p tools
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
cd yui; wget --no-check-certificate https://github.com/yui/yuicompressor/releases/download/v2.4.8/$(YUI-COMPRESSOR) -O $(YUI-COMPRESSOR) cd tools; wget --no-check-certificate https://github.com/yui/yuicompressor/releases/download/v2.4.8/$(YUI-COMPRESSOR) -O $(YUI-COMPRESSOR)
cd tools; wget --no-check-certificate https://htmlcompressor.googlecode.com/files/$(HTML-COMPRESSOR) -O $(HTML-COMPRESSOR)
else else
cd yui; wget https://github.com/yui/yuicompressor/releases/download/v2.4.8/$(YUI-COMPRESSOR) cd tools; wget https://github.com/yui/yuicompressor/releases/download/v2.4.8/$(YUI-COMPRESSOR)
cd tools; wget https://htmlcompressor.googlecode.com/files/$(HTML-COMPRESSOR)
endif endif
ifeq ("$(COMPRESS_W_YUI)","yes") ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(BUILD_BASE)/espfs_img.o: yui/$(YUI-COMPRESSOR) $(BUILD_BASE)/espfs_img.o: tools/$(HTML-COMPRESSOR)
endif endif
$(BUILD_BASE)/espfs_img.o: html/ html/wifi/ espfs/mkespfsimage/mkespfsimage $(BUILD_BASE)/espfs_img.o: html/ html/wifi/ espfs/mkespfsimage/mkespfsimage
$(Q) rm -rf html_compressed; $(Q) rm -rf html_compressed; mkdir html_compressed; mkdir html_compressed/wifi;
$(Q) cp -r html html_compressed; $(Q) cp -r html/*.ico html_compressed;
$(Q) for file in `find html_compressed -type f -name "*.htm*"`; do \ $(Q) cp -r html/*.css html_compressed;
cat html_compressed/head- $$file >$${file}-; \ $(Q) cp -r html/*.js html_compressed;
mv $$file- $$file; \ $(Q) cp -r html/wifi/*.png html_compressed/wifi;
done $(Q) cp -r html/wifi/*.js html_compressed/wifi;
ifeq ("$(COMPRESS_W_YUI)","yes") ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) echo "Compression assets with htmlcompressor. This may take a while..."
$(Q) java -jar tools/$(HTML-COMPRESSOR) \
-t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \
-o $(abspath ./html_compressed)/ \
$(HTML_PATH)head- \
$(HTML_PATH)*.html
$(Q) java -jar tools/$(HTML-COMPRESSOR) \
-t html --remove-surrounding-spaces max --remove-quotes --remove-intertag-spaces \
-o $(abspath ./html_compressed)/wifi/ \
$(WIFI_PATH)*.html
$(Q) echo "Compression assets with yui-compressor. This may take a while..." $(Q) echo "Compression assets with yui-compressor. This may take a while..."
$(Q) for file in `find html_compressed -type f -name "*.js"`; do \ $(Q) for file in `find html_compressed -type f -name "*.js"`; do \
java -jar yui/$(YUI-COMPRESSOR) $$file --nomunge --line-break 40 -o $$file; \ java -jar tools/$(YUI-COMPRESSOR) $$file -o $$file; \
done done
$(Q) for file in `find html_compressed -type f -name "*.css"`; do \ $(Q) for file in `find html_compressed -type f -name "*.css"`; do \
java -jar yui/$(YUI-COMPRESSOR) $$file -o $$file; \ java -jar tools/$(YUI-COMPRESSOR) $$file -o $$file; \
done done
endif endif
$(Q) for file in `find html_compressed -type f -name "*.htm*"`; do \
cat html_compressed/head- $$file >$${file}-; \
mv $$file- $$file; \
done
$(Q) rm html_compressed/head-
$(Q) cd html_compressed; find . \! -name \*- | ../espfs/mkespfsimage/mkespfsimage > ../build/espfs.img; cd ..; $(Q) cd html_compressed; find . \! -name \*- | ../espfs/mkespfsimage/mkespfsimage > ../build/espfs.img; cd ..;
$(Q) ls -sl build/espfs.img $(Q) ls -sl build/espfs.img
$(Q) cd build; $(OBJCP) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.espfs \ $(Q) cd build; $(OBJCP) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.espfs \
@ -398,7 +424,7 @@ clean:
$(Q) make -C espfs/mkespfsimage/ clean $(Q) make -C espfs/mkespfsimage/ clean
$(Q) rm -rf $(FW_BASE) $(Q) rm -rf $(FW_BASE)
$(Q) rm -f webpages.espfs $(Q) rm -f webpages.espfs
ifeq ("$(COMPRESS_W_YUI)","yes") ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) rm -rf html_compressed $(Q) rm -rf html_compressed
endif endif

@ -2,10 +2,8 @@
// //
// Adapted from: github.com/tuanpmt/esp_bridge, Created on: Jan 9, 2015, Author: Minh // Adapted from: github.com/tuanpmt/esp_bridge, Created on: Jan 9, 2015, Author: Minh
#include "esp8266.h"
#include "cmd.h" #include "cmd.h"
#include "crc16.h" #include "crc16.h"
#include "serbridge.h"
#include "uart.h" #include "uart.h"
extern const CmdList commands[]; extern const CmdList commands[];
@ -83,22 +81,30 @@ 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); #ifdef CMD_DBG
os_printf("CMD: Dispatching cmd=%d\n", packet->cmd);
#endif
// 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
os_printf("CMD: 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 {
//os_printf("CMD: no response (%lu)\n", packet->_return); #ifdef CMD_DBG
os_printf("CMD: no response (%lu)\n", packet->_return);
#endif
} }
return ret; return ret;
} }
scp++; scp++;
} }
#ifdef CMD_DBG
os_printf("CMD: cmd=%d not found\n", packet->cmd); os_printf("CMD: cmd=%d not found\n", packet->cmd);
#endif
return 0; return 0;
} }
@ -113,26 +119,35 @@ CMD_parse_packet(uint8_t *buf, short len) {
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;
uint16_t argc = packet->argc; uint16_t argc = packet->argc;
#ifdef CMD_DBG
uint16_t argn = 0; uint16_t argn = 0;
os_printf("CMD: cmd=%d argc=%d cb=%p ret=%lu\n", os_printf("CMD: cmd=%d argc=%d cb=%p ret=%lu\n",
packet->cmd, packet->argc, (void *)packet->callback, packet->_return); packet->cmd, packet->argc, (void *)packet->callback, packet->_return);
#endif
// print out arguments // print out arguments
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;
#ifdef CMD_DBG
os_printf("CMD: arg[%d] len=%d:", argn++, l); os_printf("CMD: arg[%d] len=%d:", argn++, l);
#endif
data_ptr += 2; data_ptr += 2;
while (data_ptr < data_limit && l--) { while (data_ptr < data_limit && l--) {
#ifdef CMD_DBG
os_printf(" %02X", *data_ptr++); os_printf(" %02X", *data_ptr++);
#endif
} }
#ifdef CMD_DBG
os_printf("\n"); os_printf("\n");
#endif
} }
if (data_ptr <= data_limit) { if (data_ptr <= data_limit) {
CMD_Exec(commands, packet); CMD_Exec(commands, packet);
} else { } else {
#ifdef CMD_DBG
os_printf("CMD: packet length overrun, parsing arg %d\n", argn-1); os_printf("CMD: packet length overrun, parsing arg %d\n", argn-1);
#endif
} }
} }

@ -41,7 +41,7 @@ const CmdList commands[] = {
{CMD_REST_REQUEST, REST_Request}, {CMD_REST_REQUEST, REST_Request},
{CMD_REST_SETHEADER, REST_SetHeader}, {CMD_REST_SETHEADER, REST_SetHeader},
#endif #endif
{ CMD_CB_ADD, CMD_AddCallback }, {CMD_CB_ADD, CMD_AddCallback},
{CMD_NULL, NULL} {CMD_NULL, NULL}
}; };
@ -52,14 +52,18 @@ cmdCallback callbacks[MAX_CALLBACKS]; // cleared in CMD_Reset
// Command handler for IsReady (healthcheck) command // Command handler for IsReady (healthcheck) command
static uint32_t ICACHE_FLASH_ATTR static uint32_t ICACHE_FLASH_ATTR
CMD_IsReady(CmdPacket *cmd) { CMD_IsReady(CmdPacket *cmd) {
#ifdef CMD_DBG
os_printf("CMD_IsReady: Check ready\n"); os_printf("CMD_IsReady: Check ready\n");
#endif
return 1; return 1;
} }
// Command handler for Null command // Command handler for Null command
static uint32_t ICACHE_FLASH_ATTR static uint32_t ICACHE_FLASH_ATTR
CMD_Null(CmdPacket *cmd) { CMD_Null(CmdPacket *cmd) {
#ifdef CMD_DBG
os_printf("CMD_Null: NULL/unsupported command\n"); os_printf("CMD_Null: NULL/unsupported command\n");
#endif
return 1; return 1;
} }
@ -68,7 +72,9 @@ CMD_Null(CmdPacket *cmd) {
// uC. // uC.
static uint32_t ICACHE_FLASH_ATTR static uint32_t ICACHE_FLASH_ATTR
CMD_Reset(CmdPacket *cmd) { CMD_Reset(CmdPacket *cmd) {
#ifdef CMD_DBG
os_printf("CMD_Reset\n"); os_printf("CMD_Reset\n");
#endif
// clear callbacks table // clear callbacks table
os_memset(callbacks, 0, sizeof(callbacks)); os_memset(callbacks, 0, sizeof(callbacks));
return 1; return 1;
@ -83,7 +89,9 @@ CMD_AddCb(char* name, uint32_t cb) {
if (os_strcmp(callbacks[i].name, name) == 0 || callbacks[i].name[0] == '\0') { if (os_strcmp(callbacks[i].name, name) == 0 || callbacks[i].name[0] == '\0') {
os_strncpy(callbacks[i].name, name, sizeof(callbacks[i].name)); os_strncpy(callbacks[i].name, name, sizeof(callbacks[i].name));
callbacks[i].callback = cb; callbacks[i].callback = cb;
#ifdef CMD_DBG
os_printf("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;
} }
} }
@ -99,7 +107,9 @@ 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_strcmp(callbacks[i].name, checkname) == 0) { if (os_strcmp(callbacks[i].name, checkname) == 0) {
#ifdef CMD_DBG
os_printf("CMD_GetCbByName: cb %s found at index %d\n", callbacks[i].name, i); os_printf("CMD_GetCbByName: cb %s found at index %d\n", callbacks[i].name, i);
#endif
return &callbacks[i]; return &callbacks[i];
} }
} }
@ -111,7 +121,9 @@ 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
os_printf("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) {
@ -128,7 +140,9 @@ static uint32_t ICACHE_FLASH_ATTR
CMD_WifiConnect(CmdPacket *cmd) { CMD_WifiConnect(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); CMD_Request(&req, cmd);
#ifdef CMD_DBG
os_printf("CMD_WifiConnect: setup argc=%ld\n", CMD_GetArgc(&req)); os_printf("CMD_WifiConnect: setup argc=%ld\n", CMD_GetArgc(&req));
#endif
if(cmd->argc != 2 || cmd->callback == 0) if(cmd->argc != 2 || cmd->callback == 0)
return 0; return 0;
@ -148,7 +162,9 @@ static uint32_t ICACHE_FLASH_ATTR
CMD_AddCallback(CmdPacket *cmd) { CMD_AddCallback(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); CMD_Request(&req, cmd);
#ifdef CMD_DBG
os_printf("CMD_AddCallback: setup argc=%ld\n", CMD_GetArgc(&req)); os_printf("CMD_AddCallback: setup argc=%ld\n", CMD_GetArgc(&req));
#endif
if (cmd->argc != 1 || cmd->callback == 0) if (cmd->argc != 1 || cmd->callback == 0)
return 0; return 0;
@ -157,11 +173,15 @@ CMD_AddCallback(CmdPacket *cmd) {
// get the sensor name // get the sensor name
len = CMD_ArgLen(&req); len = CMD_ArgLen(&req);
#ifdef CMD_DBG
os_printf("CMD_AddCallback: name len=%d\n", len); os_printf("CMD_AddCallback: name len=%d\n", len);
#endif
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
os_printf("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
} }

@ -28,7 +28,7 @@
<PropertyGroup> <PropertyGroup>
<NMakeOutput /> <NMakeOutput />
<NMakePreprocessorDefinitions>__ets__;_STDINT_H;ICACHE_FLASH;__MINGW32__;__WIN32__</NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>__ets__;_STDINT_H;ICACHE_FLASH;__MINGW32__;__WIN32__</NMakePreprocessorDefinitions>
<NMakeIncludeSearchPath>.\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>.\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>
<ExecutablePath /> <ExecutablePath />
<ReferencePath /> <ReferencePath />
<LibraryPath /> <LibraryPath />
@ -39,12 +39,12 @@
<IntDir>build</IntDir> <IntDir>build</IntDir>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
<NMakeBuildCommandLine>espmake flash</NMakeBuildCommandLine> <NMakeBuildCommandLine>espmake all wiflash</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>espmake clean all</NMakeReBuildCommandLine> <NMakeReBuildCommandLine>espmake clean all</NMakeReBuildCommandLine>
<NMakeCleanCommandLine>espmake clean</NMakeCleanCommandLine> <NMakeCleanCommandLine>espmake clean</NMakeCleanCommandLine>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
<NMakeBuildCommandLine>espmake all wiflash</NMakeBuildCommandLine> <NMakeBuildCommandLine>espmake clean all wiflash</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>espmake clean all</NMakeReBuildCommandLine> <NMakeReBuildCommandLine>espmake clean all</NMakeReBuildCommandLine>
<NMakeCleanCommandLine>espmake clean</NMakeCleanCommandLine> <NMakeCleanCommandLine>espmake clean</NMakeCleanCommandLine>
</PropertyGroup> </PropertyGroup>
@ -65,9 +65,11 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="cmd\cmd.c" /> <ClCompile Include="cmd\cmd.c" />
<ClCompile Include="cmd\handlers.c" /> <ClCompile Include="cmd\handlers.c" />
<ClCompile Include="esp-link\cgimqtt.c" />
<ClCompile Include="esp-link\mqtt_client.c" />
<ClCompile Include="mqtt\mqtt_cmd.c" /> <ClCompile Include="mqtt\mqtt_cmd.c" />
<ClCompile Include="mqtt\pktbuf.c" />
<ClCompile Include="rest\rest.c" /> <ClCompile Include="rest\rest.c" />
<ClCompile Include="cmd\tcpclient.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" />
@ -76,6 +78,7 @@
<ClCompile Include="httpd\base64.c" /> <ClCompile Include="httpd\base64.c" />
<ClCompile Include="httpd\httpd.c" /> <ClCompile Include="httpd\httpd.c" />
<ClCompile Include="httpd\httpdespfs.c" /> <ClCompile Include="httpd\httpdespfs.c" />
<ClCompile Include="libraries\Time\Time.c" />
<ClCompile Include="mqtt\mqtt.c" /> <ClCompile Include="mqtt\mqtt.c" />
<ClCompile Include="mqtt\mqtt_msg.c" /> <ClCompile Include="mqtt\mqtt_msg.c" />
<ClCompile Include="mqtt\proto.c" /> <ClCompile Include="mqtt\proto.c" />
@ -108,9 +111,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="cmd\cmd.h" /> <ClInclude Include="cmd\cmd.h" />
<ClInclude Include="esp-link\cgimqtt.h" />
<ClInclude Include="mqtt\mqtt_cmd.h" /> <ClInclude Include="mqtt\mqtt_cmd.h" />
<ClInclude Include="mqtt\pktbuf.h" />
<ClInclude Include="rest\rest.h" /> <ClInclude Include="rest\rest.h" />
<ClInclude Include="cmd\tcpclient.h" /> <ClInclude Include="serial\slip.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" />
@ -122,6 +127,7 @@
<ClInclude Include="include\espmissingincludes.h" /> <ClInclude Include="include\espmissingincludes.h" />
<ClInclude Include="include\uart_hw.h" /> <ClInclude Include="include\uart_hw.h" />
<ClInclude Include="include\user_config.h" /> <ClInclude Include="include\user_config.h" />
<ClInclude Include="libraries\Time\Time.h" />
<ClInclude Include="mqtt\mqtt.h" /> <ClInclude Include="mqtt\mqtt.h" />
<ClInclude Include="mqtt\mqtt_msg.h" /> <ClInclude Include="mqtt\mqtt_msg.h" />
<ClInclude Include="mqtt\proto.h" /> <ClInclude Include="mqtt\proto.h" />

@ -16,7 +16,6 @@ Some random cgi routines.
#include <esp8266.h> #include <esp8266.h>
#include "cgi.h" #include "cgi.h"
#include "espfs.h"
void noCacheHeaders(HttpdConnData *connData, int code) { void noCacheHeaders(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code); httpdStartResponse(connData, code);
@ -37,7 +36,9 @@ 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
os_printf("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
@ -75,6 +76,43 @@ getBoolArg(HttpdConnData *connData, char *name, bool*config) {
return -1; return -1;
} }
uint8_t ICACHE_FLASH_ATTR
UTILS_StrToIP(const char* str, void *ip){
/* The count of the number of bytes processed. */
int i;
/* A pointer to the next digit to process. */
const char * start;
start = str;
for (i = 0; i < 4; i++) {
/* The digit being processed. */
char c;
/* The value of this byte. */
int n = 0;
while (1) {
c = *start;
start++;
if (c >= '0' && c <= '9') {
n *= 10;
n += c - '0';
}
/* We insist on stopping at "." if we are still parsing
the first, second, or third numbers. If we have reached
the end of the numbers, we will allow any character. */
else if ((i < 3 && c == '.') || i == 3) {
break;
}
else {
return 0;
}
}
if (n >= 256) {
return 0;
}
((uint8_t*)ip)[i] = n;
}
return 1;
}
#define TOKEN(x) (os_strcmp(token, x) == 0) #define TOKEN(x) (os_strcmp(token, x) == 0)
#if 0 #if 0

@ -22,8 +22,10 @@ Some flash handling cgi routines. Used for reading the existing flash and updati
// 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
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
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";
@ -42,7 +44,9 @@ int ICACHE_FLASH_ATTR cgiGetFirmwareNext(HttpdConnData *connData) {
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
os_printf("Next firmware: %s (got %d)\n", next, id); os_printf("Next firmware: %s (got %d)\n", next, id);
#endif
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
@ -80,7 +84,9 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
// return an error if there is one // return an error if there is one
if (err != NULL) { if (err != NULL) {
#ifdef CGIFLASH_DBG
os_printf("Error %d: %s\n", code, err); os_printf("Error %d: %s\n", code, err);
#endif
httpdStartResponse(connData, code); httpdStartResponse(connData, code);
httpdHeader(connData, "Content-Type", "text/plain"); httpdHeader(connData, "Content-Type", "text/plain");
//httpdHeader(connData, "Content-Length", strlen(err)+2); //httpdHeader(connData, "Content-Length", strlen(err)+2);
@ -99,7 +105,9 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
// erase next flash block if necessary // erase next flash block if necessary
if (address % SPI_FLASH_SEC_SIZE == 0){ if (address % SPI_FLASH_SEC_SIZE == 0){
#ifdef CGIFLASH_DBG
os_printf("Flashing 0x%05x (id=%d)\n", address, 2-id); os_printf("Flashing 0x%05x (id=%d)\n", address, 2-id);
#endif
spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE); spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE);
} }
@ -129,11 +137,15 @@ int ICACHE_FLASH_ATTR cgiRebootFirmware(HttpdConnData *connData) {
int address = id == 1 ? 4*1024 // either start after 4KB boot partition 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 : 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; // 4KB boot, fw1, 16KB user param, 4KB reserved
uint32 buf[8]; uint32 buf[8];
#ifdef CGIFLASH_DBG
os_printf("Checking %p\n", (void *)address); os_printf("Checking %p\n", (void *)address);
#endif
spi_flash_read(address, buf, sizeof(buf)); spi_flash_read(address, buf, sizeof(buf));
char *err = check_header(buf); char *err = check_header(buf);
if (err != NULL) { if (err != NULL) {
#ifdef CGIFLASH_DBG
os_printf("Error %d: %s\n", 400, err); os_printf("Error %d: %s\n", 400, err);
#endif
httpdStartResponse(connData, 400); httpdStartResponse(connData, 400);
httpdHeader(connData, "Content-Type", "text/plain"); httpdHeader(connData, "Content-Type", "text/plain");
//httpdHeader(connData, "Content-Length", strlen(err)+2); //httpdHeader(connData, "Content-Length", strlen(err)+2);

@ -17,17 +17,29 @@ int ICACHE_FLASH_ATTR cgiMqttGet(HttpdConnData *connData) {
"\"slip-enable\":%d, " "\"slip-enable\":%d, "
"\"mqtt-enable\":%d, " "\"mqtt-enable\":%d, "
"\"mqtt-status-enable\":%d, " "\"mqtt-status-enable\":%d, "
"\"mqtt-clean-session\":%d, "
"\"mqtt-port\":%d, " "\"mqtt-port\":%d, "
"\"mqtt-timeout\":%d, "
"\"mqtt-keepalive\":%d, "
"\"mqtt-host\":\"%s\", " "\"mqtt-host\":\"%s\", "
"\"mqtt-client-id\":\"%s\", " "\"mqtt-client-id\":\"%s\", "
"\"mqtt-username\":\"%s\", " "\"mqtt-username\":\"%s\", "
"\"mqtt-password\":\"%s\", " "\"mqtt-password\":\"%s\", "
"\"mqtt-status-topic\":\"%s\", " "\"mqtt-status-topic\":\"%s\", "
"\"mqtt-state\":\"%s\" }", "\"mqtt-state\":\"%s\" }",
flashConfig.slip_enable, flashConfig.mqtt_enable, flashConfig.mqtt_status_enable, flashConfig.slip_enable,
flashConfig.mqtt_port, flashConfig.mqtt_hostname, flashConfig.mqtt_client, flashConfig.mqtt_enable,
flashConfig.mqtt_username, flashConfig.mqtt_password, flashConfig.mqtt_status_enable,
flashConfig.mqtt_status_topic, "connected"); flashConfig.mqtt_clean_session,
flashConfig.mqtt_port,
flashConfig.mqtt_timeout,
flashConfig.mqtt_keepalive,
flashConfig.mqtt_host,
flashConfig.mqtt_clientid,
flashConfig.mqtt_username,
flashConfig.mqtt_password,
flashConfig.mqtt_status_topic,
"connected");
jsonHeader(connData, 200); jsonHeader(connData, 200);
httpdSend(connData, buff, len); httpdSend(connData, buff, len);
@ -41,22 +53,30 @@ int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) {
// handle MQTT server settings // handle MQTT server settings
int mqtt_server = 0; // accumulator for changes/errors int mqtt_server = 0; // accumulator for changes/errors
mqtt_server |= getStringArg(connData, "mqtt-host", mqtt_server |= getStringArg(connData, "mqtt-host",
flashConfig.mqtt_hostname, sizeof(flashConfig.mqtt_hostname)); flashConfig.mqtt_host, sizeof(flashConfig.mqtt_host));
if (mqtt_server < 0) return HTTPD_CGI_DONE; if (mqtt_server < 0) return HTTPD_CGI_DONE;
mqtt_server |= getStringArg(connData, "mqtt-client-id", mqtt_server |= getStringArg(connData, "mqtt-client-id",
flashConfig.mqtt_client, sizeof(flashConfig.mqtt_client)); flashConfig.mqtt_clientid, sizeof(flashConfig.mqtt_clientid));
if (mqtt_server < 0) return HTTPD_CGI_DONE; if (mqtt_server < 0) return HTTPD_CGI_DONE;
mqtt_server |= getStringArg(connData, "mqtt-username", mqtt_server |= getStringArg(connData, "mqtt-username",
flashConfig.mqtt_username, sizeof(flashConfig.mqtt_username)); flashConfig.mqtt_username, sizeof(flashConfig.mqtt_username));
if (mqtt_server < 0) return HTTPD_CGI_DONE; if (mqtt_server < 0) return HTTPD_CGI_DONE;
mqtt_server |= getStringArg(connData, "mqtt-password", mqtt_server |= getStringArg(connData, "mqtt-password",
flashConfig.mqtt_password, sizeof(flashConfig.mqtt_password)); flashConfig.mqtt_password, sizeof(flashConfig.mqtt_password));
if (mqtt_server < 0) return HTTPD_CGI_DONE;
mqtt_server |= getBoolArg(connData, "mqtt-clean-session",
&flashConfig.mqtt_clean_session);
if (mqtt_server < 0) return HTTPD_CGI_DONE; if (mqtt_server < 0) return HTTPD_CGI_DONE;
mqtt_server |= getBoolArg(connData, "mqtt-enable", mqtt_server |= getBoolArg(connData, "mqtt-enable",
&flashConfig.mqtt_enable); &flashConfig.mqtt_enable);
// handle mqtt port
char buff[16]; char buff[16];
// handle mqtt port
if (httpdFindArg(connData->getArgs, "mqtt-port", buff, sizeof(buff)) > 0) { if (httpdFindArg(connData->getArgs, "mqtt-port", buff, sizeof(buff)) > 0) {
int32_t port = atoi(buff); int32_t port = atoi(buff);
if (port > 0 && port < 65536) { if (port > 0 && port < 65536) {
@ -68,9 +88,23 @@ int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) {
} }
} }
// handle mqtt timeout
if (httpdFindArg(connData->getArgs, "mqtt-timeout", buff, sizeof(buff)) > 0) {
int32_t timeout = atoi(buff);
flashConfig.mqtt_timeout = timeout;
}
// handle mqtt keepalive
if (httpdFindArg(connData->getArgs, "mqtt-keepalive", buff, sizeof(buff)) > 0) {
int32_t keepalive = atoi(buff);
flashConfig.mqtt_keepalive = keepalive;
}
// 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
os_printf("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable); os_printf("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable);
#endif
// TODO // TODO
} }
@ -85,9 +119,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) os_printf("SLIP-enable changed: %d\n", flashConfig.slip_enable); if (slip_update > 0) os_printf("SLIP-enable changed: %d\n", flashConfig.slip_enable);
os_printf("Saving config\n"); os_printf("Saving config\n");
#endif
if (configSave()) { if (configSave()) {
httpdStartResponse(connData, 200); httpdStartResponse(connData, 200);
httpdEndHeaders(connData); httpdEndHeaders(connData);

@ -85,8 +85,9 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) {
jsonHeader(connData, 400); jsonHeader(connData, 400);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
#ifdef CGIPINS_DBG
os_printf("Switching pin map to %s (%d)\n", map_names[m], m); os_printf("Switching pin map to %s (%d)\n", map_names[m], m);
#endif
int8_t *map = map_asn[m]; int8_t *map = map_asn[m];
flashConfig.reset_pin = map[0]; flashConfig.reset_pin = map[0];
flashConfig.isp_pin = map[1]; flashConfig.isp_pin = map[1];

@ -55,36 +55,48 @@ static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) {
case EVENT_STAMODE_CONNECTED: case EVENT_STAMODE_CONNECTED:
wifiState = wifiIsConnected; wifiState = wifiIsConnected;
wifiReason = 0; wifiReason = 0;
#ifdef CGIWIFI_DBG
os_printf("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, os_printf("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid,
evt->event_info.connected.channel); evt->event_info.connected.channel);
#endif
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;
#ifdef CGIWIFI_DBG
os_printf("Wifi disconnected from ssid %s, reason %s (%d)\n", os_printf("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);
#endif
statusWifiUpdate(wifiState); statusWifiUpdate(wifiState);
break; break;
case EVENT_STAMODE_AUTHMODE_CHANGE: case EVENT_STAMODE_AUTHMODE_CHANGE:
#ifdef CGIWIFI_DBG
os_printf("Wifi auth mode: %d -> %d\n", os_printf("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);
#endif
break; break;
case EVENT_STAMODE_GOT_IP: case EVENT_STAMODE_GOT_IP:
wifiState = wifiGotIP; wifiState = wifiGotIP;
wifiReason = 0; wifiReason = 0;
#ifdef CGIWIFI_DBG
os_printf("Wifi got ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR "\n", os_printf("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));
#endif
statusWifiUpdate(wifiState); statusWifiUpdate(wifiState);
break; break;
case EVENT_SOFTAPMODE_STACONNECTED: case EVENT_SOFTAPMODE_STACONNECTED:
#ifdef CGIWIFI_DBG
os_printf("Wifi AP: station " MACSTR " joined, AID = %d\n", os_printf("Wifi AP: station " MACSTR " joined, AID = %d\n",
MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid);
#endif
break; break;
case EVENT_SOFTAPMODE_STADISCONNECTED: case EVENT_SOFTAPMODE_STADISCONNECTED:
#ifdef CGIWIFI_DBG
os_printf("Wifi AP: station " MACSTR " left, AID = %d\n", os_printf("Wifi AP: station " MACSTR " left, AID = %d\n",
MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid);
#endif
break; break;
default: default:
break; break;
@ -103,7 +115,9 @@ wifiAddStateChangeCb(WifiStateChangeCb cb) {
return; return;
} }
} }
#ifdef CGIWIFI_DBG
os_printf("WIFI: max state change cb count exceeded\n"); os_printf("WIFI: max state change cb count exceeded\n");
#endif
} }
// ===== wifi scanning // ===== wifi scanning
@ -132,7 +146,9 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
struct bss_info *bss_link = (struct bss_info *)arg; struct bss_info *bss_link = (struct bss_info *)arg;
if (status!=OK) { if (status!=OK) {
#ifdef CGIWIFI_DBG
os_printf("wifiScanDoneCb status=%d\n", status); os_printf("wifiScanDoneCb status=%d\n", status);
#endif
cgiWifiAps.scanInProgress=0; cgiWifiAps.scanInProgress=0;
return; return;
} }
@ -152,7 +168,9 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
//Allocate memory for access point data //Allocate memory for access point data
cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n);
cgiWifiAps.noAps=n; cgiWifiAps.noAps=n;
#ifdef CGIWIFI_DBG
os_printf("Scan done: found %d APs\n", n); os_printf("Scan done: found %d APs\n", n);
#endif
//Copy access point data to the static struct //Copy access point data to the static struct
n=0; n=0;
@ -161,7 +179,9 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
if (n>=cgiWifiAps.noAps) { if (n>=cgiWifiAps.noAps) {
//This means the bss_link changed under our nose. Shouldn't happen! //This means the bss_link changed under our nose. Shouldn't happen!
//Break because otherwise we will write in unallocated memory. //Break because otherwise we will write in unallocated memory.
#ifdef CGIWIFI_DBG
os_printf("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); os_printf("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps);
#endif
break; break;
} }
//Save the ap data. //Save the ap data.
@ -169,7 +189,9 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
cgiWifiAps.apData[n]->rssi=bss_link->rssi; cgiWifiAps.apData[n]->rssi=bss_link->rssi;
cgiWifiAps.apData[n]->enc=bss_link->authmode; cgiWifiAps.apData[n]->enc=bss_link->authmode;
strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32);
#ifdef CGIWIFI_DBG
os_printf("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); os_printf("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi);
#endif
bss_link = bss_link->next.stqe_next; bss_link = bss_link->next.stqe_next;
n++; n++;
@ -180,7 +202,9 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) {
static ETSTimer scanTimer; static ETSTimer scanTimer;
static void ICACHE_FLASH_ATTR scanStartCb(void *arg) { static void ICACHE_FLASH_ATTR scanStartCb(void *arg) {
#ifdef CGIWIFI_DBG
os_printf("Starting a scan\n"); os_printf("Starting a scan\n");
#endif
wifi_station_scan(NULL, wifiScanDoneCb); wifi_station_scan(NULL, wifiScanDoneCb);
} }
@ -245,13 +269,17 @@ static ETSTimer resetTimer;
static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
int x = wifi_station_get_connect_status(); int x = wifi_station_get_connect_status();
int m = wifi_get_opmode() & 0x3; int m = wifi_get_opmode() & 0x3;
#ifdef CGIWIFI_DBG
os_printf("Wifi check: mode=%s status=%d\n", wifiMode[m], x); os_printf("Wifi check: mode=%s status=%d\n", wifiMode[m], x);
#endif
if (x == STATION_GOT_IP) { if (x == STATION_GOT_IP) {
if (m != 1) { if (m != 1) {
#ifdef CHANGE_TO_STA #ifdef CHANGE_TO_STA
// We're happily connected, go to STA mode // We're happily connected, go to STA mode
#ifdef CGIWIFI_DBG
os_printf("Wifi got IP. Going into STA mode..\n"); os_printf("Wifi got IP. Going into STA mode..\n");
#endif
wifi_set_opmode(1); wifi_set_opmode(1);
wifi_set_sleep_type(SLEEP_MODE); wifi_set_sleep_type(SLEEP_MODE);
os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); os_timer_arm(&resetTimer, RESET_TIMEOUT, 0);
@ -261,11 +289,15 @@ static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) {
// no more resetTimer at this point, gotta use physical reset to recover if in trouble // no more resetTimer at this point, gotta use physical reset to recover if in trouble
} else { } else {
if (m != 3) { if (m != 3) {
#ifdef CGIWIFI_DBG
os_printf("Wifi connect failed. Going into STA+AP mode..\n"); os_printf("Wifi connect failed. Going into STA+AP mode..\n");
#endif
wifi_set_opmode(3); wifi_set_opmode(3);
} }
log_uart(true); log_uart(true);
#ifdef CGIWIFI_DBG
os_printf("Enabling/continuing uart log\n"); os_printf("Enabling/continuing uart log\n");
#endif
os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); os_timer_arm(&resetTimer, RESET_TIMEOUT, 0);
} }
} }
@ -277,7 +309,9 @@ static ETSTimer reassTimer;
// Callback actually doing reassociation // Callback actually doing reassociation
static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) {
#ifdef CGIWIFI_DBG
os_printf("Wifi changing association\n"); os_printf("Wifi changing association\n");
#endif
wifi_station_disconnect(); wifi_station_disconnect();
stconf.bssid_set = 0; stconf.bssid_set = 0;
wifi_station_set_config(&stconf); wifi_station_set_config(&stconf);
@ -303,7 +337,9 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
//Set to 0 if you want to disable the actual reconnecting bit //Set to 0 if you want to disable the actual reconnecting bit
os_strncpy((char*)stconf.ssid, essid, 32); os_strncpy((char*)stconf.ssid, essid, 32);
os_strncpy((char*)stconf.password, passwd, 64); os_strncpy((char*)stconf.password, passwd, 64);
#ifdef CGIWIFI_DBG
os_printf("Wifi try to connect to AP %s pw %s\n", essid, passwd); os_printf("Wifi try to connect to AP %s pw %s\n", essid, passwd);
#endif
//Schedule disconnect/connect //Schedule disconnect/connect
os_timer_disarm(&reassTimer); os_timer_disarm(&reassTimer);
@ -342,7 +378,6 @@ static bool parse_ip(char *buff, ip_addr_t *ip_ptr) {
return false; return false;
} }
#define DEBUGIP
#ifdef DEBUGIP #ifdef DEBUGIP
static void ICACHE_FLASH_ATTR debugIP() { static void ICACHE_FLASH_ATTR debugIP() {
struct ip_info info; struct ip_info info;
@ -365,7 +400,9 @@ static void ICACHE_FLASH_ATTR configWifiIP() {
if (wifi_station_dhcpc_status() == DHCP_STARTED) if (wifi_station_dhcpc_status() == DHCP_STARTED)
wifi_station_dhcpc_stop(); wifi_station_dhcpc_stop();
wifi_station_dhcpc_start(); wifi_station_dhcpc_start();
#ifdef CGIWIFI_DBG
os_printf("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); os_printf("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname);
#endif
} else { } else {
// no DHCP, we got static network config! // no DHCP, we got static network config!
wifi_station_dhcpc_stop(); wifi_station_dhcpc_stop();
@ -374,7 +411,9 @@ static void ICACHE_FLASH_ATTR configWifiIP() {
ipi.netmask.addr = flashConfig.netmask; ipi.netmask.addr = flashConfig.netmask;
ipi.gw.addr = flashConfig.gateway; ipi.gw.addr = flashConfig.gateway;
wifi_set_ip_info(0, &ipi); wifi_set_ip_info(0, &ipi);
#ifdef CGIWIFI_DBG
os_printf("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); os_printf("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr));
#endif
} }
#ifdef DEBUGIP #ifdef DEBUGIP
debugIP(); debugIP();
@ -454,7 +493,9 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) {
len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff));
if (len!=0) { if (len!=0) {
int m = atoi(buff); int m = atoi(buff);
#ifdef CGIWIFI_DBG
os_printf("Wifi switching to mode %d\n", m); os_printf("Wifi switching to mode %d\n", m);
#endif
wifi_set_opmode(m&3); wifi_set_opmode(m&3);
if (m == 1) { if (m == 1) {
wifi_set_sleep_type(SLEEP_MODE); wifi_set_sleep_type(SLEEP_MODE);
@ -557,8 +598,9 @@ int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) {
#endif #endif
len += os_sprintf(buff+len, "\"x\":0}\n"); len += os_sprintf(buff+len, "\"x\":0}\n");
#ifdef CGIWIFI_DBG
os_printf(" -> %s\n", buff); os_printf(" -> %s\n", buff);
#endif
httpdSend(connData, buff, len); httpdSend(connData, buff, len);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
@ -582,8 +624,10 @@ int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) {
// so we can revert to STA+AP mode if we can't connect. // so we can revert to STA+AP mode if we can't connect.
void ICACHE_FLASH_ATTR wifiInit() { void ICACHE_FLASH_ATTR wifiInit() {
wifi_set_phy_mode(2); wifi_set_phy_mode(2);
#ifdef CGIWIFI_DBG
int x = wifi_get_opmode() & 0x3; int x = wifi_get_opmode() & 0x3;
os_printf("Wifi init, mode=%s\n", wifiMode[x]); os_printf("Wifi init, mode=%s\n", wifiMode[x]);
#endif
configWifiIP(); configWifiIP();
wifi_set_event_handler_cb(wifiHandleEventCb); wifi_set_event_handler_cb(wifiHandleEventCb);

@ -19,8 +19,9 @@ FlashConfig flashDefault = {
1, 0, // tcp_enable, rssi_enable 1, 0, // tcp_enable, rssi_enable
"\0", // api_key "\0", // api_key
0, 0, 0, // slip_enable, mqtt_enable, mqtt_status_enable 0, 0, 0, // slip_enable, mqtt_enable, mqtt_status_enable
1833, // mqtt port 2, 1, // mqtt_timeout, mqtt_clean_session
"\0", "\0", "\0", "\0", "\0", // mqtt host, client, user, password, status-topic 1833, 600, // mqtt port, mqtt_keepalive
"\0", "\0", "\0", "\0", "\0", // mqtt host, client_id, user, password, status-topic
}; };
typedef union { typedef union {
@ -51,8 +52,8 @@ static void memDump(void *addr, int len) {
bool ICACHE_FLASH_ATTR configSave(void) { bool ICACHE_FLASH_ATTR configSave(void) {
FlashFull ff; FlashFull ff;
memset(&ff, 0, sizeof(ff)); os_memset(&ff, 0, sizeof(ff));
memcpy(&ff, &flashConfig, sizeof(FlashConfig)); os_memcpy(&ff, &flashConfig, sizeof(FlashConfig));
uint32_t seq = ff.fc.seq+1; uint32_t seq = ff.fc.seq+1;
// erase secondary // erase secondary
uint32_t addr = FLASH_ADDR + (1-flash_pri)*FLASH_SECT; uint32_t addr = FLASH_ADDR + (1-flash_pri)*FLASH_SECT;
@ -87,7 +88,9 @@ bool ICACHE_FLASH_ATTR configSave(void) {
spi_flash_write(addr, (void *)&ff, sizeof(uint32_t)); spi_flash_write(addr, (void *)&ff, sizeof(uint32_t));
return true; return true;
fail: fail:
#ifdef CONFIG_DBG
os_printf("*** Failed to save config ***\n"); os_printf("*** Failed to save config ***\n");
#endif
return false; return false;
} }
@ -102,19 +105,28 @@ bool ICACHE_FLASH_ATTR configRestore(void) {
FlashFull ff0, ff1; FlashFull ff0, ff1;
// read both flash sectors // read both flash sectors
if (spi_flash_read(FLASH_ADDR, (void *)&ff0, sizeof(ff0)) != SPI_FLASH_RESULT_OK) if (spi_flash_read(FLASH_ADDR, (void *)&ff0, sizeof(ff0)) != SPI_FLASH_RESULT_OK)
memset(&ff0, 0, sizeof(ff0)); // clear in case of error os_memset(&ff0, 0, sizeof(ff0)); // clear in case of error
if (spi_flash_read(FLASH_ADDR+FLASH_SECT, (void *)&ff1, sizeof(ff1)) != SPI_FLASH_RESULT_OK) if (spi_flash_read(FLASH_ADDR+FLASH_SECT, (void *)&ff1, sizeof(ff1)) != SPI_FLASH_RESULT_OK)
memset(&ff1, 0, sizeof(ff1)); // clear in case of error os_memset(&ff1, 0, sizeof(ff1)); // clear in case of error
// figure out which one is good // figure out which one is good
flash_pri = selectPrimary(&ff0, &ff1); flash_pri = selectPrimary(&ff0, &ff1);
// if neither is OK, we revert to defaults // if neither is OK, we revert to defaults
if (flash_pri < 0) { if (flash_pri < 0) {
memcpy(&flashConfig, &flashDefault, sizeof(FlashConfig)); os_memcpy(&flashConfig, &flashDefault, sizeof(FlashConfig));
char chipIdStr[6];
os_sprintf(chipIdStr, "%06x", system_get_chip_id());
os_memcpy(&flashConfig.mqtt_clientid, chipIdStr, os_strlen(chipIdStr));
#ifdef CHIP_IN_HOSTNAME
char hostname[16];
os_strcpy(hostname, "esp-link-");
os_strcat(hostname, chipIdStr);
os_memcpy(&flashConfig.hostname, hostname, os_strlen(hostname));
#endif
flash_pri = 0; flash_pri = 0;
return false; return false;
} }
// copy good one into global var and return // copy good one into global var and return
memcpy(&flashConfig, flash_pri == 0 ? &ff0.fc : &ff1.fc, sizeof(FlashConfig)); os_memcpy(&flashConfig, flash_pri == 0 ? &ff0.fc : &ff1.fc, sizeof(FlashConfig));
return true; return true;
} }
@ -123,10 +135,14 @@ static int ICACHE_FLASH_ATTR selectPrimary(FlashFull *ff0, FlashFull *ff1) {
uint16_t crc = ff0->fc.crc; uint16_t crc = ff0->fc.crc;
ff0->fc.crc = 0; ff0->fc.crc = 0;
bool ff0_crc_ok = crc16_data((unsigned char*)ff0, sizeof(FlashFull), 0) == crc; bool ff0_crc_ok = crc16_data((unsigned char*)ff0, sizeof(FlashFull), 0) == crc;
#ifdef CONFIG_DBG
os_printf("FLASH chk=0x%04x crc=0x%04x full_sz=%d sz=%d\n", os_printf("FLASH chk=0x%04x crc=0x%04x full_sz=%d sz=%d chip_sz=%d\n",
crc16_data((unsigned char*)ff0, sizeof(FlashFull), 0), crc16_data((unsigned char*)ff0, sizeof(FlashFull), 0),
crc, sizeof(FlashFull), sizeof(FlashConfig)); crc,
sizeof(FlashFull),
sizeof(FlashConfig),
getFlashSize());
#endif
// check CRC of ff1 // check CRC of ff1
crc = ff1->fc.crc; crc = ff1->fc.crc;
@ -142,3 +158,15 @@ static int ICACHE_FLASH_ATTR selectPrimary(FlashFull *ff0, FlashFull *ff1) {
else else
return ff1_crc_ok ? 1 : -1; return ff1_crc_ok ? 1 : -1;
} }
// returns the flash chip's size, in BYTES
const size_t ICACHE_FLASH_ATTR
getFlashSize() {
uint32_t id = spi_flash_get_id();
uint8_t mfgr_id = id & 0xff;
uint8_t type_id = (id >> 8) & 0xff; // not relevant for size calculation
uint8_t size_id = (id >> 16) & 0xff; // lucky for us, WinBond ID's their chips as a form that lets us calculate the size
if (mfgr_id != 0xEF) // 0xEF is WinBond; that's all we care about (for now)
return 0;
return 1 << size_id;
}

@ -17,9 +17,11 @@ typedef struct {
uint8_t tcp_enable, rssi_enable; // TCP client settings uint8_t tcp_enable, rssi_enable; // TCP client settings
char api_key[48]; // RSSI submission API key (Grovestreams for now) char api_key[48]; // RSSI submission API key (Grovestreams for now)
uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client
mqtt_status_enable; // MQTT status reporting mqtt_status_enable, // MQTT status reporting
uint16_t mqtt_port; mqtt_timeout, // MQTT send timeout
char mqtt_hostname[32], mqtt_client[48], mqtt_username[32], mqtt_password[32]; mqtt_clean_session; // MQTT clean session
uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer
char mqtt_host[32], mqtt_clientid[48], mqtt_username[32], mqtt_password[32];
char mqtt_status_topic[32]; char mqtt_status_topic[32];
} FlashConfig; } FlashConfig;
extern FlashConfig flashConfig; extern FlashConfig flashConfig;
@ -27,5 +29,6 @@ extern FlashConfig flashConfig;
bool configSave(void); bool configSave(void);
bool configRestore(void); bool configRestore(void);
void configWipe(void); void configWipe(void);
const size_t getFlashSize();
#endif #endif

@ -25,14 +25,18 @@ log_uart(bool enable) {
if (!enable && !log_no_uart && flashConfig.log_mode != LOG_MODE_ON) { if (!enable && !log_no_uart && flashConfig.log_mode != LOG_MODE_ON) {
// we're asked to turn uart off, and uart is on, and the flash setting isn't always-on // we're asked to turn uart off, and uart is on, and the flash setting isn't always-on
#if 1 #if 1
#ifdef LOG_DBG
os_printf("Turning OFF uart log\n"); os_printf("Turning OFF uart log\n");
#endif
os_delay_us(4*1000L); // time for uart to flush os_delay_us(4*1000L); // time for uart to flush
log_no_uart = !enable; log_no_uart = !enable;
#endif #endif
} else if (enable && log_no_uart && flashConfig.log_mode != LOG_MODE_OFF) { } else if (enable && log_no_uart && flashConfig.log_mode != LOG_MODE_OFF) {
// we're asked to turn uart on, and uart is off, and the flash setting isn't always-off // we're asked to turn uart on, and uart is off, and the flash setting isn't always-off
log_no_uart = !enable; log_no_uart = !enable;
#ifdef LOG_DBG
os_printf("Turning ON uart log\n"); os_printf("Turning ON uart log\n");
#endif
} }
} }

@ -30,24 +30,24 @@
#include "log.h" #include "log.h"
#include <gpio.h> #include <gpio.h>
#define SHOW_HEAP_USE //#define SHOW_HEAP_USE
//Function that tells the authentication system what users/passwords live on the system. //Function that tells the authentication system what users/passwords live on the system.
//This is disabled in the default build; if you want to try it, enable the authBasic line in //This is disabled in the default build; if you want to try it, enable the authBasic line in
//the builtInUrls below. //the builtInUrls below.
int myPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen) { //int myPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen) {
if (no == 0) { // if (no == 0) {
os_strcpy(user, "admin"); // os_strcpy(user, "admin");
os_strcpy(pass, "s3cr3t"); // os_strcpy(pass, "s3cr3t");
return 1; // return 1;
//Add more users this way. Check against incrementing no for each user added. //Add more users this way. Check against incrementing no for each user added.
// } else if (no==1) { // } else if (no==1) {
// os_strcpy(user, "user1"); // os_strcpy(user, "user1");
// os_strcpy(pass, "something"); // os_strcpy(pass, "something");
// return 1; // return 1;
} // }
return 0; // return 0;
} //}
/* /*
@ -97,9 +97,6 @@ HttpdBuiltInUrl builtInUrls[] = {
{ NULL, NULL, NULL } { NULL, NULL, NULL }
}; };
//#define SHOW_HEAP_USE
#ifdef SHOW_HEAP_USE #ifdef SHOW_HEAP_USE
static ETSTimer prHeapTimer; static ETSTimer prHeapTimer;

@ -10,8 +10,8 @@ static ETSTimer mqttTimer;
static int once = 0; static int once = 0;
static void ICACHE_FLASH_ATTR mqttTimerCb(void *arg) { static void ICACHE_FLASH_ATTR mqttTimerCb(void *arg) {
if (once++ > 0) return; if (once++ > 0) return;
MQTT_Init(&mqttClient, flashConfig.mqtt_hostname, flashConfig.mqtt_port, 0, 2, MQTT_Init(&mqttClient, flashConfig.mqtt_host, flashConfig.mqtt_port, 0, 2,
flashConfig.mqtt_client, flashConfig.mqtt_username, flashConfig.mqtt_password, 60); flashConfig.mqtt_clientid, flashConfig.mqtt_username, flashConfig.mqtt_password, 60);
MQTT_Connect(&mqttClient); MQTT_Connect(&mqttClient);
MQTT_Subscribe(&mqttClient, "system/time", 0); MQTT_Subscribe(&mqttClient, "system/time", 0);
} }

@ -107,7 +107,9 @@ void ICACHE_FLASH_ATTR statusInit(void) {
makeGpio(flashConfig.conn_led_pin); makeGpio(flashConfig.conn_led_pin);
setLed(1); setLed(1);
} }
#ifdef STATUS_DBG
os_printf("CONN led=%d\n", flashConfig.conn_led_pin); os_printf("CONN led=%d\n", flashConfig.conn_led_pin);
#endif
os_timer_disarm(&ledTimer); os_timer_disarm(&ledTimer);
os_timer_setfn(&ledTimer, ledTimerCb, NULL); os_timer_setfn(&ledTimer, ledTimerCb, NULL);

@ -109,7 +109,9 @@ void ICACHE_FLASH_ATTR memcpyAligned(char *dst, char *src, int len) {
// Returns flags of opened file. // Returns flags of opened file.
int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) { int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) {
if (fh == NULL) { if (fh == NULL) {
#ifdef ESPFS_DBG
os_printf("File handle not ready\n"); os_printf("File handle not ready\n");
#endif
return -1; return -1;
} }
@ -121,7 +123,9 @@ int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) {
//Open a file and return a pointer to the file desc struct. //Open a file and return a pointer to the file desc struct.
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) { EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
if (espFsData == NULL) { if (espFsData == NULL) {
#ifdef ESPFS_DBG
os_printf("Call espFsInit first!\n"); os_printf("Call espFsInit first!\n");
#endif
return NULL; return NULL;
} }
char *p=espFsData; char *p=espFsData;
@ -137,7 +141,9 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
//Grab the next file header. //Grab the next file header.
os_memcpy(&h, p, sizeof(EspFsHeader)); os_memcpy(&h, p, sizeof(EspFsHeader));
if (h.magic!=ESPFS_MAGIC) { if (h.magic!=ESPFS_MAGIC) {
#ifdef ESPFS_DBG
os_printf("Magic mismatch. EspFS image broken.\n"); os_printf("Magic mismatch. EspFS image broken.\n");
#endif
return NULL; return NULL;
} }
if (h.flags&FLAG_LASTFILE) { if (h.flags&FLAG_LASTFILE) {
@ -163,7 +169,9 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
if (h.compression==COMPRESS_NONE) { if (h.compression==COMPRESS_NONE) {
r->decompData=NULL; r->decompData=NULL;
} else { } else {
#ifdef ESPFS_DBG
os_printf("Invalid compression: %d\n", h.compression); os_printf("Invalid compression: %d\n", h.compression);
#endif
return NULL; return NULL;
} }
return r; return r;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 874 B

After

Width:  |  Height:  |  Size: 498 B

@ -28,27 +28,30 @@
<div id="mqtt-spinner" class="spinner spinner-small"></div> <div id="mqtt-spinner" class="spinner spinner-small"></div>
</h1> </h1>
<form action="#" id="mqtt-form" class="pure-form" hidden> <form action="#" id="mqtt-form" class="pure-form" hidden>
<div class="form-horizontal">
<input type="checkbox" name="mqtt-enable"/> <input type="checkbox" name="mqtt-enable"/>
<label>Enable MQTT client</label> <label>Enable MQTT client</label>
</div> <br>
<div class="form-horizontal">
<label>MQTT client state: </label> <label>MQTT client state: </label>
<b id="mqtt-state"></b> <b id="mqtt-state"></b>
</div>
<br> <br>
<legend>MQTT server settings</legend> <legend>MQTT server settings</legend>
<div class="pure-form-stacked"> <div class="pure-form-stacked">
<label>Server hostname/ip</label> <label>Server hostname or IP</label>
<input type="text" name="mqtt-host"/> <input type="text" name="mqtt-host"/>
<label>Server port/ip</label> <label>Server port</label>
<input type="text" name="mqtt-port"/> <input type="text" name="mqtt-port"/>
<label>Client Timeout</label>
<input type="text" name="mqtt-timeout" />
<label>Client ID</label> <label>Client ID</label>
<input type="text" name="mqtt-client-id"/> <input type="text" name="mqtt-client-id"/>
<label>Username</label> <label>Username</label>
<input type="text" name="mqtt-username"/> <input type="text" name="mqtt-username"/>
<label>Password</label> <label>Password</label>
<input type="password" name="mqtt-password"/> <input type="password" name="mqtt-password"/>
<label>Keep Alive Interval (seconds)</label>
<input type="text" name="mqtt-keepalive" />
<input type="checkbox" name="mqtt-clean-session" />
<label>Clean Session?</label>
</div> </div>
<button id="mqtt-button" type="submit" class="pure-button button-primary"> <button id="mqtt-button" type="submit" class="pure-button button-primary">
Update server settings! Update server settings!

@ -7,6 +7,11 @@ input[type="text"], input[type="password"] {
width: 100%; width: 100%;
} }
input[type=checkbox] {
float: left;
margin: .35em 0.4em;
}
body { body {
color: #777; color: #777;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 425 B

@ -3,15 +3,15 @@ Esp8266 http server - core routines
*/ */
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42): * "THE BEER-WARE LICENSE" (Revision 42):
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain * Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day, * this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return. * and you think this stuff is worth it, you can buy me a beer in return.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Modified and enhanced by Thorsten von Eicken in 2015 * Modified and enhanced by Thorsten von Eicken in 2015
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
#include <esp8266.h> #include <esp8266.h>
@ -56,29 +56,29 @@ typedef struct {
//The mappings from file extensions to mime types. If you need an extra mime type, //The mappings from file extensions to mime types. If you need an extra mime type,
//add it here. //add it here.
static const MimeMap mimeTypes[]={ static const MimeMap mimeTypes[] = {
{"htm", "text/htm"}, { "htm", "text/htm" },
{"html", "text/html; charset=UTF-8"}, { "html", "text/html; charset=UTF-8" },
{"css", "text/css"}, { "css", "text/css" },
{"js", "text/javascript"}, { "js", "text/javascript" },
{"txt", "text/plain"}, { "txt", "text/plain" },
{"jpg", "image/jpeg"}, { "jpg", "image/jpeg" },
{"jpeg", "image/jpeg"}, { "jpeg", "image/jpeg" },
{"png", "image/png"}, { "png", "image/png" },
{"tpl", "text/html; charset=UTF-8"}, { "tpl", "text/html; charset=UTF-8" },
{NULL, "text/html"}, //default value { NULL, "text/html" }, //default value
}; };
//Returns a static char* to a mime type for a given url to a file. //Returns a static char* to a mime type for a given url to a file.
const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) { const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) {
int i=0; int i = 0;
//Go find the extension //Go find the extension
char *ext=url+(strlen(url)-1); char *ext = url + (strlen(url) - 1);
while (ext!=url && *ext!='.') ext--; while (ext != url && *ext != '.') ext--;
if (*ext=='.') ext++; if (*ext == '.') ext++;
//ToDo: os_strcmp is case sensitive; we may want to do case-intensive matching here... //ToDo: os_strcmp is case sensitive; we may want to do case-intensive matching here...
while (mimeTypes[i].ext!=NULL && os_strcmp(ext, mimeTypes[i].ext)!=0) i++; while (mimeTypes[i].ext != NULL && os_strcmp(ext, mimeTypes[i].ext) != 0) i++;
return mimeTypes[i].mimetype; return mimeTypes[i].mimetype;
} }
@ -98,21 +98,25 @@ static void debugConn(void *arg, char *what) {
//Looks up the connData info for a specific esp connection //Looks up the connData info for a specific esp connection
static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) { static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) {
struct espconn *espconn = arg; struct espconn *espconn = arg;
for (int i=0; i<MAX_CONN; i++) { for (int i = 0; i<MAX_CONN; i++) {
if (connData[i].remote_port == espconn->proto.tcp->remote_port && if (connData[i].remote_port == espconn->proto.tcp->remote_port &&
os_memcmp(connData[i].remote_ip, espconn->proto.tcp->remote_ip, 4) == 0) os_memcmp(connData[i].remote_ip, espconn->proto.tcp->remote_ip, 4) == 0)
{ {
#if 0 #if 0
#ifdef HTTPD_DBG
os_printf("FindConn: 0x%p->0x%p", arg, &connData[i]); os_printf("FindConn: 0x%p->0x%p", arg, &connData[i]);
if (arg == connData[i].conn) os_printf("\n"); if (arg == connData[i].conn) os_printf("\n");
else os_printf(" *** was 0x%p\n", connData[i].conn); else os_printf(" *** was 0x%p\n", connData[i].conn);
#endif
#endif #endif
if (arg != connData[i].conn) connData[i].conn = arg; // yes, this happens!? if (arg != connData[i].conn) connData[i].conn = arg; // yes, this happens!?
return &connData[i]; return &connData[i];
} }
} }
//Shouldn't happen. //Shouldn't happen.
#ifdef HTTPD_DBG
os_printf("%s *** Unknown connection 0x%p\n", connStr, arg); os_printf("%s *** Unknown connection 0x%p\n", connStr, arg);
#endif
return NULL; return NULL;
} }
@ -123,22 +127,24 @@ static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
if (conn->post->buff != NULL) { if (conn->post->buff != NULL) {
os_free(conn->post->buff); os_free(conn->post->buff);
} }
conn->cgi=NULL; conn->cgi = NULL;
conn->post->buff=NULL; conn->post->buff = NULL;
conn->remote_port = 0; conn->remote_port = 0;
conn->remote_ip[0] = 0; conn->remote_ip[0] = 0;
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;
#ifdef HTTPD_DBG
os_printf("%s Closed, %ums, heap=%ld\n", connStr, dt, os_printf("%s Closed, %ums, heap=%ld\n", connStr, dt,
(unsigned long)system_get_free_heap_size()); (unsigned long)system_get_free_heap_size());
#endif
} }
//Stupid li'l helper function that returns the value of a hex char. //Stupid li'l helper function that returns the value of a hex char.
static int httpdHexVal(char c) { static int httpdHexVal(char c) {
if (c>='0' && c<='9') return c-'0'; if (c >= '0' && c <= '9') return c - '0';
if (c>='A' && c<='F') return c-'A'+10; if (c >= 'A' && c <= 'F') return c - 'A' + 10;
if (c>='a' && c<='f') return c-'a'+10; if (c >= 'a' && c <= 'f') return c - 'a' + 10;
return 0; return 0;
} }
@ -147,26 +153,30 @@ static int httpdHexVal(char c) {
//are stored in the ret buffer. Returns the actual amount of bytes used in ret. Also //are stored in the ret buffer. Returns the actual amount of bytes used in ret. Also
//zero-terminates the ret buffer. //zero-terminates the ret buffer.
int httpdUrlDecode(char *val, int valLen, char *ret, int retLen) { int httpdUrlDecode(char *val, int valLen, char *ret, int retLen) {
int s=0, d=0; int s = 0, d = 0;
int esced=0, escVal=0; int esced = 0, escVal = 0;
while (s<valLen && d<retLen) { while (s<valLen && d<retLen) {
if (esced==1) { if (esced == 1) {
escVal=httpdHexVal(val[s])<<4; escVal = httpdHexVal(val[s]) << 4;
esced=2; esced = 2;
} else if (esced==2) { }
escVal+=httpdHexVal(val[s]); else if (esced == 2) {
ret[d++]=escVal; escVal += httpdHexVal(val[s]);
esced=0; ret[d++] = escVal;
} else if (val[s]=='%') { esced = 0;
esced=1; }
} else if (val[s]=='+') { else if (val[s] == '%') {
ret[d++]=' '; esced = 1;
} else { }
ret[d++]=val[s]; else if (val[s] == '+') {
ret[d++] = ' ';
}
else {
ret[d++] = val[s];
} }
s++; s++;
} }
if (d<retLen) ret[d]=0; if (d<retLen) ret[d] = 0;
return d; return d;
} }
@ -177,19 +187,19 @@ int httpdUrlDecode(char *val, int valLen, char *ret, int retLen) {
//returned string will be urldecoded already. //returned string will be urldecoded already.
int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLen) { int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLen) {
char *p, *e; char *p, *e;
if (line==NULL) return 0; if (line == NULL) return 0;
p=line; p = line;
while(p!=NULL && *p!='\n' && *p!='\r' && *p!=0) { while (p != NULL && *p != '\n' && *p != '\r' && *p != 0) {
//os_printf("findArg: %s\n", p); //os_printf("findArg: %s\n", p);
if (os_strncmp(p, arg, os_strlen(arg))==0 && p[strlen(arg)]=='=') { if (os_strncmp(p, arg, os_strlen(arg)) == 0 && p[strlen(arg)] == '=') {
p+=os_strlen(arg)+1; //move p to start of value p += os_strlen(arg) + 1; //move p to start of value
e=(char*)os_strstr(p, "&"); e = (char*)os_strstr(p, "&");
if (e==NULL) e=p+os_strlen(p); if (e == NULL) e = p + os_strlen(p);
//os_printf("findArg: val %s len %d\n", p, (e-p)); //os_printf("findArg: val %s len %d\n", p, (e-p));
return httpdUrlDecode(p, (e-p), buff, buffLen); return httpdUrlDecode(p, (e - p), buff, buffLen);
} }
p=(char*)os_strstr(p, "&"); p = (char*)os_strstr(p, "&");
if (p!=NULL) p+=1; if (p != NULL) p += 1;
} }
//os_printf("Finding %s in %s: Not found :/\n", arg, line); //os_printf("Finding %s in %s: Not found :/\n", arg, line);
return -1; //not found return -1; //not found
@ -197,28 +207,28 @@ int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLe
//Get the value of a certain header in the HTTP client head //Get the value of a certain header in the HTTP client head
int ICACHE_FLASH_ATTR httpdGetHeader(HttpdConnData *conn, char *header, char *ret, int retLen) { int ICACHE_FLASH_ATTR httpdGetHeader(HttpdConnData *conn, char *header, char *ret, int retLen) {
char *p=conn->priv->head; char *p = conn->priv->head;
p=p+strlen(p)+1; //skip GET/POST part p = p + strlen(p) + 1; //skip GET/POST part
p=p+strlen(p)+1; //skip HTTP part p = p + strlen(p) + 1; //skip HTTP part
while (p<(conn->priv->head+conn->priv->headPos)) { while (p<(conn->priv->head + conn->priv->headPos)) {
while(*p<=32 && *p!=0) p++; //skip crap at start while (*p <= 32 && *p != 0) p++; //skip crap at start
//See if this is the header //See if this is the header
if (os_strncmp(p, header, strlen(header))==0 && p[strlen(header)]==':') { if (os_strncmp(p, header, strlen(header)) == 0 && p[strlen(header)] == ':') {
//Skip 'key:' bit of header line //Skip 'key:' bit of header line
p=p+strlen(header)+1; p = p + strlen(header) + 1;
//Skip past spaces after the colon //Skip past spaces after the colon
while(*p==' ') p++; while (*p == ' ') p++;
//Copy from p to end //Copy from p to end
while (*p!=0 && *p!='\r' && *p!='\n' && retLen>1) { while (*p != 0 && *p != '\r' && *p != '\n' && retLen>1) {
*ret++=*p++; *ret++ = *p++;
retLen--; retLen--;
} }
//Zero-terminate string //Zero-terminate string
*ret=0; *ret = 0;
//All done :) //All done :)
return 1; return 1;
} }
p+=strlen(p)+1; //Skip past end of string and \0 terminator p += strlen(p) + 1; //Skip past end of string and \0 terminator
} }
return 0; return 0;
} }
@ -237,7 +247,7 @@ void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const
char buff[256]; char buff[256];
int l; int l;
l=os_sprintf(buff, "%s: %s\r\n", field, val); l = os_sprintf(buff, "%s: %s\r\n", field, val);
httpdSend(conn, buff, l); httpdSend(conn, buff, l);
} }
@ -251,13 +261,13 @@ void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn) {
void ICACHE_FLASH_ATTR httpdRedirect(HttpdConnData *conn, char *newUrl) { void ICACHE_FLASH_ATTR httpdRedirect(HttpdConnData *conn, char *newUrl) {
char buff[1024]; char buff[1024];
int l; int l;
l=os_sprintf(buff, "HTTP/1.0 302 Found\r\nServer: esp8266-link\r\nConnection: close\r\nLocation: %s\r\n\r\nRedirecting to %s\r\n", newUrl, newUrl); l = os_sprintf(buff, "HTTP/1.0 302 Found\r\nServer: esp8266-link\r\nConnection: close\r\nLocation: %s\r\n\r\nRedirecting to %s\r\n", newUrl, newUrl);
httpdSend(conn, buff, l); httpdSend(conn, buff, l);
} }
//Use this as a cgi function to redirect one url to another. //Use this as a cgi function to redirect one url to another.
int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData) {
if (connData->conn==NULL) { if (connData->conn == NULL) {
//Connection aborted. Clean up. //Connection aborted. Clean up.
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
@ -270,25 +280,29 @@ int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData) {
//the data is seen as a C-string. //the data is seen as a C-string.
//Returns 1 for success, 0 for out-of-memory. //Returns 1 for success, 0 for out-of-memory.
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
os_printf("%s ERROR! httpdSend full (%d of %d)\n", os_printf("%s ERROR! 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);
conn->priv->sendBuffLen+=len; conn->priv->sendBuffLen += len;
return 1; return 1;
} }
//Helper function to send any data in conn->priv->sendBuff //Helper function to send any data in conn->priv->sendBuff
static void ICACHE_FLASH_ATTR xmitSendBuff(HttpdConnData *conn) { 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
os_printf("%s ERROR! espconn_sent returned %d\n", connStr, status); os_printf("%s ERROR! espconn_sent returned %d\n", connStr, status);
#endif
} }
conn->priv->sendBuffLen=0; conn->priv->sendBuffLen = 0;
} }
} }
@ -296,31 +310,33 @@ static void ICACHE_FLASH_ATTR xmitSendBuff(HttpdConnData *conn) {
static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) { static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) {
debugConn(arg, "httpdSentCb"); debugConn(arg, "httpdSentCb");
int r; int r;
HttpdConnData *conn=httpdFindConnData(arg); HttpdConnData *conn = httpdFindConnData(arg);
char sendBuff[MAX_SENDBUFF_LEN]; char sendBuff[MAX_SENDBUFF_LEN];
if (conn==NULL) return; if (conn == NULL) return;
conn->priv->sendBuff=sendBuff; conn->priv->sendBuff = sendBuff;
conn->priv->sendBuffLen=0; conn->priv->sendBuffLen = 0;
if (conn->cgi==NULL) { //Marked for destruction? if (conn->cgi == NULL) { //Marked for destruction?
//os_printf("Closing 0x%p/0x%p->0x%p\n", arg, conn->conn, conn); //os_printf("Closing 0x%p/0x%p->0x%p\n", arg, conn->conn, conn);
espconn_disconnect(conn->conn); // we will get a disconnect callback espconn_disconnect(conn->conn); // we will get a disconnect callback
return; //No need to call xmitSendBuff. return; //No need to call xmitSendBuff.
} }
r=conn->cgi(conn); //Execute cgi fn. r = conn->cgi(conn); //Execute cgi fn.
if (r==HTTPD_CGI_DONE) { if (r == HTTPD_CGI_DONE) {
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
os_printf("%s ERROR! Bad CGI code %d\n", connStr, r); os_printf("%s ERROR! Bad CGI code %d\n", connStr, r);
conn->cgi=NULL; //mark for destruction. #endif
conn->cgi = NULL; //mark for destruction.
} }
xmitSendBuff(conn); xmitSendBuff(conn);
} }
static const char *httpNotFoundHeader="HTTP/1.0 404 Not Found\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nNot Found.\r\n"; static const char *httpNotFoundHeader = "HTTP/1.0 404 Not Found\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nNot Found.\r\n";
//This is called when the headers have been received and the connection is ready to send //This is called when the headers have been received and the connection is ready to send
//the result headers and data. //the result headers and data.
@ -328,53 +344,59 @@ static const char *httpNotFoundHeader="HTTP/1.0 404 Not Found\r\nConnection: clo
//find the next cgi function, wait till the cgi data is sent or close up the connection. //find the next cgi function, wait till the cgi data is sent or close up the connection.
static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) { 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
os_printf("%s WtF? url = NULL\n", connStr); os_printf("%s WtF? 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.
while (1) { while (1) {
//Look up URL in the built-in URL table. //Look up URL in the built-in URL table.
while (builtInUrls[i].url!=NULL) { while (builtInUrls[i].url != NULL) {
int match=0; int match = 0;
//See if there's a literal match //See if there's a literal match
if (os_strcmp(builtInUrls[i].url, conn->url)==0) match=1; if (os_strcmp(builtInUrls[i].url, conn->url) == 0) match = 1;
//See if there's a wildcard match //See if there's a wildcard match
if (builtInUrls[i].url[os_strlen(builtInUrls[i].url)-1]=='*' && if (builtInUrls[i].url[os_strlen(builtInUrls[i].url) - 1] == '*' &&
os_strncmp(builtInUrls[i].url, conn->url, os_strlen(builtInUrls[i].url)-1)==0) match=1; os_strncmp(builtInUrls[i].url, conn->url, os_strlen(builtInUrls[i].url) - 1) == 0) match = 1;
if (match) { if (match) {
//os_printf("Is url index %d\n", i); //os_printf("Is url index %d\n", i);
conn->cgiData=NULL; conn->cgiData = NULL;
conn->cgi=builtInUrls[i].cgiCb; conn->cgi = builtInUrls[i].cgiCb;
conn->cgiArg=builtInUrls[i].cgiArg; conn->cgiArg = builtInUrls[i].cgiArg;
break; break;
} }
i++; i++;
} }
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
os_printf("%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
return; return;
} }
//Okay, we have a CGI function that matches the URL. See if it wants to handle the //Okay, we have a CGI function that matches the URL. See if it wants to handle the
//particular URL we're supposed to handle. //particular URL we're supposed to handle.
r=conn->cgi(conn); r = conn->cgi(conn);
if (r==HTTPD_CGI_MORE) { if (r == HTTPD_CGI_MORE) {
//Yep, it's happy to do so and has more data to send. //Yep, it's happy to do so and has more data to send.
xmitSendBuff(conn); xmitSendBuff(conn);
return; return;
} else if (r==HTTPD_CGI_DONE) { }
else if (r == HTTPD_CGI_DONE) {
//Yep, it's happy to do so and already is done sending data. //Yep, it's happy to do so and already is done sending data.
xmitSendBuff(conn); xmitSendBuff(conn);
conn->cgi=NULL; //mark conn for destruction conn->cgi = NULL; //mark conn for destruction
return; return;
} else if (r==HTTPD_CGI_NOTFOUND || r==HTTPD_CGI_AUTHENTICATED) { }
else if (r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED) {
//URL doesn't want to handle the request: either the data isn't found or there's no //URL doesn't want to handle the request: either the data isn't found or there's no
//need to generate a login screen. //need to generate a login screen.
i++; //look at next url the next iteration of the loop. i++; //look at next url the next iteration of the loop.
@ -387,10 +409,11 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
int i; int i;
char first_line = false; char first_line = false;
if (os_strncmp(h, "GET ", 4)==0) { if (os_strncmp(h, "GET ", 4) == 0) {
conn->requestType = HTTPD_METHOD_GET; conn->requestType = HTTPD_METHOD_GET;
first_line = true; first_line = true;
} else if (os_strncmp(h, "POST ", 5)==0) { }
else if (os_strncmp(h, "POST ", 5) == 0) {
conn->requestType = HTTPD_METHOD_POST; conn->requestType = HTTPD_METHOD_POST;
first_line = true; first_line = true;
} }
@ -399,49 +422,56 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) {
char *e; char *e;
//Skip past the space after POST/GET //Skip past the space after POST/GET
i=0; i = 0;
while (h[i]!=' ') i++; while (h[i] != ' ') i++;
conn->url=h+i+1; conn->url = h + i + 1;
//Figure out end of url. //Figure out end of url.
e=(char*)os_strstr(conn->url, " "); e = (char*)os_strstr(conn->url, " ");
if (e==NULL) return; //wtf? if (e == NULL) return; //wtf?
*e=0; //terminate url part *e = 0; //terminate url part
// Count number of open connections // Count number of open connections
int open = 0; int open = 0;
for (int j=0; j<MAX_CONN; j++) if (connData[j].conn != NULL) open++; for (int j = 0; j<MAX_CONN; j++) if (connData[j].conn != NULL) open++;
#ifdef HTTPD_DBG
os_printf("%s %s %s (%d conn open)\n", connStr, os_printf("%s %s %s (%d conn open)\n", connStr,
conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, open); conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, open);
#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
os_printf("%s args = %s\n", connStr, conn->getArgs); os_printf("%s args = %s\n", connStr, conn->getArgs);
} else { #endif
conn->getArgs=NULL; }
else {
conn->getArgs = NULL;
} }
} else if (os_strncmp(h, "Content-Length:", 15)==0) { }
i=15; else if (os_strncmp(h, "Content-Length:", 15) == 0) {
i = 15;
//Skip trailing spaces //Skip trailing spaces
while (h[i]==' ') i++; while (h[i] == ' ') i++;
//Get POST data length //Get POST data length
conn->post->len=atoi(h+i); conn->post->len = atoi(h + i);
// Allocate the buffer // Allocate the buffer
if (conn->post->len > MAX_POST) { if (conn->post->len > MAX_POST) {
// we'll stream this in in chunks // we'll stream this in in chunks
conn->post->buffSize = MAX_POST; conn->post->buffSize = MAX_POST;
} 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); //os_printf("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;
} else if (os_strncmp(h, "Content-Type: ", 14)==0) { }
else if (os_strncmp(h, "Content-Type: ", 14) == 0) {
if (os_strstr(h, "multipart/form-data")) { if (os_strstr(h, "multipart/form-data")) {
// It's multipart form data so let's pull out the boundary for future use // It's multipart form data so let's pull out the boundary for future use
char *b; char *b;
@ -462,10 +492,10 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short
int x; int x;
char *p, *e; char *p, *e;
char sendBuff[MAX_SENDBUFF_LEN]; char sendBuff[MAX_SENDBUFF_LEN];
HttpdConnData *conn=httpdFindConnData(arg); HttpdConnData *conn = httpdFindConnData(arg);
if (conn==NULL) return; if (conn == NULL) return;
conn->priv->sendBuff=sendBuff; conn->priv->sendBuff = sendBuff;
conn->priv->sendBuffLen=0; conn->priv->sendBuffLen = 0;
//This is slightly evil/dirty: we abuse conn->post->len as a state variable for where in the http communications we are: //This is slightly evil/dirty: we abuse conn->post->len as a state variable for where in the http communications we are:
//<0 (-1): Post len unknown because we're still receiving headers //<0 (-1): Post len unknown because we're still receiving headers
@ -473,38 +503,39 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short
//>0: Need to receive post data //>0: Need to receive post data
//ToDo: See if we can use something more elegant for this. //ToDo: See if we can use something more elegant for this.
for (x=0; x<len; x++) { for (x = 0; x<len; x++) {
if (conn->post->len<0) { if (conn->post->len<0) {
//This byte is a header byte. //This byte is a header byte.
if (conn->priv->headPos!=MAX_HEAD_LEN) conn->priv->head[conn->priv->headPos++]=data[x]; if (conn->priv->headPos != MAX_HEAD_LEN) conn->priv->head[conn->priv->headPos++] = data[x];
conn->priv->head[conn->priv->headPos]=0; conn->priv->head[conn->priv->headPos] = 0;
//Scan for /r/n/r/n. Receiving this indicate the headers end. //Scan for /r/n/r/n. Receiving this indicate the headers end.
if (data[x]=='\n' && (char *)os_strstr(conn->priv->head, "\r\n\r\n")!=NULL) { if (data[x] == '\n' && (char *)os_strstr(conn->priv->head, "\r\n\r\n") != NULL) {
//Indicate we're done with the headers. //Indicate we're done with the headers.
conn->post->len=0; conn->post->len = 0;
//Reset url data //Reset url data
conn->url=NULL; conn->url = NULL;
//Iterate over all received headers and parse them. //Iterate over all received headers and parse them.
p=conn->priv->head; p = conn->priv->head;
while(p<(&conn->priv->head[conn->priv->headPos-4])) { while (p<(&conn->priv->head[conn->priv->headPos - 4])) {
e=(char *)os_strstr(p, "\r\n"); //Find end of header line e = (char *)os_strstr(p, "\r\n"); //Find end of header line
if (e==NULL) break; //Shouldn't happen. if (e == NULL) break; //Shouldn't happen.
e[0]=0; //Zero-terminate header e[0] = 0; //Zero-terminate header
httpdParseHeader(p, conn); //and parse it. httpdParseHeader(p, conn); //and parse it.
p=e+2; //Skip /r/n (now /0/n) p = e + 2; //Skip /r/n (now /0/n)
} }
//If we don't need to receive post data, we can send the response now. //If we don't need to receive post data, we can send the response now.
if (conn->post->len==0) { if (conn->post->len == 0) {
httpdProcessRequest(conn); httpdProcessRequest(conn);
} }
} }
} else if (conn->post->len!=0) { }
else if (conn->post->len != 0) {
//This byte is a POST byte. //This byte is a POST byte.
conn->post->buff[conn->post->buffLen++]=data[x]; conn->post->buff[conn->post->buffLen++] = data[x];
conn->post->received++; conn->post->received++;
if (conn->post->buffLen >= conn->post->buffSize || conn->post->received == conn->post->len) { if (conn->post->buffLen >= conn->post->buffSize || conn->post->received == conn->post->len) {
//Received a chunk of post data //Received a chunk of post data
conn->post->buff[conn->post->buffLen]=0; //zero-terminate, in case the cgi handler knows it can use strings conn->post->buff[conn->post->buffLen] = 0; //zero-terminate, in case the cgi handler knows it can use strings
//Send the response. //Send the response.
httpdProcessRequest(conn); httpdProcessRequest(conn);
conn->post->buffLen = 0; conn->post->buffLen = 0;
@ -525,7 +556,9 @@ static void ICACHE_FLASH_ATTR httpdDisconCb(void *arg) {
static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) { static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) {
debugConn(arg, "httpdReconCb"); debugConn(arg, "httpdReconCb");
HttpdConnData *conn = httpdFindConnData(arg); HttpdConnData *conn = httpdFindConnData(arg);
#ifdef HTTPD_DBG
os_printf("%s ***** reset, err=%d\n", connStr, err); os_printf("%s ***** reset, err=%d\n", connStr, err);
#endif
if (conn == NULL) return; if (conn == NULL) return;
httpdRetireConn(conn); httpdRetireConn(conn);
} }
@ -533,33 +566,37 @@ static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) {
static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) { static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) {
debugConn(arg, "httpdConnectCb"); debugConn(arg, "httpdConnectCb");
struct espconn *conn=arg; struct espconn *conn = arg;
int i; int i;
//Find empty conndata in pool //Find empty conndata in pool
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); //os_printf("Con req, conn=%p, pool slot %d\n", conn, i);
if (i==MAX_CONN) { if (i == MAX_CONN) {
#ifdef HTTPD_DBG
os_printf("%s Aiee, conn pool overflow!\n", connStr); os_printf("%s Aiee, conn pool overflow!\n", connStr);
#endif
espconn_disconnect(conn); espconn_disconnect(conn);
return; return;
} }
#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++;
os_printf("%s Connect (%d open)\n", connStr, num+1); #ifdef HTTPD_DBG
os_printf("%s Connect (%d open)\n", connStr, num + 1);
#endif
#endif #endif
connData[i].priv=&connPrivData[i]; connData[i].priv = &connPrivData[i];
connData[i].conn=conn; connData[i].conn = conn;
connData[i].remote_port = conn->proto.tcp->remote_port; connData[i].remote_port = conn->proto.tcp->remote_port;
os_memcpy(connData[i].remote_ip, conn->proto.tcp->remote_ip, 4); os_memcpy(connData[i].remote_ip, conn->proto.tcp->remote_ip, 4);
connData[i].priv->headPos=0; connData[i].priv->headPos = 0;
connData[i].post=&connPostData[i]; connData[i].post = &connPostData[i];
connData[i].post->buff=NULL; connData[i].post->buff = NULL;
connData[i].post->buffLen=0; connData[i].post->buffLen = 0;
connData[i].post->received=0; connData[i].post->received = 0;
connData[i].post->len=-1; connData[i].post->len = -1;
connData[i].startTime = system_get_time(); connData[i].startTime = system_get_time();
espconn_regist_recvcb(conn, httpdRecvCb); espconn_regist_recvcb(conn, httpdRecvCb);
@ -567,23 +604,24 @@ static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) {
espconn_regist_disconcb(conn, httpdDisconCb); espconn_regist_disconcb(conn, httpdDisconCb);
espconn_regist_sentcb(conn, httpdSentCb); espconn_regist_sentcb(conn, httpdSentCb);
espconn_set_opt(conn, ESPCONN_REUSEADDR|ESPCONN_NODELAY); espconn_set_opt(conn, ESPCONN_REUSEADDR | ESPCONN_NODELAY);
} }
//Httpd initialization routine. Call this to kick off webserver functionality. //Httpd initialization routine. Call this to kick off webserver functionality.
void ICACHE_FLASH_ATTR httpdInit(HttpdBuiltInUrl *fixedUrls, int port) { void ICACHE_FLASH_ATTR httpdInit(HttpdBuiltInUrl *fixedUrls, int port) {
int i; int i;
for (i=0; i<MAX_CONN; i++) { for (i = 0; i<MAX_CONN; i++) {
connData[i].conn=NULL; connData[i].conn = NULL;
} }
httpdConn.type=ESPCONN_TCP; httpdConn.type = ESPCONN_TCP;
httpdConn.state=ESPCONN_NONE; httpdConn.state = ESPCONN_NONE;
httpdTcp.local_port=port; httpdTcp.local_port = port;
httpdConn.proto.tcp=&httpdTcp; httpdConn.proto.tcp = &httpdTcp;
builtInUrls=fixedUrls; builtInUrls = fixedUrls;
#ifdef HTTPD_DBG
os_printf("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);

@ -5,26 +5,32 @@
#include <_mingw.h> #include <_mingw.h>
#endif #endif
#define MQTT_RECONNECT_TIMEOUT 5 // seconds #define DEBUGIP
#define MQTT_BUF_SIZE 1024
#define CMD_DBG
#define MQTT_HOST "10.0.0.220" // "mqtt.yourdomain.com" or ip "10.0.0.1" #define ESPFS_DBG
#define MQTT_PORT 1883 #define CGI_DBG
#define MQTT_SECURITY 0 #define CGIFLASH_DBG
#define CGIMQTT_DBG
#define MQTT_CLIENT_ID "esp-link" // "" #define CGIPINS_DBG
#define MQTT_USER "" #define CGIWIFI_DBG
#define MQTT_PASS "" #define CONFIG_DBG
#define MQTT_KEEPALIVE 120 // seconds #define LOG_DBG
#define MQTT_CLSESSION true #define STATUS_DBG
#define HTTPD_DBG
#define PROTOCOL_NAMEv31 // MQTT version 3.1 compatible with Mosquitto v0.15 #define MQTT_DBG
//PROTOCOL_NAMEv311 // MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/ #define MQTTCMD_DBG
#define PKTBUF_DBG
#define REST_DBG
#define RESTCMD_DBG
#define SERBR_DBG
#define SERLED_DBG
#define SLIP_DBG
#define UART_DBG
#define CHIP_IN_HOSTNAME
extern char* esp_link_version; extern char* esp_link_version;
extern uint8_t UTILS_StrToIP(const char* str, void *ip); extern uint8_t UTILS_StrToIP(const char* str, void *ip);
extern void ICACHE_FLASH_ATTR init(void);
#endif #endif

@ -59,10 +59,12 @@ sint8 espconn_secure_sent(struct espconn *espconn, uint8 *psent, uint16 length)
// max message size for sending (except publish) // max message size for sending (except publish)
#define MQTT_MAX_SHORT_MESSAGE 128 #define MQTT_MAX_SHORT_MESSAGE 128
#ifdef MQTT_DBG
static char* mqtt_msg_type[] = { static char* mqtt_msg_type[] = {
"NULL", "TYPE_CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP", "NULL", "TYPE_CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP",
"SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT", "RESV", "SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT", "RESV",
}; };
#endif
// forward declarations // forward declarations
static void mqtt_enq_message(MQTT_Client *client, const uint8_t *data, uint16_t len); static void mqtt_enq_message(MQTT_Client *client, const uint8_t *data, uint16_t len);
@ -127,7 +129,9 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
if (msg_len > client->in_buffer_size) { if (msg_len > client->in_buffer_size) {
// oops, too long a message for us to digest, disconnect and hope for a miracle // oops, too long a message for us to digest, disconnect and hope for a miracle
#ifdef MQTT_DBG
os_printf("MQTT: Too long a message (%d bytes)\n", msg_len); os_printf("MQTT: Too long a message (%d bytes)\n", msg_len);
#endif
mqtt_doAbort(client); mqtt_doAbort(client);
return; return;
} }
@ -137,7 +141,9 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
if (client->connState != MQTT_CONNECTED) { if (client->connState != MQTT_CONNECTED) {
// why are we receiving something?? // why are we receiving something??
#ifdef MQTT_DBG
os_printf("MQTT ERROR: recv in invalid state %d\n", client->connState); os_printf("MQTT ERROR: recv in invalid state %d\n", client->connState);
#endif
mqtt_doAbort(client); mqtt_doAbort(client);
return; return;
} }
@ -149,13 +155,16 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
pending_msg_type = mqtt_get_type(client->pending_buffer->data); pending_msg_type = mqtt_get_type(client->pending_buffer->data);
pending_msg_id = mqtt_get_id(client->pending_buffer->data, client->pending_buffer->filled); pending_msg_id = mqtt_get_id(client->pending_buffer->data, client->pending_buffer->filled);
} }
#ifdef MQTT_DBG
os_printf("MQTT: Recv type=%s id=%04X len=%d; Pend type=%s id=%04X\n", os_printf("MQTT: Recv type=%s id=%04X len=%d; Pend type=%s id=%02X\n",
mqtt_msg_type[msg_type], msg_id, msg_len, mqtt_msg_type[pending_msg_type], pending_msg_id); mqtt_msg_type[msg_type], msg_id, msg_len, mqtt_msg_type[pending_msg_type],pending_msg_id);
#endif
switch (msg_type) { switch (msg_type) {
case MQTT_MSG_TYPE_CONNACK: case MQTT_MSG_TYPE_CONNACK:
#ifdef MQTT_DBG
os_printf("MQTT: Connect successful\n"); os_printf("MQTT: Connect successful\n");
#endif
// callbacks for internal and external clients // callbacks for internal and external clients
if (client->connectedCb) client->connectedCb((uint32_t*)client); if (client->connectedCb) client->connectedCb((uint32_t*)client);
if (client->cmdConnectedCb) client->cmdConnectedCb((uint32_t*)client); if (client->cmdConnectedCb) client->cmdConnectedCb((uint32_t*)client);
@ -163,28 +172,36 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
case MQTT_MSG_TYPE_SUBACK: case MQTT_MSG_TYPE_SUBACK:
if (pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && pending_msg_id == msg_id) { if (pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: Subscribe successful\n"); os_printf("MQTT: Subscribe successful\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
} }
break; break;
case MQTT_MSG_TYPE_UNSUBACK: case MQTT_MSG_TYPE_UNSUBACK:
if (pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && pending_msg_id == msg_id) { if (pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: Unsubscribe successful\n"); os_printf("MQTT: Unsubscribe successful\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
} }
break; break;
case MQTT_MSG_TYPE_PUBACK: // ack for a publish we sent case MQTT_MSG_TYPE_PUBACK: // ack for a publish we sent
if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) { if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: QoS1 Publish successful\n"); os_printf("MQTT: QoS1 Publish successful\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
} }
break; break;
case MQTT_MSG_TYPE_PUBREC: // rec for a publish we sent case MQTT_MSG_TYPE_PUBREC: // rec for a publish we sent
if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) { if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: QoS2 publish cont\n"); os_printf("MQTT: QoS2 publish cont\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
// we need to send PUBREL // we need to send PUBREL
mqtt_msg_pubrel(&client->mqtt_connection, msg_id); mqtt_msg_pubrel(&client->mqtt_connection, msg_id);
@ -195,7 +212,9 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
case MQTT_MSG_TYPE_PUBCOMP: // comp for a pubrel we sent (originally publish we sent) case MQTT_MSG_TYPE_PUBCOMP: // comp for a pubrel we sent (originally publish we sent)
if (pending_msg_type == MQTT_MSG_TYPE_PUBREL && pending_msg_id == msg_id) { if (pending_msg_type == MQTT_MSG_TYPE_PUBREL && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: QoS2 Publish successful\n"); os_printf("MQTT: QoS2 Publish successful\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
} }
break; break;
@ -203,9 +222,11 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
case MQTT_MSG_TYPE_PUBLISH: { // incoming publish case MQTT_MSG_TYPE_PUBLISH: { // incoming publish
// we may need to ACK the publish // we may need to ACK the publish
uint8_t msg_qos = mqtt_get_qos(client->in_buffer); uint8_t msg_qos = mqtt_get_qos(client->in_buffer);
#ifdef MQTT_DBG
uint16_t topic_length = msg_len; uint16_t topic_length = msg_len;
os_printf("MQTT: Recv PUBLISH qos=%d %s\n", msg_qos, os_printf("MQTT: Recv PUBLISH qos=%d %s\n", msg_qos,
mqtt_get_publish_topic(client->in_buffer, &topic_length)); mqtt_get_publish_topic(client->in_buffer, &topic_length));
#endif
if (msg_qos == 1) mqtt_msg_puback(&client->mqtt_connection, msg_id); if (msg_qos == 1) mqtt_msg_puback(&client->mqtt_connection, msg_id);
if (msg_qos == 2) mqtt_msg_pubrec(&client->mqtt_connection, msg_id); if (msg_qos == 2) mqtt_msg_pubrec(&client->mqtt_connection, msg_id);
if (msg_qos == 1 || msg_qos == 2) { if (msg_qos == 1 || msg_qos == 2) {
@ -219,7 +240,9 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
case MQTT_MSG_TYPE_PUBREL: // rel for a rec we sent (originally publish received) case MQTT_MSG_TYPE_PUBREL: // rel for a rec we sent (originally publish received)
if (pending_msg_type == MQTT_MSG_TYPE_PUBREC && pending_msg_id == msg_id) { if (pending_msg_type == MQTT_MSG_TYPE_PUBREC && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: Cont QoS2 recv\n"); os_printf("MQTT: Cont QoS2 recv\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
// we need to send PUBCOMP // we need to send PUBCOMP
mqtt_msg_pubcomp(&client->mqtt_connection, msg_id); mqtt_msg_pubcomp(&client->mqtt_connection, msg_id);
@ -296,7 +319,9 @@ mqtt_timer(void* arg) {
// check whether our last keep-alive timed out // check whether our last keep-alive timed out
if (client->keepAliveAckTick > 0 && --client->keepAliveAckTick == 0) { if (client->keepAliveAckTick > 0 && --client->keepAliveAckTick == 0) {
#ifdef MQTT_DBG
os_printf("\nMQTT ERROR: Keep-alive timed out\n"); os_printf("\nMQTT ERROR: Keep-alive timed out\n");
#endif
mqtt_doAbort(client); mqtt_doAbort(client);
return; return;
} }
@ -340,15 +365,17 @@ void ICACHE_FLASH_ATTR
mqtt_tcpclient_discon_cb(void* arg) { mqtt_tcpclient_discon_cb(void* arg) {
struct espconn* pespconn = (struct espconn *)arg; struct espconn* pespconn = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pespconn->reverse; MQTT_Client* client = (MQTT_Client *)pespconn->reverse;
#ifdef MQTT_DBG
os_printf("MQTT: Disconnect CB, freeing espconn %p\n", arg); os_printf("MQTT: Disconnect CB, freeing espconn %p\n", arg);
#endif
if (pespconn->proto.tcp) os_free(pespconn->proto.tcp); if (pespconn->proto.tcp) os_free(pespconn->proto.tcp);
os_free(pespconn); os_free(pespconn);
// if this is an aborted connection we're done // if this is an aborted connection we're done
if (client == NULL) return; if (client == NULL) return;
#ifdef MQTT_DBG
os_printf("MQTT: Disconnected from %s:%d\n", client->host, client->port); os_printf("MQTT: Disconnected from %s:%d\n", client->host, client->port);
#endif
if (client->disconnectedCb) client->disconnectedCb((uint32_t*)client); if (client->disconnectedCb) client->disconnectedCb((uint32_t*)client);
if (client->cmdDisconnectedCb) client->cmdDisconnectedCb((uint32_t*)client); if (client->cmdDisconnectedCb) client->cmdDisconnectedCb((uint32_t*)client);
@ -367,12 +394,14 @@ static void ICACHE_FLASH_ATTR
mqtt_tcpclient_recon_cb(void* arg, int8_t err) { mqtt_tcpclient_recon_cb(void* arg, int8_t err) {
struct espconn* pespconn = (struct espconn *)arg; struct espconn* pespconn = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pespconn->reverse; MQTT_Client* client = (MQTT_Client *)pespconn->reverse;
#ifdef MQTT_DBG
os_printf("MQTT: Reset CB, freeing espconn %p (err=%d)\n", arg, err); os_printf("MQTT: Reset CB, freeing espconn %p (err=%d)\n", arg, err);
#endif
if (pespconn->proto.tcp) os_free(pespconn->proto.tcp); if (pespconn->proto.tcp) os_free(pespconn->proto.tcp);
os_free(pespconn); os_free(pespconn);
#ifdef MQTT_DBG
os_printf("MQTT: Connection reset from %s:%d\n", client->host, client->port); os_printf("MQTT: Connection reset from %s:%d\n", client->host, client->port);
#endif
if (client->disconnectedCb) client->disconnectedCb((uint32_t*)client); if (client->disconnectedCb) client->disconnectedCb((uint32_t*)client);
if (client->cmdDisconnectedCb) client->cmdDisconnectedCb((uint32_t*)client); if (client->cmdDisconnectedCb) client->cmdDisconnectedCb((uint32_t*)client);
@ -397,7 +426,9 @@ mqtt_tcpclient_connect_cb(void* arg) {
espconn_regist_disconcb(client->pCon, mqtt_tcpclient_discon_cb); espconn_regist_disconcb(client->pCon, mqtt_tcpclient_discon_cb);
espconn_regist_recvcb(client->pCon, mqtt_tcpclient_recv); espconn_regist_recvcb(client->pCon, mqtt_tcpclient_recv);
espconn_regist_sentcb(client->pCon, mqtt_tcpclient_sent_cb); espconn_regist_sentcb(client->pCon, mqtt_tcpclient_sent_cb);
#ifdef MQTT_DBG
os_printf("MQTT: TCP connected to %s:%d\n", client->host, client->port); os_printf("MQTT: TCP connected to %s:%d\n", client->host, client->port);
#endif
// send MQTT connect message to broker // send MQTT connect message to broker
mqtt_msg_connect(&client->mqtt_connection, &client->connect_info); mqtt_msg_connect(&client->mqtt_connection, &client->connect_info);
@ -438,8 +469,9 @@ mqtt_send_message(MQTT_Client* client) {
// get some details about the message // get some details about the message
uint16_t msg_type = mqtt_get_type(buf->data); uint16_t msg_type = mqtt_get_type(buf->data);
uint8_t msg_id = mqtt_get_id(buf->data, buf->filled); uint8_t msg_id = mqtt_get_id(buf->data, buf->filled);
msg_id = msg_id;
#ifdef MQTT_DBG
os_printf("MQTT: Send type=%s id=%04X len=%d\n", mqtt_msg_type[msg_type], msg_id, buf->filled); os_printf("MQTT: Send type=%s id=%04X len=%d\n", mqtt_msg_type[msg_type], msg_id, buf->filled);
#if 0
for (int i=0; i<buf->filled; i++) { for (int i=0; i<buf->filled; i++) {
if (buf->data[i] >= ' ' && buf->data[i] <= '~') os_printf("%c", buf->data[i]); if (buf->data[i] >= ' ' && buf->data[i] <= '~') os_printf("%c", buf->data[i]);
else os_printf("\\x%02X", buf->data[i]); else os_printf("\\x%02X", buf->data[i]);
@ -484,17 +516,20 @@ mqtt_dns_found(const char* name, ip_addr_t* ipaddr, void* arg) {
MQTT_Client* client = (MQTT_Client *)pConn->reverse; MQTT_Client* client = (MQTT_Client *)pConn->reverse;
if (ipaddr == NULL) { if (ipaddr == NULL) {
#ifdef MQTT_DBG
os_printf("MQTT DNS: Got no ip, try to reconnect\n"); os_printf("MQTT DNS: Got no ip, try to reconnect\n");
#endif
client->timeoutTick = 10; client->timeoutTick = 10;
client->connState = TCP_RECONNECT_REQ; // the timer will kick-off a reconnection client->connState = TCP_RECONNECT_REQ; // the timer will kick-off a reconnection
return; return;
} }
#ifdef MQTT_DBG
os_printf("MQTT DNS: found ip %d.%d.%d.%d\n", os_printf("MQTT DNS: found ip %d.%d.%d.%d\n",
*((uint8 *)&ipaddr->addr), *((uint8 *)&ipaddr->addr),
*((uint8 *)&ipaddr->addr + 1), *((uint8 *)&ipaddr->addr + 1),
*((uint8 *)&ipaddr->addr + 2), *((uint8 *)&ipaddr->addr + 2),
*((uint8 *)&ipaddr->addr + 3)); *((uint8 *)&ipaddr->addr + 3));
#endif
if (client->ip.addr == 0 && ipaddr->addr != 0) { if (client->ip.addr == 0 && ipaddr->addr != 0) {
os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4); os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4);
@ -504,11 +539,15 @@ mqtt_dns_found(const char* name, ip_addr_t* ipaddr, void* arg) {
else else
err = espconn_connect(client->pCon); err = espconn_connect(client->pCon);
if (err != 0) { if (err != 0) {
#ifdef MQTT_DBG
os_printf("MQTT ERROR: Failed to connect\n"); os_printf("MQTT ERROR: Failed to connect\n");
#endif
client->connState = TCP_RECONNECT_REQ; client->connState = TCP_RECONNECT_REQ;
client->timeoutTick = 10; client->timeoutTick = 10;
} else { } else {
#ifdef MQTT_DBG
os_printf("MQTT: connecting...\n"); os_printf("MQTT: connecting...\n");
#endif
} }
} }
} }
@ -542,7 +581,9 @@ MQTT_Publish(MQTT_Client* client, const char* topic, const char* data, uint8_t q
uint16_t buf_len = 3 + 2 + 2 + topic_length + data_length + 16; uint16_t buf_len = 3 + 2 + 2 + topic_length + data_length + 16;
PktBuf *buf = PktBuf_New(buf_len); PktBuf *buf = PktBuf_New(buf_len);
if (buf == NULL) { if (buf == NULL) {
#ifdef MQTT_DBG
os_printf("MQTT ERROR: Cannot allocate buffer for %d byte publish\n", buf_len); os_printf("MQTT ERROR: Cannot allocate buffer for %d byte publish\n", buf_len);
#endif
return FALSE; return FALSE;
} }
// use a temporary mqtt_message_t pointing to our buffer, this is a bit of a mess because we // use a temporary mqtt_message_t pointing to our buffer, this is a bit of a mess because we
@ -551,7 +592,9 @@ MQTT_Publish(MQTT_Client* client, const char* topic, const char* data, uint8_t q
msg_conn_init(&msg, &client->mqtt_connection, buf->data, buf_len); msg_conn_init(&msg, &client->mqtt_connection, buf->data, buf_len);
uint16_t msg_id; uint16_t msg_id;
if (!mqtt_msg_publish(&msg, topic, data, data_length, qos, retain, &msg_id)){ if (!mqtt_msg_publish(&msg, topic, data, data_length, qos, retain, &msg_id)){
#ifdef MQTT_DBG
os_printf("MQTT ERROR: Queuing Publish failed\n"); os_printf("MQTT ERROR: Queuing Publish failed\n");
#endif
os_free(buf); os_free(buf);
return FALSE; return FALSE;
} }
@ -581,10 +624,14 @@ bool ICACHE_FLASH_ATTR
MQTT_Subscribe(MQTT_Client* client, char* topic, uint8_t qos) { MQTT_Subscribe(MQTT_Client* client, char* topic, uint8_t qos) {
uint16_t msg_id; uint16_t msg_id;
if (!mqtt_msg_subscribe(&client->mqtt_connection, topic, 0, &msg_id)) { if (!mqtt_msg_subscribe(&client->mqtt_connection, topic, 0, &msg_id)) {
#ifdef MQTT_DBG
os_printf("MQTT ERROR: Queuing Subscribe failed (too long)\n"); os_printf("MQTT ERROR: Queuing Subscribe failed (too long)\n");
#endif
return FALSE; return FALSE;
} }
#ifdef MQTT_DBG
os_printf("MQTT: Subscribe, topic: \"%s\"\n", topic); os_printf("MQTT: Subscribe, topic: \"%s\"\n", topic);
#endif
mqtt_enq_message(client, client->mqtt_connection.message.data, mqtt_enq_message(client, client->mqtt_connection.message.data,
client->mqtt_connection.message.length); client->mqtt_connection.message.length);
return TRUE; return TRUE;
@ -602,14 +649,20 @@ MQTT_Subscribe(MQTT_Client* client, char* topic, uint8_t qos) {
* @param client_user: MQTT client user * @param client_user: MQTT client user
* @param client_pass: MQTT client password * @param client_pass: MQTT client password
* @param keepAliveTime: MQTT keep alive timer, in second * @param keepAliveTime: MQTT keep alive timer, in second
* @param cleanSession: MQTT ... * @param cleanSession: On connection, a client sets the "clean session" flag, which is sometimes also known as the "clean start" flag.
* If clean session is set to false, then the connection is treated as durable. This means that when the client
* disconnects, any subscriptions it has will remain and any subsequent QoS 1 or 2 messages will be stored until
* it connects again in the future. If clean session is true, then all subscriptions will be removed for the client
* when it disconnects.
* @retval None * @retval None
*/ */
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
MQTT_Init(MQTT_Client* mqttClient, char* host, uint32 port, uint8_t security, uint8_t sendTimeout, MQTT_Init(MQTT_Client* mqttClient, char* host, uint32 port, uint8_t security, uint8_t sendTimeout,
char* client_id, char* client_user, char* client_pass, char* client_id, char* client_user, char* client_pass,
uint8_t keepAliveTime) { uint8_t keepAliveTime) {
#ifdef MQTT_DBG
os_printf("MQTT_Init\n"); os_printf("MQTT_Init\n");
#endif
os_memset(mqttClient, 0, sizeof(MQTT_Client)); os_memset(mqttClient, 0, sizeof(MQTT_Client));
@ -686,7 +739,9 @@ MQTT_Connect(MQTT_Client* mqttClient) {
os_timer_arm(&mqttClient->mqttTimer, 1000, 1); os_timer_arm(&mqttClient->mqttTimer, 1000, 1);
// initiate the TCP connection or DNS lookup // initiate the TCP connection or DNS lookup
#ifdef MQTT_DBG
os_printf("MQTT: Connect to %s:%d %p\n", mqttClient->host, mqttClient->port, mqttClient->pCon); os_printf("MQTT: Connect to %s:%d %p\n", mqttClient->host, mqttClient->port, mqttClient->pCon);
#endif
if (UTILS_StrToIP((const char *)mqttClient->host, if (UTILS_StrToIP((const char *)mqttClient->host,
(void*)&mqttClient->pCon->proto.tcp->remote_ip)) { (void*)&mqttClient->pCon->proto.tcp->remote_ip)) {
uint8_t err; uint8_t err;
@ -695,7 +750,9 @@ MQTT_Connect(MQTT_Client* mqttClient) {
else else
err = espconn_connect(mqttClient->pCon); err = espconn_connect(mqttClient->pCon);
if (err != 0) { if (err != 0) {
#ifdef MQTT_DBG
os_printf("MQTT ERROR: Failed to connect\n"); os_printf("MQTT ERROR: Failed to connect\n");
#endif
os_free(mqttClient->pCon->proto.tcp); os_free(mqttClient->pCon->proto.tcp);
os_free(mqttClient->pCon); os_free(mqttClient->pCon);
mqttClient->pCon = NULL; mqttClient->pCon = NULL;
@ -713,7 +770,9 @@ MQTT_Connect(MQTT_Client* mqttClient) {
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
mqtt_doAbort(MQTT_Client* client) { mqtt_doAbort(MQTT_Client* client) {
#ifdef MQTT_DBG
os_printf("MQTT: Disconnecting from %s:%d (%p)\n", client->host, client->port, client->pCon); os_printf("MQTT: Disconnecting from %s:%d (%p)\n", client->host, client->port, client->pCon);
#endif
client->pCon->reverse = NULL; // ensure we jettison this pCon... client->pCon->reverse = NULL; // ensure we jettison this pCon...
if (client->security) if (client->security)
espconn_secure_disconnect(client->pCon); espconn_secure_disconnect(client->pCon);

@ -8,11 +8,13 @@ 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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: Connected connectedCb=%p, disconnectedCb=%p, publishedCb=%p, dataCb=%p\n", os_printf("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,
(void*)cb->dataCb); (void*)cb->dataCb);
#endif
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->connectedCb, 0, 0); uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->connectedCb, 0, 0);
CMD_ResponseEnd(crc); CMD_ResponseEnd(crc);
} }
@ -21,7 +23,9 @@ void ICACHE_FLASH_ATTR
cmdMqttTcpDisconnectedCb(uint32_t *args) { cmdMqttTcpDisconnectedCb(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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: TCP Disconnected\n"); os_printf("MQTT: TCP Disconnected\n");
#endif
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->tcpDisconnectedCb, 0, 0); uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->tcpDisconnectedCb, 0, 0);
CMD_ResponseEnd(crc); CMD_ResponseEnd(crc);
} }
@ -30,7 +34,9 @@ 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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: Disconnected\n"); os_printf("MQTT: Disconnected\n");
#endif
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);
} }
@ -39,7 +45,9 @@ 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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: Published\n"); os_printf("MQTT: Published\n");
#endif
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);
} }
@ -103,8 +111,9 @@ 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
os_printf("MQTT: MQTTCMD_Setup clientid=%s, user=%s, pw=%s, keepalive=%ld, clean_session=%ld\n", client_id, user_data, pass_data, keepalive, clean_session); os_printf("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
// init client // init client
// TODO: why malloc these all here, pass to MQTT_InitClient to be malloc'd again? // TODO: why malloc these all here, pass to MQTT_InitClient to be malloc'd again?
@ -155,7 +164,9 @@ MQTTCMD_Lwt(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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Lwt client ptr=%p\n", (void*)client_ptr); os_printf("MQTT: MQTTCMD_Lwt client ptr=%p\n", (void*)client_ptr);
#endif
uint16_t len; uint16_t len;
@ -182,12 +193,13 @@ 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);
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Lwt topic=%s, message=%s, qos=%d, retain=%d\n", os_printf("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,
client->connect_info.will_retain); client->connect_info.will_retain);
#endif
return 1; return 1;
} }
@ -203,7 +215,9 @@ 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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Connect client ptr=%p\n", (void*)client_ptr); os_printf("MQTT: MQTTCMD_Connect client ptr=%p\n", (void*)client_ptr);
#endif
uint16_t len; uint16_t len;
@ -221,11 +235,12 @@ MQTTCMD_Connect(CmdPacket *cmd) {
// get security // get security
CMD_PopArg(&req, (uint8_t*)&client->security, 4); CMD_PopArg(&req, (uint8_t*)&client->security, 4);
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n", os_printf("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n",
client->host, client->host,
client->port, client->port,
client->security); client->security);
#endif
MQTT_Connect(client); MQTT_Connect(client);
return 1; return 1;
@ -243,7 +258,9 @@ 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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Disconnect client ptr=%p\n", (void*)client_ptr); os_printf("MQTT: MQTTCMD_Disconnect client ptr=%p\n", (void*)client_ptr);
#endif
// disconnect // disconnect
MQTT_Disconnect(client); MQTT_Disconnect(client);
@ -262,7 +279,9 @@ MQTTCMD_Publish(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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Publish client ptr=%p\n", (void*)client_ptr); os_printf("MQTT: MQTTCMD_Publish client ptr=%p\n", (void*)client_ptr);
#endif
uint16_t len; uint16_t len;
uint8_t *topic, *data; uint8_t *topic, *data;
@ -293,12 +312,13 @@ MQTTCMD_Publish(CmdPacket *cmd) {
// get retain // get retain
CMD_PopArg(&req, (uint8_t*)&retain, 4); CMD_PopArg(&req, (uint8_t*)&retain, 4);
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Publish topic=%s, data_len=%d, qos=%ld, retain=%ld\n", os_printf("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,
retain); retain);
#endif
MQTT_Publish(client, (char*)topic, (char*)data, (uint8_t)qos, (uint8_t)retain); MQTT_Publish(client, (char*)topic, (char*)data, (uint8_t)qos, (uint8_t)retain);
os_free(topic); os_free(topic);
@ -318,7 +338,9 @@ MQTTCMD_Subscribe(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;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Subscribe client ptr=%p\n", (void*)client_ptr); os_printf("MQTT: MQTTCMD_Subscribe client ptr=%p\n", (void*)client_ptr);
#endif
uint16_t len; uint16_t len;
uint8_t* topic; uint8_t* topic;
@ -333,8 +355,9 @@ MQTTCMD_Subscribe(CmdPacket *cmd) {
// get qos // get qos
CMD_PopArg(&req, (uint8_t*)&qos, 4); CMD_PopArg(&req, (uint8_t*)&qos, 4);
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Subscribe topic=%s, qos=%ld\n", topic, qos); os_printf("MQTT: MQTTCMD_Subscribe topic=%s, qos=%ld\n", topic, qos);
#endif
MQTT_Subscribe(client, (char*)topic, (uint8_t)qos); MQTT_Subscribe(client, (char*)topic, (uint8_t)qos);
os_free(topic); os_free(topic);
return 1; return 1;

@ -73,7 +73,7 @@ typedef struct mqtt_connect_info {
char* password; char* password;
char* will_topic; char* will_topic;
char* will_message; char* will_message;
uint32_t keepalive; uint8_t keepalive;
uint8_t will_qos; uint8_t will_qos;
uint8_t will_retain; uint8_t will_retain;
uint8_t clean_session; uint8_t clean_session;

@ -3,7 +3,8 @@
#include <esp8266.h> #include <esp8266.h>
#include "pktbuf.h" #include "pktbuf.h"
void ICACHE_FLASH_ATTR #ifdef PKTBUF_DBG
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++)
@ -15,6 +16,7 @@ PktBuf_Print(PktBuf *buf) {
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
PktBuf * ICACHE_FLASH_ATTR PktBuf * ICACHE_FLASH_ATTR

@ -24,6 +24,4 @@ PktBuf *PktBuf_Shift(PktBuf *headBuf);
// Shift first buffer off queue, free it, return new head // Shift first buffer off queue, free it, return new head
PktBuf *PktBuf_ShiftFree(PktBuf *headBuf); PktBuf *PktBuf_ShiftFree(PktBuf *headBuf);
void PktBuf_Print(PktBuf *buf);
#endif #endif

@ -73,16 +73,20 @@ tcpclient_recv(void *arg, char *pdata, unsigned short len) {
// collect body and send it // collect body and send it
uint16_t crc; uint16_t crc;
int body_len = len-pi; int body_len = len-pi;
#ifdef REST_DBG
os_printf("REST: status=%ld, body=%d\n", code, body_len); os_printf("REST: status=%ld, body=%d\n", code, body_len);
#endif
if (pi == len) { if (pi == len) {
crc = CMD_ResponseStart(CMD_REST_EVENTS, client->resp_cb, code, 0); crc = CMD_ResponseStart(CMD_REST_EVENTS, client->resp_cb, code, 0);
} else { } else {
crc = CMD_ResponseStart(CMD_REST_EVENTS, client->resp_cb, code, 1); crc = CMD_ResponseStart(CMD_REST_EVENTS, client->resp_cb, code, 1);
crc = CMD_ResponseBody(crc, (uint8_t*)(pdata+pi), body_len); crc = CMD_ResponseBody(crc, (uint8_t*)(pdata+pi), body_len);
CMD_ResponseEnd(crc); CMD_ResponseEnd(crc);
#ifdef REST_DBG
os_printf("REST: body="); os_printf("REST: body=");
for (int j=pi; j<len; j++) os_printf(" %02x", pdata[j]); for (int j=pi; j<len; j++) os_printf(" %02x", pdata[j]);
os_printf("\n"); os_printf("\n");
#endif
} }
//if(client->security) //if(client->security)
@ -96,7 +100,9 @@ static void ICACHE_FLASH_ATTR
tcpclient_sent_cb(void *arg) { tcpclient_sent_cb(void *arg) {
struct espconn *pCon = (struct espconn *)arg; struct espconn *pCon = (struct espconn *)arg;
RestClient* client = (RestClient *)pCon->reverse; RestClient* client = (RestClient *)pCon->reverse;
#ifdef REST_DBG
os_printf("REST: Sent\n"); os_printf("REST: Sent\n");
#endif
if (client->data_sent != client->data_len) { if (client->data_sent != client->data_len) {
// we only sent part of the buffer, send the rest // we only sent part of the buffer, send the rest
espconn_sent(client->pCon, (uint8_t*)(client->data+client->data_sent), espconn_sent(client->pCon, (uint8_t*)(client->data+client->data_sent),
@ -113,14 +119,17 @@ static void ICACHE_FLASH_ATTR
tcpclient_connect_cb(void *arg) { tcpclient_connect_cb(void *arg) {
struct espconn *pCon = (struct espconn *)arg; struct espconn *pCon = (struct espconn *)arg;
RestClient* client = (RestClient *)pCon->reverse; RestClient* client = (RestClient *)pCon->reverse;
#ifdef REST_DBG
os_printf("REST #%d: connected\n", client-restClient); os_printf("REST #%d: connected\n", client-restClient);
#endif
espconn_regist_disconcb(client->pCon, tcpclient_discon_cb); espconn_regist_disconcb(client->pCon, tcpclient_discon_cb);
espconn_regist_recvcb(client->pCon, tcpclient_recv); espconn_regist_recvcb(client->pCon, tcpclient_recv);
espconn_regist_sentcb(client->pCon, tcpclient_sent_cb); espconn_regist_sentcb(client->pCon, tcpclient_sent_cb);
client->data_sent = client->data_len <= 1400 ? client->data_len : 1400; client->data_sent = client->data_len <= 1400 ? client->data_len : 1400;
#ifdef REST_DBG
os_printf("REST #%d: sending %d\n", client-restClient, client->data_sent); os_printf("REST #%d: sending %d\n", client-restClient, client->data_sent);
#endif
//if(client->security){ //if(client->security){
// espconn_secure_sent(client->pCon, client->data, client->data_sent); // espconn_secure_sent(client->pCon, client->data, client->data_sent);
//} //}
@ -133,7 +142,9 @@ static void ICACHE_FLASH_ATTR
tcpclient_recon_cb(void *arg, sint8 errType) { tcpclient_recon_cb(void *arg, sint8 errType) {
struct espconn *pCon = (struct espconn *)arg; struct espconn *pCon = (struct espconn *)arg;
RestClient* client = (RestClient *)pCon->reverse; RestClient* client = (RestClient *)pCon->reverse;
#ifdef REST_DBG
os_printf("REST #%d: conn reset\n", client-restClient); os_printf("REST #%d: conn reset\n", client-restClient);
#endif
} }
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
@ -142,16 +153,18 @@ rest_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) {
RestClient* client = (RestClient *)pConn->reverse; RestClient* client = (RestClient *)pConn->reverse;
if(ipaddr == NULL) { if(ipaddr == NULL) {
#ifdef REST_DBG
os_printf("REST DNS: Got no ip, try to reconnect\n"); os_printf("REST DNS: Got no ip, try to reconnect\n");
#endif
return; return;
} }
#ifdef REST_DBG
os_printf("REST DNS: found ip %d.%d.%d.%d\n", os_printf("REST DNS: found ip %d.%d.%d.%d\n",
*((uint8 *) &ipaddr->addr), *((uint8 *) &ipaddr->addr),
*((uint8 *) &ipaddr->addr + 1), *((uint8 *) &ipaddr->addr + 1),
*((uint8 *) &ipaddr->addr + 2), *((uint8 *) &ipaddr->addr + 2),
*((uint8 *) &ipaddr->addr + 3)); *((uint8 *) &ipaddr->addr + 3));
#endif
if(client->ip.addr == 0 && ipaddr->addr != 0) { if(client->ip.addr == 0 && ipaddr->addr != 0) {
os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4); os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4);
#ifdef CLIENT_SSL_ENABLE #ifdef CLIENT_SSL_ENABLE
@ -160,7 +173,9 @@ rest_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) {
} else } else
#endif #endif
espconn_connect(client->pCon); espconn_connect(client->pCon);
#ifdef REST_DBG
os_printf("REST: connecting...\n"); os_printf("REST: connecting...\n");
#endif
} }
} }
@ -213,8 +228,9 @@ REST_Setup(CmdPacket *cmd) {
os_free(client->pCon); os_free(client->pCon);
} }
os_memset(client, 0, sizeof(RestClient)); os_memset(client, 0, sizeof(RestClient));
#ifdef CMDREST_DBG
os_printf("REST: setup #%d host=%s port=%ld security=%ld\n", clientNum, rest_host, port, security); os_printf("REST: setup #%d host=%s port=%ld security=%ld\n", clientNum, rest_host, port, security);
#endif
client->resp_cb = cmd->callback; client->resp_cb = cmd->callback;
@ -273,7 +289,9 @@ REST_SetHeader(CmdPacket *cmd) {
client->header[len] = '\r'; client->header[len] = '\r';
client->header[len+1] = '\n'; client->header[len+1] = '\n';
client->header[len+2] = 0; client->header[len+2] = 0;
#ifdef CMDREST_DBG
os_printf("REST: Set header: %s\r\n", client->header); os_printf("REST: Set header: %s\r\n", client->header);
#endif
break; break;
case HEADER_CONTENT_TYPE: case HEADER_CONTENT_TYPE:
if(client->content_type) os_free(client->content_type); if(client->content_type) os_free(client->content_type);
@ -282,7 +300,9 @@ REST_SetHeader(CmdPacket *cmd) {
client->content_type[len] = '\r'; client->content_type[len] = '\r';
client->content_type[len+1] = '\n'; client->content_type[len+1] = '\n';
client->content_type[len+2] = 0; client->content_type[len+2] = 0;
#ifdef CMDREST_DBG
os_printf("REST: Set content_type: %s\r\n", client->content_type); os_printf("REST: Set content_type: %s\r\n", client->content_type);
#endif
break; break;
case HEADER_USER_AGENT: case HEADER_USER_AGENT:
if(client->user_agent) os_free(client->user_agent); if(client->user_agent) os_free(client->user_agent);
@ -291,7 +311,9 @@ REST_SetHeader(CmdPacket *cmd) {
client->user_agent[len] = '\r'; client->user_agent[len] = '\r';
client->user_agent[len+1] = '\n'; client->user_agent[len+1] = '\n';
client->user_agent[len+2] = 0; client->user_agent[len+2] = 0;
#ifdef CMDREST_DBG
os_printf("REST: Set user_agent: %s\r\n", client->user_agent); os_printf("REST: Set user_agent: %s\r\n", client->user_agent);
#endif
break; break;
} }
return 1; return 1;
@ -301,32 +323,36 @@ uint32_t ICACHE_FLASH_ATTR
REST_Request(CmdPacket *cmd) { REST_Request(CmdPacket *cmd) {
CmdRequest req; CmdRequest req;
CMD_Request(&req, cmd); CMD_Request(&req, cmd);
#ifdef CMDREST_DBG
os_printf("REST: request"); os_printf("REST: request");
#endif
// Get client // Get client
uint32_t clientNum; uint32_t clientNum;
if (CMD_PopArg(&req, (uint8_t*)&clientNum, 4)) goto fail; if (CMD_PopArg(&req, (uint8_t*)&clientNum, 4)) goto fail;
if ((clientNum & 0xffff0000) != REST_CB) goto fail; if ((clientNum & 0xffff0000) != REST_CB) goto fail;
clientNum &= 0xffff; clientNum &= 0xffff;
RestClient *client = restClient + clientNum % MAX_REST; RestClient *client = restClient + clientNum % MAX_REST;
#ifdef CMDREST_DBG
os_printf(" #%ld", clientNum); os_printf(" #%ld", clientNum);
#endif
// Get HTTP method // Get HTTP method
uint16_t len = CMD_ArgLen(&req); uint16_t len = CMD_ArgLen(&req);
if (len > 15) goto fail; if (len > 15) goto fail;
char method[16]; char method[16];
CMD_PopArg(&req, method, len); CMD_PopArg(&req, method, len);
method[len] = 0; method[len] = 0;
#ifdef CMDREST_DBG
os_printf(" method=%s", method); os_printf(" method=%s", method);
#endif
// Get HTTP path // Get HTTP path
len = CMD_ArgLen(&req); len = CMD_ArgLen(&req);
if (len > 1023) goto fail; if (len > 1023) goto fail;
char path[1024]; char path[1024];
CMD_PopArg(&req, path, len); CMD_PopArg(&req, path, len);
path[len] = 0; path[len] = 0;
#ifdef CMDREST_DBG
os_printf(" path=%s", path); os_printf(" path=%s", path);
#endif
// Get HTTP body // Get HTTP body
uint32_t realLen = 0; uint32_t realLen = 0;
if (CMD_GetArgc(&req) == 3) { if (CMD_GetArgc(&req) == 3) {
@ -338,7 +364,9 @@ REST_Request(CmdPacket *cmd) {
len = CMD_ArgLen(&req); len = CMD_ArgLen(&req);
if (len > 2048 || realLen > len) goto fail; if (len > 2048 || realLen > len) goto fail;
} }
#ifdef CMDREST_DBG
os_printf(" bodyLen=%ld", realLen); os_printf(" bodyLen=%ld", realLen);
#endif
// we need to allocate memory for the header plus the body. First we count the length of the // we need to allocate memory for the header plus the body. First we count the length of the
// header (including some extra counted "%s" and then we add the body length. We allocate the // header (including some extra counted "%s" and then we add the body length. We allocate the
@ -353,30 +381,40 @@ REST_Request(CmdPacket *cmd) {
"User-Agent: %s\r\n\r\n"; "User-Agent: %s\r\n\r\n";
uint16_t headerLen = strlen(headerFmt) + strlen(method) + strlen(path) + strlen(client->host) + uint16_t headerLen = strlen(headerFmt) + strlen(method) + strlen(path) + strlen(client->host) +
strlen(client->header) + strlen(client->content_type) + strlen(client->user_agent); strlen(client->header) + strlen(client->content_type) + strlen(client->user_agent);
#ifdef CMDREST_DBG
os_printf(" hdrLen=%d", headerLen); os_printf(" hdrLen=%d", headerLen);
#endif
if (client->data) os_free(client->data); if (client->data) os_free(client->data);
client->data = (char*)os_zalloc(headerLen + realLen); client->data = (char*)os_zalloc(headerLen + realLen);
if (client->data == NULL) goto fail; if (client->data == NULL) goto fail;
#ifdef CMDREST_DBG
os_printf(" totLen=%ld data=%p", headerLen + realLen, client->data); os_printf(" totLen=%ld data=%p", headerLen + realLen, client->data);
#endif
client->data_len = os_sprintf((char*)client->data, headerFmt, method, path, client->host, client->data_len = os_sprintf((char*)client->data, headerFmt, method, path, client->host,
client->header, realLen, client->content_type, client->user_agent); client->header, realLen, client->content_type, client->user_agent);
#ifdef CMDREST_DBG
os_printf(" hdrLen=%d", client->data_len); os_printf(" hdrLen=%d", client->data_len);
#endif
if (realLen > 0) { if (realLen > 0) {
CMD_PopArg(&req, client->data + client->data_len, realLen); CMD_PopArg(&req, client->data + client->data_len, realLen);
client->data_len += realLen; client->data_len += realLen;
} }
#ifdef CMDREST_DBG
os_printf("\n"); os_printf("\n");
//os_printf("REST request: %s", (char*)client->data); //os_printf("REST request: %s", (char*)client->data);
os_printf("REST: pCon state=%d\n", client->pCon->state); os_printf("REST: pCon state=%d\n", client->pCon->state);
#endif
client->pCon->state = ESPCONN_NONE; client->pCon->state = ESPCONN_NONE;
espconn_regist_connectcb(client->pCon, tcpclient_connect_cb); espconn_regist_connectcb(client->pCon, tcpclient_connect_cb);
espconn_regist_reconcb(client->pCon, tcpclient_recon_cb); espconn_regist_reconcb(client->pCon, tcpclient_recon_cb);
if(UTILS_StrToIP((char *)client->host, &client->pCon->proto.tcp->remote_ip)) { if(UTILS_StrToIP((char *)client->host, &client->pCon->proto.tcp->remote_ip)) {
#ifdef CMDREST_DBG
os_printf("REST: Connect to ip %s:%ld\n",client->host, client->port); os_printf("REST: Connect to ip %s:%ld\n",client->host, client->port);
#endif
//if(client->security){ //if(client->security){
// espconn_secure_connect(client->pCon); // espconn_secure_connect(client->pCon);
//} //}
@ -384,13 +422,17 @@ REST_Request(CmdPacket *cmd) {
espconn_connect(client->pCon); espconn_connect(client->pCon);
//} //}
} else { } else {
#ifdef CMDREST_DBG
os_printf("REST: Connect to host %s:%ld\n", client->host, client->port); os_printf("REST: Connect to host %s:%ld\n", client->host, client->port);
#endif
espconn_gethostbyname(client->pCon, (char *)client->host, &client->ip, rest_dns_found); espconn_gethostbyname(client->pCon, (char *)client->host, &client->ip, rest_dns_found);
} }
return 1; return 1;
fail: fail:
#ifdef CMDREST_DBG
os_printf("\n"); os_printf("\n");
#endif
return 0; return 0;
} }

@ -100,10 +100,15 @@ telnetUnwrap(uint8_t *inBuf, int len, uint8_t state)
switch (c) { switch (c) {
case DTR_ON: case DTR_ON:
if (mcu_reset_pin >= 0) { if (mcu_reset_pin >= 0) {
#ifdef SERBR_DBG
os_printf("MCU reset gpio%d\n", mcu_reset_pin); os_printf("MCU reset gpio%d\n", mcu_reset_pin);
#endif
GPIO_OUTPUT_SET(mcu_reset_pin, 0); GPIO_OUTPUT_SET(mcu_reset_pin, 0);
os_delay_us(100L); os_delay_us(100L);
} else os_printf("MCU reset: no pin\n"); }
#ifdef SERBR_DBG
else os_printf("MCU reset: no pin\n");
#endif
break; break;
case DTR_OFF: case DTR_OFF:
if (mcu_reset_pin >= 0) { if (mcu_reset_pin >= 0) {
@ -113,10 +118,15 @@ telnetUnwrap(uint8_t *inBuf, int len, uint8_t state)
break; break;
case RTS_ON: case RTS_ON:
if (mcu_isp_pin >= 0) { if (mcu_isp_pin >= 0) {
#ifdef SERBR_DBG
os_printf("MCU ISP gpio%d\n", mcu_isp_pin); os_printf("MCU ISP gpio%d\n", mcu_isp_pin);
#endif
GPIO_OUTPUT_SET(mcu_isp_pin, 0); GPIO_OUTPUT_SET(mcu_isp_pin, 0);
os_delay_us(100L); os_delay_us(100L);
} else os_printf("MCU isp: no pin\n"); }
#ifdef SERBR_DBG
else os_printf("MCU isp: no pin\n");
#endif
slip_disabled++; slip_disabled++;
break; break;
case RTS_OFF: case RTS_OFF:
@ -137,11 +147,16 @@ telnetUnwrap(uint8_t *inBuf, int len, uint8_t state)
// Generate a reset pulse for the attached microcontroller // Generate a reset pulse for the attached microcontroller
void ICACHE_FLASH_ATTR serbridgeReset() { void ICACHE_FLASH_ATTR serbridgeReset() {
if (mcu_reset_pin >= 0) { if (mcu_reset_pin >= 0) {
#ifdef SERBR_DBG
os_printf("MCU reset gpio%d\n", mcu_reset_pin); os_printf("MCU reset gpio%d\n", mcu_reset_pin);
#endif
GPIO_OUTPUT_SET(mcu_reset_pin, 0); GPIO_OUTPUT_SET(mcu_reset_pin, 0);
os_delay_us(100L); os_delay_us(100L);
GPIO_OUTPUT_SET(mcu_reset_pin, 1); GPIO_OUTPUT_SET(mcu_reset_pin, 1);
} else os_printf("MCU reset: no pin\n"); }
#ifdef SERBR_DBG
else os_printf("MCU reset: no pin\n");
#endif
} }
// Receive callback // Receive callback
@ -162,7 +177,9 @@ static void ICACHE_FLASH_ATTR serbridgeRecvCb(void *arg, char *data, unsigned sh
if ((len == 2 && strncmp(data, "0 ", 2) == 0) || if ((len == 2 && strncmp(data, "0 ", 2) == 0) ||
(len == 2 && strncmp(data, "?\n", 2) == 0) || (len == 2 && strncmp(data, "?\n", 2) == 0) ||
(len == 3 && strncmp(data, "?\r\n", 3) == 0)) { (len == 3 && strncmp(data, "?\r\n", 3) == 0)) {
#ifdef SERBR_DBG
os_printf("MCU Reset=gpio%d ISP=gpio%d\n", mcu_reset_pin, mcu_isp_pin); os_printf("MCU Reset=gpio%d ISP=gpio%d\n", mcu_reset_pin, mcu_isp_pin);
#endif
os_delay_us(2*1000L); // time for os_printf to happen os_delay_us(2*1000L); // time for os_printf to happen
// send reset to arduino/ARM // send reset to arduino/ARM
if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 0); if (mcu_reset_pin >= 0) GPIO_OUTPUT_SET(mcu_reset_pin, 0);
@ -177,14 +194,18 @@ static void ICACHE_FLASH_ATTR serbridgeRecvCb(void *arg, char *data, unsigned sh
slip_disabled++; // disable SLIP so it doesn't interfere with flashing slip_disabled++; // disable SLIP so it doesn't interfere with flashing
// If the connection starts with a telnet negotiation we will do telnet // If the connection starts with a telnet negotiation we will do telnet
} else if (len >= 3 && strncmp(data, (char[]){IAC, WILL, ComPortOpt}, 3) == 0) { }
else if (len >= 3 && strncmp(data, (char[]){IAC, WILL, ComPortOpt}, 3) == 0) {
conn->conn_mode = cmTelnet; conn->conn_mode = cmTelnet;
conn->telnet_state = TN_normal; conn->telnet_state = TN_normal;
// note that the three negotiation chars will be gobbled-up by telnetUnwrap // note that the three negotiation chars will be gobbled-up by telnetUnwrap
#ifdef SERBR_DBG
os_printf("telnet mode\n"); os_printf("telnet mode\n");
#endif
// looks like a plain-vanilla connection! // looks like a plain-vanilla connection!
} else { }
else {
conn->conn_mode = cmTransparent; conn->conn_mode = cmTransparent;
} }
@ -218,9 +239,11 @@ sendtxbuffer(serbridgeConnData *conn) {
conn->readytosend = false; conn->readytosend = false;
result = espconn_sent(conn->conn, (uint8_t*)conn->txbuffer, conn->txbufferlen); result = espconn_sent(conn->conn, (uint8_t*)conn->txbuffer, conn->txbufferlen);
conn->txbufferlen = 0; conn->txbufferlen = 0;
#ifdef SERBR_DBG
if (result != ESPCONN_OK) { if (result != ESPCONN_OK) {
os_printf("sendtxbuffer: espconn_sent error %d on conn %p\n", result, conn); os_printf("sendtxbuffer: espconn_sent error %d on conn %p\n", result, conn);
} }
#endif
} }
return result; return result;
} }
@ -233,7 +256,9 @@ sendtxbuffer(serbridgeConnData *conn) {
static sint8 ICACHE_FLASH_ATTR static sint8 ICACHE_FLASH_ATTR
espbuffsend(serbridgeConnData *conn, const char *data, uint16 len) { espbuffsend(serbridgeConnData *conn, const char *data, uint16 len) {
if (conn->txbufferlen + len > MAX_TXBUFFER) { if (conn->txbufferlen + len > MAX_TXBUFFER) {
#ifdef SERBR_DBG
os_printf("espbuffsend: txbuffer full on conn %p\n", conn); os_printf("espbuffsend: txbuffer full on conn %p\n", conn);
#endif
return -128; return -128;
} }
os_memcpy(conn->txbuffer + conn->txbufferlen, data, len); os_memcpy(conn->txbuffer + conn->txbufferlen, data, len);
@ -323,10 +348,14 @@ static void ICACHE_FLASH_ATTR serbridgeConnectCb(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;
#ifdef SERBR_DBG
os_printf("Accept port 23, conn=%p, pool slot %d\n", conn, i); os_printf("Accept port 23, conn=%p, pool slot %d\n", conn, i);
#endif
if (i==MAX_CONN) { if (i==MAX_CONN) {
#ifdef SERBR_DBG
os_printf("Aiee, conn pool overflow!\n"); os_printf("Aiee, conn pool overflow!\n");
#endif
espconn_disconnect(conn); espconn_disconnect(conn);
return; return;
} }
@ -351,8 +380,10 @@ static void ICACHE_FLASH_ATTR serbridgeConnectCb(void *arg) {
void ICACHE_FLASH_ATTR serbridgeInitPins() { void ICACHE_FLASH_ATTR serbridgeInitPins() {
mcu_reset_pin = flashConfig.reset_pin; mcu_reset_pin = flashConfig.reset_pin;
mcu_isp_pin = flashConfig.isp_pin; mcu_isp_pin = flashConfig.isp_pin;
#ifdef SERBR_DBG
os_printf("Serbridge pins: reset=%d isp=%d swap=%d\n", os_printf("Serbridge pins: reset=%d isp=%d swap=%d\n",
mcu_reset_pin, mcu_isp_pin, flashConfig.swap_uart); mcu_reset_pin, mcu_isp_pin, flashConfig.swap_uart);
#endif
if (flashConfig.swap_uart) { if (flashConfig.swap_uart) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 4); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 4);

@ -35,7 +35,9 @@ void ICACHE_FLASH_ATTR serledInit(void) {
gpio_output_set(0, 0, (1<<pin), 0); gpio_output_set(0, 0, (1<<pin), 0);
serledFlash(1000); // turn it on for 1 second serledFlash(1000); // turn it on for 1 second
} }
#ifdef SERLED_DBG
os_printf("SER led=%d\n", pin); os_printf("SER led=%d\n", pin);
#endif
} }
// Make a pin be GPIO, i.e. set the mux so the pin has the gpio function // Make a pin be GPIO, i.e. set the mux so the pin has the gpio function

@ -46,7 +46,9 @@ slip_process() {
if (crc == rcv) { if (crc == rcv) {
CMD_parse_packet((uint8_t*)slip_buf, slip_len-2); CMD_parse_packet((uint8_t*)slip_buf, slip_len-2);
} else { } else {
#ifdef SLIP_DBG
os_printf("SLIP: bad CRC, crc=%x rcv=%x\n", crc, rcv); os_printf("SLIP: bad CRC, crc=%x rcv=%x\n", crc, rcv);
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]); os_printf("%c", slip_buf[i]);
@ -54,6 +56,7 @@ slip_process() {
os_printf("\\%02X", slip_buf[i]); os_printf("\\%02X", slip_buf[i]);
} }
os_printf("\n"); os_printf("\n");
#endif
} }
} }
} }
@ -83,7 +86,9 @@ 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
os_printf("SLIP: start\n"); os_printf("SLIP: start\n");
#endif
return; return;
} }
} else if (slip_escaped) { } else if (slip_escaped) {

@ -190,7 +190,9 @@ uart0_rx_intr_handler(void *para)
if (READ_PERI_REG(UART_INT_RAW(uart_no)) & UART_FRM_ERR_INT_RAW) { if (READ_PERI_REG(UART_INT_RAW(uart_no)) & UART_FRM_ERR_INT_RAW) {
uint32 now = system_get_time(); uint32 now = system_get_time();
if (last_frm_err == 0 || (now - last_frm_err) > one_sec) { if (last_frm_err == 0 || (now - last_frm_err) > one_sec) {
#ifdef UART_DBG
os_printf("UART framing error (bad baud rate?)\n"); os_printf("UART framing error (bad baud rate?)\n");
#endif
last_frm_err = now; last_frm_err = now;
} }
// clear rx fifo (apparently this is not optional at this point) // clear rx fifo (apparently this is not optional at this point)
@ -206,7 +208,9 @@ uart0_rx_intr_handler(void *para)
if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST) if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)
|| UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) || UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST))
{ {
//os_printf("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no)); #ifdef UART_DBG
os_printf("stat:%02X",*(uint8 *)UART_INT_ENA(uart_no));
#endif
ETS_UART_INTR_DISABLE(); ETS_UART_INTR_DISABLE();
system_os_post(recvTaskPrio, 0, 0); system_os_post(recvTaskPrio, 0, 0);
} }
@ -229,7 +233,9 @@ uart_recvTask(os_event_t *events)
(length < 128)) { (length < 128)) {
buf[length++] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF; buf[length++] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
} }
//os_printf("%d ix %d\n", system_get_time(), length); #ifdef UART_DBG
os_printf("%d ix %d\n", system_get_time(), length);
#endif
for (int i=0; i<MAX_CB; i++) { for (int i=0; i<MAX_CB; i++) {
if (uart_recv_cb[i] != NULL) (uart_recv_cb[i])(buf, length); if (uart_recv_cb[i] != NULL) (uart_recv_cb[i])(buf, length);
@ -241,7 +247,9 @@ uart_recvTask(os_event_t *events)
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
uart0_baud(int rate) { uart0_baud(int rate) {
#ifdef UART_DBG
os_printf("UART %d baud\n", rate); os_printf("UART %d baud\n", rate);
#endif
uart_div_modify(UART0, UART_CLK_FREQ / rate); uart_div_modify(UART0, UART_CLK_FREQ / rate);
} }
@ -278,7 +286,9 @@ uart_add_recv_cb(UartRecv_cb cb) {
return; return;
} }
} }
#ifdef UART_DBG
os_printf("UART: max cb count exceeded\n"); os_printf("UART: max cb count exceeded\n");
#endif
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR

Loading…
Cancel
Save