From 9d6a5727a559f7b0a6579919fb800d8667a820c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xose=20P=C3=A9rez?= Date: Sun, 7 Jan 2018 15:26:29 +0100 Subject: [PATCH] Non SSL version of Thingspeak module --- code/espurna/config/arduino.h | 1 + code/espurna/config/general.h | 20 +++++- code/espurna/config/sensors.h | 2 +- code/espurna/espurna.ino | 6 ++ code/espurna/relay.ino | 5 ++ code/espurna/sensor.ino | 8 +++ code/espurna/thinkspeak.ino | 125 ++++++++++++++++++++++++++++------ code/html/custom.js | 2 + 8 files changed, 144 insertions(+), 25 deletions(-) diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index 2ddfdadc..a68184a2 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -83,6 +83,7 @@ //#define SSDP_SUPPORT 1 //#define TELNET_SUPPORT 0 //#define TERMINAL_SUPPORT 0 +//#define THINGSPEAK_SUPPORT 0 //#define WEB_SUPPORT 0 //-------------------------------------------------------------------------------- diff --git a/code/espurna/config/general.h b/code/espurna/config/general.h index 4765f1bc..f56022bb 100644 --- a/code/espurna/config/general.h +++ b/code/espurna/config/general.h @@ -306,7 +306,7 @@ PROGMEM const char* const custom_reset_string[] = { #endif // This is not working at the moment!! -// Requires ASYNC_TCP_SSL_ENABLED to 1 and ESP8266 Arduino Core staging version. +// Requires ASYNC_TCP_SSL_ENABLED to 1 and ESP8266 Arduino Core 2.4.0 #define WEB_SSL_ENABLED 0 // Use HTTPS web interface #define WEB_MODE_NORMAL 0 @@ -405,7 +405,7 @@ PROGMEM const char* const custom_reset_string[] = { // MQTT OVER SSL // Using MQTT over SSL works pretty well but generates problems with the web interface. // It could be a good idea to use it in conjuntion with WEB_SUPPORT=0. -// Requires ASYNC_TCP_SSL_ENABLED to 1 and ESP8266 Arduino Core staging version. +// Requires ASYNC_TCP_SSL_ENABLED to 1 and ESP8266 Arduino Core 2.4.0. // // You can use it with MQTT_USE_ASYNC=1 (AsyncMqttClient library) // but you might experience hiccups on the web interface, so my recommendation is: @@ -621,9 +621,23 @@ PROGMEM const char* const custom_reset_string[] = { #endif #define THINGSPEAK_ENABLED 0 // Thingspeak disabled by default +#define THINGSPEAK_USE_SSL 0 // Use secure connection +#define THINGSPEAK_USE_ASYNC 0 // Use AsyncClient instead of WiFiClientSecure +#define THINGSPEAK_APIKEY "" // Default API KEY + #define THINGSPEAK_HOST "api.thingspeak.com" +#if THINGSPEAK_USE_SSL +#define THINGSPEAK_PORT 443 +#else +#define THINGSPEAK_PORT 80 +#endif #define THINGSPEAK_URL "/update" -#define THINGSPEAK_APIKEY "" // Default API KEY + +#ifndef ASYNC_TCP_SSL_ENABLED +#if THINGSPEAK_USE_SSL && THINGSPEAK_USE_ASYNC +#undef THINGSPEAK_SUPPORT // Thingspeak in ASYNC mode requires ASYNC_TCP_SSL_ENABLED +#endif +#endif // ----------------------------------------------------------------------------- // NTP diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 4dad0ab1..fe177e53 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -396,7 +396,7 @@ //------------------------------------------------------------------------------ #ifndef SI7021_SUPPORT -#define SI7021_SUPPORT 0 +#define SI7021_SUPPORT 1 #endif #ifndef SI7021_ADDRESS diff --git a/code/espurna/espurna.ino b/code/espurna/espurna.ino index 0ba5c7b5..7db73882 100644 --- a/code/espurna/espurna.ino +++ b/code/espurna/espurna.ino @@ -189,6 +189,9 @@ void welcome() { #if TERMINAL_SUPPORT DEBUG_MSG_P(PSTR(" TERMINAL")); #endif + #if THINGSPEAK_SUPPORT + DEBUG_MSG_P(PSTR(" THINGSPEAK")); + #endif #if WEB_SUPPORT DEBUG_MSG_P(PSTR(" WEB")); #endif @@ -357,6 +360,9 @@ void setup() { #if INFLUXDB_SUPPORT idbSetup(); #endif + #if THINGSPEAK_SUPPORT + tspkSetup(); + #endif #if RF_SUPPORT rfSetup(); #endif diff --git a/code/espurna/relay.ino b/code/espurna/relay.ino index 074fd97e..8b6fbd0a 100644 --- a/code/espurna/relay.ino +++ b/code/espurna/relay.ino @@ -747,6 +747,11 @@ void relayLoop(void) { relayInfluxDB(id); #endif + #if THINGSPEAK_SUPPORT + tspkEnqueueRelay(id, status); + tspkFlush(); + #endif + // Flag relay-based LEDs to update status ledUpdate(true); diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index fefe633b..e2a5be2e 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -649,6 +649,10 @@ void sensorLoop() { } #endif // INFLUXDB_SUPPORT + #if THINGSPEAK_SUPPORT + tspkEnqueueMeasurement(i, buffer); + #endif + #if DOMOTICZ_SUPPORT { char key[15]; @@ -685,6 +689,10 @@ void sensorLoop() { wsSend(_sensorWebSocketSendData); #endif + #if THINGSPEAK_SUPPORT + if (report_count == 0) tspkFlush(); + #endif + } } diff --git a/code/espurna/thinkspeak.ino b/code/espurna/thinkspeak.ino index bbd631ca..b74945ee 100644 --- a/code/espurna/thinkspeak.ino +++ b/code/espurna/thinkspeak.ino @@ -8,18 +8,37 @@ Copyright (C) 2018 by Xose PĂ©rez #if THINGSPEAK_SUPPORT -#include +#if THINGSPEAK_USE_ASYNC + #include + AsyncClient _tspk_client; + + const char THINGSPEAK_REQUEST_TEMPLATE[] PROGMEM = + "POST %s HTTP/1.1\r\n" + "Host: %s\r\n" + "User-Agent: ESPurna\r\n" + "Connection: close\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: %d\r\n\r\n" + "%s\r\n"; + +#else + #include + #if THINGSPEAK_USE_SSL + WiFiClientSecure _tspk_client; + #else + WiFiClient _tspk_client; + #endif +#endif bool _tspk_enabled = false; -WiFiClientSecure _tspk_client; -char * _tspk_queue[0]; +char * _tspk_queue[8] = {NULL}; // ----------------------------------------------------------------------------- void _tspkWebSocketOnSend(JsonObject& root) { root["tspkVisible"] = 1; - root["tspkEnabled"] = getSetting("idbEnabled", THINGSPEAK_ENABLED).toInt() == 1; + root["tspkEnabled"] = getSetting("tspkEnabled", THINGSPEAK_ENABLED).toInt() == 1; JsonArray& relays = root.createNestedArray("tspkRelays"); for (byte i=0; ionData([](void * arg, AsyncClient * c, void * response, size_t len) { + char * b = (char *) response; + b[len] = 0; + Serial.println(b); + char * p = strstr((char *)response, "\r\n\r\n"); + unsigned int code = (p != NULL) ? atoi(&p[4]) : 0; + DEBUG_MSG("[THINGSPEAK] Response value: %d\n", code); + }, NULL); + + char buffer[strlen_P(THINGSPEAK_REQUEST_TEMPLATE) + strlen(THINGSPEAK_URL) + strlen(THINGSPEAK_HOST) + data.length()]; + snprintf_P(buffer, sizeof(buffer), + THINGSPEAK_REQUEST_TEMPLATE, + THINGSPEAK_URL, + THINGSPEAK_HOST, + data.length(), + data.c_str() + ); + + client->write(buffer); + + }, NULL); + + #if ASYNC_TCP_SSL_ENABLED + if (!_tspk_client.connect(THINGSPEAK_HOST, THINGSPEAK_PORT, THINGSPEAK_USE_SSL)) { + #else + if (!_tspk_client.connect(THINGSPEAK_HOST, THINGSPEAK_PORT)) { + #endif + DEBUG_MSG("[THINGSPEAK] Connection failed\n"); + } + +} + +#else + bool _tspkPost(String data) { - if (_tspk_client.connect(THINGSPEAK_HOST, 443)) { + + if (_tspk_client.connect(THINGSPEAK_HOST, THINGSPEAK_PORT)) { + + DEBUG_MSG("[THINGSPEAK] POST %s\n", data.c_str()); + _tspk_client.println("POST " + String(THINGSPEAK_URL) + " HTTP/1.1"); _tspk_client.println("Host: " + String(THINGSPEAK_HOST)); - //_tspk_client.println("User-Agent: ESPurna"); + _tspk_client.println("User-Agent: ESPurna"); _tspk_client.println("Connection: close"); - _tspk_client.println("Content-Type: application/x-www-form-urlencoded;"); + _tspk_client.println("Content-Type: application/x-www-form-urlencoded"); _tspk_client.print("Content-Length: "); _tspk_client.println(data.length()); _tspk_client.println(); _tspk_client.println(data); + _tspk_client.println(); + delay(10); + String response = _tspk_client.readString(); - int bodypos = response.indexOf("\r\n\r\n") + 4; - Serial.println(response.substring(bodypos)); - return true; + int pos = response.indexOf("\r\n\r\n"); + unsigned int code = (pos > 0) ? response.substring(pos + 4).toInt() : 0; + DEBUG_MSG("[THINGSPEAK] Response value: %d\n", code); + _tspk_client.stop(); + return (code > 0); + } + + DEBUG_MSG("[THINGSPEAK] Connection failed\n"); return false; + +} + +#endif + +bool _tspkEnqueue(unsigned char index, char * payload) { + DEBUG_MSG("[THINGSPEAK] Enqueuing field #%d with value %s\n", index, payload); + --index; + if (_tspk_queue[index] != NULL) free(_tspk_queue[index]); + _tspk_queue[index] = strdup(payload); } // ----------------------------------------------------------------------------- -bool tspkSendRelay(unsigned char index, unsigned char status, bool enqueue) { +bool tspkEnqueueRelay(unsigned char index, unsigned char status) { if (!_tspk_enabled) return true; unsigned char id = getSetting("tspkRelay", index, 0).toInt(); if (id > 0) { - --id; char payload[3]; itoa(status ? 1 : 0, payload, 10); - if (_tspk_queue[id]) free(_tspk_queue[id]); - _tspk_queue[id] = strdup(payload); - if (!enqueue) tspkFlush(); + _tspkEnqueue(id, payload); } } -bool tspkSendMeasurement(unsigned char index, char * payload, bool enqueue) { +bool tspkEnqueueMeasurement(unsigned char index, char * payload) { if (!_tspk_enabled) return true; unsigned char id = getSetting("tspkMagnitude", index, 0).toInt(); if (id > 0) { - --id; - if (_tspk_queue[id]) free(_tspk_queue[id]); - _tspk_queue[id] = strdup(payload); - if (!enqueue) tspkFlush(); + _tspkEnqueue(id, payload); } } @@ -102,10 +184,11 @@ bool tspkFlush() { // Walk the fields for (unsigned char id=0; id<8; id++) { - if (_tspk_queue[id]) { + if (_tspk_queue[id] != NULL) { if (data.length() > 0) data = data + String("&"); data = data + String("field") + String(id+1) + String("=") + String(_tspk_queue[id]); free(_tspk_queue[id]); + _tspk_queue[id] = NULL; } } diff --git a/code/html/custom.js b/code/html/custom.js index f371f21c..b3697175 100644 --- a/code/html/custom.js +++ b/code/html/custom.js @@ -684,6 +684,8 @@ function rfbSend() { function processData(data) { + console.log(data); + // title if ("app_name" in data) { var title = data.app_name;