mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-07 00:37:04 +01:00
Thingspeak support over SSL
This commit is contained in:
@@ -639,7 +639,13 @@ PROGMEM const char* const custom_reset_string[] = {
|
||||
#define THINGSPEAK_APIKEY "" // Default API KEY
|
||||
|
||||
#define THINGSPEAK_USE_ASYNC 1 // Use AsyncClient instead of WiFiClientSecure
|
||||
|
||||
// THINGSPEAK OVER SSL
|
||||
// Using THINGSPEAK over SSL works well but generates problems with the web interface,
|
||||
// so you should compile it with WEB_SUPPORT to 0.
|
||||
// When THINGSPEAK_USE_ASYNC is 1, requires ASYNC_TCP_SSL_ENABLED to 1 and ESP8266 Arduino Core 2.4.0.
|
||||
#define THINGSPEAK_USE_SSL 0 // Use secure connection
|
||||
#define THINGSPEAK_FINGERPRINT "78 60 18 44 81 35 BF DF 77 84 D4 0A 22 0D 9B 4E 6C DC 57 2C"
|
||||
|
||||
#define THINGSPEAK_HOST "api.thingspeak.com"
|
||||
#if THINGSPEAK_USE_SSL
|
||||
|
||||
@@ -319,47 +319,6 @@ void _mqttOnMessage(char* topic, char* payload, unsigned int len) {
|
||||
|
||||
}
|
||||
|
||||
#if MQTT_USE_ASYNC
|
||||
|
||||
bool mqttFormatFP(const char * fingerprint, unsigned char * bytearray) {
|
||||
|
||||
// check length (20 2-character digits ':' or ' ' separated => 20*2+19 = 59)
|
||||
if (strlen(fingerprint) != 59) return false;
|
||||
|
||||
DEBUG_MSG_P(PSTR("[MQTT] Fingerprint %s\n"), fingerprint);
|
||||
|
||||
// walk the fingerprint
|
||||
for (unsigned int i=0; i<20; i++) {
|
||||
bytearray[i] = strtol(fingerprint + 3*i, NULL, 16);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool mqttFormatFP(const char * fingerprint, char * destination) {
|
||||
|
||||
// check length (20 2-character digits ':' or ' ' separated => 20*2+19 = 59)
|
||||
if (strlen(fingerprint) != 59) return false;
|
||||
|
||||
DEBUG_MSG_P(PSTR("[MQTT] Fingerprint %s\n"), fingerprint);
|
||||
|
||||
// copy it
|
||||
strncpy(destination, fingerprint, 59);
|
||||
|
||||
// walk the fingerprint replacing ':' for ' '
|
||||
for (unsigned char i = 0; i<59; i++) {
|
||||
if (destination[i] == ':') destination[i] = ' ';
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void mqttEnabled(bool status) {
|
||||
_mqtt_enabled = status;
|
||||
setSetting("mqttEnabled", status ? 1 : 0);
|
||||
@@ -423,7 +382,7 @@ void mqttConnect() {
|
||||
if (secure) {
|
||||
DEBUG_MSG_P(PSTR("[MQTT] Using SSL\n"));
|
||||
unsigned char fp[20] = {0};
|
||||
if (mqttFormatFP(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) {
|
||||
if (sslFingerPrintArray(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) {
|
||||
_mqtt.addServerFingerprint(fp);
|
||||
} else {
|
||||
DEBUG_MSG_P(PSTR("[MQTT] Wrong fingerprint\n"));
|
||||
@@ -450,7 +409,7 @@ void mqttConnect() {
|
||||
DEBUG_MSG_P(PSTR("[MQTT] Using SSL\n"));
|
||||
if (_mqtt_client_secure.connect(host, port)) {
|
||||
char fp[60] = {0};
|
||||
if (mqttFormatFP(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) {
|
||||
if (sslFingerPrintChar(getSetting("mqttFP", MQTT_SSL_FINGERPRINT).c_str(), fp)) {
|
||||
if (_mqtt_client_secure.verify(fp, host)) {
|
||||
_mqtt.setClient(_mqtt_client_secure);
|
||||
} else {
|
||||
|
||||
@@ -10,14 +10,9 @@ Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
|
||||
|
||||
#if THINGSPEAK_USE_ASYNC
|
||||
#include <ESPAsyncTCP.h>
|
||||
AsyncClient _tspk_client;
|
||||
AsyncClient * _tspk_client;
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
#if THINGSPEAK_USE_SSL
|
||||
WiFiClientSecure _tspk_client;
|
||||
#else
|
||||
WiFiClient _tspk_client;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char THINGSPEAK_REQUEST_TEMPLATE[] PROGMEM =
|
||||
@@ -73,23 +68,45 @@ void _tspkConfigure() {
|
||||
|
||||
void _tspkPost(String data) {
|
||||
|
||||
_tspk_client.onError([](void * arg, AsyncClient * client, int error) {
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Connection error (%d)\n", error);
|
||||
if (_tspk_client == NULL) {
|
||||
_tspk_client = new AsyncClient();
|
||||
}
|
||||
|
||||
_tspk_client->onDisconnect([](void *s, AsyncClient *c) {
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Disconnected\n"));
|
||||
_tspk_client->free();
|
||||
delete _tspk_client;
|
||||
_tspk_client = NULL;
|
||||
}, 0);
|
||||
|
||||
_tspk_client->onTimeout([](void *s, AsyncClient *c, uint32_t time) {
|
||||
_tspk_client->close(true);
|
||||
}, 0);
|
||||
|
||||
_tspk_client->onData([](void * arg, AsyncClient * c, void * response, size_t len) {
|
||||
char * b = (char *) response;
|
||||
b[len] = 0;
|
||||
char * p = strstr((char *)response, "\r\n\r\n");
|
||||
unsigned int code = (p != NULL) ? atoi(&p[4]) : 0;
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Response value: %d\n"), code);
|
||||
_tspk_client->close(true);
|
||||
}, NULL);
|
||||
|
||||
_tspk_client.onConnect([data](void * arg, AsyncClient * client) {
|
||||
_tspk_client->onConnect([data](void * arg, AsyncClient * client) {
|
||||
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Connected to %s:%d\n"), THINGSPEAK_HOST, THINGSPEAK_PORT);
|
||||
|
||||
#if THINGSPEAK_USE_SSL
|
||||
uint8_t fp[20] = {0};
|
||||
sslFingerPrintArray(THINGSPEAK_FINGERPRINT, fp);
|
||||
SSL * ssl = _tspk_client->getSSL();
|
||||
if (ssl_match_fingerprint(ssl, fp) != SSL_OK) {
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Warning: certificate doesn't match\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] POST %s\n"), data.c_str());
|
||||
|
||||
client->onData([](void * arg, AsyncClient * c, void * response, size_t len) {
|
||||
char * b = (char *) response;
|
||||
b[len] = 0;
|
||||
char * p = strstr((char *)response, "\r\n\r\n");
|
||||
unsigned int code = (p != NULL) ? atoi(&p[4]) : 0;
|
||||
DEBUG_MSG_P(PSTR("[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,
|
||||
@@ -104,14 +121,15 @@ void _tspkPost(String data) {
|
||||
}, NULL);
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
if (!_tspk_client.connect(THINGSPEAK_HOST, THINGSPEAK_PORT, THINGSPEAK_USE_SSL)) {
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Connection failed\n"));
|
||||
}
|
||||
#else // ASYNC_TCP_SSL_ENABLED
|
||||
if (!_tspk_client.connect(THINGSPEAK_HOST, THINGSPEAK_PORT)) {
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Connection failed\n"));
|
||||
}
|
||||
#endif // ASYNC_TCP_SSL_ENABLED
|
||||
bool connected = _tspk_client->connect(THINGSPEAK_HOST, THINGSPEAK_PORT, THINGSPEAK_USE_SSL);
|
||||
#else
|
||||
bool connected = _tspk_client->connect(THINGSPEAK_HOST, THINGSPEAK_PORT);
|
||||
#endif
|
||||
|
||||
if (!connected) {
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Connection failed\n"));
|
||||
_tspk_client->close(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -119,10 +137,21 @@ void _tspkPost(String data) {
|
||||
|
||||
void _tspkPost(String data) {
|
||||
|
||||
#if THINGSPEAK_USE_SSL
|
||||
WiFiClientSecure _tspk_client;
|
||||
#else
|
||||
WiFiClient _tspk_client;
|
||||
#endif
|
||||
|
||||
if (_tspk_client.connect(THINGSPEAK_HOST, THINGSPEAK_PORT)) {
|
||||
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] POST %s\n"), data.c_str());
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Connected to %s:%d\n"), THINGSPEAK_HOST, THINGSPEAK_PORT);
|
||||
|
||||
if (!_tspk_client.verify(THINGSPEAK_FINGERPRINT, THINGSPEAK_HOST)) {
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] Warning: certificate doesn't match\n"));
|
||||
}
|
||||
|
||||
DEBUG_MSG_P(PSTR("[THINGSPEAK] POST %s\n"), data.c_str());
|
||||
char buffer[strlen_P(THINGSPEAK_REQUEST_TEMPLATE) + strlen(THINGSPEAK_URL) + strlen(THINGSPEAK_HOST) + data.length()];
|
||||
snprintf_P(buffer, sizeof(buffer),
|
||||
THINGSPEAK_REQUEST_TEMPLATE,
|
||||
|
||||
@@ -201,6 +201,51 @@ void heartbeat() {
|
||||
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SSL
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
|
||||
bool sslCheckFingerPrint(const char * fingerprint) {
|
||||
return (strlen(fingerprint) == 59);
|
||||
}
|
||||
|
||||
bool sslFingerPrintArray(const char * fingerprint, unsigned char * bytearray) {
|
||||
|
||||
// check length (20 2-character digits ':' or ' ' separated => 20*2+19 = 59)
|
||||
if (!sslCheckFingerPrint(fingerprint)) return false;
|
||||
|
||||
// walk the fingerprint
|
||||
for (unsigned int i=0; i<20; i++) {
|
||||
bytearray[i] = strtol(fingerprint + 3*i, NULL, 16);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool sslFingerPrintChar(const char * fingerprint, char * destination) {
|
||||
|
||||
// check length (20 2-character digits ':' or ' ' separated => 20*2+19 = 59)
|
||||
if (!sslCheckFingerPrint(fingerprint)) return false;
|
||||
|
||||
// copy it
|
||||
strncpy(destination, fingerprint, 59);
|
||||
|
||||
// walk the fingerprint replacing ':' for ' '
|
||||
for (unsigned char i = 0; i<59; i++) {
|
||||
if (destination[i] == ':') destination[i] = ' ';
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Reset
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
unsigned char resetReason() {
|
||||
|
||||
Reference in New Issue
Block a user