merged in ifdefs for debug and mqtt webpage additions

pull/47/head
Benjamin Runnels 9 years ago
commit 3337cc1508
  1. 1
      .gitignore
  2. 90
      Makefile
  3. 27
      cmd/cmd.c
  4. 22
      cmd/handlers.c
  5. 16
      esp-link.vcxproj
  6. 112
      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. 216
      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. 23
      html/mqtt.html
  20. 5
      html/style.css
  21. BIN
      html/wifi/icons.png
  22. 894
      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. 60
      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
espfs/mkespfsimage/mman-win32/libmman.a
.localhistory/
tools/

@ -136,15 +136,20 @@ CHANGE_TO_STA ?= yes
#Static gzipping is disabled by default.
GZIP_COMPRESSION ?= yes
# If COMPRESS_W_YUI 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".
# If COMPRESS_W_HTMLCOMPRESSOR is set to "yes" then the static css and js files will be compressed with
# 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/
#Disabled by default.
COMPRESS_W_YUI ?= yes
# enabled by default.
COMPRESS_W_HTMLCOMPRESSOR ?= yes
HTML-COMPRESSOR ?= htmlcompressor-1.5.3.jar
YUI-COMPRESSOR ?= yuicompressor-2.4.8.jar
HTML_PATH = $(abspath ./html)/
WIFI_PATH = $(HTML_PATH)wifi/
# Optional Modules
MODULES ?= rest
MODULES ?= mqtt rest
# -------------- End of config options -------------
@ -170,19 +175,23 @@ ifneq (,$(findstring rest,$(MODULES)))
CFLAGS += -DREST
endif
ifneq (,$(findstring tcpclient,$(MODULES)))
CFLAGS += -DTCPCLIENT
endif
# which modules (subdirectories) of the project to include in compiling
LIBRARIES_DIR = libraries
MODULES += espfs httpd user serial cmd esp-link
LIBRARIES_DIR = libraries
MODULES += espfs httpd user serial cmd esp-link
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
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
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 \
-Wno-unused-function -Wno-unused-variable \
-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) \
-DLED_CONN_PIN=$(LED_CONN_PIN) -DLED_SERIAL_PIN=$(LED_SERIAL_PIN) \
@ -217,17 +226,17 @@ BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES))
SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR))
SDK_LDDIR := $(addprefix $(SDK_BASE)/,$(SDK_LDDIR))
SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR))
SDK_TOOLS := $(addprefix $(SDK_BASE)/,$(SDK_TOOLSDIR))
SDK_TOOLS := $(addprefix $(SDK_BASE)/,$(SDK_TOOLSDIR))
APPGEN_TOOL := $(addprefix $(SDK_TOOLS)/,$(APPGEN_TOOL))
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) $(BUILD_BASE)/espfs_img.o
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) $(BUILD_BASE)/espfs_img.o
LIBS := $(addprefix -l,$(LIBS))
APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a)
USER1_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).user1.out)
USER2_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).user2.out)
INCDIR := $(addprefix -I,$(SRC_DIR))
INCDIR := $(addprefix -I,$(SRC_DIR))
EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR))
MODULE_INCDIR := $(addsuffix /include,$(INCDIR))
@ -320,35 +329,52 @@ flash: all
$(Q) $(ESPTOOL) --port $(ESPPORT) --baud $(ESPBAUD) write_flash -fs $(ET_FS) -ff $(ET_FF) \
0x00000 "$(SDK_BASE)/bin/boot_v1.4(b1).bin" 0x01000 $(FW_BASE)/user1.bin \
$(ET_BLANK) $(SDK_BASE)/bin/blank.bin
yui/$(YUI-COMPRESSOR):
$(Q) mkdir -p yui
tools/$(HTML-COMPRESSOR):
$(Q) mkdir -p tools
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
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
ifeq ("$(COMPRESS_W_YUI)","yes")
$(BUILD_BASE)/espfs_img.o: yui/$(YUI-COMPRESSOR)
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(BUILD_BASE)/espfs_img.o: tools/$(HTML-COMPRESSOR)
endif
$(BUILD_BASE)/espfs_img.o: html/ html/wifi/ espfs/mkespfsimage/mkespfsimage
$(Q) rm -rf html_compressed;
$(Q) cp -r html html_compressed;
$(Q) for file in `find html_compressed -type f -name "*.htm*"`; do \
cat html_compressed/head- $$file >$${file}-; \
mv $$file- $$file; \
done
ifeq ("$(COMPRESS_W_YUI)","yes")
$(Q) rm -rf html_compressed; mkdir html_compressed; mkdir html_compressed/wifi;
$(Q) cp -r html/*.ico html_compressed;
$(Q) cp -r html/*.css html_compressed;
$(Q) cp -r html/*.js html_compressed;
$(Q) cp -r html/wifi/*.png html_compressed/wifi;
$(Q) cp -r html/wifi/*.js html_compressed/wifi;
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) echo "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) 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
$(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
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) ls -sl build/espfs.img
$(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) rm -rf $(FW_BASE)
$(Q) rm -f webpages.espfs
ifeq ("$(COMPRESS_W_YUI)","yes")
ifeq ("$(COMPRESS_W_HTMLCOMPRESSOR)","yes")
$(Q) rm -rf html_compressed
endif

@ -2,10 +2,8 @@
//
// Adapted from: github.com/tuanpmt/esp_bridge, Created on: Jan 9, 2015, Author: Minh
#include "esp8266.h"
#include "cmd.h"
#include "crc16.h"
#include "serbridge.h"
#include "uart.h"
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
while (scp->sc_function != NULL) {
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
uint32_t ret = scp->sc_function(packet);
// if requestor asked for a response, send it
if (packet->_return){
#ifdef CMD_DBG
os_printf("CMD: Response: 0x%lx, cmd: %d\r\n", ret, packet->cmd);
#endif
crc = CMD_ResponseStart(packet->cmd, 0, ret, 0);
CMD_ResponseEnd(crc);
} 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;
}
scp++;
}
#ifdef CMD_DBG
os_printf("CMD: cmd=%d not found\n", packet->cmd);
#endif
return 0;
}
@ -112,27 +118,36 @@ CMD_parse_packet(uint8_t *buf, short len) {
CmdPacket *packet = (CmdPacket*)buf;
uint8_t *data_ptr = (uint8_t*)&packet->args;
uint8_t *data_limit = data_ptr+len;
uint16_t argc = packet->argc;
uint16_t argc = packet->argc;
#ifdef CMD_DBG
uint16_t argn = 0;
os_printf("CMD: cmd=%d argc=%d cb=%p ret=%lu\n",
packet->cmd, packet->argc, (void *)packet->callback, packet->_return);
#endif
// print out arguments
while (data_ptr+2 < data_limit && argc--) {
short l = *(uint16_t*)data_ptr;
#ifdef CMD_DBG
os_printf("CMD: arg[%d] len=%d:", argn++, l);
#endif
data_ptr += 2;
while (data_ptr < data_limit && l--) {
#ifdef CMD_DBG
os_printf(" %02X", *data_ptr++);
#endif
}
#ifdef CMD_DBG
os_printf("\n");
#endif
}
if (data_ptr <= data_limit) {
CMD_Exec(commands, packet);
} else {
#ifdef CMD_DBG
os_printf("CMD: packet length overrun, parsing arg %d\n", argn-1);
#endif
}
}

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

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

@ -16,20 +16,19 @@ Some random cgi routines.
#include <esp8266.h>
#include "cgi.h"
#include "espfs.h"
void noCacheHeaders(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code);
httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate");
httpdHeader(connData, "Pragma", "no-cache");
httpdHeader(connData, "Expires", "0");
httpdStartResponse(connData, code);
httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate");
httpdHeader(connData, "Pragma", "no-cache");
httpdHeader(connData, "Expires", "0");
}
void ICACHE_FLASH_ATTR
jsonHeader(HttpdConnData *connData, int code) {
noCacheHeaders(connData, code);
httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData);
httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData);
}
void ICACHE_FLASH_ATTR
@ -37,7 +36,9 @@ errorResponse(HttpdConnData *connData, int code, char *message) {
noCacheHeaders(connData, code);
httpdEndHeaders(connData);
httpdSend(connData, message, -1);
#ifdef CGI_DBG
os_printf("HTTP %d error response: \"%s\"\n", code, message);
#endif
}
// look for the HTTP arg 'name' and store it at 'config' with max length 'max_len' (incl
@ -65,59 +66,96 @@ getBoolArg(HttpdConnData *connData, char *name, bool*config) {
if (strcmp(buff, "1") == 0 || strcmp(buff, "true") == 0) {
*config = true;
return 1;
}
}
if (strcmp(buff, "0") == 0 || strcmp(buff, "false") == 0) {
*config = false;
return 1;
}
}
os_sprintf(buff, "Invalid value for %s", name);
errorResponse(connData, 400, buff);
return -1;
}
uint8_t ICACHE_FLASH_ATTR
UTILS_StrToIP(const char* str, void *ip){
/* 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)
#if 0
// Handle system information variables and print their value, returns the number of
// characters appended to buff
int ICACHE_FLASH_ATTR printGlobalInfo(char *buff, int buflen, char *token) {
if (TOKEN("si_chip_id")) {
return os_sprintf(buff, "0x%x", system_get_chip_id());
} else if (TOKEN("si_freeheap")) {
return os_sprintf(buff, "%dKB", system_get_free_heap_size()/1024);
} else if (TOKEN("si_uptime")) {
uint32 t = system_get_time() / 1000000; // in seconds
return os_sprintf(buff, "%dd%dh%dm%ds", t/(24*3600), (t/(3600))%24, (t/60)%60, t%60);
} else if (TOKEN("si_boot_version")) {
return os_sprintf(buff, "%d", system_get_boot_version());
} else if (TOKEN("si_boot_address")) {
return os_sprintf(buff, "0x%x", system_get_userbin_addr());
} else if (TOKEN("si_cpu_freq")) {
return os_sprintf(buff, "%dMhz", system_get_cpu_freq());
} else {
return 0;
}
if (TOKEN("si_chip_id")) {
return os_sprintf(buff, "0x%x", system_get_chip_id());
} else if (TOKEN("si_freeheap")) {
return os_sprintf(buff, "%dKB", system_get_free_heap_size()/1024);
} else if (TOKEN("si_uptime")) {
uint32 t = system_get_time() / 1000000; // in seconds
return os_sprintf(buff, "%dd%dh%dm%ds", t/(24*3600), (t/(3600))%24, (t/60)%60, t%60);
} else if (TOKEN("si_boot_version")) {
return os_sprintf(buff, "%d", system_get_boot_version());
} else if (TOKEN("si_boot_address")) {
return os_sprintf(buff, "0x%x", system_get_userbin_addr());
} else if (TOKEN("si_cpu_freq")) {
return os_sprintf(buff, "%dMhz", system_get_cpu_freq());
} else {
return 0;
}
}
#endif
extern char *esp_link_version; // in user_main.c
int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
char buff[1024];
// don't use jsonHeader so the response does get cached
httpdStartResponse(connData, 200);
httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate");
httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData);
// construct json response
os_sprintf(buff,
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
char buff[1024];
// don't use jsonHeader so the response does get cached
httpdStartResponse(connData, 200);
httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate");
httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData);
// construct json response
os_sprintf(buff,
"{\"menu\": [\"Home\", \"/home.html\", "
"\"Wifi\", \"/wifi/wifi.html\","
"\"\xC2\xB5" "C Console\", \"/console.html\", "
"\"REST/MQTT\", \"/mqtt.html\","
"\"Debug log\", \"/log.html\" ],\n"
" \"version\": \"%s\" }", esp_link_version);
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
" \"version\": \"%s\" }", esp_link_version);
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
}

@ -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...
static char* ICACHE_FLASH_ATTR check_header(void *buf) {
uint8_t *cd = (uint8_t *)buf;
#ifdef CGIFLASH_DBG
uint32_t *buf32 = buf;
os_printf("%p: %08lX %08lX %08lX %08lX\n", buf, buf32[0], buf32[1], buf32[2], buf32[3]);
#endif
if (cd[0] != 0xEA) return "IROM magic missing";
if (cd[1] != 4 || cd[2] > 3 || (cd[3]>>4) > 6) return "bad flash header";
if (((uint16_t *)buf)[3] != 0x4010) return "Invalid entry addr";
@ -42,7 +44,9 @@ int ICACHE_FLASH_ATTR cgiGetFirmwareNext(HttpdConnData *connData) {
httpdEndHeaders(connData);
char *next = id == 1 ? "user1.bin" : "user2.bin";
httpdSend(connData, next, -1);
#ifdef CGIFLASH_DBG
os_printf("Next firmware: %s (got %d)\n", next, id);
#endif
return HTTPD_CGI_DONE;
}
@ -80,7 +84,9 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
// return an error if there is one
if (err != NULL) {
#ifdef CGIFLASH_DBG
os_printf("Error %d: %s\n", code, err);
#endif
httpdStartResponse(connData, code);
httpdHeader(connData, "Content-Type", "text/plain");
//httpdHeader(connData, "Content-Length", strlen(err)+2);
@ -99,7 +105,9 @@ int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) {
// erase next flash block if necessary
if (address % SPI_FLASH_SEC_SIZE == 0){
#ifdef CGIFLASH_DBG
os_printf("Flashing 0x%05x (id=%d)\n", address, 2-id);
#endif
spi_flash_erase_sector(address/SPI_FLASH_SEC_SIZE);
}
@ -129,11 +137,15 @@ int ICACHE_FLASH_ATTR cgiRebootFirmware(HttpdConnData *connData) {
int address = id == 1 ? 4*1024 // either start after 4KB boot partition
: 4*1024 + FIRMWARE_SIZE + 16*1024 + 4*1024; // 4KB boot, fw1, 16KB user param, 4KB reserved
uint32 buf[8];
#ifdef CGIFLASH_DBG
os_printf("Checking %p\n", (void *)address);
#endif
spi_flash_read(address, buf, sizeof(buf));
char *err = check_header(buf);
if (err != NULL) {
#ifdef CGIFLASH_DBG
os_printf("Error %d: %s\n", 400, err);
#endif
httpdStartResponse(connData, 400);
httpdHeader(connData, "Content-Type", "text/plain");
//httpdHeader(connData, "Content-Length", strlen(err)+2);

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

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

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

@ -19,8 +19,9 @@ FlashConfig flashDefault = {
1, 0, // tcp_enable, rssi_enable
"\0", // api_key
0, 0, 0, // slip_enable, mqtt_enable, mqtt_status_enable
1833, // mqtt port
"\0", "\0", "\0", "\0", "\0", // mqtt host, client, user, password, status-topic
2, 1, // mqtt_timeout, mqtt_clean_session
1833, 600, // mqtt port, mqtt_keepalive
"\0", "\0", "\0", "\0", "\0", // mqtt host, client_id, user, password, status-topic
};
typedef union {
@ -51,8 +52,8 @@ static void memDump(void *addr, int len) {
bool ICACHE_FLASH_ATTR configSave(void) {
FlashFull ff;
memset(&ff, 0, sizeof(ff));
memcpy(&ff, &flashConfig, sizeof(FlashConfig));
os_memset(&ff, 0, sizeof(ff));
os_memcpy(&ff, &flashConfig, sizeof(FlashConfig));
uint32_t seq = ff.fc.seq+1;
// erase secondary
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));
return true;
fail:
#ifdef CONFIG_DBG
os_printf("*** Failed to save config ***\n");
#endif
return false;
}
@ -102,19 +105,28 @@ bool ICACHE_FLASH_ATTR configRestore(void) {
FlashFull ff0, ff1;
// read both flash sectors
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)
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
flash_pri = selectPrimary(&ff0, &ff1);
// if neither is OK, we revert to defaults
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;
return false;
}
// 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;
}
@ -123,10 +135,14 @@ static int ICACHE_FLASH_ATTR selectPrimary(FlashFull *ff0, FlashFull *ff1) {
uint16_t crc = ff0->fc.crc;
ff0->fc.crc = 0;
bool ff0_crc_ok = crc16_data((unsigned char*)ff0, sizeof(FlashFull), 0) == crc;
os_printf("FLASH chk=0x%04x crc=0x%04x full_sz=%d sz=%d\n",
#ifdef CONFIG_DBG
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),
crc, sizeof(FlashFull), sizeof(FlashConfig));
crc,
sizeof(FlashFull),
sizeof(FlashConfig),
getFlashSize());
#endif
// check CRC of ff1
crc = ff1->fc.crc;
@ -142,3 +158,15 @@ static int ICACHE_FLASH_ATTR selectPrimary(FlashFull *ff0, FlashFull *ff1) {
else
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
char api_key[48]; // RSSI submission API key (Grovestreams for now)
uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client
mqtt_status_enable; // MQTT status reporting
uint16_t mqtt_port;
char mqtt_hostname[32], mqtt_client[48], mqtt_username[32], mqtt_password[32];
mqtt_status_enable, // MQTT status reporting
mqtt_timeout, // MQTT send timeout
mqtt_clean_session; // MQTT clean session
uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer
char mqtt_host[32], mqtt_clientid[48], mqtt_username[32], mqtt_password[32];
char mqtt_status_topic[32];
} FlashConfig;
extern FlashConfig flashConfig;
@ -27,5 +29,6 @@ extern FlashConfig flashConfig;
bool configSave(void);
bool configRestore(void);
void configWipe(void);
const size_t getFlashSize();
#endif

@ -22,135 +22,139 @@ static bool log_newline; // at start of a new line
// when we connect to wifi AP. Here this is gated by the flash setting
void ICACHE_FLASH_ATTR
log_uart(bool enable) {
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
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
#if 1
os_printf("Turning OFF uart log\n");
os_delay_us(4*1000L); // time for uart to flush
log_no_uart = !enable;
#ifdef LOG_DBG
os_printf("Turning OFF uart log\n");
#endif
} 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
log_no_uart = !enable;
os_printf("Turning ON uart log\n");
}
os_delay_us(4*1000L); // time for uart to flush
log_no_uart = !enable;
#endif
} 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
log_no_uart = !enable;
#ifdef LOG_DBG
os_printf("Turning ON uart log\n");
#endif
}
}
static void ICACHE_FLASH_ATTR
log_write(char c) {
log_buf[log_wr] = c;
log_wr = (log_wr+1) % BUF_MAX;
if (log_wr == log_rd) {
log_rd = (log_rd+1) % BUF_MAX; // full, eat first char
log_pos++;
}
log_buf[log_wr] = c;
log_wr = (log_wr+1) % BUF_MAX;
if (log_wr == log_rd) {
log_rd = (log_rd+1) % BUF_MAX; // full, eat first char
log_pos++;
}
}
#if 0
static char ICACHE_FLASH_ATTR
log_read(void) {
char c = 0;
if (log_rd != log_wr) {
c = log_buf[log_rd];
log_rd = (log_rd+1) % BUF_MAX;
}
return c;
char c = 0;
if (log_rd != log_wr) {
c = log_buf[log_rd];
log_rd = (log_rd+1) % BUF_MAX;
}
return c;
}
#endif
static void ICACHE_FLASH_ATTR
log_write_char(char c) {
// Uart output unless disabled
if (!log_no_uart) {
if (log_newline) {
char buff[16];
int l = os_sprintf(buff, "%6d> ", (system_get_time()/1000)%1000000);
for (int i=0; i<l; i++)
uart0_write_char(buff[i]);
log_newline = false;
}
uart0_write_char(c);
if (c == '\n') {
log_newline = true;
uart0_write_char('\r');
}
}
// Store in log buffer
if (c == '\n') log_write('\r');
log_write(c);
// Uart output unless disabled
if (!log_no_uart) {
if (log_newline) {
char buff[16];
int l = os_sprintf(buff, "%6d> ", (system_get_time()/1000)%1000000);
for (int i=0; i<l; i++)
uart0_write_char(buff[i]);
log_newline = false;
}
uart0_write_char(c);
if (c == '\n') {
log_newline = true;
uart0_write_char('\r');
}
}
// Store in log buffer
if (c == '\n') log_write('\r');
log_write(c);
}
int ICACHE_FLASH_ATTR
ajaxLog(HttpdConnData *connData) {
char buff[2048];
int len; // length of text in buff
int log_len = (log_wr+BUF_MAX-log_rd) % BUF_MAX; // num chars in log_buf
int start = 0; // offset onto log_wr to start sending out chars
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
jsonHeader(connData, 200);
// figure out where to start in buffer based on URI param
len = httpdFindArg(connData->getArgs, "start", buff, sizeof(buff));
if (len > 0) {
start = atoi(buff);
if (start < log_pos) {
start = 0;
} else if (start >= log_pos+log_len) {
start = log_len;
} else {
start = start - log_pos;
}
}
// start outputting
len = os_sprintf(buff, "{\"len\":%d, \"start\":%d, \"text\": \"",
log_len-start, log_pos+start);
int rd = (log_rd+start) % BUF_MAX;
while (len < 2040 && rd != log_wr) {
uint8_t c = log_buf[rd];
if (c == '\\' || c == '"') {
buff[len++] = '\\';
buff[len++] = c;
} else if (c < ' ') {
len += os_sprintf(buff+len, "\\u%04x", c);
} else {
buff[len++] = c;
}
rd = (rd + 1) % BUF_MAX;
}
os_strcpy(buff+len, "\"}"); len+=2;
httpdSend(connData, buff, len);
return HTTPD_CGI_DONE;
char buff[2048];
int len; // length of text in buff
int log_len = (log_wr+BUF_MAX-log_rd) % BUF_MAX; // num chars in log_buf
int start = 0; // offset onto log_wr to start sending out chars
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
jsonHeader(connData, 200);
// figure out where to start in buffer based on URI param
len = httpdFindArg(connData->getArgs, "start", buff, sizeof(buff));
if (len > 0) {
start = atoi(buff);
if (start < log_pos) {
start = 0;
} else if (start >= log_pos+log_len) {
start = log_len;
} else {
start = start - log_pos;
}
}
// start outputting
len = os_sprintf(buff, "{\"len\":%d, \"start\":%d, \"text\": \"",
log_len-start, log_pos+start);
int rd = (log_rd+start) % BUF_MAX;
while (len < 2040 && rd != log_wr) {
uint8_t c = log_buf[rd];
if (c == '\\' || c == '"') {
buff[len++] = '\\';
buff[len++] = c;
} else if (c < ' ') {
len += os_sprintf(buff+len, "\\u%04x", c);
} else {
buff[len++] = c;
}
rd = (rd + 1) % BUF_MAX;
}
os_strcpy(buff+len, "\"}"); len+=2;
httpdSend(connData, buff, len);
return HTTPD_CGI_DONE;
}
static char *dbg_mode[] = { "auto", "off", "on" };
int ICACHE_FLASH_ATTR
ajaxLogDbg(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
char buff[512];
int len, status = 400;
len = httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff));
if (len > 0) {
int8_t mode = -1;
if (os_strcmp(buff, "auto") == 0) mode = LOG_MODE_AUTO;
if (os_strcmp(buff, "off") == 0) mode = LOG_MODE_OFF;
if (os_strcmp(buff, "on") == 0) mode = LOG_MODE_ON;
if (mode >= 0) {
flashConfig.log_mode = mode;
if (mode != LOG_MODE_AUTO) log_uart(mode == LOG_MODE_ON);
status = configSave() ? 200 : 400;
}
} else if (connData->requestType == HTTPD_METHOD_GET) {
status = 200;
}
jsonHeader(connData, status);
os_sprintf(buff, "{\"mode\": \"%s\"}", dbg_mode[flashConfig.log_mode]);
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up.
char buff[512];
int len, status = 400;
len = httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff));
if (len > 0) {
int8_t mode = -1;
if (os_strcmp(buff, "auto") == 0) mode = LOG_MODE_AUTO;
if (os_strcmp(buff, "off") == 0) mode = LOG_MODE_OFF;
if (os_strcmp(buff, "on") == 0) mode = LOG_MODE_ON;
if (mode >= 0) {
flashConfig.log_mode = mode;
if (mode != LOG_MODE_AUTO) log_uart(mode == LOG_MODE_ON);
status = configSave() ? 200 : 400;
}
} else if (connData->requestType == HTTPD_METHOD_GET) {
status = 200;
}
jsonHeader(connData, status);
os_sprintf(buff, "{\"mode\": \"%s\"}", dbg_mode[flashConfig.log_mode]);
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
}
void ICACHE_FLASH_ATTR dumpMem(void *addr, int len) {
@ -168,9 +172,9 @@ void ICACHE_FLASH_ATTR dumpMem(void *addr, int len) {
}
void ICACHE_FLASH_ATTR logInit() {
log_no_uart = flashConfig.log_mode == LOG_MODE_OFF; // ON unless set to always-off
log_wr = 0;
log_rd = 0;
log_no_uart = flashConfig.log_mode == LOG_MODE_OFF; // ON unless set to always-off
log_wr = 0;
log_rd = 0;
os_install_putc1((void *)log_write_char);
}

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

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

@ -107,7 +107,9 @@ void ICACHE_FLASH_ATTR statusInit(void) {
makeGpio(flashConfig.conn_led_pin);
setLed(1);
}
#ifdef STATUS_DBG
os_printf("CONN led=%d\n", flashConfig.conn_led_pin);
#endif
os_timer_disarm(&ledTimer);
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.
int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) {
if (fh == NULL) {
#ifdef ESPFS_DBG
os_printf("File handle not ready\n");
#endif
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.
EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
if (espFsData == NULL) {
#ifdef ESPFS_DBG
os_printf("Call espFsInit first!\n");
#endif
return NULL;
}
char *p=espFsData;
@ -137,7 +141,9 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
//Grab the next file header.
os_memcpy(&h, p, sizeof(EspFsHeader));
if (h.magic!=ESPFS_MAGIC) {
#ifdef ESPFS_DBG
os_printf("Magic mismatch. EspFS image broken.\n");
#endif
return NULL;
}
if (h.flags&FLAG_LASTFILE) {
@ -163,7 +169,9 @@ EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) {
if (h.compression==COMPRESS_NONE) {
r->decompData=NULL;
} else {
#ifdef ESPFS_DBG
os_printf("Invalid compression: %d\n", h.compression);
#endif
return NULL;
}
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>
</h1>
<form action="#" id="mqtt-form" class="pure-form" hidden>
<div class="form-horizontal">
<input type="checkbox" name="mqtt-enable"/>
<label>Enable MQTT client</label>
</div>
<div class="form-horizontal">
<label>MQTT client state: </label>
<b id="mqtt-state"></b>
</div>
<input type="checkbox" name="mqtt-enable"/>
<label>Enable MQTT client</label>
<br>
<label>MQTT client state: </label>
<b id="mqtt-state"></b>
<br>
<legend>MQTT server settings</legend>
<div class="pure-form-stacked">
<label>Server hostname/ip</label>
<label>Server hostname or IP</label>
<input type="text" name="mqtt-host"/>
<label>Server port/ip</label>
<label>Server port</label>
<input type="text" name="mqtt-port"/>
<label>Client Timeout</label>
<input type="text" name="mqtt-timeout" />
<label>Client ID</label>
<input type="text" name="mqtt-client-id"/>
<label>Username</label>
<input type="text" name="mqtt-username"/>
<label>Password</label>
<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>
<button id="mqtt-button" type="submit" class="pure-button button-primary">
Update server settings!

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 914 B

After

Width:  |  Height:  |  Size: 425 B

File diff suppressed because it is too large Load Diff

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

@ -59,10 +59,12 @@ sint8 espconn_secure_sent(struct espconn *espconn, uint8 *psent, uint16 length)
// max message size for sending (except publish)
#define MQTT_MAX_SHORT_MESSAGE 128
#ifdef MQTT_DBG
static char* mqtt_msg_type[] = {
"NULL", "TYPE_CONNECT", "CONNACK", "PUBLISH", "PUBACK", "PUBREC", "PUBREL", "PUBCOMP",
"SUBSCRIBE", "SUBACK", "UNSUBSCRIBE", "UNSUBACK", "PINGREQ", "PINGRESP", "DISCONNECT", "RESV",
};
#endif
// forward declarations
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) {
// 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);
#endif
mqtt_doAbort(client);
return;
}
@ -137,7 +141,9 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
if (client->connState != MQTT_CONNECTED) {
// why are we receiving something??
#ifdef MQTT_DBG
os_printf("MQTT ERROR: recv in invalid state %d\n", client->connState);
#endif
mqtt_doAbort(client);
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_id = mqtt_get_id(client->pending_buffer->data, client->pending_buffer->filled);
}
os_printf("MQTT: Recv type=%s id=%04X len=%d; Pend type=%s id=%04X\n",
mqtt_msg_type[msg_type], msg_id, msg_len, mqtt_msg_type[pending_msg_type], pending_msg_id);
#ifdef MQTT_DBG
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);
#endif
switch (msg_type) {
case MQTT_MSG_TYPE_CONNACK:
#ifdef MQTT_DBG
os_printf("MQTT: Connect successful\n");
#endif
// callbacks for internal and external clients
if (client->connectedCb) client->connectedCb((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:
if (pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: Subscribe successful\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
}
break;
case MQTT_MSG_TYPE_UNSUBACK:
if (pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: Unsubscribe successful\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
}
break;
case MQTT_MSG_TYPE_PUBACK: // ack for a publish we sent
if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: QoS1 Publish successful\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
}
break;
case MQTT_MSG_TYPE_PUBREC: // rec for a publish we sent
if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: QoS2 publish cont\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
// we need to send PUBREL
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)
if (pending_msg_type == MQTT_MSG_TYPE_PUBREL && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: QoS2 Publish successful\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
}
break;
@ -203,9 +222,11 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) {
case MQTT_MSG_TYPE_PUBLISH: { // incoming publish
// we may need to ACK the publish
uint8_t msg_qos = mqtt_get_qos(client->in_buffer);
#ifdef MQTT_DBG
uint16_t topic_length = msg_len;
os_printf("MQTT: Recv PUBLISH qos=%d %s\n", msg_qos,
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 == 2) mqtt_msg_pubrec(&client->mqtt_connection, msg_id);
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)
if (pending_msg_type == MQTT_MSG_TYPE_PUBREC && pending_msg_id == msg_id) {
#ifdef MQTT_DBG
os_printf("MQTT: Cont QoS2 recv\n");
#endif
client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer);
// we need to send PUBCOMP
mqtt_msg_pubcomp(&client->mqtt_connection, msg_id);
@ -296,7 +319,9 @@ mqtt_timer(void* arg) {
// check whether our last keep-alive timed out
if (client->keepAliveAckTick > 0 && --client->keepAliveAckTick == 0) {
#ifdef MQTT_DBG
os_printf("\nMQTT ERROR: Keep-alive timed out\n");
#endif
mqtt_doAbort(client);
return;
}
@ -340,15 +365,17 @@ void ICACHE_FLASH_ATTR
mqtt_tcpclient_discon_cb(void* arg) {
struct espconn* pespconn = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pespconn->reverse;
#ifdef MQTT_DBG
os_printf("MQTT: Disconnect CB, freeing espconn %p\n", arg);
#endif
if (pespconn->proto.tcp) os_free(pespconn->proto.tcp);
os_free(pespconn);
// if this is an aborted connection we're done
if (client == NULL) return;
#ifdef MQTT_DBG
os_printf("MQTT: Disconnected from %s:%d\n", client->host, client->port);
#endif
if (client->disconnectedCb) client->disconnectedCb((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) {
struct espconn* pespconn = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pespconn->reverse;
#ifdef MQTT_DBG
os_printf("MQTT: Reset CB, freeing espconn %p (err=%d)\n", arg, err);
#endif
if (pespconn->proto.tcp) os_free(pespconn->proto.tcp);
os_free(pespconn);
#ifdef MQTT_DBG
os_printf("MQTT: Connection reset from %s:%d\n", client->host, client->port);
#endif
if (client->disconnectedCb) client->disconnectedCb((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_recvcb(client->pCon, mqtt_tcpclient_recv);
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);
#endif
// send MQTT connect message to broker
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
uint16_t msg_type = mqtt_get_type(buf->data);
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);
#if 0
for (int i=0; i<buf->filled; i++) {
if (buf->data[i] >= ' ' && buf->data[i] <= '~') os_printf("%c", 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;
if (ipaddr == NULL) {
#ifdef MQTT_DBG
os_printf("MQTT DNS: Got no ip, try to reconnect\n");
#endif
client->timeoutTick = 10;
client->connState = TCP_RECONNECT_REQ; // the timer will kick-off a reconnection
return;
}
#ifdef MQTT_DBG
os_printf("MQTT DNS: found ip %d.%d.%d.%d\n",
*((uint8 *)&ipaddr->addr),
*((uint8 *)&ipaddr->addr + 1),
*((uint8 *)&ipaddr->addr + 2),
*((uint8 *)&ipaddr->addr + 3));
#endif
if (client->ip.addr == 0 && ipaddr->addr != 0) {
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
err = espconn_connect(client->pCon);
if (err != 0) {
#ifdef MQTT_DBG
os_printf("MQTT ERROR: Failed to connect\n");
#endif
client->connState = TCP_RECONNECT_REQ;
client->timeoutTick = 10;
} else {
#ifdef MQTT_DBG
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;
PktBuf *buf = PktBuf_New(buf_len);
if (buf == NULL) {
#ifdef MQTT_DBG
os_printf("MQTT ERROR: Cannot allocate buffer for %d byte publish\n", buf_len);
#endif
return FALSE;
}
// 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);
uint16_t 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");
#endif
os_free(buf);
return FALSE;
}
@ -581,10 +624,14 @@ bool ICACHE_FLASH_ATTR
MQTT_Subscribe(MQTT_Client* client, char* topic, uint8_t qos) {
uint16_t 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");
#endif
return FALSE;
}
#ifdef MQTT_DBG
os_printf("MQTT: Subscribe, topic: \"%s\"\n", topic);
#endif
mqtt_enq_message(client, client->mqtt_connection.message.data,
client->mqtt_connection.message.length);
return TRUE;
@ -602,14 +649,20 @@ MQTT_Subscribe(MQTT_Client* client, char* topic, uint8_t qos) {
* @param client_user: MQTT client user
* @param client_pass: MQTT client password
* @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
*/
void ICACHE_FLASH_ATTR
MQTT_Init(MQTT_Client* mqttClient, char* host, uint32 port, uint8_t security, uint8_t sendTimeout,
char* client_id, char* client_user, char* client_pass,
uint8_t keepAliveTime) {
#ifdef MQTT_DBG
os_printf("MQTT_Init\n");
#endif
os_memset(mqttClient, 0, sizeof(MQTT_Client));
@ -686,7 +739,9 @@ MQTT_Connect(MQTT_Client* mqttClient) {
os_timer_arm(&mqttClient->mqttTimer, 1000, 1);
// 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);
#endif
if (UTILS_StrToIP((const char *)mqttClient->host,
(void*)&mqttClient->pCon->proto.tcp->remote_ip)) {
uint8_t err;
@ -695,7 +750,9 @@ MQTT_Connect(MQTT_Client* mqttClient) {
else
err = espconn_connect(mqttClient->pCon);
if (err != 0) {
#ifdef MQTT_DBG
os_printf("MQTT ERROR: Failed to connect\n");
#endif
os_free(mqttClient->pCon->proto.tcp);
os_free(mqttClient->pCon);
mqttClient->pCon = NULL;
@ -713,7 +770,9 @@ MQTT_Connect(MQTT_Client* mqttClient) {
static void ICACHE_FLASH_ATTR
mqtt_doAbort(MQTT_Client* client) {
#ifdef MQTT_DBG
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...
if (client->security)
espconn_secure_disconnect(client->pCon);

@ -8,11 +8,13 @@ void ICACHE_FLASH_ATTR
cmdMqttConnectedCb(uint32_t* args) {
MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
#ifdef MQTTCMD_DBG
os_printf("MQTT: Connected connectedCb=%p, disconnectedCb=%p, publishedCb=%p, dataCb=%p\n",
(void*)cb->connectedCb,
(void*)cb->disconnectedCb,
(void*)cb->publishedCb,
(void*)cb->dataCb);
#endif
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->connectedCb, 0, 0);
CMD_ResponseEnd(crc);
}
@ -21,7 +23,9 @@ void ICACHE_FLASH_ATTR
cmdMqttTcpDisconnectedCb(uint32_t *args) {
MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb *cb = (MqttCmdCb*)client->user_data;
#ifdef MQTTCMD_DBG
os_printf("MQTT: TCP Disconnected\n");
#endif
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->tcpDisconnectedCb, 0, 0);
CMD_ResponseEnd(crc);
}
@ -30,7 +34,9 @@ void ICACHE_FLASH_ATTR
cmdMqttDisconnectedCb(uint32_t* args) {
MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
#ifdef MQTTCMD_DBG
os_printf("MQTT: Disconnected\n");
#endif
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->disconnectedCb, 0, 0);
CMD_ResponseEnd(crc);
}
@ -39,7 +45,9 @@ void ICACHE_FLASH_ATTR
cmdMqttPublishedCb(uint32_t* args) {
MQTT_Client* client = (MQTT_Client*)args;
MqttCmdCb* cb = (MqttCmdCb*)client->user_data;
#ifdef MQTTCMD_DBG
os_printf("MQTT: Published\n");
#endif
uint16_t crc = CMD_ResponseStart(CMD_MQTT_EVENTS, cb->publishedCb, 0, 0);
CMD_ResponseEnd(crc);
}
@ -103,8 +111,9 @@ MQTTCMD_Setup(CmdPacket *cmd) {
// get clean session
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);
#endif
// init client
// 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;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Lwt client ptr=%p\n", (void*)client_ptr);
#endif
uint16_t len;
@ -182,12 +193,13 @@ MQTTCMD_Lwt(CmdPacket *cmd) {
// get retain
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",
client->connect_info.will_topic,
client->connect_info.will_message,
client->connect_info.will_qos,
client->connect_info.will_retain);
#endif
return 1;
}
@ -203,7 +215,9 @@ MQTTCMD_Connect(CmdPacket *cmd) {
uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Connect client ptr=%p\n", (void*)client_ptr);
#endif
uint16_t len;
@ -221,11 +235,12 @@ MQTTCMD_Connect(CmdPacket *cmd) {
// get security
CMD_PopArg(&req, (uint8_t*)&client->security, 4);
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n",
client->host,
client->port,
client->security);
#endif
MQTT_Connect(client);
return 1;
@ -243,7 +258,9 @@ MQTTCMD_Disconnect(CmdPacket *cmd) {
uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Disconnect client ptr=%p\n", (void*)client_ptr);
#endif
// disconnect
MQTT_Disconnect(client);
@ -262,7 +279,9 @@ MQTTCMD_Publish(CmdPacket *cmd) {
uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Publish client ptr=%p\n", (void*)client_ptr);
#endif
uint16_t len;
uint8_t *topic, *data;
@ -293,12 +312,13 @@ MQTTCMD_Publish(CmdPacket *cmd) {
// get retain
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",
topic,
os_strlen((char*)data),
qos,
retain);
#endif
MQTT_Publish(client, (char*)topic, (char*)data, (uint8_t)qos, (uint8_t)retain);
os_free(topic);
@ -318,7 +338,9 @@ MQTTCMD_Subscribe(CmdPacket *cmd) {
uint32_t client_ptr;
CMD_PopArg(&req, (uint8_t*)&client_ptr, 4);
MQTT_Client* client = (MQTT_Client*)client_ptr;
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Subscribe client ptr=%p\n", (void*)client_ptr);
#endif
uint16_t len;
uint8_t* topic;
@ -333,8 +355,9 @@ MQTTCMD_Subscribe(CmdPacket *cmd) {
// get qos
CMD_PopArg(&req, (uint8_t*)&qos, 4);
#ifdef MQTTCMD_DBG
os_printf("MQTT: MQTTCMD_Subscribe topic=%s, qos=%ld\n", topic, qos);
#endif
MQTT_Subscribe(client, (char*)topic, (uint8_t)qos);
os_free(topic);
return 1;

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

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

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

@ -73,16 +73,20 @@ tcpclient_recv(void *arg, char *pdata, unsigned short len) {
// collect body and send it
uint16_t crc;
int body_len = len-pi;
#ifdef REST_DBG
os_printf("REST: status=%ld, body=%d\n", code, body_len);
#endif
if (pi == len) {
crc = CMD_ResponseStart(CMD_REST_EVENTS, client->resp_cb, code, 0);
} else {
crc = CMD_ResponseStart(CMD_REST_EVENTS, client->resp_cb, code, 1);
crc = CMD_ResponseBody(crc, (uint8_t*)(pdata+pi), body_len);
CMD_ResponseEnd(crc);
#ifdef REST_DBG
os_printf("REST: body=");
for (int j=pi; j<len; j++) os_printf(" %02x", pdata[j]);
os_printf("\n");
#endif
}
//if(client->security)
@ -96,7 +100,9 @@ static void ICACHE_FLASH_ATTR
tcpclient_sent_cb(void *arg) {
struct espconn *pCon = (struct espconn *)arg;
RestClient* client = (RestClient *)pCon->reverse;
#ifdef REST_DBG
os_printf("REST: Sent\n");
#endif
if (client->data_sent != client->data_len) {
// we only sent part of the buffer, send the rest
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) {
struct espconn *pCon = (struct espconn *)arg;
RestClient* client = (RestClient *)pCon->reverse;
#ifdef REST_DBG
os_printf("REST #%d: connected\n", client-restClient);
#endif
espconn_regist_disconcb(client->pCon, tcpclient_discon_cb);
espconn_regist_recvcb(client->pCon, tcpclient_recv);
espconn_regist_sentcb(client->pCon, tcpclient_sent_cb);
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);
#endif
//if(client->security){
// 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) {
struct espconn *pCon = (struct espconn *)arg;
RestClient* client = (RestClient *)pCon->reverse;
#ifdef REST_DBG
os_printf("REST #%d: conn reset\n", client-restClient);
#endif
}
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;
if(ipaddr == NULL) {
#ifdef REST_DBG
os_printf("REST DNS: Got no ip, try to reconnect\n");
#endif
return;
}
#ifdef REST_DBG
os_printf("REST DNS: found ip %d.%d.%d.%d\n",
*((uint8 *) &ipaddr->addr),
*((uint8 *) &ipaddr->addr + 1),
*((uint8 *) &ipaddr->addr + 2),
*((uint8 *) &ipaddr->addr + 3));
#endif
if(client->ip.addr == 0 && ipaddr->addr != 0) {
os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4);
#ifdef CLIENT_SSL_ENABLE
@ -159,8 +172,10 @@ rest_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) {
espconn_secure_connect(client->pCon);
} else
#endif
espconn_connect(client->pCon);
espconn_connect(client->pCon);
#ifdef REST_DBG
os_printf("REST: connecting...\n");
#endif
}
}
@ -213,8 +228,9 @@ REST_Setup(CmdPacket *cmd) {
os_free(client->pCon);
}
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);
#endif
client->resp_cb = cmd->callback;
@ -273,7 +289,9 @@ REST_SetHeader(CmdPacket *cmd) {
client->header[len] = '\r';
client->header[len+1] = '\n';
client->header[len+2] = 0;
#ifdef CMDREST_DBG
os_printf("REST: Set header: %s\r\n", client->header);
#endif
break;
case HEADER_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+1] = '\n';
client->content_type[len+2] = 0;
#ifdef CMDREST_DBG
os_printf("REST: Set content_type: %s\r\n", client->content_type);
#endif
break;
case HEADER_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+1] = '\n';
client->user_agent[len+2] = 0;
#ifdef CMDREST_DBG
os_printf("REST: Set user_agent: %s\r\n", client->user_agent);
#endif
break;
}
return 1;
@ -301,32 +323,36 @@ uint32_t ICACHE_FLASH_ATTR
REST_Request(CmdPacket *cmd) {
CmdRequest req;
CMD_Request(&req, cmd);
#ifdef CMDREST_DBG
os_printf("REST: request");
#endif
// Get client
uint32_t clientNum;
if (CMD_PopArg(&req, (uint8_t*)&clientNum, 4)) goto fail;
if ((clientNum & 0xffff0000) != REST_CB) goto fail;
clientNum &= 0xffff;
RestClient *client = restClient + clientNum % MAX_REST;
#ifdef CMDREST_DBG
os_printf(" #%ld", clientNum);
#endif
// Get HTTP method
uint16_t len = CMD_ArgLen(&req);
if (len > 15) goto fail;
char method[16];
CMD_PopArg(&req, method, len);
method[len] = 0;
#ifdef CMDREST_DBG
os_printf(" method=%s", method);
#endif
// Get HTTP path
len = CMD_ArgLen(&req);
if (len > 1023) goto fail;
char path[1024];
CMD_PopArg(&req, path, len);
path[len] = 0;
#ifdef CMDREST_DBG
os_printf(" path=%s", path);
#endif
// Get HTTP body
uint32_t realLen = 0;
if (CMD_GetArgc(&req) == 3) {
@ -338,7 +364,9 @@ REST_Request(CmdPacket *cmd) {
len = CMD_ArgLen(&req);
if (len > 2048 || realLen > len) goto fail;
}
#ifdef CMDREST_DBG
os_printf(" bodyLen=%ld", realLen);
#endif
// 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
@ -353,30 +381,40 @@ REST_Request(CmdPacket *cmd) {
"User-Agent: %s\r\n\r\n";
uint16_t headerLen = strlen(headerFmt) + strlen(method) + strlen(path) + strlen(client->host) +
strlen(client->header) + strlen(client->content_type) + strlen(client->user_agent);
#ifdef CMDREST_DBG
os_printf(" hdrLen=%d", headerLen);
#endif
if (client->data) os_free(client->data);
client->data = (char*)os_zalloc(headerLen + realLen);
if (client->data == NULL) goto fail;
#ifdef CMDREST_DBG
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->header, realLen, client->content_type, client->user_agent);
#ifdef CMDREST_DBG
os_printf(" hdrLen=%d", client->data_len);
#endif
if (realLen > 0) {
CMD_PopArg(&req, client->data + client->data_len, realLen);
client->data_len += realLen;
}
#ifdef CMDREST_DBG
os_printf("\n");
//os_printf("REST request: %s", (char*)client->data);
os_printf("REST: pCon state=%d\n", client->pCon->state);
#endif
client->pCon->state = ESPCONN_NONE;
espconn_regist_connectcb(client->pCon, tcpclient_connect_cb);
espconn_regist_reconcb(client->pCon, tcpclient_recon_cb);
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);
#endif
//if(client->security){
// espconn_secure_connect(client->pCon);
//}
@ -384,13 +422,17 @@ REST_Request(CmdPacket *cmd) {
espconn_connect(client->pCon);
//}
} else {
#ifdef CMDREST_DBG
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);
}
return 1;
fail:
#ifdef CMDREST_DBG
os_printf("\n");
#endif
return 0;
}

@ -100,10 +100,15 @@ telnetUnwrap(uint8_t *inBuf, int len, uint8_t state)
switch (c) {
case DTR_ON:
if (mcu_reset_pin >= 0) {
#ifdef SERBR_DBG
os_printf("MCU reset gpio%d\n", mcu_reset_pin);
#endif
GPIO_OUTPUT_SET(mcu_reset_pin, 0);
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;
case DTR_OFF:
if (mcu_reset_pin >= 0) {
@ -113,10 +118,15 @@ telnetUnwrap(uint8_t *inBuf, int len, uint8_t state)
break;
case RTS_ON:
if (mcu_isp_pin >= 0) {
#ifdef SERBR_DBG
os_printf("MCU ISP gpio%d\n", mcu_isp_pin);
#endif
GPIO_OUTPUT_SET(mcu_isp_pin, 0);
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++;
break;
case RTS_OFF:
@ -137,11 +147,16 @@ telnetUnwrap(uint8_t *inBuf, int len, uint8_t state)
// Generate a reset pulse for the attached microcontroller
void ICACHE_FLASH_ATTR serbridgeReset() {
if (mcu_reset_pin >= 0) {
#ifdef SERBR_DBG
os_printf("MCU reset gpio%d\n", mcu_reset_pin);
#endif
GPIO_OUTPUT_SET(mcu_reset_pin, 0);
os_delay_us(100L);
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
@ -162,7 +177,9 @@ static void ICACHE_FLASH_ATTR serbridgeRecvCb(void *arg, char *data, unsigned sh
if ((len == 2 && strncmp(data, "0 ", 2) == 0) ||
(len == 2 && strncmp(data, "?\n", 2) == 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);
#endif
os_delay_us(2*1000L); // time for os_printf to happen
// send reset to arduino/ARM
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
// 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->telnet_state = TN_normal;
// note that the three negotiation chars will be gobbled-up by telnetUnwrap
#ifdef SERBR_DBG
os_printf("telnet mode\n");
#endif
// looks like a plain-vanilla connection!
} else {
}
else {
conn->conn_mode = cmTransparent;
}
@ -218,9 +239,11 @@ sendtxbuffer(serbridgeConnData *conn) {
conn->readytosend = false;
result = espconn_sent(conn->conn, (uint8_t*)conn->txbuffer, conn->txbufferlen);
conn->txbufferlen = 0;
#ifdef SERBR_DBG
if (result != ESPCONN_OK) {
os_printf("sendtxbuffer: espconn_sent error %d on conn %p\n", result, conn);
}
#endif
}
return result;
}
@ -233,7 +256,9 @@ sendtxbuffer(serbridgeConnData *conn) {
static sint8 ICACHE_FLASH_ATTR
espbuffsend(serbridgeConnData *conn, const char *data, uint16 len) {
if (conn->txbufferlen + len > MAX_TXBUFFER) {
#ifdef SERBR_DBG
os_printf("espbuffsend: txbuffer full on conn %p\n", conn);
#endif
return -128;
}
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
int i;
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);
#endif
if (i==MAX_CONN) {
#ifdef SERBR_DBG
os_printf("Aiee, conn pool overflow!\n");
#endif
espconn_disconnect(conn);
return;
}
@ -351,8 +380,10 @@ static void ICACHE_FLASH_ATTR serbridgeConnectCb(void *arg) {
void ICACHE_FLASH_ATTR serbridgeInitPins() {
mcu_reset_pin = flashConfig.reset_pin;
mcu_isp_pin = flashConfig.isp_pin;
#ifdef SERBR_DBG
os_printf("Serbridge pins: reset=%d isp=%d swap=%d\n",
mcu_reset_pin, mcu_isp_pin, flashConfig.swap_uart);
#endif
if (flashConfig.swap_uart) {
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);
serledFlash(1000); // turn it on for 1 second
}
#ifdef SERLED_DBG
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

@ -46,7 +46,9 @@ slip_process() {
if (crc == rcv) {
CMD_parse_packet((uint8_t*)slip_buf, slip_len-2);
} else {
#ifdef SLIP_DBG
os_printf("SLIP: bad CRC, crc=%x rcv=%x\n", crc, rcv);
for (short i=0; i<slip_len; i++) {
if (slip_buf[i] >= ' ' && slip_buf[i] <= '~')
os_printf("%c", slip_buf[i]);
@ -54,6 +56,7 @@ slip_process() {
os_printf("\\%02X", slip_buf[i]);
}
os_printf("\n");
#endif
}
}
}
@ -83,7 +86,9 @@ slip_parse_char(char c) {
if (slip_len > 0) console_process(slip_buf, slip_len);
slip_reset();
slip_inpkt = true;
#ifdef SLIP_DBG
os_printf("SLIP: start\n");
#endif
return;
}
} 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) {
uint32 now = system_get_time();
if (last_frm_err == 0 || (now - last_frm_err) > one_sec) {
#ifdef UART_DBG
os_printf("UART framing error (bad baud rate?)\n");
#endif
last_frm_err = now;
}
// 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)
|| 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();
system_os_post(recvTaskPrio, 0, 0);
}
@ -229,7 +233,9 @@ uart_recvTask(os_event_t *events)
(length < 128)) {
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++) {
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
uart0_baud(int rate) {
#ifdef UART_DBG
os_printf("UART %d baud\n", rate);
#endif
uart_div_modify(UART0, UART_CLK_FREQ / rate);
}
@ -278,7 +286,9 @@ uart_add_recv_cb(UartRecv_cb cb) {
return;
}
}
#ifdef UART_DBG
os_printf("UART: max cb count exceeded\n");
#endif
}
void ICACHE_FLASH_ATTR

Loading…
Cancel
Save