lots of ifdef

pull/47/head
Benjamin Runnels 9 years ago
parent 965b70a408
commit b7dd0b180f
  1. 1
      .gitignore
  2. 97
      Makefile
  3. 2
      cmd/cmd.c
  4. 4
      cmd/cmd.h
  5. 22
      cmd/handlers.c
  6. 11
      esp-link.vcxproj
  7. 12
      esp-link/cgi.c
  8. 1
      esp-link/cgi.h
  9. 12
      esp-link/cgiflash.c
  10. 50
      esp-link/cgimqtt.c
  11. 3
      esp-link/cgipins.c
  12. 48
      esp-link/cgiwifi.c
  13. 49
      esp-link/config.c
  14. 9
      esp-link/config.h
  15. 4
      esp-link/log.c
  16. 5
      esp-link/main.c
  17. 15
      esp-link/status.c
  18. 8
      espfs/espfs.c
  19. 72
      html/console.js
  20. BIN
      html/favicon.ico
  21. 10
      html/head-
  22. 88
      html/home.html
  23. 49
      html/log.html
  24. 23
      html/mqtt.html
  25. 1388
      html/pure.css
  26. 5
      html/style.css
  27. BIN
      html/wifi/icons.png
  28. 85
      html/wifi/wifi.html
  29. 200
      html/wifi/wifi.js
  30. 894
      httpd/httpd.c
  31. 44
      include/user_config.h
  32. 78
      mqtt/mqtt.c
  33. 33
      mqtt/mqtt_cmd.c
  34. 4
      mqtt/pktbuf.c
  35. 2
      mqtt/pktbuf.h
  36. 60
      rest/rest.c
  37. 41
      serial/serbridge.c
  38. 2
      serial/serled.c
  39. 5
      serial/slip.c
  40. 0
      tcpclient/tcpclient.c
  41. 0
      tcpclient/tcpclient.h
  42. 64
      user/latch_json.c
  43. 12
      user/latch_json.h
  44. 9
      user/user_funcs.c
  45. 1
      user/user_funcs.h
  46. 76
      user/user_main.c

1
.gitignore vendored

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

@ -32,7 +32,7 @@ ESPBAUD ?= 230400
# --------------- chipset configuration ---------------
# Pick your flash size: "512KB", "1MB", or "4MB"
FLASH_SIZE ?= 512KB
FLASH_SIZE ?= 4MB
ifeq ("$(FLASH_SIZE)","512KB")
# Winbond 25Q40 512KB flash, typ for esp-01 thru esp-11
@ -70,7 +70,7 @@ ET_BLANK ?= 0x3FE000 # where to flash blank.bin to erase wireless set
endif
# hostname or IP address for wifi flashing
ESP_HOSTNAME ?= esp-link
ESP_HOSTNAME ?= esp-nodemcu
# The pin assignments below are used when the settings in flash are invalid, they
# can be changed via the web interface
@ -122,15 +122,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 ?=
MODULES ?= mqtt rest
# -------------- End of config options -------------
@ -144,7 +149,6 @@ TARGET = httpd
# espressif tool to concatenate sections for OTA upload using bootloader v1.2+
APPGEN_TOOL ?= gen_appbin.py
CFLAGS=
# set defines for optional modules
@ -156,19 +160,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 mqtt esp-link
LIBRARIES_DIR = libraries
MODULES += espfs httpd user serial cmd esp-link
MODULES += $(foreach sdir,$(LIBRARIES_DIR),$(wildcard $(sdir)/*))
EXTRA_INCDIR = include . include/json
EXTRA_INCDIR = include .
# libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal phy pp net80211 wpa main lwip json
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-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) \
@ -203,17 +211,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))
@ -275,7 +283,7 @@ $(FW_BASE)/user1.bin: $(USER1_OUT) $(FW_BASE)
$(Q) rm -f eagle.app.v6.*.bin
$(Q) mv eagle.app.flash.bin $@
@echo "** user1.bin uses $$(stat -c '%s' $@) bytes of" $(ESP_FLASH_MAX) "available"
$(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; false; fi
$(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; true; fi
$(FW_BASE)/user2.bin: $(USER2_OUT) $(FW_BASE)
$(Q) $(OBJCP) --only-section .text -O binary $(USER2_OUT) eagle.app.v6.text.bin
@ -285,7 +293,7 @@ $(FW_BASE)/user2.bin: $(USER2_OUT) $(FW_BASE)
$(Q) COMPILE=gcc PATH=$(XTENSA_TOOLS_ROOT):$(PATH) python $(APPGEN_TOOL) $(USER2_OUT) 2 $(ESP_FLASH_MODE) $(ESP_FLASH_FREQ_DIV) $(ESP_SPI_SIZE)
$(Q) rm -f eagle.app.v6.*.bin
$(Q) mv eagle.app.flash.bin $@
$(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; false; fi
$(Q) if [ $$(stat -c '%s' $@) -gt $$(( $(ESP_FLASH_MAX) )) ]; then echo "$@ too big!"; true; fi
$(APP_AR): $(OBJ)
$(vecho) "AR $@"
@ -307,34 +315,51 @@ flash: all
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 \
@ -384,7 +409,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[];

@ -55,8 +55,8 @@ typedef enum {
CMD_REST_REQUEST,
CMD_REST_SETHEADER,
CMD_REST_EVENTS,
CMD_ADD_CALLBACK, // 15
CMD_SENSOR_EVENTS
CMD_CB_ADD, // 15
CMD_CB_EVENTS
} CmdName;
typedef uint32_t (*cmdfunc_t)(CmdPacket *cmd);

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

@ -65,9 +65,11 @@
<ItemGroup>
<ClCompile Include="cmd\cmd.c" />
<ClCompile Include="cmd\handlers.c" />
<ClCompile Include="tcpclient\tcpclient.c" />
<ClCompile Include="esp-link\cgimqtt.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" />
@ -103,6 +105,7 @@
<ClCompile Include="user\cgitcp.c" />
<ClCompile Include="user\cgiwifi.c" />
<ClCompile Include="user\config.c" />
<ClCompile Include="user\latch_json.c" />
<ClCompile Include="user\log.c" />
<ClCompile Include="user\status.c" />
<ClCompile Include="user\user_funcs.c" />
@ -111,9 +114,12 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="cmd\cmd.h" />
<ClInclude Include="tcpclient\tcpclient.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" />
@ -150,6 +156,7 @@
<ClInclude Include="user\cgitcp.h" />
<ClInclude Include="user\cgiwifi.h" />
<ClInclude Include="user\config.h" />
<ClInclude Include="user\latch_json.h" />
<ClInclude Include="user\log.h" />
<ClInclude Include="user\status.h" />
<ClInclude Include="user\user_funcs.h" />

@ -16,14 +16,6 @@ Some random cgi routines.
#include <esp8266.h>
#include "cgi.h"
static char* chipIdStr = "";
char* ICACHE_FLASH_ATTR system_get_chip_id_str(){
if (os_strlen(chipIdStr) == 0) {
chipIdStr = (char*)os_zalloc(9);
os_sprintf(chipIdStr, "%06x", system_get_chip_id());
}
return chipIdStr;
}
void noCacheHeaders(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code);
@ -44,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
@ -58,7 +52,7 @@ getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) {
os_sprintf(buff, "Value for %s too long (%d > %d allowed)", name, len, max_len-1);
errorResponse(connData, 400, buff);
return -1;
}
}
strcpy(config, buff);
return 1;
}

@ -10,6 +10,5 @@ int getStringArg(HttpdConnData *connData, char *name, char *config, int max_len)
int getBoolArg(HttpdConnData *connData, char *name, bool*config);
int cgiMenu(HttpdConnData *connData);
uint8_t UTILS_StrToIP(const char* str, void *ip);
char* system_get_chip_id_str();
#endif

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

@ -6,6 +6,7 @@
#include "config.h"
#include "espfs.h"
#include "crc16.h"
#include <user_funcs.h>
FlashConfig flashConfig;
FlashConfig flashDefault = {
@ -19,8 +20,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 +53,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;
@ -104,19 +106,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;
}
@ -125,10 +136,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;
@ -144,3 +159,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

@ -25,14 +25,18 @@ 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 1
#ifdef LOG_DBG
os_printf("Turning OFF uart log\n");
#endif
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
}
}

@ -30,7 +30,7 @@
#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
@ -97,9 +97,6 @@ HttpdBuiltInUrl builtInUrls[] = {
{ NULL, NULL, NULL }
};
//#define SHOW_HEAP_USE
#ifdef SHOW_HEAP_USE
static ETSTimer prHeapTimer;

@ -4,8 +4,9 @@
#include "config.h"
#include "serled.h"
#include "cgiwifi.h"
#include "tcpclient.h"
#ifdef TCPCLIENT
#include <tcpclient.h>
#endif
//===== "CONN" LED status indication
static ETSTimer ledTimer;
@ -66,6 +67,8 @@ void ICACHE_FLASH_ATTR statusWifiUpdate(uint8_t state) {
os_timer_arm(&ledTimer, 500, 0);
}
#ifdef TCPCLIENT
//===== RSSI Status update sent to GroveStreams
#define RSSI_INTERVAL (60*1000)
@ -112,6 +115,7 @@ static void ICACHE_FLASH_ATTR rssiTimerCb(void *v) {
}
tcpClientSendPush(chan);
}
#endif // TCPCLIENT
//===== Init status stuff
@ -120,15 +124,20 @@ 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);
os_timer_arm(&ledTimer, 2000, 0);
#ifdef TCPCLIENT
os_timer_disarm(&rssiTimer);
os_timer_setfn(&rssiTimer, rssiTimerCb, NULL);
os_timer_arm(&rssiTimer, RSSI_INTERVAL, 1); // recurring timer
#endif // TCPCLIENT
}

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

@ -0,0 +1,72 @@
function fetchText(delay, repeat) {
var el = $("#console");
if (el.textEnd == undefined) {
el.textEnd = 0;
el.innerHTML = "";
}
window.setTimeout(function() {
ajaxJson('GET', console_url + "?start=" + el.textEnd,
function(resp) {
var dly = updateText(resp);
if (repeat) fetchText(dly, repeat);
},
function() { retryLoad(repeat); });
}, delay);
}
function updateText(resp) {
var el = $("#console");
var delay = 3000;
if (resp != null && resp.len > 0) {
console.log("updateText got", resp.len, "chars at", resp.start);
if (resp.start > el.textEnd) {
el.innerHTML = el.innerHTML.concat("\r\n<missing lines\r\n");
}
el.innerHTML = el.innerHTML.concat(resp.text);
el.textEnd = resp.start + resp.len;
delay = 500;
}
return delay;
}
function retryLoad(repeat) {
fetchText(1000, repeat);
}
//===== Console page
function showRate(rate) {
rates.forEach(function(r) {
var el = $("#"+r+"-button");
el.className = el.className.replace(" button-selected", "");
});
var el = $("#"+rate+"-button");
if (el != null) el.className += " button-selected";
}
function baudButton(baud) {
$("#baud-btns").appendChild(m(
' <a id="'+baud+'-button" href="#" class="pure-button">'+baud+'</a>'));
$("#"+baud+"-button").addEventListener("click", function(e) {
e.preventDefault();
ajaxSpin('POST', "/console/baud?rate="+baud,
function(resp) { showNotification("" + baud + " baud set"); showRate(baud); },
function(s, st) { showWarning("Error setting baud rate: " + st); }
);
});
}
//===== Log page
function showDbgMode(mode) {
var btns = $('.dbg-btn');
for (var i=0; i < btns.length; i++) {
if (btns[i].id === "dbg-"+mode)
addClass(btns[i], "button-selected");
else
removeClass(btns[i], "button-selected");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

@ -0,0 +1,10 @@
<!doctype html>
<html><head>
<title>esp-link</title>
<link rel="stylesheet" href="/pure.css">
<link rel="stylesheet" href="/style.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="/ui.js"></script>
</head>
<body>
<div id="layout">

@ -1 +1,87 @@
<!DOCTYPE html><script src='http://linux-ws/esplink/home.js'></script>
<div id="main">
<div class="header">
<div><img src="favicon.ico" height="64"><span class="jl">JEELABS</span></div>
<h1 style="margin-top:0"><span class="esp">esp</span>-link</h1>
<h2 id="version"></h2>
</div>
<div class="content">
<div class="pure-g">
<div class="pure-u-1"><div class="card">
<p>The JeeLabs esp-link firmware bridges the ESP8266 serial port to Wifi and can
program microcontrollers over the serial port, in particular Arduinos, AVRs, and
NXP's LPC800 and other ARM processors.</p>
<p style="margin-bottom:0;">Program an Arduino/AVR using avrdude using a command
line similar to:</p>
<div class="tt">/home/arduino-1.0.5/hardware/tools/avrdude \<br>
&nbsp;&nbsp;-DV -patmega328p -Pnet:esp-link.local:23 -carduino -b115200 -U \<br>
&nbsp;&nbsp;-C /home/arduino-1.0.5/hardware/tools/avrdude.conf flash:w:my_sketch.hex:i
</div>
<p>where <tt>-Pnet:esp-link.local:23</tt> tells avrdude to connect to port 23 of esp-link.
You can substitute the IP address of your esp-link for esp-link.local if necessary.</p>
<p>Please refer to
<a href="https://github.com/jeelabs/esp-link/blob/master/README.md">the online README</a>
for up-to-date help and to the forthcoming
<a href="http://jeelabs.org">JeeLabs blog</a> for an intro to the codebase.</p>
</div></div>
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2">
<div class="card">
<h1>Wifi summary</h1>
<div id="wifi-spinner" class="spinner spinner-small"></div>
<table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>WiFi mode</td><td id="wifi-mode"></td></tr>
<tr><td>Configured network</td><td id="wifi-ssid"></td></tr>
<tr><td>Wifi channel</td><td id="wifi-chan"></td></tr>
<tr><td>Wifi status</td><td id="wifi-status"></td></tr>
<tr><td>Wifi address</td><td id="wifi-ip"></td></tr>
<tr><td>Configured hostname</td><td id="wifi-hostname"></td></tr>
</tbody> </table>
</div>
<div class="card">
<h1>TCP client</h1>
<form action="#" id="tcpform" class="pure-form">
<legend>TCP client support in esp-link</legend>
<div class="form-horizontal">
<input type="checkbox" name="tcp_enable"/>
<label>Enable serial port TCP client</label>
</div>
<br>
<legend>Grovestreams data push</legend>
<div class="form-horizontal">
<input type="checkbox" name="rssi_enable"/>
<label>Send RSSI</label>
</div>
<div class="pure-form-stacked">
<label>API key/passwd</label>
<input type="password" name="api_key"/>
</div>
<button id="tcp-button" type="submit"
class="pure-button button-primary">Change!</button>
</form>
</div>
</div>
<div class="pure-u-1 pure-u-md-1-2"><div class="card">
<h1>Pin assignment</h1>
<legend>Select one of the following signal/pin assignments to match your hardware</legend>
<fieldset class='radios' id='pin-mux'>
<div class="spinner spinner-small"></div>
</fieldset>
</div></div>
</div>
<div class="pure-g">
</div>
</div>
</div>
</div>
<script type="text/javascript">
onLoad(function() {
fetchPins();
getWifiInfo();
fetchTcpClient();
bnd($("#tcpform"), "submit", changeTcpClient);
});
</script>
</body></html>

@ -1 +1,48 @@
<!DOCTYPE html><script src='http://linux-ws/esplink/log.js'></script>
<div id="main">
<div class="header">
<h1>Debug Log</h1>
</div>
<div class="content">
<p>The debug log shows the most recent characters printed by the esp-link software itself to
its own debug log.</p>
<div class="pure-g">
<p class="pure-u-1-4">
<a id="refresh-button" class="pure-button button-primary" href="#">Refresh</a>
</p>
<p class="pure-u-3-4" style="vertical-align: baseline">
UART debug log:
<a id="dbg-auto" class="dbg-btn pure-button" href="#">auto</a>
<a id="dbg-off" class="dbg-btn pure-button" href="#">off</a>
<a id="dbg-on" class="dbg-btn pure-button" href="#">on</a>
</p>
</div>
<pre id="console" class="console" style="margin-top: 0px;"></pre>
</div>
</div>
</div>
<script type="text/javascript">console_url = "/log/text"</script>
<script src="console.js"></script>
<script type="text/javascript">
onLoad(function() {
fetchText(100, false);
$("#refresh-button").addEventListener("click", function(e) {
e.preventDefault();
fetchText(100, false);
});
["auto", "off", "on"].forEach(function(mode) {
bnd($('#dbg-'+mode), "click", function(el) {
ajaxJsonSpin('POST', "/log/dbg?mode="+mode,
function(data) { showNotification("UART mode " + data.mode); showDbgMode(data.mode); },
function(s, st) { showWarning("Error setting UART mode: " + st); }
);
});
});
ajaxJson('GET', "/log/dbg", function(data) { showDbgMode(data.mode); }, function() {});
});
</script>
</body></html>

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

File diff suppressed because it is too large Load Diff

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

After

Width:  |  Height:  |  Size: 425 B

@ -1 +1,84 @@
<!DOCTYPE html><script src='http://linux-ws/esplink/wifi/wifi.js'></script>
<div id="main">
<div class="header">
<h1>Wifi Configuration</h1>
</div>
<div class="content">
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2"><div class="card">
<h1>Wifi State</h1>
<div id="wifi-spinner" class="spinner spinner-small"></div>
<table id="wifi-table" class="pure-table pure-table-horizontal" hidden><tbody>
<tr><td>WiFi mode</td><td id="wifi-mode"></td></tr>
<tr><td>Wifi channel</td><td id="wifi-chan"></td></tr>
<tr><td>Configured network</td><td id="wifi-ssid"></td></tr>
<tr><td>Wifi status</td><td id="wifi-status"></td></tr>
<tr><td>Wifi address</td><td id="wifi-ip"></td></tr>
<tr><td>Wifi rssi</td><td id="wifi-rssi"></td></tr>
<tr><td>Wifi phy</td><td id="wifi-phy"></td></tr>
<tr><td>Wifi MAC</td><td id="wifi-mac"></td></tr>
<tr><td colspan="2" id="wifi-warn"></td></tr>
</tbody> </table>
</div></div>
<div class="pure-u-1 pure-u-md-1-2"><div class="card">
<h1>Wifi Association</h1>
<p id="reconnect" style="color: #600" hidden></p>
<form action="#" id="wifiform" class="pure-form pure-form-stacked">
<legend>To connect to a WiFi network, please select one of the detected networks,
enter the password, and hit the connect button...</legend>
<label>Network SSID</label>
<div id="aps">Scanning... <div class="spinner spinner-small"></div></div>
<label>WiFi password, if applicable:</label>
<input id="wifi-passwd" type="password" name="passwd" placeholder="password">
<button id="connect-button" type="submit" class="pure-button button-primary">Connect!</button>
</form>
</div></div>
</div>
<div class="pure-g">
<div class="pure-u-1 pure-u-md-1-2"><div class="card">
<h1>Special Settings</h1>
<form action="#" id="specform" class="pure-form">
<legend>Special settings, use with care!</legend>
<div class="form-horizontal">
<label for="dhcp-ron" style="margin-right:1em">
<input type="radio" name="dhcp" value="on" id="dhcp-ron"/>
DHCP</label>
<label for="dhcp-roff">
<input type="radio" name="dhcp" value="off" id="dhcp-roff"/>
Static IP</label>
</div>
<div id="dhcp-on" class="pure-form-stacked">
<label>Hostname when requesting DHCP lease</label>
<input id="wifi-hostname" type="text" name="hostname"/>
</div>
<div id="dhcp-off" class="pure-form-stacked">
<label>Static IP address</label>
<input id="wifi-staticip" type="text" name="staticip"/>
<label>Netmask (for static IP)</label>
<input id="wifi-netmask" type="text" name="netmask"/>
<label>Gateway (for static IP)</label>
<input id="wifi-gateway" type="text" name="gateway"/>
</div>
<button id="special-button" type="submit"
class="pure-button button-primary">Change!</button>
</form>
</div></div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
</script>
<script src="wifi.js"></script>
<script type="text/javascript">
onLoad(function() {
getWifiInfo();
bnd($("#wifiform"), "submit", changeWifiAp);
bnd($("#specform"), "submit", changeSpecial);
bnd($("#dhcp-ron"), "click", doDhcp);
bnd($("#dhcp-roff"), "click", doStatic);
scanTimeout = window.setTimeout(scanAPs, 500);
});
</script>
</body></html>

@ -0,0 +1,200 @@
var currAp = "";
var blockScan = 0;
function createInputForAp(ap) {
if (ap.essid=="" && ap.rssi==0) return;
var input = e("input");
input.type = "radio";
input.name = "essid";
input.value=ap.essid;
input.id = "opt-" + ap.essid;
if (currAp == ap.essid) input.checked = "1";
var bars = e("div");
var rssiVal = -Math.floor(ap.rssi/51)*32;
bars.className = "lock-icon";
bars.style.backgroundPosition = "0px "+rssiVal+"px";
var rssi = e("div");
rssi.innerHTML = "" + ap.rssi +"dB";
var encrypt = e("div");
var encVal = "-64"; //assume wpa/wpa2
if (ap.enc == "0") encVal = "0"; //open
if (ap.enc == "1") encVal = "-32"; //wep
encrypt.className = "lock-icon";
encrypt.style.backgroundPosition = "-32px "+encVal+"px";
var label = e("div");
label.innerHTML = ap.essid;
var div = m('<label for=\"opt-' + ap.essid + '"></label>').childNodes[0];
div.appendChild(input);
div.appendChild(encrypt);
div.appendChild(bars);
div.appendChild(rssi);
div.appendChild(label);
return div;
}
function getSelectedEssid() {
var e = document.forms.wifiform.elements;
for (var i=0; i<e.length; i++) {
if (e[i].type == "radio" && e[i].checked) return e[i].value;
}
return currAp;
}
var scanTimeout = null;
var scanReqCnt = 0;
function scanResult() {
if (scanReqCnt > 60) {
return scanAPs();
}
scanReqCnt += 1;
ajaxJson('GET', "scan", function(data) {
currAp = getSelectedEssid();
if (data.result.inProgress == "0" && data.result.APs.length > 1) {
$("#aps").innerHTML = "";
var n = 0;
for (var i=0; i<data.result.APs.length; i++) {
if (data.result.APs[i].essid == "" && data.result.APs[i].rssi == 0) continue;
$("#aps").appendChild(createInputForAp(data.result.APs[i]));
n = n+1;
}
showNotification("Scan found " + n + " networks");
var cb = $("#connect-button");
cb.className = cb.className.replace(" pure-button-disabled", "");
if (scanTimeout != null) clearTimeout(scanTimeout);
scanTimeout = window.setTimeout(scanAPs, 20000);
} else {
window.setTimeout(scanResult, 1000);
}
}, function(s, st) {
window.setTimeout(scanResult, 5000);
});
}
function scanAPs() {
console.log("scanning now");
if (blockScan) {
scanTimeout = window.setTimeout(scanAPs, 1000);
return;
}
scanTimeout = null;
scanReqCnt = 0;
ajaxReq('POST', "scan", function(data) {
//showNotification("Wifi scan started");
window.setTimeout(scanResult, 1000);
}, function(s, st) {
//showNotification("Wifi scan may have started?");
window.setTimeout(scanResult, 1000);
});
}
function getStatus() {
ajaxJsonSpin("GET", "connstatus", function(data) {
if (data.status == "idle" || data.status == "connecting") {
$("#aps").innerHTML = "Connecting...";
showNotification("Connecting...");
window.setTimeout(getStatus, 1000);
} else if (data.status == "got IP address") {
var txt = "Connected! Got IP "+data.ip;
showNotification(txt);
showWifiInfo(data);
blockScan = 0;
if (data.modechange == "yes") {
var txt2 = "esp-link will switch to STA-only mode in a few seconds";
window.setTimeout(function() { showNotification(txt2); }, 4000);
}
$("#reconnect").removeAttribute("hidden");
$("#reconnect").innerHTML =
"If you are in the same network, go to <a href=\"http://"+data.ip+
"/\">"+data.ip+"</a>, else connect to network "+data.ssid+" first.";
} else {
blockScan = 0;
showWarning("Connection failed: " + data.status + ", " + data.reason);
$("#aps").innerHTML =
"Check password and selected AP. <a href=\"wifi.tpl\">Go Back</a>";
}
}, function(s, st) {
//showWarning("Can't get status: " + st);
window.setTimeout(getStatus, 2000);
});
}
function changeWifiMode(m) {
blockScan = 1;
hideWarning();
ajaxSpin("POST", "setmode?mode=" + m, function(resp) {
showNotification("Mode changed");
window.setTimeout(getWifiInfo, 100);
blockScan = 0;
}, function(s, st) {
showWarning("Error changing mode: " + st);
window.setTimeout(getWifiInfo, 100);
blockScan = 0;
});
}
function changeWifiAp(e) {
e.preventDefault();
var passwd = $("#wifi-passwd").value;
var essid = getSelectedEssid();
showNotification("Connecting to " + essid);
var url = "connect?essid="+encodeURIComponent(essid)+"&passwd="+encodeURIComponent(passwd);
hideWarning();
$("#reconnect").setAttribute("hidden", "");
$("#wifi-passwd").value = "";
var cb = $("#connect-button");
var cn = cb.className;
cb.className += ' pure-button-disabled';
blockScan = 1;
ajaxSpin("POST", url, function(resp) {
$("#spinner").removeAttribute('hidden'); // hack
showNotification("Waiting for network change...");
window.scrollTo(0, 0);
window.setTimeout(getStatus, 2000);
}, function(s, st) {
showWarning("Error switching network: "+st);
cb.className = cn;
window.setTimeout(scanAPs, 1000);
});
}
function changeSpecial(e) {
e.preventDefault();
var url = "special";
url += "?dhcp=" + document.querySelector('input[name="dhcp"]:checked').value;
url += "&hostname=" + encodeURIComponent($("#wifi-hostname").value);
url += "&staticip=" + encodeURIComponent($("#wifi-staticip").value);
url += "&netmask=" + encodeURIComponent($("#wifi-netmask").value);
url += "&gateway=" + encodeURIComponent($("#wifi-gateway").value);
hideWarning();
var cb = $("#special-button");
addClass(cb, 'pure-button-disabled');
ajaxSpin("POST", url, function(resp) {
removeClass(cb, 'pure-button-disabled');
getWifiInfo();
}, function(s, st) {
showWarning("Error: "+st);
removeClass(cb, 'pure-button-disabled');
getWifiInfo();
});
}
function doDhcp() {
$('#dhcp-on').removeAttribute('hidden');
$('#dhcp-off').setAttribute('hidden', '');
}
function doStatic() {
$('#dhcp-off').removeAttribute('hidden');
$('#dhcp-on').setAttribute('hidden', '');
}

File diff suppressed because it is too large Load Diff

@ -4,30 +4,32 @@
#ifdef __WIN32__
#include <_mingw.h>
#endif
//#define CMD_DBG
#define MQTT_RECONNECT_TIMEOUT 5 // seconds
#define MQTT_BUF_SIZE 512
#define QUEUE_BUFFER_SIZE 512
#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 system_get_chip_id_str() // "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 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
//#define REST
extern char* esp_link_version;
extern uint8_t UTILS_StrToIP(const char* str, void *ip);
extern void ICACHE_FLASH_ATTR init(void);
extern char* ICACHE_FLASH_ATTR system_get_chip_id_str();
#endif

@ -57,10 +57,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);
@ -125,7 +127,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;
}
@ -135,7 +139,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;
}
@ -147,13 +153,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);
}
#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);
@ -161,28 +170,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);
@ -193,7 +210,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;
@ -201,9 +220,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) {
@ -217,7 +238,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);
@ -294,7 +317,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;
}
@ -337,15 +362,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);
@ -364,12 +391,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);
@ -394,7 +423,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);
@ -435,8 +466,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]);
@ -481,17 +513,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);
@ -501,11 +536,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
}
}
}
@ -539,7 +578,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
@ -548,13 +589,16 @@ 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;
}
client->mqtt_connection.message_id = msg.message_id;
#ifdef MQTT_DBG
os_printf("MQTT: Publish, topic: \"%s\", length: %d\n", topic, msg.message.length);
#endif
client->msgQueue = PktBuf_Push(client->msgQueue, buf);
if (!client->sending && client->pending_buffer == NULL) {
@ -574,10 +618,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;
@ -595,14 +643,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, uint8_t cleanSession) {
#ifdef MQTT_DBG
os_printf("MQTT_Init\n");
#endif
os_memset(mqttClient, 0, sizeof(MQTT_Client));
@ -679,7 +733,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;
@ -688,7 +744,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;
@ -707,7 +765,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;

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

@ -0,0 +1,64 @@
#include "latch_json.h"
#include "user_funcs.h"
#include <json/jsontree.h>
#include <json/jsonparse.h>
#include <cmd.h>
static LatchState latch;
static void ICACHE_FLASH_ATTR
updateLatch() {
os_printf("ESP: Latch Callback\n");
cmdCallback* latchCb = CMD_GetCbByName("Latch");
if (latchCb->callback != -1) {
uint16_t crc = CMD_ResponseStart(CMD_CB_EVENTS, (uint32_t)&latchCb->callback, 0, 1);
crc = CMD_ResponseBody(crc, (uint8_t*)&latch, sizeof(LatchState));
CMD_ResponseEnd(crc);
}
}
static int ICACHE_FLASH_ATTR
latchGet(struct jsontree_context *js_ctx) {
return 0;
}
static int ICACHE_FLASH_ATTR
latchSet(struct jsontree_context *js_ctx, struct jsonparse_state *parser) {
int type;
int ix = -1;
while ((type = jsonparse_next(parser)) != 0) {
if (type == JSON_TYPE_ARRAY) {
ix = -1;
}
else if (type == JSON_TYPE_OBJECT) {
ix++;
}
else if (type == JSON_TYPE_PAIR_NAME) {
if (jsonparse_strcmp_value(parser, "states") == 0) {
char latchStates[9];
jsonparse_next(parser); jsonparse_next(parser);
jsonparse_copy_value(parser, latchStates, sizeof(latchStates));
os_printf("latch states %s\n", latchStates);
uint8_t states = binToByte(latchStates);
latch.stateBits = states;
}
else if (jsonparse_strcmp_value(parser, "fallbackstates") == 0) {
char fallbackStates[9];
jsonparse_next(parser); jsonparse_next(parser);
jsonparse_copy_value(parser, fallbackStates, sizeof(fallbackStates));
os_printf("latch states %s\n", fallbackStates);
uint8_t fbstates = binToByte(fallbackStates);
latch.fallbackStateBits = fbstates;
}
}
}
return 0;
}
static struct jsontree_callback latchCallback = JSONTREE_CALLBACK(latchGet, latchSet);
static char* latchQueueName;
JSONTREE_OBJECT(latchJsonObj,
JSONTREE_PAIR("states", &latchCallback),
JSONTREE_PAIR("fallbackstates", &latchCallback));

@ -0,0 +1,12 @@
#ifndef _LATCH_JSON_H_
#define _LATCH_JSON_H_
#include <esp8266.h>
typedef struct {
uint8_t fallbackStateBits;
uint8_t stateBits;
uint8_t init;
uint8_t fallbackSecondsForBits[8];
} LatchState;
#endif // _LATCH_JSON_H_

@ -1,6 +1,7 @@
#include "user_funcs.h"
bool ICACHE_FLASH_ATTR pwmPinStateForSchedule(uint8_t onHour, uint8_t onMinute, uint8_t offHour, uint8_t offMinute) {
bool ICACHE_FLASH_ATTR
pwmPinStateForSchedule(uint8_t onHour, uint8_t onMinute, uint8_t offHour, uint8_t offMinute) {
uint16_t NumMinsToday = totalMinutes(hour(), minute());
bool state = false;
@ -19,7 +20,8 @@ bool ICACHE_FLASH_ATTR pwmPinStateForSchedule(uint8_t onHour, uint8_t onMinute,
return state;
}
const char* ICACHE_FLASH_ATTR byteToBin(uint8_t num) {
const char* ICACHE_FLASH_ATTR
byteToBin(uint8_t num) {
static char b[9];
b[0] = '\0';
@ -30,7 +32,8 @@ const char* ICACHE_FLASH_ATTR byteToBin(uint8_t num) {
return b;
}
const uint8_t ICACHE_FLASH_ATTR binToByte(char* bin_str) {
const uint8_t ICACHE_FLASH_ATTR
binToByte(char* bin_str) {
char * tmp;
long x = strtol(bin_str, &tmp, 2);
return (x <= 255) ? (uint8_t)x : -1;

@ -7,4 +7,5 @@ bool pwmPinStateForSchedule(uint8_t onHour, uint8_t onMinute, uint8_t offHour, u
const char* byteToBin(uint8_t num);
const uint8_t binToByte(char* bin_str);
#endif // _USER_FUNCS_H_

@ -1,38 +1,14 @@
#include <esp8266.h>
#include "cgiwifi.h"
#include "mqtt.h"
#include <mqtt.h>
#include <config.h>
#include "latch_json.h"
#include "user_funcs.h"
MQTT_Client mqttClient;
static ETSTimer mqttTimer;
static int once = 0;
static void ICACHE_FLASH_ATTR mqttTimerCb(void *arg) {
if (once++ > 0) return;
MQTT_Init(&mqttClient, "h.voneicken.com", 1883, 0, 2, "test1", "", "", 10, 1);
MQTT_Connect(&mqttClient);
MQTT_Subscribe(&mqttClient, "system/time", 0);
}
void ICACHE_FLASH_ATTR
wifiStateChangeCb(uint8_t status)
{
if (status == wifiGotIP) {
os_timer_disarm(&mqttTimer);
os_timer_setfn(&mqttTimer, mqttTimerCb, NULL);
os_timer_arm(&mqttTimer, 15000, 0);
}
}
// initialize the custom stuff that goes beyond esp-link
void app_init() {
wifiAddStateChangeCb(wifiStateChangeCb);
}
#if 0
MQTT_Client mqttClient;
//static ETSTimer mqttTimer;
void ICACHE_FLASH_ATTR
mqttConnectedCb(uint32_t *args) {
@ -60,11 +36,10 @@ mqttPublishedCb(uint32_t *args) {
void ICACHE_FLASH_ATTR
mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len) {
// MQTT_Client* client = (MQTT_Client*)args;
char *topicBuf = (char*)os_zalloc(topic_len + 1);
char *dataBuf = (char*)os_zalloc(data_len + 1);
// MQTT_Client* client = (MQTT_Client*)args;
os_memcpy(topicBuf, topic, topic_len);
topicBuf[topic_len] = 0;
@ -76,12 +51,33 @@ mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *da
os_free(dataBuf);
}
MQTT_InitConnection(&mqttClient, MQTT_HOST, MQTT_PORT, MQTT_SECURITY);
MQTT_InitClient(&mqttClient, MQTT_CLIENT_ID, MQTT_USER, MQTT_PASS, MQTT_KEEPALIVE, MQTT_CLSESSION);
MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0);
MQTT_OnConnected(&mqttClient, mqttConnectedCb);
MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
MQTT_OnDisconnected(&mqttClient, mqttTcpDisconnectedCb);
MQTT_OnPublished(&mqttClient, mqttPublishedCb);
MQTT_OnData(&mqttClient, mqttDataCb);
#endif
void ICACHE_FLASH_ATTR
wifiStateChangeCb(uint8_t status) {
if (flashConfig.mqtt_enable) {
if (status == wifiGotIP && mqttClient.connState != TCP_CONNECTING) {
MQTT_Connect(&mqttClient);
}
else if (status == wifiIsDisconnected && mqttClient.connState == TCP_CONNECTING) {
MQTT_Disconnect(&mqttClient);
}
}
}
// initialize the custom stuff that goes beyond esp-link
void app_init() {
if (flashConfig.mqtt_enable) {
MQTT_Init(&mqttClient, flashConfig.mqtt_host, flashConfig.mqtt_port, 0, flashConfig.mqtt_timeout,
flashConfig.mqtt_clientid, flashConfig.mqtt_username, flashConfig.mqtt_password, flashConfig.mqtt_keepalive, flashConfig.mqtt_clean_session
);
MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0);
MQTT_OnConnected(&mqttClient, mqttConnectedCb);
MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
MQTT_OnDisconnected(&mqttClient, mqttTcpDisconnectedCb);
MQTT_OnPublished(&mqttClient, mqttPublishedCb);
MQTT_OnData(&mqttClient, mqttDataCb);
}
wifiAddStateChangeCb(wifiStateChangeCb);
}

Loading…
Cancel
Save