From ef01fc76b7e59f0e760806b62746be97a3d02aa7 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Sat, 29 Aug 2015 13:51:08 -0700 Subject: [PATCH 1/6] makefile tweak --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 451d7f3..7f47c20 100644 --- a/Makefile +++ b/Makefile @@ -356,8 +356,8 @@ release: all $(Q) egrep -a 'esp-link [a-z0-9.]+ - 201' $(FW_BASE)/user2.bin | cut -b 1-80 $(Q) cp $(FW_BASE)/user1.bin $(FW_BASE)/user2.bin $(SDK_BASE)/bin/blank.bin \ "$(SDK_BASE)/bin/boot_v1.4(b1).bin" wiflash release/esp-link-$(BRANCH) - $(Q) tar zcf esp-link-$(BRANCH)-$(FLASH_SIZE).tgz -C release esp-link-$(BRANCH) - $(Q) echo "Release file: esp-link-$(BRANCH)-$(FLASH_SIZE).tgz" + $(Q) tar zcf esp-link-$(BRANCH).tgz -C release esp-link-$(BRANCH) + $(Q) echo "Release file: esp-link-$(BRANCH).tgz" $(Q) rm -rf release clean: From 0bb7dba4988f9617409e0f6f662534c8a092086a Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Sat, 29 Aug 2015 19:01:35 -0700 Subject: [PATCH 2/6] readme update --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 34d3090..d90fa9b 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,28 @@ Many thanks to https://github.com/brunnels for contributions around the espduino For quick support and questions: [![Chat at https://gitter.im/jeelabs/esp-link](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jeelabs/esp-link?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +Esp-link uses +------------- +The simplest use of esp-link is as a transparent serial to wifi bridge. You can flash an attached +uC over wifi and you can watch the uC's serial debug output by connecting to port 23 or looking +at the uC Console web page. + +The next level is to use the outbound connectivity of esp-link in the uC code. For example, the +uC can use REST requests to services like thingspeak.com to send sensor values that then get +stored and plotted by the external service. +The uC can also use REST requests to retrieve simple configuration +information or push other forms of notifications. (MQTT functionality is forthcoming.) + +An additional option is to add code to esp-link to customize it and put all the communication +code into esp-link and only keep simple sensor/actuator control in the attached uC. In this +mode the attached uC sends custom commands to esp-link with sensor/acturator info and +registers a set of callbacks with esp-link that control sensors/actuators. This way, custom +commands in esp-link can receive MQTT messages, make simple callbacks into the uC to get sensor +values or change actuators, and then respond back with MQTT. The way this is architected is that +the attached uC registers callbacks at start-up such that the code in the esp doesn't need to +know which exact sensors/actuators the attached uC has, it learns thta through the initial +callback registration. + Eye Candy --------- These screen shots show the Home page, the Wifi configuration page, the console for the @@ -237,7 +259,22 @@ The attached micro-controller can open outbound TCP connections using a simple [serial protocol](https://gist.github.com/tve/a46c44bf1f6b42bc572e). More info and sample code forthcoming... +Outbound HTTP REST requests +--------------------------- +The V2 versions of esp-link support the espduino SLIP protocol that supports simple outbound +HTTP REST requests. The SLIP protocol consists of commands with binary arguments sent from the +attached microcontroller to the esp8266, which then performs the command and responds back. +The responses back use a callback address in the attached microcontroller code, i.e., the +command sent by the uC contains a callback address and the response from the esp8266 starts +with that callback address. This enables asynchronous communication where esp-link can notify the +uC when requests complete or when other actions happen, such as wifi connectivity status changes. +Support for MQTT is forthcoming. + +You can find a demo sketch in a fork of the espduino library at +https://github.com/tve/espduino in the +[examples/demo folder](https://github.com/tve/espduino/tree/master/espduino/examples/demo). + Contact ------- If you find problems with esp-link, please create a github issue. If you have a question, please -use the gitter link at the top of this page. +use the gitter chat link at the top of this page. From da7a1b913f5b2d35c8626bd19095ec1e47a7191a Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Sun, 6 Sep 2015 10:12:59 -0700 Subject: [PATCH 3/6] indentation changes --- esp-link/cgiwifi.c | 824 ++++++++++++++++++++++----------------------- 1 file changed, 412 insertions(+), 412 deletions(-) diff --git a/esp-link/cgiwifi.c b/esp-link/cgiwifi.c index 2354b13..69d59b4 100644 --- a/esp-link/cgiwifi.c +++ b/esp-link/cgiwifi.c @@ -31,12 +31,12 @@ uint8_t wifiState = wifiIsDisconnected; // reasons for which a connection failed uint8_t wifiReason = 0; static char *wifiReasons[] = { - "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", - "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", - "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", - "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", - "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", - "beacon_timeout", "no_ap_found" }; + "", "unspecified", "auth_expire", "auth_leave", "assoc_expire", "assoc_toomany", "not_authed", + "not_assoced", "assoc_leave", "assoc_not_authed", "disassoc_pwrcap_bad", "disassoc_supchan_bad", + "ie_invalid", "mic_failure", "4way_handshake_timeout", "group_key_update_timeout", + "ie_in_4way_differs", "group_cipher_invalid", "pairwise_cipher_invalid", "akmp_invalid", + "unsupp_rsn_ie_version", "invalid_rsn_ie_cap", "802_1x_auth_failed", "cipher_suite_rejected", + "beacon_timeout", "no_ap_found" }; static char *wifiMode[] = { 0, "STA", "AP", "AP+STA" }; static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; @@ -44,51 +44,51 @@ static char *wifiPhy[] = { 0, "11b", "11g", "11n" }; void (*wifiStatusCb)(uint8_t); // callback when wifi status changes static char* ICACHE_FLASH_ATTR wifiGetReason(void) { - if (wifiReason <= 24) return wifiReasons[wifiReason]; - if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; - return wifiReasons[1]; + if (wifiReason <= 24) return wifiReasons[wifiReason]; + if (wifiReason >= 200 && wifiReason <= 201) return wifiReasons[wifiReason-200+24]; + return wifiReasons[1]; } // handler for wifi status change callback coming in from espressif library static void ICACHE_FLASH_ATTR wifiHandleEventCb(System_Event_t *evt) { - switch (evt->event) { - case EVENT_STAMODE_CONNECTED: - wifiState = wifiIsConnected; - wifiReason = 0; - os_printf("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, - evt->event_info.connected.channel); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_DISCONNECTED: - wifiState = wifiIsDisconnected; - wifiReason = evt->event_info.disconnected.reason; - os_printf("Wifi disconnected from ssid %s, reason %s (%d)\n", - evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); - statusWifiUpdate(wifiState); - break; - case EVENT_STAMODE_AUTHMODE_CHANGE: - os_printf("Wifi auth mode: %d -> %d\n", - evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); - break; - case EVENT_STAMODE_GOT_IP: - wifiState = wifiGotIP; - wifiReason = 0; - 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)); - statusWifiUpdate(wifiState); - break; - case EVENT_SOFTAPMODE_STACONNECTED: - os_printf("Wifi AP: station " MACSTR " joined, AID = %d\n", - MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); - break; - case EVENT_SOFTAPMODE_STADISCONNECTED: - os_printf("Wifi AP: station " MACSTR " left, AID = %d\n", - MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); - break; - default: - break; - } + switch (evt->event) { + case EVENT_STAMODE_CONNECTED: + wifiState = wifiIsConnected; + wifiReason = 0; + os_printf("Wifi connected to ssid %s, ch %d\n", evt->event_info.connected.ssid, + evt->event_info.connected.channel); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_DISCONNECTED: + wifiState = wifiIsDisconnected; + wifiReason = evt->event_info.disconnected.reason; + os_printf("Wifi disconnected from ssid %s, reason %s (%d)\n", + evt->event_info.disconnected.ssid, wifiGetReason(), evt->event_info.disconnected.reason); + statusWifiUpdate(wifiState); + break; + case EVENT_STAMODE_AUTHMODE_CHANGE: + os_printf("Wifi auth mode: %d -> %d\n", + evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); + break; + case EVENT_STAMODE_GOT_IP: + wifiState = wifiGotIP; + wifiReason = 0; + 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)); + statusWifiUpdate(wifiState); + break; + case EVENT_SOFTAPMODE_STACONNECTED: + os_printf("Wifi AP: station " MACSTR " joined, AID = %d\n", + MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); + break; + case EVENT_SOFTAPMODE_STADISCONNECTED: + os_printf("Wifi AP: station " MACSTR " left, AID = %d\n", + MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); + break; + default: + break; + } for (int i = 0; i < 4; i++) { if (wifi_state_change_cb[i] != NULL) (wifi_state_change_cb[i])(wifiState); @@ -110,16 +110,16 @@ wifiAddStateChangeCb(WifiStateChangeCb cb) { //WiFi access point data typedef struct { - char ssid[32]; - sint8 rssi; - char enc; + char ssid[32]; + sint8 rssi; + char enc; } ApData; //Scan result typedef struct { - char scanInProgress; //if 1, don't access the underlying stuff from the webpage. - ApData **apData; - int noAps; + char scanInProgress; //if 1, don't access the underlying stuff from the webpage. + ApData **apData; + int noAps; } ScanResultData; //Static scan status storage. @@ -128,109 +128,109 @@ static ScanResultData cgiWifiAps; //Callback the code calls when a wlan ap scan is done. Basically stores the result in //the cgiWifiAps struct. void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { - int n; - struct bss_info *bss_link = (struct bss_info *)arg; - - if (status!=OK) { - os_printf("wifiScanDoneCb status=%d\n", status); - cgiWifiAps.scanInProgress=0; - return; - } - - //Clear prev ap data if needed. - if (cgiWifiAps.apData!=NULL) { - for (n=0; nnext.stqe_next; - n++; - } - //Allocate memory for access point data - cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); - cgiWifiAps.noAps=n; - os_printf("Scan done: found %d APs\n", n); - - //Copy access point data to the static struct - n=0; - bss_link = (struct bss_info *)arg; - while (bss_link != NULL) { - 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. - os_printf("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); - break; - } - //Save the ap data. - cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); - cgiWifiAps.apData[n]->rssi=bss_link->rssi; - cgiWifiAps.apData[n]->enc=bss_link->authmode; - strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); - os_printf("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); - - bss_link = bss_link->next.stqe_next; - n++; - } - //We're done. - cgiWifiAps.scanInProgress=0; + int n; + struct bss_info *bss_link = (struct bss_info *)arg; + + if (status!=OK) { + os_printf("wifiScanDoneCb status=%d\n", status); + cgiWifiAps.scanInProgress=0; + return; + } + + //Clear prev ap data if needed. + if (cgiWifiAps.apData!=NULL) { + for (n=0; nnext.stqe_next; + n++; + } + //Allocate memory for access point data + cgiWifiAps.apData=(ApData **)os_malloc(sizeof(ApData *)*n); + cgiWifiAps.noAps=n; + os_printf("Scan done: found %d APs\n", n); + + //Copy access point data to the static struct + n=0; + bss_link = (struct bss_info *)arg; + while (bss_link != NULL) { + 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. + os_printf("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); + break; + } + //Save the ap data. + cgiWifiAps.apData[n]=(ApData *)os_malloc(sizeof(ApData)); + cgiWifiAps.apData[n]->rssi=bss_link->rssi; + cgiWifiAps.apData[n]->enc=bss_link->authmode; + strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); + os_printf("bss%d: %s (%d)\n", n+1, (char*)bss_link->ssid, bss_link->rssi); + + bss_link = bss_link->next.stqe_next; + n++; + } + //We're done. + cgiWifiAps.scanInProgress=0; } static ETSTimer scanTimer; static void ICACHE_FLASH_ATTR scanStartCb(void *arg) { - os_printf("Starting a scan\n"); - wifi_station_scan(NULL, wifiScanDoneCb); + os_printf("Starting a scan\n"); + wifi_station_scan(NULL, wifiScanDoneCb); } static int ICACHE_FLASH_ATTR cgiWiFiStartScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); - if (!cgiWifiAps.scanInProgress) { - cgiWifiAps.scanInProgress = 1; - os_timer_disarm(&scanTimer); - os_timer_setfn(&scanTimer, scanStartCb, NULL); - os_timer_arm(&scanTimer, 1000, 0); - } - return HTTPD_CGI_DONE; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); + if (!cgiWifiAps.scanInProgress) { + cgiWifiAps.scanInProgress = 1; + os_timer_disarm(&scanTimer); + os_timer_setfn(&scanTimer, scanStartCb, NULL); + os_timer_arm(&scanTimer, 1000, 0); + } + return HTTPD_CGI_DONE; } static int ICACHE_FLASH_ATTR cgiWiFiGetScan(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - char buff[2048]; - int len; - - jsonHeader(connData, 200); - - if (cgiWifiAps.scanInProgress==1) { - //We're still scanning. Tell Javascript code that. - len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; - } - - len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); - for (int pos=0; posssid, cgiWifiAps.apData[pos]->rssi, - cgiWifiAps.apData[pos]->enc, (pos==cgiWifiAps.noAps-1)?"":","); - } - len += os_sprintf(buff+len, "]}}\n"); - //os_printf("Sending %d bytes: %s\n", len, buff); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + char buff[2048]; + int len; + + jsonHeader(connData, 200); + + if (cgiWifiAps.scanInProgress==1) { + //We're still scanning. Tell Javascript code that. + len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; + } + + len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); + for (int pos=0; posssid, cgiWifiAps.apData[pos]->rssi, + cgiWifiAps.apData[pos]->enc, (pos==cgiWifiAps.noAps-1)?"":","); + } + len += os_sprintf(buff+len, "]}}\n"); + //os_printf("Sending %d bytes: %s\n", len, buff); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; } int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { - if (connData->requestType == HTTPD_METHOD_GET) { - return cgiWiFiGetScan(connData); - } else if (connData->requestType == HTTPD_METHOD_POST) { - return cgiWiFiStartScan(connData); - } else { - jsonHeader(connData, 404); - return HTTPD_CGI_DONE; - } + if (connData->requestType == HTTPD_METHOD_GET) { + return cgiWiFiGetScan(connData); + } else if (connData->requestType == HTTPD_METHOD_POST) { + return cgiWiFiStartScan(connData); + } else { + jsonHeader(connData, 404); + return HTTPD_CGI_DONE; + } } // ===== timers to change state and rescue from failed associations @@ -243,31 +243,31 @@ static ETSTimer resetTimer; // the connect succeeds, this gets the module in STA-only mode. If it fails, it ensures // that the module is in STA+AP mode so the user has a chance to recover. static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { - int x = wifi_station_get_connect_status(); - int m = wifi_get_opmode() & 0x3; - os_printf("Wifi check: mode=%s status=%d\n", wifiMode[m], x); + int x = wifi_station_get_connect_status(); + int m = wifi_get_opmode() & 0x3; + os_printf("Wifi check: mode=%s status=%d\n", wifiMode[m], x); - if (x == STATION_GOT_IP) { - if (m != 1) { + if (x == STATION_GOT_IP) { + if (m != 1) { #ifdef CHANGE_TO_STA - // We're happily connected, go to STA mode - os_printf("Wifi got IP. Going into STA mode..\n"); - wifi_set_opmode(1); - wifi_set_sleep_type(SLEEP_MODE); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + // We're happily connected, go to STA mode + os_printf("Wifi got IP. Going into STA mode..\n"); + wifi_set_opmode(1); + wifi_set_sleep_type(SLEEP_MODE); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); #endif - } - log_uart(false); - // no more resetTimer at this point, gotta use physical reset to recover if in trouble - } else { - if (m != 3) { - os_printf("Wifi connect failed. Going into STA+AP mode..\n"); - wifi_set_opmode(3); - } - log_uart(true); - os_printf("Enabling/continuing uart log\n"); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); - } + } + log_uart(false); + // no more resetTimer at this point, gotta use physical reset to recover if in trouble + } else { + if (m != 3) { + os_printf("Wifi connect failed. Going into STA+AP mode..\n"); + wifi_set_opmode(3); + } + log_uart(true); + os_printf("Enabling/continuing uart log\n"); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + } } // Temp store for new ap info. @@ -277,206 +277,206 @@ static ETSTimer reassTimer; // Callback actually doing reassociation static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { - os_printf("Wifi changing association\n"); - wifi_station_disconnect(); - stconf.bssid_set = 0; - wifi_station_set_config(&stconf); - wifi_station_connect(); - // Schedule check - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + os_printf("Wifi changing association\n"); + wifi_station_disconnect(); + stconf.bssid_set = 0; + wifi_station_set_config(&stconf); + wifi_station_connect(); + // Schedule check + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } // This cgi uses the routines above to connect to a specific access point with the // given ESSID using the given password. int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { - char essid[128]; - char passwd[128]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); - int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); - - if (el > 0 && pl >= 0) { - //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); - os_printf("Wifi try to connect to AP %s pw %s\n", essid, passwd); - - //Schedule disconnect/connect - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, reassTimerCb, NULL); - os_timer_arm(&reassTimer, 1000, 0); - jsonHeader(connData, 200); - } else { - jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse ssid or password", -1); - } - return HTTPD_CGI_DONE; + char essid[128]; + char passwd[128]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); + int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); + + if (el > 0 && pl >= 0) { + //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); + os_printf("Wifi try to connect to AP %s pw %s\n", essid, passwd); + + //Schedule disconnect/connect + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, reassTimerCb, NULL); + os_timer_arm(&reassTimer, 1000, 0); + jsonHeader(connData, 200); + } else { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse ssid or password", -1); + } + return HTTPD_CGI_DONE; } static bool parse_ip(char *buff, ip_addr_t *ip_ptr) { - char *next = buff; // where to start parsing next integer - int found = 0; // number of integers parsed - uint32_t ip = 0; // the ip addres parsed - for (int i=0; i<32; i++) { // 32 is just a safety limit - char c = buff[i]; - if (c == '.' || c == 0) { - // parse the preceding integer and accumulate into IP address - bool last = c == 0; - buff[i] = 0; - uint32_t v = atoi(next); - ip = ip | ((v&0xff)<<(found*8)); - next = buff+i+1; // next integer starts after the '.' - found++; - if (last) { // if at end of string we better got 4 integers - ip_ptr->addr = ip; - return found == 4; - } - continue; - } - if (c < '0' || c > '9') return false; - } - return false; + char *next = buff; // where to start parsing next integer + int found = 0; // number of integers parsed + uint32_t ip = 0; // the ip addres parsed + for (int i=0; i<32; i++) { // 32 is just a safety limit + char c = buff[i]; + if (c == '.' || c == 0) { + // parse the preceding integer and accumulate into IP address + bool last = c == 0; + buff[i] = 0; + uint32_t v = atoi(next); + ip = ip | ((v&0xff)<<(found*8)); + next = buff+i+1; // next integer starts after the '.' + found++; + if (last) { // if at end of string we better got 4 integers + ip_ptr->addr = ip; + return found == 4; + } + continue; + } + if (c < '0' || c > '9') return false; + } + return false; } #define DEBUGIP #ifdef DEBUGIP static void ICACHE_FLASH_ATTR debugIP() { - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); - os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); - os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); - os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); - } else { - os_printf("\"ip\": \"-none-\"\n"); - } + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr)); + os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr)); + os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr)); + os_printf("\"hostname\": \"%s\"\n", wifi_station_get_hostname()); + } else { + os_printf("\"ip\": \"-none-\"\n"); + } } #endif // configure Wifi, specifically DHCP vs static IP address based on flash config static void ICACHE_FLASH_ATTR configWifiIP() { - if (flashConfig.staticip == 0) { - // let's DHCP! - wifi_station_set_hostname(flashConfig.hostname); - if (wifi_station_dhcpc_status() == DHCP_STARTED) - wifi_station_dhcpc_stop(); - wifi_station_dhcpc_start(); - os_printf("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); - } else { - // no DHCP, we got static network config! - wifi_station_dhcpc_stop(); - struct ip_info ipi; - ipi.ip.addr = flashConfig.staticip; - ipi.netmask.addr = flashConfig.netmask; - ipi.gw.addr = flashConfig.gateway; - wifi_set_ip_info(0, &ipi); - os_printf("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); - } + if (flashConfig.staticip == 0) { + // let's DHCP! + wifi_station_set_hostname(flashConfig.hostname); + if (wifi_station_dhcpc_status() == DHCP_STARTED) + wifi_station_dhcpc_stop(); + wifi_station_dhcpc_start(); + os_printf("Wifi uses DHCP, hostname=%s\n", flashConfig.hostname); + } else { + // no DHCP, we got static network config! + wifi_station_dhcpc_stop(); + struct ip_info ipi; + ipi.ip.addr = flashConfig.staticip; + ipi.netmask.addr = flashConfig.netmask; + ipi.gw.addr = flashConfig.gateway; + wifi_set_ip_info(0, &ipi); + os_printf("Wifi uses static IP %d.%d.%d.%d\n", IP2STR(&ipi.ip.addr)); + } #ifdef DEBUGIP - debugIP(); + debugIP(); #endif } // Change special settings int ICACHE_FLASH_ATTR cgiWiFiSpecial(HttpdConnData *connData) { - char dhcp[8]; - char hostname[32]; - char staticip[20]; - char netmask[20]; - char gateway[20]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; - - // get args and their string lengths - int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); - int hl = httpdFindArg(connData->getArgs, "hostname", hostname, sizeof(hostname)); - int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); - int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); - int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); - - if (!(dl > 0 && hl >= 0 && sl >= 0 && nl >= 0 && gl >= 0)) { - jsonHeader(connData, 400); - httpdSend(connData, "Request is missing fields", -1); - return HTTPD_CGI_DONE; - } - - char url[64]; // redirect URL - if (os_strcmp(dhcp, "off") == 0) { - // parse static IP params - struct ip_info ipi; - bool ok = parse_ip(staticip, &ipi.ip); - if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); - else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); - if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); - else ipi.gw.addr = 0; - if (!ok) { - jsonHeader(connData, 400); - httpdSend(connData, "Cannot parse static IP config", -1); - return HTTPD_CGI_DONE; - } - // save the params in flash - flashConfig.staticip = ipi.ip.addr; - flashConfig.netmask = ipi.netmask.addr; - flashConfig.gateway = ipi.gw.addr; - // construct redirect URL - os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); - - } else { - // no static IP, set hostname - if (hl == 0) os_strcpy(hostname, "esp-link"); - flashConfig.staticip = 0; - os_strcpy(flashConfig.hostname, hostname); - os_sprintf(url, "{\"url\": \"http://%s\"}", hostname); - } - - configSave(); // ignore error... - // schedule change-over - os_timer_disarm(&reassTimer); - os_timer_setfn(&reassTimer, configWifiIP, NULL); - os_timer_arm(&reassTimer, 1000, 0); - // return redirect info - jsonHeader(connData, 200); - httpdSend(connData, url, -1); - return HTTPD_CGI_DONE; + char dhcp[8]; + char hostname[32]; + char staticip[20]; + char netmask[20]; + char gateway[20]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; + + // get args and their string lengths + int dl = httpdFindArg(connData->getArgs, "dhcp", dhcp, sizeof(dhcp)); + int hl = httpdFindArg(connData->getArgs, "hostname", hostname, sizeof(hostname)); + int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip)); + int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask)); + int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway)); + + if (!(dl > 0 && hl >= 0 && sl >= 0 && nl >= 0 && gl >= 0)) { + jsonHeader(connData, 400); + httpdSend(connData, "Request is missing fields", -1); + return HTTPD_CGI_DONE; + } + + char url[64]; // redirect URL + if (os_strcmp(dhcp, "off") == 0) { + // parse static IP params + struct ip_info ipi; + bool ok = parse_ip(staticip, &ipi.ip); + if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask); + else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0); + if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw); + else ipi.gw.addr = 0; + if (!ok) { + jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse static IP config", -1); + return HTTPD_CGI_DONE; + } + // save the params in flash + flashConfig.staticip = ipi.ip.addr; + flashConfig.netmask = ipi.netmask.addr; + flashConfig.gateway = ipi.gw.addr; + // construct redirect URL + os_sprintf(url, "{\"url\": \"http://%d.%d.%d.%d\"}", IP2STR(&ipi.ip)); + + } else { + // no static IP, set hostname + if (hl == 0) os_strcpy(hostname, "esp-link"); + flashConfig.staticip = 0; + os_strcpy(flashConfig.hostname, hostname); + os_sprintf(url, "{\"url\": \"http://%s\"}", hostname); + } + + configSave(); // ignore error... + // schedule change-over + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, configWifiIP, NULL); + os_timer_arm(&reassTimer, 1000, 0); + // return redirect info + jsonHeader(connData, 200); + httpdSend(connData, url, -1); + return HTTPD_CGI_DONE; } //This cgi changes the operating mode: STA / AP / STA+AP int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { - int len; - char buff[1024]; - - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - - len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); - if (len!=0) { - int m = atoi(buff); - os_printf("Wifi switching to mode %d\n", m); - wifi_set_opmode(m&3); - if (m == 1) { - wifi_set_sleep_type(SLEEP_MODE); - // STA-only mode, reset into STA+AP after a timeout - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); - } - jsonHeader(connData, 200); - } else { - jsonHeader(connData, 400); - } - return HTTPD_CGI_DONE; + int len; + char buff[1024]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); + if (len!=0) { + int m = atoi(buff); + os_printf("Wifi switching to mode %d\n", m); + wifi_set_opmode(m&3); + if (m == 1) { + wifi_set_sleep_type(SLEEP_MODE); + // STA-only mode, reset into STA+AP after a timeout + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + } + jsonHeader(connData, 200); + } else { + jsonHeader(connData, 400); + } + return HTTPD_CGI_DONE; } static char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found", "failed", "got IP address" }; static char *wifiWarn[] = { 0, - "Switch to STA+AP mode", - "Can't scan in this mode! Switch to STA+AP mode", - "Switch to STA mode", + "Switch to STA+AP mode", + "Can't scan in this mode! Switch to STA+AP mode", + "Switch to STA mode", }; #ifdef CHANGE_TO_STA @@ -487,109 +487,109 @@ static char *wifiWarn[] = { 0, // print various Wifi information into json buffer int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { - int len; - - struct station_config stconf; - wifi_station_get_config(&stconf); - - uint8_t op = wifi_get_opmode() & 0x3; - char *mode = wifiMode[op]; - char *status = "unknown"; - int st = wifi_station_get_connect_status(); - if (st >= 0 && st < sizeof(connStatuses)) status = connStatuses[st]; - int p = wifi_get_phy_mode(); - char *phy = wifiPhy[p&3]; - char *warn = wifiWarn[op]; - sint8 rssi = wifi_station_get_rssi(); - if (rssi > 0) rssi = 0; - uint8 mac_addr[6]; - wifi_get_macaddr(0, mac_addr); - uint8_t chan = wifi_get_channel(); - - len = os_sprintf(buff, - "\"mode\": \"%s\", \"modechange\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " - "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\", \"chan\":%d", - mode, MODECHANGE, (char*)stconf.ssid, status, phy, rssi, warn, - mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], chan); - - struct ip_info info; - if (wifi_get_ip_info(0, &info)) { - len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr)); - len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr)); - len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr)); - len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname); - } else { - len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); - } - len += os_sprintf(buff+len, ", \"staticip\": \"%d.%d.%d.%d\"", IP2STR(&flashConfig.staticip)); - len += os_sprintf(buff+len, ", \"dhcp\": \"%s\"", flashConfig.staticip > 0 ? "off" : "on"); - - return len; + int len; + + struct station_config stconf; + wifi_station_get_config(&stconf); + + uint8_t op = wifi_get_opmode() & 0x3; + char *mode = wifiMode[op]; + char *status = "unknown"; + int st = wifi_station_get_connect_status(); + if (st >= 0 && st < sizeof(connStatuses)) status = connStatuses[st]; + int p = wifi_get_phy_mode(); + char *phy = wifiPhy[p&3]; + char *warn = wifiWarn[op]; + sint8 rssi = wifi_station_get_rssi(); + if (rssi > 0) rssi = 0; + uint8 mac_addr[6]; + wifi_get_macaddr(0, mac_addr); + uint8_t chan = wifi_get_channel(); + + len = os_sprintf(buff, + "\"mode\": \"%s\", \"modechange\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " + "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\", \"chan\":%d", + mode, MODECHANGE, (char*)stconf.ssid, status, phy, rssi, warn, + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5], chan); + + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr)); + len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr)); + len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr)); + len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname); + } else { + len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); + } + len += os_sprintf(buff+len, ", \"staticip\": \"%d.%d.%d.%d\"", IP2STR(&flashConfig.staticip)); + len += os_sprintf(buff+len, ", \"dhcp\": \"%s\"", flashConfig.staticip > 0 ? "off" : "on"); + + return len; } int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { - char buff[1024]; - int len; + char buff[1024]; + int len; - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - jsonHeader(connData, 200); + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + jsonHeader(connData, 200); - len = os_sprintf(buff, "{"); - len += printWifiInfo(buff+len); - len += os_sprintf(buff+len, ", "); + len = os_sprintf(buff, "{"); + len += printWifiInfo(buff+len); + len += os_sprintf(buff+len, ", "); - if (wifiReason != 0) { - len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); - } + if (wifiReason != 0) { + len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); + } #if 0 - // commented out 'cause often the client that requested the change can't get a request in to - // find out that it succeeded. Better to just wait the std 15 seconds... - int st=wifi_station_get_connect_status(); - if (st == STATION_GOT_IP) { - if (wifi_get_opmode() != 1) { - // Reset into AP-only mode sooner. - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, 1000, 0); - } - } + // commented out 'cause often the client that requested the change can't get a request in to + // find out that it succeeded. Better to just wait the std 15 seconds... + int st=wifi_station_get_connect_status(); + if (st == STATION_GOT_IP) { + if (wifi_get_opmode() != 1) { + // Reset into AP-only mode sooner. + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 1000, 0); + } + } #endif - len += os_sprintf(buff+len, "\"x\":0}\n"); + len += os_sprintf(buff+len, "\"x\":0}\n"); - os_printf(" -> %s\n", buff); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + os_printf(" -> %s\n", buff); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; } // Cgi to return various Wifi information int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { - char buff[1024]; + char buff[1024]; - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - os_strcpy(buff, "{"); - printWifiInfo(buff+1); - os_strcat(buff, "}"); + os_strcpy(buff, "{"); + printWifiInfo(buff+1); + os_strcat(buff, "}"); - jsonHeader(connData, 200); - httpdSend(connData, buff, -1); - return HTTPD_CGI_DONE; + jsonHeader(connData, 200); + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; } // Init the wireless, which consists of setting a timer if we expect to connect to an AP // so we can revert to STA+AP mode if we can't connect. void ICACHE_FLASH_ATTR wifiInit() { - wifi_set_phy_mode(2); - int x = wifi_get_opmode() & 0x3; - os_printf("Wifi init, mode=%s\n", wifiMode[x]); - configWifiIP(); - - wifi_set_event_handler_cb(wifiHandleEventCb); - // check on the wifi in a few seconds to see whether we need to switch mode - os_timer_disarm(&resetTimer); - os_timer_setfn(&resetTimer, resetTimerCb, NULL); - os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); + wifi_set_phy_mode(2); + int x = wifi_get_opmode() & 0x3; + os_printf("Wifi init, mode=%s\n", wifiMode[x]); + configWifiIP(); + + wifi_set_event_handler_cb(wifiHandleEventCb); + // check on the wifi in a few seconds to see whether we need to switch mode + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, RESET_TIMEOUT, 0); } From 9e4cbb0dbd49ef7f692d19f34b86ef216625ee47 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Mon, 7 Sep 2015 19:53:23 -0700 Subject: [PATCH 4/6] massive rework of MQTT --- Makefile | 2 +- cmd/handlers.c | 2 +- cmd/mqtt_cmd.c | 47 ++- cmd/mqtt_cmd.h | 1 - cmd/rest.c | 12 +- esp-link/cgipins.c | 46 +-- esp-link/main.c | 12 +- esp-link/status.c | 176 ++++---- html/console.html | 2 +- httpd/httpd.c | 2 +- include/user_config.h | 18 +- mqtt/mqtt.c | 924 ++++++++++++++++++++++++------------------ mqtt/mqtt.h | 171 ++++---- mqtt/mqtt_msg.c | 51 +-- mqtt/mqtt_msg.h | 48 ++- mqtt/pktbuf.c | 64 +++ mqtt/pktbuf.h | 29 ++ mqtt/proto.c | 86 ---- mqtt/proto.h | 21 - mqtt/queue.c | 53 --- mqtt/queue.h | 46 --- mqtt/ringbuf.c | 63 --- mqtt/ringbuf.h | 17 - serial/serbridge.c | 1 + serial/serled.h | 1 - serial/uart.c | 2 +- user/user_main.c | 59 ++- 27 files changed, 946 insertions(+), 1010 deletions(-) create mode 100644 mqtt/pktbuf.c create mode 100644 mqtt/pktbuf.h delete mode 100644 mqtt/proto.c delete mode 100644 mqtt/proto.h delete mode 100644 mqtt/queue.c delete mode 100644 mqtt/queue.h delete mode 100644 mqtt/ringbuf.c delete mode 100644 mqtt/ringbuf.h diff --git a/Makefile b/Makefile index 7f47c20..98a8361 100644 --- a/Makefile +++ b/Makefile @@ -147,7 +147,7 @@ MODULES = espfs httpd user serial cmd mqtt esp-link EXTRA_INCDIR = include . # libraries used in this project, mainly provided by the SDK -LIBS = c gcc hal phy pp net80211 wpa main lwip +LIBS = c gcc hal phy pp net80211 wpa main lwip # crypto ssl # compiler flags using during compilation of source files CFLAGS = -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ diff --git a/cmd/handlers.c b/cmd/handlers.c index b54773f..e20686c 100644 --- a/cmd/handlers.c +++ b/cmd/handlers.c @@ -95,7 +95,7 @@ cmdCallback* ICACHE_FLASH_ATTR CMD_GetCbByName(char* name) { char checkname[16]; os_strncpy(checkname, name, sizeof(checkname)); - for (uint8_t i = 0; i < sizeof(commands); i++) { + for (uint8_t i = 0; i < MAX_CALLBACKS; i++) { //os_printf("CMD_GetCbByName: index %d name=%s cb=%p\n", i, callbacks[i].name, // (void *)callbacks[i].callback); // if callback doesn't exist or it's null diff --git a/cmd/mqtt_cmd.c b/cmd/mqtt_cmd.c index 358ad48..d2a01e2 100644 --- a/cmd/mqtt_cmd.c +++ b/cmd/mqtt_cmd.c @@ -1,8 +1,10 @@ +#include +#include "mqtt.h" #include "mqtt_cmd.h" uint32_t connectedCb = 0, disconnectCb = 0, tcpDisconnectedCb = 0, publishedCb = 0, dataCb = 0; -void ICACHE_FLASH_ATTR +void ICACHE_FLASH_ATTR cmdMqttConnectedCb(uint32_t* args) { MQTT_Client* client = (MQTT_Client*)args; MqttCmdCb* cb = (MqttCmdCb*)client->user_data; @@ -24,7 +26,7 @@ cmdMqttTcpDisconnectedCb(uint32_t *args) { CMD_ResponseEnd(crc); } -void ICACHE_FLASH_ATTR +void ICACHE_FLASH_ATTR cmdMqttDisconnectedCb(uint32_t* args) { MQTT_Client* client = (MQTT_Client*)args; MqttCmdCb* cb = (MqttCmdCb*)client->user_data; @@ -33,7 +35,7 @@ cmdMqttDisconnectedCb(uint32_t* args) { CMD_ResponseEnd(crc); } -void ICACHE_FLASH_ATTR +void ICACHE_FLASH_ATTR cmdMqttPublishedCb(uint32_t* args) { MQTT_Client* client = (MQTT_Client*)args; MqttCmdCb* cb = (MqttCmdCb*)client->user_data; @@ -42,7 +44,7 @@ cmdMqttPublishedCb(uint32_t* args) { CMD_ResponseEnd(crc); } -void ICACHE_FLASH_ATTR +void ICACHE_FLASH_ATTR cmdMqttDataCb(uint32_t* args, const char* topic, uint32_t topic_len, const char* data, uint32_t data_len) { uint16_t crc = 0; MQTT_Client* client = (MQTT_Client*)args; @@ -54,7 +56,7 @@ cmdMqttDataCb(uint32_t* args, const char* topic, uint32_t topic_len, const char* CMD_ResponseEnd(crc); } -uint32_t ICACHE_FLASH_ATTR +uint32_t ICACHE_FLASH_ATTR MQTTCMD_Setup(CmdPacket *cmd) { CmdRequest req; CMD_Request(&req, cmd); @@ -65,10 +67,12 @@ MQTTCMD_Setup(CmdPacket *cmd) { // create mqtt client uint8_t clientLen = sizeof(MQTT_Client); MQTT_Client* client = (MQTT_Client*)os_zalloc(clientLen); - if (client == NULL) - return 0; + if (client == NULL) return 0; os_memset(client, 0, clientLen); + return 0; +#if 0 + uint16_t len; uint8_t *client_id, *user_data, *pass_data; uint32_t keepalive, clean_session, cb_data; @@ -102,7 +106,7 @@ MQTTCMD_Setup(CmdPacket *cmd) { 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); - // init client + // init client // TODO: why malloc these all here, pass to MQTT_InitClient to be malloc'd again? MQTT_InitClient(client, (char*)client_id, (char*)user_data, (char*)pass_data, keepalive, clean_session); @@ -112,11 +116,11 @@ MQTTCMD_Setup(CmdPacket *cmd) { CMD_PopArg(&req, (uint8_t*)&cb_data, 4); callback->connectedCb = cb_data; CMD_PopArg(&req, (uint8_t*)&cb_data, 4); - callback->disconnectedCb = cb_data; + callback->disconnectedCb = cb_data; CMD_PopArg(&req, (uint8_t*)&cb_data, 4); callback->publishedCb = cb_data; CMD_PopArg(&req, (uint8_t*)&cb_data, 4); - callback->dataCb = cb_data; + callback->dataCb = cb_data; client->user_data = callback; @@ -136,9 +140,10 @@ MQTTCMD_Setup(CmdPacket *cmd) { os_free(pass_data); return (uint32_t)client; +#endif } -uint32_t ICACHE_FLASH_ATTR +uint32_t ICACHE_FLASH_ATTR MQTTCMD_Lwt(CmdPacket *cmd) { CmdRequest req; CMD_Request(&req, cmd); @@ -153,7 +158,7 @@ MQTTCMD_Lwt(CmdPacket *cmd) { os_printf("MQTT: MQTTCMD_Lwt client ptr=%p\n", (void*)client_ptr); uint16_t len; - + // get topic if (client->connect_info.will_topic) os_free(client->connect_info.will_topic); @@ -174,7 +179,7 @@ MQTTCMD_Lwt(CmdPacket *cmd) { // get qos CMD_PopArg(&req, (uint8_t*)&client->connect_info.will_qos, 4); - + // get retain CMD_PopArg(&req, (uint8_t*)&client->connect_info.will_retain, 4); @@ -186,13 +191,13 @@ MQTTCMD_Lwt(CmdPacket *cmd) { return 1; } -uint32_t ICACHE_FLASH_ATTR +uint32_t ICACHE_FLASH_ATTR MQTTCMD_Connect(CmdPacket *cmd) { CmdRequest req; CMD_Request(&req, cmd); if (CMD_GetArgc(&req) != 4) - return 0; + return 0; // get mqtt client uint32_t client_ptr; @@ -202,7 +207,7 @@ MQTTCMD_Connect(CmdPacket *cmd) { uint16_t len; - // get host + // get host if (client->host) os_free(client->host); len = CMD_ArgLen(&req); @@ -217,7 +222,7 @@ MQTTCMD_Connect(CmdPacket *cmd) { // get security CMD_PopArg(&req, (uint8_t*)&client->security, 4); - os_printf("MQTT: MQTTCMD_Connect host=%s, port=%ld, security=%d\n", + os_printf("MQTT: MQTTCMD_Connect host=%s, port=%d, security=%d\n", client->host, client->port, client->security); @@ -226,7 +231,7 @@ MQTTCMD_Connect(CmdPacket *cmd) { return 1; } -uint32_t ICACHE_FLASH_ATTR +uint32_t ICACHE_FLASH_ATTR MQTTCMD_Disconnect(CmdPacket *cmd) { CmdRequest req; CMD_Request(&req, cmd); @@ -245,7 +250,7 @@ MQTTCMD_Disconnect(CmdPacket *cmd) { return 1; } -uint32_t ICACHE_FLASH_ATTR +uint32_t ICACHE_FLASH_ATTR MQTTCMD_Publish(CmdPacket *cmd) { CmdRequest req; CMD_Request(&req, cmd); @@ -279,7 +284,7 @@ MQTTCMD_Publish(CmdPacket *cmd) { // TODO: next line not originally present data[len] = 0; - // get data length + // get data length // TODO: this isn't used but we have to pull it off the stack CMD_PopArg(&req, (uint8_t*)&data_len, 4); @@ -301,7 +306,7 @@ MQTTCMD_Publish(CmdPacket *cmd) { return 1; } -uint32_t ICACHE_FLASH_ATTR +uint32_t ICACHE_FLASH_ATTR MQTTCMD_Subscribe(CmdPacket *cmd) { CmdRequest req; CMD_Request(&req, cmd); diff --git a/cmd/mqtt_cmd.h b/cmd/mqtt_cmd.h index 9ccbd08..72ffe98 100644 --- a/cmd/mqtt_cmd.h +++ b/cmd/mqtt_cmd.h @@ -2,7 +2,6 @@ #define MODULES_MQTT_CMD_H_ #include "cmd.h" -#include "mqtt.h" typedef struct { uint32_t connectedCb; diff --git a/cmd/rest.c b/cmd/rest.c index 3556681..2c8d606 100644 --- a/cmd/rest.c +++ b/cmd/rest.c @@ -154,12 +154,12 @@ rest_dns_found(const char *name, ip_addr_t *ipaddr, void *arg) { if(client->ip.addr == 0 && ipaddr->addr != 0) { os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4); - //if(client->security){ - // espconn_secure_connect(client->pCon); - //} - //else { +#ifdef CLIENT_SSL_ENABLE + if(client->security) { + espconn_secure_connect(client->pCon); + } else +#endif espconn_connect(client->pCon); - //} os_printf("REST: connecting...\n"); } } @@ -368,6 +368,8 @@ REST_Request(CmdPacket *cmd) { } os_printf("\n"); + //os_printf("REST request: %s", (char*)client->data); + os_printf("REST: pCon state=%d\n", client->pCon->state); client->pCon->state = ESPCONN_NONE; espconn_regist_connectcb(client->pCon, tcpclient_connect_cb); diff --git a/esp-link/cgipins.c b/esp-link/cgipins.c index 2d71849..dabc1fd 100644 --- a/esp-link/cgipins.c +++ b/esp-link/cgipins.c @@ -24,9 +24,9 @@ static const int num_map_func = sizeof(map_func)/sizeof(char*); // Cgi to return choice of pin assignments int ICACHE_FLASH_ATTR cgiPinsGet(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted - char buff[2048]; + char buff[2048]; int len; // figure out current mapping @@ -62,27 +62,27 @@ int ICACHE_FLASH_ATTR cgiPinsGet(HttpdConnData *connData) { } len += os_sprintf(buff+len, "\n] }"); - jsonHeader(connData, 200); - httpdSend(connData, buff, len); - return HTTPD_CGI_DONE; + jsonHeader(connData, 200); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; } // Cgi to change choice of pin assignments int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) { - if (connData->conn==NULL) { - return HTTPD_CGI_DONE; // Connection aborted - } + if (connData->conn==NULL) { + return HTTPD_CGI_DONE; // Connection aborted + } char buff[128]; - int len = httpdFindArg(connData->getArgs, "map", buff, sizeof(buff)); - if (len <= 0) { - jsonHeader(connData, 400); + int len = httpdFindArg(connData->getArgs, "map", buff, sizeof(buff)); + if (len <= 0) { + jsonHeader(connData, 400); return HTTPD_CGI_DONE; } int m = atoi(buff); - if (m < 0 || m >= num_map_names) { - jsonHeader(connData, 400); + if (m < 0 || m >= num_map_names) { + jsonHeader(connData, 400); return HTTPD_CGI_DONE; } @@ -106,17 +106,17 @@ int ICACHE_FLASH_ATTR cgiPinsSet(HttpdConnData *connData) { httpdEndHeaders(connData); httpdSend(connData, "Failed to save config", -1); } - return HTTPD_CGI_DONE; + return HTTPD_CGI_DONE; } int ICACHE_FLASH_ATTR cgiPins(HttpdConnData *connData) { - if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. - if (connData->requestType == HTTPD_METHOD_GET) { - return cgiPinsGet(connData); - } else if (connData->requestType == HTTPD_METHOD_POST) { - return cgiPinsSet(connData); - } else { - jsonHeader(connData, 404); - return HTTPD_CGI_DONE; - } + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + if (connData->requestType == HTTPD_METHOD_GET) { + return cgiPinsGet(connData); + } else if (connData->requestType == HTTPD_METHOD_POST) { + return cgiPinsSet(connData); + } else { + jsonHeader(connData, 404); + return HTTPD_CGI_DONE; + } } diff --git a/esp-link/main.c b/esp-link/main.c index 5febf87..12d715e 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -29,7 +29,7 @@ #include "log.h" #include -//#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 @@ -120,13 +120,16 @@ static char *rst_codes[] = { # define VERS_STR(V) VERS_STR_STR(V) char* esp_link_version = VERS_STR(VERSION); -//Main routine. Initialize stdout, the I/O, filesystem and the webserver and we're done. +extern void app_init(void); + +// Main routine to initialize esp-link. void user_init(void) { // get the flash config so we know how to init things //configWipe(); // uncomment to reset the config for testing purposes bool restoreOk = configRestore(); // init gpio pin registers gpio_init(); + gpio_output_set(0, 0, 0, (1<<15)); // some people tie it GND, gotta ensure it's disabled // init UART uart_init(flashConfig.baud_rate, 115200); logInit(); // must come after init of uart @@ -163,6 +166,5 @@ void user_init(void) { os_printf("** esp-link ready\n"); - // call user_main init - init(); -} \ No newline at end of file + app_init(); +} diff --git a/esp-link/status.c b/esp-link/status.c index a6080fe..4e0da55 100644 --- a/esp-link/status.c +++ b/esp-link/status.c @@ -14,56 +14,56 @@ static ETSTimer ledTimer; static void ICACHE_FLASH_ATTR setLed(int on) { int8_t pin = flashConfig.conn_led_pin; if (pin < 0) return; // disabled - // LED is active-low - if (on) { - gpio_output_set(0, (1<= 0) return; // not connected or other error - - // compose TCP command - uint8_t chan = MAX_TCP_CHAN-1; - tcpClientCommand(chan, 'T', "grovestreams.com:80"); - - // compose http header - char buf[1024]; - int hdrLen = os_sprintf(buf, - "PUT /api/feed?api_key=%s HTTP/1.0\r\n" - "Content-Type: application/json\r\n" - "Content-Length: XXXXX\r\n\r\n", - flashConfig.api_key); - - // http body - int dataLen = os_sprintf(buf+hdrLen, - "[{\"compId\":\"%s\", \"streamId\":\"%s\", \"data\":%d}]\r", - flashConfig.hostname, GS_STREAM, rssi); - buf[hdrLen+dataLen++] = 0; - buf[hdrLen+dataLen++] = '\n'; - - // hackish way to fill in the content-length - os_sprintf(buf+hdrLen-9, "%5d", dataLen); - buf[hdrLen-4] = '\r'; // fix-up the \0 inserted by sprintf (hack!) - - // send the request off and forget about it... - for (short i=0; i= 0) return; // not connected or other error + + // compose TCP command + uint8_t chan = MAX_TCP_CHAN-1; + tcpClientCommand(chan, 'T', "grovestreams.com:80"); + + // compose http header + char buf[1024]; + int hdrLen = os_sprintf(buf, + "PUT /api/feed?api_key=%s HTTP/1.0\r\n" + "Content-Type: application/json\r\n" + "Content-Length: XXXXX\r\n\r\n", + flashConfig.api_key); + + // http body + int dataLen = os_sprintf(buf+hdrLen, + "[{\"compId\":\"%s\", \"streamId\":\"%s\", \"data\":%d}]\r", + flashConfig.hostname, GS_STREAM, rssi); + buf[hdrLen+dataLen++] = 0; + buf[hdrLen+dataLen++] = '\n'; + + // hackish way to fill in the content-length + os_sprintf(buf+hdrLen-9, "%5d", dataLen); + buf[hdrLen-4] = '\r'; // fix-up the \0 inserted by sprintf (hack!) + + // send the request off and forget about it... + for (short i=0; i= 0) { - makeGpio(flashConfig.conn_led_pin); - setLed(1); - } - os_printf("CONN led=%d\n", flashConfig.conn_led_pin); - - os_timer_disarm(&ledTimer); - os_timer_setfn(&ledTimer, ledTimerCb, NULL); - os_timer_arm(&ledTimer, 2000, 0); - - os_timer_disarm(&rssiTimer); - os_timer_setfn(&rssiTimer, rssiTimerCb, NULL); - os_timer_arm(&rssiTimer, RSSI_INTERVAL, 1); // recurring timer + if (flashConfig.conn_led_pin >= 0) { + makeGpio(flashConfig.conn_led_pin); + setLed(1); + } + os_printf("CONN led=%d\n", flashConfig.conn_led_pin); + + os_timer_disarm(&ledTimer); + os_timer_setfn(&ledTimer, ledTimerCb, NULL); + os_timer_arm(&ledTimer, 2000, 0); + + os_timer_disarm(&rssiTimer); + os_timer_setfn(&rssiTimer, rssiTimerCb, NULL); + os_timer_arm(&rssiTimer, RSSI_INTERVAL, 1); // recurring timer } diff --git a/html/console.html b/html/console.html index db4c0a6..9dc359c 100644 --- a/html/console.html +++ b/html/console.html @@ -20,7 +20,7 @@ + diff --git a/html/style.css b/html/style.css index 29d15a3..ca072d8 100644 --- a/html/style.css +++ b/html/style.css @@ -3,6 +3,10 @@ html, button, input, select, textarea, .pure-g [class *= "pure-u"] { font-family: sans-serif; } +input[type="text"], input[type="password"] { + width: 100%; +} + body { color: #777; } diff --git a/html/ui.js b/html/ui.js index 56cc256..2a4e20e 100644 --- a/html/ui.js +++ b/html/ui.js @@ -374,11 +374,11 @@ function changeTcpClient(e) { addClass(cb, 'pure-button-disabled'); ajaxSpin("POST", url, function(resp) { removeClass(cb, 'pure-button-disabled'); - getWifiInfo(); + fetchTcpClient(); }, function(s, st) { showWarning("Error: "+st); removeClass(cb, 'pure-button-disabled'); - getWifiInfo(); + fetchTcpClient(); }); } @@ -394,4 +394,69 @@ function fetchTcpClient() { }); } +//===== MQTT cards + +function changeMqtt(e) { + e.preventDefault(); + var url = "mqtt?1=1"; + var i, inputs = $("input"); + for (i=0; i 0; + else el.value = data[v]; + } + }); + $("#mqtt-spinner").setAttribute("hidden", ""); + $("#mqtt-status-spinner").setAttribute("hidden", ""); + $("#mqtt-form").removeAttribute("hidden"); + $("#mqtt-status-form").removeAttribute("hidden"); + + var i, inputs = $("input"); + for (i=0; ipending_buffer->data, client->pending_buffer->filled); } - os_printf("MQTT: Recv type=%d id=%04X len=%d; Pend type=%d id=%02X\n", - msg_type, msg_id, msg_len, pending_msg_type, pending_msg_id); + 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); switch (msg_type) { case MQTT_MSG_TYPE_CONNACK: @@ -177,7 +182,7 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) { case MQTT_MSG_TYPE_PUBREC: // rec for a publish we sent if (pending_msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg_id == msg_id) { - os_printf("MQTT: Recv PUBREC, cont QoS2 publish\n"); + os_printf("MQTT: QoS2 publish cont\n"); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); // we need to send PUBREL mqtt_msg_pubrel(&client->mqtt_connection, msg_id); @@ -202,7 +207,6 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) { 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) { - os_printf("MQTT: Queue response QoS: %d\n", msg_qos); mqtt_enq_message(client, client->mqtt_connection.message.data, client->mqtt_connection.message.length); } @@ -213,7 +217,7 @@ 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) { - os_printf("MQTT: Recv PUBREL, cont QoS2 recv\n"); + os_printf("MQTT: Cont QoS2 recv\n"); client->pending_buffer = PktBuf_ShiftFree(client->pending_buffer); // we need to send PUBCOMP mqtt_msg_pubcomp(&client->mqtt_connection, msg_id); @@ -223,7 +227,6 @@ mqtt_tcpclient_recv(void* arg, char* pdata, unsigned short len) { break; case MQTT_MSG_TYPE_PINGRESP: - os_printf("MQTT: Recv PINGRESP\n"); client->keepAliveAckTick = 0; break; } @@ -299,7 +302,7 @@ mqtt_timer(void* arg) { // check whether we need to send a keep-alive message if (client->keepAliveTick > 0 && --client->keepAliveTick == 0) { // timeout: we need to send a ping message - os_printf("MQTT: Send keepalive to %s:%d\n", client->host, client->port); + //os_printf("MQTT: Send keepalive\n"); mqtt_msg_pingreq(&client->mqtt_connection); PktBuf *buf = PktBuf_New(client->mqtt_connection.message.length); os_memcpy(buf->data, client->mqtt_connection.message.data, @@ -432,7 +435,7 @@ 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); - os_printf("MQTT: Send type=%d, id=%04X len=%d\n", msg_type, msg_id, buf->filled); + os_printf("MQTT: Send type=%s id=%04X len=%d\n", mqtt_msg_type[msg_type], msg_id, buf->filled); #if 0 for (int i=0; ifilled; i++) { if (buf->data[i] >= ' ' && buf->data[i] <= '~') os_printf("%c", buf->data[i]); From c1ed3695a9e7a33ef1a08a82d39f54af8de3dead Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Tue, 8 Sep 2015 23:24:49 -0700 Subject: [PATCH 6/6] server-side handling of MQTT web page --- esp-link/cgi.c | 52 +++++++++++++++++++++++++++-- esp-link/cgi.h | 3 ++ esp-link/cgimqtt.c | 66 ++++++++++++++++++++++++------------ html/mqtt.html | 10 +++--- html/ui.js | 83 ++++++++++++++++++++++++++-------------------- httpd/httpd.c | 2 +- serial/serbridge.c | 14 ++++++++ serial/slip.c | 19 ++--------- serial/slip.h | 6 ++++ 9 files changed, 173 insertions(+), 82 deletions(-) create mode 100644 serial/slip.h diff --git a/esp-link/cgi.c b/esp-link/cgi.c index 3a37347..bfb7028 100644 --- a/esp-link/cgi.c +++ b/esp-link/cgi.c @@ -18,16 +18,64 @@ Some random cgi routines. #include "cgi.h" #include "espfs.h" -void ICACHE_FLASH_ATTR -jsonHeader(HttpdConnData *connData, int code) { +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"); +} + +void ICACHE_FLASH_ATTR +jsonHeader(HttpdConnData *connData, int code) { + noCacheHeaders(connData, code); httpdHeader(connData, "Content-Type", "application/json"); httpdEndHeaders(connData); } +void ICACHE_FLASH_ATTR +errorResponse(HttpdConnData *connData, int code, char *message) { + noCacheHeaders(connData, code); + httpdEndHeaders(connData); + httpdSend(connData, message, -1); + os_printf("HTTP %d error response: \"%s\"\n", code, message); +} + +// look for the HTTP arg 'name' and store it at 'config' with max length 'max_len' (incl +// terminating zero), returns -1 on error, 0 if not found, 1 if found and OK +int ICACHE_FLASH_ATTR +getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) { + char buff[128]; + int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); + if (len < 0) return 0; // not found, skip + if (len >= 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; +} + +int ICACHE_FLASH_ATTR +getBoolArg(HttpdConnData *connData, char *name, bool*config) { + char buff[64]; + int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff)); + if (len < 0) return 0; // not found, skip + + if (strcmp(buff, "1") == 0 || strcmp(buff, "true") == 0) { + *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; +} + + #define TOKEN(x) (os_strcmp(token, x) == 0) #if 0 // Handle system information variables and print their value, returns the number of diff --git a/esp-link/cgi.h b/esp-link/cgi.h index b5690cf..8d61f36 100644 --- a/esp-link/cgi.h +++ b/esp-link/cgi.h @@ -4,6 +4,9 @@ #include "httpd.h" void jsonHeader(HttpdConnData *connData, int code); +void errorResponse(HttpdConnData *connData, int code, char *message); +int getStringArg(HttpdConnData *connData, char *name, char *config, int max_len); +int getBoolArg(HttpdConnData *connData, char *name, bool*config); int cgiMenu(HttpdConnData *connData); #endif diff --git a/esp-link/cgimqtt.c b/esp-link/cgimqtt.c index dbfbc14..cbf4c16 100644 --- a/esp-link/cgimqtt.c +++ b/esp-link/cgimqtt.c @@ -38,34 +38,56 @@ int ICACHE_FLASH_ATTR cgiMqttGet(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) { if (connData->conn==NULL) return HTTPD_CGI_DONE; -#if 0 - // Handle tcp_enable flag - char buff[128]; - int len = httpdFindArg(connData->getArgs, "tcp_enable", buff, sizeof(buff)); - if (len <= 0) { - jsonHeader(connData, 400); - return HTTPD_CGI_DONE; + // 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)); + if (mqtt_server < 0) return HTTPD_CGI_DONE; + mqtt_server |= getStringArg(connData, "mqtt-client-id", + flashConfig.mqtt_client, sizeof(flashConfig.mqtt_client)); + 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-enable", + &flashConfig.mqtt_enable); + + // handle mqtt port + char buff[16]; + if (httpdFindArg(connData->getArgs, "mqtt-port", buff, sizeof(buff)) > 0) { + int32_t port = atoi(buff); + if (port > 0 && port < 65536) { + flashConfig.mqtt_port = port; + mqtt_server |= 1; + } else { + errorResponse(connData, 400, "Invalid MQTT port"); + return HTTPD_CGI_DONE; + } } - flashConfig.tcp_enable = os_strcmp(buff, "true") == 0; - // Handle rssi_enable flag - len = httpdFindArg(connData->getArgs, "rssi_enable", buff, sizeof(buff)); - if (len <= 0) { - jsonHeader(connData, 400); - return HTTPD_CGI_DONE; + // if server setting changed, we need to "make it so" + if (mqtt_server) { + os_printf("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable); + // TODO } - flashConfig.rssi_enable = os_strcmp(buff, "true") == 0; - // Handle api_key flag - len = httpdFindArg(connData->getArgs, "api_key", buff, sizeof(buff)); - if (len < 0) { - jsonHeader(connData, 400); + // no action required if mqtt status settings change, they just get picked up at the + // next status tick + if (getBoolArg(connData, "mqtt-status-enable", &flashConfig.mqtt_status_enable) < 0) return HTTPD_CGI_DONE; - } - buff[sizeof(flashConfig.api_key)-1] = 0; // ensure we don't get an overrun - os_strcpy(flashConfig.api_key, buff); -#endif + if (getStringArg(connData, "mqtt-status-topic", + flashConfig.mqtt_status_topic, sizeof(flashConfig.mqtt_status_topic)) < 0) + return HTTPD_CGI_DONE; + + // 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; + if (slip_update > 0) os_printf("SLIP-enable changed: %d\n", flashConfig.slip_enable); + os_printf("Saving config\n"); if (configSave()) { httpdStartResponse(connData, 200); httpdEndHeaders(connData); diff --git a/html/mqtt.html b/html/mqtt.html index dd9653c..257c137 100644 --- a/html/mqtt.html +++ b/html/mqtt.html @@ -71,18 +71,17 @@
+ Suffixes: rssi, heap-free, ...
+

REST

REST requests are enabled as soon as SLIP is enabled. There are no REST-specific settings.

-
@@ -94,6 +93,7 @@ onLoad(function() { fetchMqtt(); bnd($("#mqtt-form"), "submit", changeMqtt); + bnd($("#mqtt-status-form"), "submit", changeMqttStatus); }); diff --git a/html/ui.js b/html/ui.js index 2a4e20e..1d4c365 100644 --- a/html/ui.js +++ b/html/ui.js @@ -316,44 +316,44 @@ function createInputForPin(pin) { input.type = "radio"; input.name = "pins"; input.data = pin.name; - input.className = "pin-input"; + input.className = "pin-input"; input.value= pin.value; input.id = "opt-" + pin.value; if (currPin == pin.name) input.checked = "1"; - var descr = m('"); - var div = document.createElement("div"); - div.appendChild(input); - div.appendChild(descr); - return div; + var descr = m('"); + var div = document.createElement("div"); + div.appendChild(input); + div.appendChild(descr); + return div; } function displayPins(resp) { - var po = $("#pin-mux"); - po.innerHTML = ""; - currPin = resp.curr; - resp.map.forEach(function(v) { - po.appendChild(createInputForPin(v)); - }); - var i, inputs = $(".pin-input"); - for (i=0; i 0) { + //os_printf("SLIP: disabled got %d\n", length); + console_process(buf, length); + } else { + slip_parse_buf(buf, length); + } + + serledFlash(50); // short blink on serial LED +} + //callback after the data are sent static void ICACHE_FLASH_ATTR serbridgeSentCb(void *arg) { diff --git a/serial/slip.c b/serial/slip.c index 0e067a1..76948d5 100644 --- a/serial/slip.c +++ b/serial/slip.c @@ -4,11 +4,10 @@ #include "uart.h" #include "crc16.h" #include "serbridge.h" -#include "serled.h" #include "console.h" #include "cmd.h" -uint8_t slip_disabled; // disable slip to allow flashing of attached MCU +uint8_t slip_disabled; // temporarily disable slip to allow flashing of attached MCU extern void ICACHE_FLASH_ATTR console_process(char *buf, short len); @@ -115,18 +114,7 @@ slip_parse_char(char c) { // callback with a buffer of characters that have arrived on the uart void ICACHE_FLASH_ATTR -serbridgeUartCb(char *buf, short length) { - if (slip_disabled > 0) { - //os_printf("SLIP: disabled got %d\n", length); - console_process(buf, length); - for (short i=0; i