From 012bdd0735439e950960b02fbe90fa74e18214a9 Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Wed, 8 May 2019 14:24:33 +0200 Subject: [PATCH 1/6] SpejsNode: Delay WiFi connection --- spejsiot/SpejsNode.cpp | 7 ++++++- spejsiot/SpejsNode.h | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/spejsiot/SpejsNode.cpp b/spejsiot/SpejsNode.cpp index bac82c0..dd50e87 100644 --- a/spejsiot/SpejsNode.cpp +++ b/spejsiot/SpejsNode.cpp @@ -19,9 +19,14 @@ void SpejsNode::init(bool debug) { debugf("*** SpejsNode init, runnning on: %s, current rom: %d", deviceID.c_str(), currentSlot); + System.onReady(SystemReadyDelegate(&SpejsNode::systemReady, this)); +} + +void SpejsNode::systemReady() { WifiAccessPoint.enable(false); WifiStation.enable(true); - WifiStation.config(WIFI_SSID, WIFI_PWD); + WifiStation.config(wifiSSID, wifiPassword); + WifiStation.connect(); WifiEvents.onStationGotIP(StationGotIPDelegate(&SpejsNode::gotIP, this)); diff --git a/spejsiot/SpejsNode.h b/spejsiot/SpejsNode.h index 7bbcd03..d3671b9 100644 --- a/spejsiot/SpejsNode.h +++ b/spejsiot/SpejsNode.h @@ -69,6 +69,13 @@ protected: void otaUpdateCallback(bool result); void httpFile(HttpRequest &request, HttpResponse &response); void httpIndex(HttpRequest &request, HttpResponse &response); + + void systemReady(void); + + String wifiSSID = WIFI_SSID; + String wifiPassword = WIFI_PWD; + + bool brokerUseTLS = false; public: MqttClient mqtt; HttpServer http; From 5879a80f48f12d78b53d0d79c3bcf216a1da964d Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Wed, 8 May 2019 14:25:47 +0200 Subject: [PATCH 2/6] SpejsNode: add /config.json endpoint --- base-firmware/app/application.cpp | 2 +- spejsiot/SpejsNode.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/base-firmware/app/application.cpp b/base-firmware/app/application.cpp index 291766e..05365ca 100644 --- a/base-firmware/app/application.cpp +++ b/base-firmware/app/application.cpp @@ -5,7 +5,7 @@ SpejsNode node("unconfigured-generic-device"); void init() { - node.init(); + node.init(true); node.loadJSON({ &OutputEndpoint::fromJSON, &DHTEndpoint::fromJSON, diff --git a/spejsiot/SpejsNode.cpp b/spejsiot/SpejsNode.cpp index dd50e87..1a06bb6 100644 --- a/spejsiot/SpejsNode.cpp +++ b/spejsiot/SpejsNode.cpp @@ -164,8 +164,22 @@ void SpejsNode::onConnected() { // HTTP initialization http.listen(80); http.addPath("/", HttpPathDelegate(&SpejsNode::httpIndex, this)); + http.addPath("/config.json", HttpPathDelegate(&SpejsNode::httpConfig, this)); http.setDefaultHandler(HttpPathDelegate(&SpejsNode::httpFile, this)); + http.setBodyParser("application/json", bodyToStringParser); +} +void SpejsNode::httpConfig(HttpRequest &request, HttpResponse &response) +{ + if (request.method == HTTP_POST) { + debugf("settings data"); + String body = request.getBody(); + Serial.println(body); + fileSetContent("config.json", body); + response.sendString("{\"status\": 200}"); + } else { + response.sendFile("config.json"); + } } void SpejsNode::httpFile(HttpRequest &request, HttpResponse &response) From 24924811b2bb54aea780479fc19e2604d34bf4e4 Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Wed, 8 May 2019 14:26:09 +0200 Subject: [PATCH 3/6] SpejsNode: add JSON network configuration loading --- spejsiot/SpejsNode.cpp | 16 +++++++++++++++- spejsiot/SpejsNode.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/spejsiot/SpejsNode.cpp b/spejsiot/SpejsNode.cpp index 1a06bb6..6b867c4 100644 --- a/spejsiot/SpejsNode.cpp +++ b/spejsiot/SpejsNode.cpp @@ -58,7 +58,21 @@ void SpejsNode::loadJSON(std::vector initializers) { if (root.containsKey("name")) deviceType = (root["name"]).asString(); - JsonObject& data = root["endpoints"].asObject(); + JsonArray& networks = root.get("networks"); + if (networks.success() && networks.size()) { + debugf("got networks"); + JsonObject& network = networks.get(0); + + if (network.success() && network.containsKey("ssid")) { + debugf("Loaded JSON network configuration"); + wifiSSID = network["ssid"].as(); + wifiPassword = network["psk"].as(); + } else { + debugf("invalid network configuration"); + } + } + + JsonObject& data = root.get("endpoints"); for (auto it: data) { bool found = false; diff --git a/spejsiot/SpejsNode.h b/spejsiot/SpejsNode.h index d3671b9..dfc2380 100644 --- a/spejsiot/SpejsNode.h +++ b/spejsiot/SpejsNode.h @@ -68,6 +68,7 @@ protected: void mqttCallback(String, String); void otaUpdateCallback(bool result); void httpFile(HttpRequest &request, HttpResponse &response); + void httpConfig(HttpRequest &request, HttpResponse &response); void httpIndex(HttpRequest &request, HttpResponse &response); void systemReady(void); From 517ceea15cb508dee31a76946a10892f594069c4 Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Wed, 8 May 2019 15:55:06 +0200 Subject: [PATCH 4/6] Sming 3.8.0 update --- spejsiot/SpejsNode.cpp | 30 +++++++++++++++++++++--------- spejsiot/SpejsNode.h | 3 +-- spejsiot/endpoints/DHTEndpoint.cpp | 2 +- spejsiot/endpoints/DHTEndpoint.h | 2 +- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/spejsiot/SpejsNode.cpp b/spejsiot/SpejsNode.cpp index 6b867c4..61cf223 100644 --- a/spejsiot/SpejsNode.cpp +++ b/spejsiot/SpejsNode.cpp @@ -33,7 +33,7 @@ void SpejsNode::systemReady() { registerEndpoint("$implementation", new ImplementationEndpoint()); // Keepalive Timer initialization - keepaliveTimer.initializeMs(10000, TimerDelegate(&SpejsNode::keepAliveHandler, this)).start(); + keepaliveTimer.initializeMs(10000, [=]() { keepAliveHandler(); }).start(); statusLED.high(); } @@ -147,18 +147,30 @@ void SpejsNode::onConnected() { debugf("Connection successful"); + mqtt.setMessageHandler([=](MqttClient& client, mqtt_message_t* message) -> int { + if (message == nullptr) return -1; + + String topic = String((const char*)message->publish.topic_name.data, message->publish.topic_name.length); + String content; + if(message->publish.content.data) { + content.concat((const char*)message->publish.content.data, message->publish.content.length); + } + + mqttCallback(topic, content); + return 0; + }); + // MQTT initialization mqtt.setWill(DEV_TOPIC("$online"), "false", 1, true); #ifdef ENABLE_SSL const uint8_t sha1Fingerprint[] = SSL_FINGERPRINT; - mqtt.connect("iot-" + deviceID, "", "", true); mqtt.addSslOptions(SSL_SERVER_VERIFY_LATER); mqtt.setSslFingerprint(sha1Fingerprint, 20); -#else - mqtt.connect("iot-" + deviceID); #endif + mqtt.connect(brokerURL, "iot-" + deviceID); + for(unsigned int i = 0 ; i < endpoints.count() ; i++) { endpoints.valueAt(i)->onConnected(); } @@ -177,9 +189,9 @@ void SpejsNode::onConnected() { // HTTP initialization http.listen(80); - http.addPath("/", HttpPathDelegate(&SpejsNode::httpIndex, this)); - http.addPath("/config.json", HttpPathDelegate(&SpejsNode::httpConfig, this)); - http.setDefaultHandler(HttpPathDelegate(&SpejsNode::httpFile, this)); + http.paths.set("/", HttpPathDelegate(&SpejsNode::httpIndex, this)); + http.paths.set("/config.json", HttpPathDelegate(&SpejsNode::httpConfig, this)); + http.paths.setDefault(HttpPathDelegate(&SpejsNode::httpFile, this)); http.setBodyParser("application/json", bodyToStringParser); } @@ -198,7 +210,7 @@ void SpejsNode::httpConfig(HttpRequest &request, HttpResponse &response) void SpejsNode::httpFile(HttpRequest &request, HttpResponse &response) { - String file = request.getPath(); + String file = request.uri.Path; if (file[0] == '/') file = file.substring(1); @@ -215,7 +227,7 @@ void SpejsNode::httpFile(HttpRequest &request, HttpResponse &response) JsonObjectStream* stream = new JsonObjectStream(); JsonObject& json = stream->getRoot(); json["status"] = result.status; - response.sendJsonObject(stream); + response.sendDataStream(stream, MIME_JSON); } } } diff --git a/spejsiot/SpejsNode.h b/spejsiot/SpejsNode.h index dfc2380..17123fa 100644 --- a/spejsiot/SpejsNode.h +++ b/spejsiot/SpejsNode.h @@ -42,7 +42,7 @@ public: highState = highState_; pinMode(pin, OUTPUT); - animateTimer.initializeMs(50, TimerDelegate(&LED::animate, this)).start(); + animateTimer.initializeMs(50, [=]() { animate(); }).start(); } void idle() { @@ -89,7 +89,6 @@ public: uint8_t currentSlot; SpejsNode(String _deviceType) : - mqtt(MQTT_BROKER, MQTT_PORT, MqttStringSubscriptionCallback(&SpejsNode::mqttCallback, this)), deviceType(_deviceType) {}; void onConnected(); diff --git a/spejsiot/endpoints/DHTEndpoint.cpp b/spejsiot/endpoints/DHTEndpoint.cpp index 319eedc..b5745b9 100644 --- a/spejsiot/endpoints/DHTEndpoint.cpp +++ b/spejsiot/endpoints/DHTEndpoint.cpp @@ -4,7 +4,7 @@ void DHTEndpoint::bind(String _name, SpejsNode* _parent) { Endpoint::bind(_name, _parent); sensor.setup(pin, sensor_type); - samplingTimer.initializeMs(samplingRate, TimerDelegate(&DHTEndpoint::sample, this)).start(); + samplingTimer.initializeMs(samplingRate, [=]() { sample(); }).start(); } void DHTEndpoint::sample() { diff --git a/spejsiot/endpoints/DHTEndpoint.h b/spejsiot/endpoints/DHTEndpoint.h index d37b6b4..7bc5329 100644 --- a/spejsiot/endpoints/DHTEndpoint.h +++ b/spejsiot/endpoints/DHTEndpoint.h @@ -18,7 +18,7 @@ protected: public: DHTEndpoint(int _pin, int _samplingRate = 10000, DHTesp::DHT_MODEL_t _sensor_type=DHTesp::DHT11) : - ValueEndpoint("dht"), pin(_pin), sensor_type(_sensor_type), + ValueEndpoint("dht"), sensor_type(_sensor_type), pin(_pin), samplingRate(_samplingRate) {} void bind(String name, SpejsNode* _parent); From 19a58cf28fae4039d74c3fb364a52c775cba1244 Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Wed, 8 May 2019 16:09:44 +0200 Subject: [PATCH 5/6] SpejsNode: JSON broker configuration & initial TLS setup --- base-firmware/Makefile-user.mk | 1 + spejsiot/SpejsNode.cpp | 41 ++++++++++++++++++++++++++++++---- spejsiot/SpejsNode.h | 7 ++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/base-firmware/Makefile-user.mk b/base-firmware/Makefile-user.mk index 73a4d8f..5711392 100644 --- a/base-firmware/Makefile-user.mk +++ b/base-firmware/Makefile-user.mk @@ -1,2 +1,3 @@ SPIFF_SIZE = 196600 DISABLE_SPIFFS = 0 +ENABLE_SSL = 1 diff --git a/spejsiot/SpejsNode.cpp b/spejsiot/SpejsNode.cpp index 61cf223..579d436 100644 --- a/spejsiot/SpejsNode.cpp +++ b/spejsiot/SpejsNode.cpp @@ -6,8 +6,15 @@ #define CONFIG_FILE "config.json" +uint8_t hexToInt(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return c - 'a' + 10; +} + void SpejsNode::init(bool debug) { deviceID = WifiStation.getMAC().substring(6, 12); + brokerClient = "iot-" + deviceID; currentSlot = 0; if(!rboot_get_last_boot_rom(¤tSlot)) { @@ -48,12 +55,18 @@ void SpejsNode::loadJSON(std::vector initializers) { #endif DynamicJsonBuffer jsonBuffer; + if (fileExist(CONFIG_FILE)) { int size = fileGetSize(CONFIG_FILE); debugf("Found config file, %d bytes", size); char* jsonString = new char[size + 1]; fileGetContent(CONFIG_FILE, jsonString, size + 1); + JsonObject& root = jsonBuffer.parseObject(jsonString); + if (!root.success()) { + debugf("invalid config"); + return; + } if (root.containsKey("name")) deviceType = (root["name"]).asString(); @@ -72,6 +85,25 @@ void SpejsNode::loadJSON(std::vector initializers) { } } + // Broker configuration + if (root.containsKey("broker")) { + auto brokerPort = root.containsKey("brokerPort") ? root["brokerPort"] : 1883; + brokerUseTLS = root["brokerUseTLS"]; + brokerURL = root["broker"].as(); + + String hash = root.get("brokerSHA1"); + if ((hash.length() + 1) % 3 == 0) { + int hashLength = (hash.length() + 1) / 3; + uint8_t* hashBlob = new uint8_t[hashLength]; + + for (int i = 0; i < hashLength; i++) { + hashBlob[i] = hexToInt(hash[3*i]) << 4 | hexToInt(hash[3*i+1]); + } + + fingerprints.certSha1 = hashBlob; + } + } + JsonObject& data = root.get("endpoints"); for (auto it: data) { bool found = false; @@ -164,12 +196,13 @@ void SpejsNode::onConnected() { mqtt.setWill(DEV_TOPIC("$online"), "false", 1, true); #ifdef ENABLE_SSL - const uint8_t sha1Fingerprint[] = SSL_FINGERPRINT; - mqtt.addSslOptions(SSL_SERVER_VERIFY_LATER); - mqtt.setSslFingerprint(sha1Fingerprint, 20); + if (brokerUseTLS) { + mqtt.addSslOptions(SSL_SERVER_VERIFY_LATER); + mqtt.pinCertificate(fingerprints); + } #endif - mqtt.connect(brokerURL, "iot-" + deviceID); + mqtt.connect(brokerURL, brokerClient); for(unsigned int i = 0 ; i < endpoints.count() ; i++) { endpoints.valueAt(i)->onConnected(); diff --git a/spejsiot/SpejsNode.h b/spejsiot/SpejsNode.h index 17123fa..cc61ca8 100644 --- a/spejsiot/SpejsNode.h +++ b/spejsiot/SpejsNode.h @@ -76,7 +76,14 @@ protected: String wifiSSID = WIFI_SSID; String wifiPassword = WIFI_PWD; + String brokerURL = "mqtt://" MQTT_BROKER; + String brokerClient; + bool brokerUseTLS = false; + +#ifdef ENABLE_SSL + SslFingerprints fingerprints; +#endif public: MqttClient mqtt; HttpServer http; From 87ce4d473da9d3b6f7805f62a6fd538139277007 Mon Sep 17 00:00:00 2001 From: Piotr Dobrowolski Date: Wed, 8 May 2019 18:03:29 +0200 Subject: [PATCH 6/6] Initial TLS connection --- base-firmware/files/config.json | 10 +++- master/README.md | 3 ++ spejsiot/Endpoint.cpp | 4 +- spejsiot/SpejsNode.cpp | 87 +++++++++++++++++++++++---------- spejsiot/SpejsNode.h | 2 +- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/base-firmware/files/config.json b/base-firmware/files/config.json index df09c94..407d6f0 100644 --- a/base-firmware/files/config.json +++ b/base-firmware/files/config.json @@ -1,5 +1,5 @@ { - "name": "testdev", + "name": "unprovisioned", "extras": { "owner": "informatic", @@ -10,5 +10,11 @@ "out": {"type": "output", "gpio": 2}, "testInput": {"type": "input", "gpio": 3}, "testtemp": {"type": "dht"} - } + }, + + "broker": "mqtts://10.8.0.136:8883", + "brokerSHA1": "E7:FA:91:2B:E9:D6:7E:55:83:16:8D:09:68:BF:DD:4F:5D:F4:AC:DA", + "brokerSHA256": "29:10:5e:29:27:d6:2f:05:21:cc:8b:0e:f2:ca:e9:aa:1d:f4:1a:63:58:ed:4e:c8:92:b2:cb:9e:d7:71:a9:1d", + "brokerClient": "testing", + "brokerUseTLS": true } diff --git a/master/README.md b/master/README.md index f5b19a5..41e9911 100644 --- a/master/README.md +++ b/master/README.md @@ -6,4 +6,7 @@ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out s # Extract SHA-1 openssl x509 -in server.crt -sha1 -noout -fingerprint | sed 's/.*=/0x/g; s/:/, 0x/g' + +# extract sha256 +openssl x509 -in mqtt/certs/server.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 | sed -r 's/.*= //g; s/([0-9a-z]{2})/\1:/g; s/:$//g' ``` diff --git a/spejsiot/Endpoint.cpp b/spejsiot/Endpoint.cpp index 2212992..cfe66c5 100644 --- a/spejsiot/Endpoint.cpp +++ b/spejsiot/Endpoint.cpp @@ -13,7 +13,9 @@ void Endpoint::notify(String property, String value) { void Endpoint::onConnected() { parent->subscribe(name + "/+/set"); - parent->notify(name + "/$type", type); + if (type.length()) { + parent->notify(name + "/$type", type); + } } void Endpoint::onMessage(String topic, String payload) { diff --git a/spejsiot/SpejsNode.cpp b/spejsiot/SpejsNode.cpp index 579d436..b8a585a 100644 --- a/spejsiot/SpejsNode.cpp +++ b/spejsiot/SpejsNode.cpp @@ -59,10 +59,19 @@ void SpejsNode::loadJSON(std::vector initializers) { if (fileExist(CONFIG_FILE)) { int size = fileGetSize(CONFIG_FILE); debugf("Found config file, %d bytes", size); + char* jsonString = new char[size + 1]; + if (jsonString == nullptr) { + debugf("CAN'T CALLOCATE JSONSTRING"); + return; + } + debugf("allocated %08x",jsonString); + fileGetContent(CONFIG_FILE, jsonString, size + 1); + debugf("loaded %s", jsonString); JsonObject& root = jsonBuffer.parseObject(jsonString); + debugf("parsed: %d", root.success()); if (!root.success()) { debugf("invalid config"); return; @@ -71,6 +80,8 @@ void SpejsNode::loadJSON(std::vector initializers) { if (root.containsKey("name")) deviceType = (root["name"]).asString(); + debugf("Loading networks..."); + JsonArray& networks = root.get("networks"); if (networks.success() && networks.size()) { debugf("got networks"); @@ -86,13 +97,15 @@ void SpejsNode::loadJSON(std::vector initializers) { } // Broker configuration + debugf("Loading broker configuration..."); if (root.containsKey("broker")) { auto brokerPort = root.containsKey("brokerPort") ? root["brokerPort"] : 1883; brokerUseTLS = root["brokerUseTLS"]; brokerURL = root["broker"].as(); - String hash = root.get("brokerSHA1"); + String hash = root.get("brokerSHA256"); if ((hash.length() + 1) % 3 == 0) { + debugf("Loading sha256 certificate/pubkey hash"); int hashLength = (hash.length() + 1) / 3; uint8_t* hashBlob = new uint8_t[hashLength]; @@ -100,11 +113,17 @@ void SpejsNode::loadJSON(std::vector initializers) { hashBlob[i] = hexToInt(hash[3*i]) << 4 | hexToInt(hash[3*i+1]); } - fingerprints.certSha1 = hashBlob; + mqtt.pinCertificate(hashBlob, eSFT_PkSha256); } } + debugf("Loading endpoints..."); + JsonObject& data = root.get("endpoints"); + if (!data.success()) { + debugf("No endpoints found..."); + return; + } for (auto it: data) { bool found = false; @@ -155,7 +174,7 @@ void SpejsNode::keepAliveHandler() { } } -inline String SpejsNode::DEV_TOPIC(String t) { +String SpejsNode::DEV_TOPIC(String t) { return TOPIC_PREFIX + deviceID + "/" + t; } @@ -179,6 +198,16 @@ void SpejsNode::onConnected() { debugf("Connection successful"); + debugf("http init"); + + // HTTP initialization + http.listen(80); + http.paths.set("/", HttpPathDelegate(&SpejsNode::httpIndex, this)); + http.paths.set("/config.json", HttpPathDelegate(&SpejsNode::httpConfig, this)); + http.paths.setDefault(HttpPathDelegate(&SpejsNode::httpFile, this)); + http.setBodyParser("application/json", bodyToStringParser); + + debugf("mqtt init"); mqtt.setMessageHandler([=](MqttClient& client, mqtt_message_t* message) -> int { if (message == nullptr) return -1; @@ -197,35 +226,38 @@ void SpejsNode::onConnected() { #ifdef ENABLE_SSL if (brokerUseTLS) { + debugf("Using TLS"); mqtt.addSslOptions(SSL_SERVER_VERIFY_LATER); - mqtt.pinCertificate(fingerprints); + //mqtt.pinCertificate(fingerprints); } #endif + debugf("Connecting: %s as %s", brokerURL.c_str(), brokerClient.c_str()); + + mqtt.setConnectedHandler([=](MqttClient& client, mqtt_message_t* message) { + debugf("Initializing endpoints"); + for(unsigned int i = 0 ; i < endpoints.count() ; i++) { + endpoints.valueAt(i)->onConnected(); + } + + debugf("subscribing"); + subscribe("$implementation/+"); + + debugf("say hello"); + + // Say hello + notify("$online", "true"); + notify("$homie", "2"); + notify("$name", deviceType); + notify("$localip", WifiStation.getIP().toString()); + notify("$mac", WifiStation.getMAC()); + notify("$fw/name", "spejsiot"); + notify("$fw/version", BUILD_ID); + notify("$fw/slot", String(currentSlot)); + + return 0; + }); mqtt.connect(brokerURL, brokerClient); - - for(unsigned int i = 0 ; i < endpoints.count() ; i++) { - endpoints.valueAt(i)->onConnected(); - } - - subscribe("$implementation/+"); - - // Say hello - notify("$online", "true"); - notify("$homie", "2"); - notify("$name", deviceType); - notify("$localip", WifiStation.getIP().toString()); - notify("$mac", WifiStation.getMAC()); - notify("$fw/name", "spejsiot"); - notify("$fw/version", BUILD_ID); - notify("$implementation/slot", String(currentSlot)); - - // HTTP initialization - http.listen(80); - http.paths.set("/", HttpPathDelegate(&SpejsNode::httpIndex, this)); - http.paths.set("/config.json", HttpPathDelegate(&SpejsNode::httpConfig, this)); - http.paths.setDefault(HttpPathDelegate(&SpejsNode::httpFile, this)); - http.setBodyParser("application/json", bodyToStringParser); } void SpejsNode::httpConfig(HttpRequest &request, HttpResponse &response) @@ -269,6 +301,7 @@ void SpejsNode::httpFile(HttpRequest &request, HttpResponse &response) * Publish on device-specific topic */ bool SpejsNode::notify(String key, String value) { + debugf("%s [%d] = %s [%d]", key.c_str(), key.length(), value.c_str(), value.length()); mqtt.publish(DEV_TOPIC(key), value, true); return mqtt.getConnectionState() == eTCS_Connected; } diff --git a/spejsiot/SpejsNode.h b/spejsiot/SpejsNode.h index cc61ca8..849c48f 100644 --- a/spejsiot/SpejsNode.h +++ b/spejsiot/SpejsNode.h @@ -77,7 +77,7 @@ protected: String wifiPassword = WIFI_PWD; String brokerURL = "mqtt://" MQTT_BROKER; - String brokerClient; + String brokerClient = ""; bool brokerUseTLS = false;