From 586ad7a0e038b758dd6722239b8617df4f5c5e4e Mon Sep 17 00:00:00 2001 From: Marvin Roger Date: Fri, 19 Aug 2016 14:49:40 +0200 Subject: [PATCH] Add type and properties node properties --- README.md | 7 ++++- src/Homie/Boot/BootNormal.cpp | 57 ++++++++++++++++++++++++----------- src/Homie/Boot/BootNormal.hpp | 1 + 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 2879e68a..5c7cee3d 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,16 @@ bool lightOnHandler(String value) { } void setup() { + Serial.begin(115200); + Serial.println(); + Serial.println(); pinMode(PIN_RELAY, OUTPUT); digitalWrite(PIN_RELAY, LOW); Homie_setFirmware("awesome-relay", "1.0.0"); - lightNode.subscribe("on", lightOnHandler); + + lightNode.advertise("on")->settable(lightOnHandler); + Homie.setup(); } diff --git a/src/Homie/Boot/BootNormal.cpp b/src/Homie/Boot/BootNormal.cpp index c6bf5950..fa865228 100644 --- a/src/Homie/Boot/BootNormal.cpp +++ b/src/Homie/Boot/BootNormal.cpp @@ -20,10 +20,13 @@ BootNormal::BootNormal() BootNormal::~BootNormal() { } -char* BootNormal::_prefixMqttTopic(PGM_P topic) { - _mqttTopic = std::unique_ptr(new char[strlen(_interface->config->get().mqtt.baseTopic) + strlen(_interface->config->get().deviceId) + strlen_P(topic) + 1]); +void BootNormal::_prefixMqttTopic() { strcpy(_mqttTopic.get(), _interface->config->get().mqtt.baseTopic); strcat(_mqttTopic.get(), _interface->config->get().deviceId); +} + +char* BootNormal::_prefixMqttTopic(PGM_P topic) { + _prefixMqttTopic(); strcat_P(_mqttTopic.get(), topic); return _mqttTopic.get(); @@ -78,25 +81,27 @@ void BootNormal::_onMqttConnected() { _interface->mqttClient->publish(_prefixMqttTopic(PSTR("/$homie")), 1, true, HOMIE_VERSION); _interface->mqttClient->publish(_prefixMqttTopic(PSTR("/$implementation")), 1, true, "esp8266"); - _interface->mqttClient->publish(_prefixMqttTopic(PSTR("/$online")), 1, true, "true"); - - char nodes[HomieNode::nodes.size() * (MAX_NODE_ID_LENGTH + 1 + MAX_NODE_ID_LENGTH + 1) - 1]; - char *begin = nodes; - char *ptr = nodes; for (HomieNode* iNode : HomieNode::nodes) { - if (ptr != begin) *ptr++ = ','; - auto len = strlen(iNode->getId()); - memcpy(ptr, iNode->getId(), len); - ptr += len; - *ptr++ = ':'; - len = strlen(iNode->getType()); - memcpy(ptr, iNode->getType(), len); - ptr += len; + std::unique_ptr subtopic = std::unique_ptr(new char[1 + strlen(iNode->getId()) + 12 + 1]); // /id/$properties + strcpy_P(subtopic.get(), PSTR("/")); + strcat(subtopic.get(), iNode->getId()); + strcat_P(subtopic.get(), PSTR("/$type")); + _interface->mqttClient->publish(_prefixMqttTopic(subtopic.get()), 1, true, iNode->getType()); + + strcpy_P(subtopic.get(), PSTR("/")); + strcat(subtopic.get(), iNode->getId()); + strcat_P(subtopic.get(), PSTR("/$properties")); + String properties; + for (Property* iProperty : iNode->getProperties()) { + properties.concat(iProperty->getProperty()); + if (iProperty->isSettable()) properties.concat(":settable"); + properties.concat(","); + } + if (iNode->getProperties().size() >= 1) properties.remove(properties.length() - 1); + _interface->mqttClient->publish(_prefixMqttTopic(subtopic.get()), 1, true, properties.c_str()); } - *ptr = '\0'; - _interface->mqttClient->publish(_prefixMqttTopic(PSTR("/$nodes")), 1, true, nodes); _interface->mqttClient->publish(_prefixMqttTopic(PSTR("/$name")), 1, true, _interface->config->get().name); IPAddress localIp = WiFi.localIP(); @@ -138,6 +143,8 @@ void BootNormal::_onMqttConnected() { _interface->mqttClient->subscribe(_prefixMqttTopic(PSTR("/$ota")), 2); } + _interface->mqttClient->publish(_prefixMqttTopic(PSTR("/$online")), 1, true, "true"); + _interface->readyToOperate = true; if (_interface->led.enabled) _interface->blinker->stop(); @@ -326,6 +333,22 @@ void BootNormal::setup() { if (_interface->led.enabled) _interface->blinker->start(LED_WIFI_DELAY); + // Generate topic buffer + size_t baseTopicLength = strlen(_interface->config->get().mqtt.baseTopic) + strlen(_interface->config->get().deviceId); + size_t longestSubtopicLength = 28 + 1; // /$implementation/ota/enabled + for (HomieNode* iNode : HomieNode::nodes) { + size_t nodeMaxTopicLength = 1 + strlen(iNode->getId()) + 12 + 1; // /id/$properties + if (nodeMaxTopicLength > longestSubtopicLength) longestSubtopicLength = nodeMaxTopicLength; + + for (Property* iProperty : iNode->getProperties()) { + size_t propertyMaxTopicLength = 1 + strlen(iNode->getId()) + 1 + strlen(iProperty->getProperty()) + 1; + if (iProperty->isSettable()) propertyMaxTopicLength += 4; // /set + + if (propertyMaxTopicLength > longestSubtopicLength) longestSubtopicLength = propertyMaxTopicLength; + } + } + _mqttTopic = std::unique_ptr(new char[baseTopicLength + longestSubtopicLength]); + _wifiGotIpHandler = WiFi.onStationModeGotIP(std::bind(&BootNormal::_onWifiGotIp, this, std::placeholders::_1)); _wifiDisconnectedHandler = WiFi.onStationModeDisconnected(std::bind(&BootNormal::_onWifiDisconnected, this, std::placeholders::_1)); diff --git a/src/Homie/Boot/BootNormal.hpp b/src/Homie/Boot/BootNormal.hpp index 929c7fbb..fe11ff80 100644 --- a/src/Homie/Boot/BootNormal.hpp +++ b/src/Homie/Boot/BootNormal.hpp @@ -54,6 +54,7 @@ class BootNormal : public Boot { void _onMqttConnected(); void _onMqttDisconnected(AsyncMqttClientDisconnectReason reason); void _onMqttMessage(char* topic, char* payload, uint8_t qos, size_t len, size_t index, size_t total); + void _prefixMqttTopic(); char* _prefixMqttTopic(PGM_P topic); }; } // namespace HomieInternals