-
Notifications
You must be signed in to change notification settings - Fork 306
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adapt library to Homie 3.0.0 #550
Conversation
* update file permissions * Update CI Build
… +Send when online only (#512) * Add option for ota_updater script to connect to TLS-protected brokers * Fix ota_updater not working when device is in deep sleep mode
Hi @marvinroger and @timpur! I'm going to add the "$retained" property attribute to conform to Homie 3.0.1 and I see this as the perfect opportunity to refactor the "advertise" function. Do you agree that the best option is to define the advertise function with the only required attribute (id) and add the optional ones (name, unit, format, datatype, retained and settable) following a "builder" pattern? We actually do that with the settable attribute, so it's natural to extend that principle to the rest non-mandatory attributes. What's your favorite name? ".withName", ".name", ".setName",...? Many thanks for you help and looking forward to hearing from you guys! Aitor |
Done, Homie 3.0.1 fully supported! |
sorry need to still have a proper review .... |
} | ||
|
||
PropertyInterface& PropertyInterface::setProperty(Property* property) { | ||
_property = property; | ||
return *this; | ||
} | ||
|
||
HomieNode::HomieNode(const char* id, const char* type, const NodeInputHandler& inputHandler) | ||
HomieNode::HomieNode(const char* id, const char* name, const char* type, bool range, uint16_t lower, uint16_t upper, const NodeInputHandler& inputHandler) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all your examples the "id" is the same as "type".
"type" is actually optional, at least it doesn't say anything about the node in the controller perspective.
Could you maybe remove it from the constructor and make it a chainable setter instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make all the array specific parameters a dedicated setter as well (setArray(uint16_t lower, uint16_t upper)
). That way if arrays change at some point, we don't need to change the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"type" is actually optional, at least it doesn't say anything about the node in the controller perspective.
Type is a required attribute for Nodes in Homie 3.0.1, see here: https://homieiot.github.io/spec-core-v3_0_1/#node-attributes. That's why I have added it to the class constructor. Perhaps we can remove it for Homie 4.0, but that discussion doesn't belong here 😉
Make all the array specific parameters a dedicated setter as well (setArray(uint16_t lower, uint16_t upper)). That way if arrays change at some point, we don't need to change the constructor.
I didn't want to change that part of the code too much, because it was already implemented, just the minimum necessary changes. What do you think @marvinroger?
@@ -50,16 +50,16 @@ uint16_t SendingPromise::send(const String& value) { | |||
strcat(topic, Interface::get().getConfig().get().deviceId); | |||
strcat_P(topic, PSTR("/")); | |||
strcat(topic, _node->getId()); | |||
strcat_P(topic, PSTR("/")); | |||
strcat(topic, _property->c_str()); | |||
|
|||
if (_range.isRange) { | |||
char rangeStr[5 + 1]; // max 65536 | |||
itoa(_range.index, rangeStr, 10); | |||
strcat_P(topic, PSTR("_")); | |||
strcat(topic, rangeStr); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ranges are not part of Homie 3?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ranges are how Node arrays are called in homie-esp8266, it's just an internal attribute name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Be aware that "SendingPromise" is part of the Homie object, not of the Node. So if one Node sets the range it is used for other Nodes, too.
So Homierange needs to be reset after sending.
(TBH: I don't understad why it worked in V2?!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@euphi
How can we do that ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jeanvdr :
Just add after line 57 (strcat(topic, rangeStr);
):
_range.isRange = false;
_range.index = 0;
It is a quick workaround. I think the range-mechanism has to be rewritten.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@euphi
Thanks
|
||
bool globalInputHandler(const HomieNode& node, const String& property, const HomieRange& range, const String& value) { | ||
bool globalInputHandler(const HomieNode& node, const HomieRange& range, const String& property, const String& value) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ranges are not part of Homie 3?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ranges are how Node arrays are called in homie-esp8266, it's just an internal attribute name.
Hi! When PR will be merged? |
@marvinroger any chance you'll find time to look into this one? @bodiroga would you be interested to invest more time as a maintainer of this project? |
I just created arendst/Tasmota#4696. Would be nice to have all esp DIY firmwares out there supported. MySensors is also interested. |
My C++ knowledge is very limited to maintain a project like this, but I could help keeping the library up to date with the Homie convention 👍 |
I wish we could get this merged and released 😕 I'm running my fork of @bodiroga 's develop-v3 branch and it's fine. ESPs running this code integrates easily into Openhab 2.4. |
Come on guys! A little Christmas gift :) |
Please merge it. I usw actualy this Form and work perfect. |
return Interface::get().getSendingPromise().setNode(*this).setProperty(property).setQos(1).setRetained(true); | ||
else | ||
return Interface::get().getSendingPromise().setNode(*this).setProperty(property).setQos(1); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here a reference to SendingPromise MUST be returned. For now, this result in a crash if you want to set a Property that has not been configured.
Solutions:
- Change signature of HomieNode::setProperty to
SendingPromise *HomieNode::setProperty(...)
and return NULL --> caller can check for NULL - Create error message and
abort()
--> Homie-ESP8266 enforces that you can only send to advertised properties - Return a generic SendingPromise& to be able to send on arbitrary topics (old behaviour. Maybe that is what you wanted to do and just messed with the nested
if
s?
I suggest to stick to the Homie-2.0 behaviour for now (third solution)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just change the line 81 und 82 to one line:
if (iProperty && iProperty->isRetained())
void setDatatype(const char* datatype) { _datatype = datatype; } | ||
void setFormat(const char* format) { _format = format; } | ||
void setRetained(const bool retained = true) { _retained = retained; } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change to String
(see detailed comment below)
const char* _name; | ||
const char* _unit; | ||
const char* _datatype; | ||
const char* _format; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these should be stored as String, so it is automatically copied.
Of course most of the Strings that are set here a constants and thus in global memory.
However, it is possible to receive dynamically created strings here and these could be on stack memory. For example, the allowed values for an ENUM could be generated dynamically.
@bodiroga Thank for you work - it's work, but ota_update don't :-( |
Is it possible to do a pull on this PR? How? |
+1 on having this released! Even if it will only have partial functionality (like OTA not working yet in initial release). Thank you all for this work, Amazing stuff!!! |
@mjcumming You can pull the fork from bodiroga and chekout develop-v3
With platformio, you can change your lib_deps from "Homie" to "https://github.com/bodiroga/homie-esp8266#develop-v3". |
@bodiroga, gorec2005, dikodahan That's it |
@euphi thank you for the instructions! |
It seems this branch sometimes looses events:
--> MQTT Connected event is missing, although the homie-esp8266 client reconnected to MQTT. The LED is still blinking quickly. However, the client receives set-commands and handles them correctly, so this is a minor issue. |
Actually. The over-use of the Arduino String class and std::function will fragment the heap memory very fast and I assume this firmware is just crashing from time to time. The esp is quite fast with rebooting and reconnecting so that may not have been noticed yet. |
@davidgraeff RTOS seems to be quite robust. When using many debug outputs with format strings, I have some problems that outgoing MQTT messages are lost, but no crashes/resets. All of my homie devices run very stable (uptime is months and I never saw any reset) Exception:
|
Initial development for Homie Convention V3.0.x by @bodiroga |
Hi @marvinroger and @timpur!
Here you have my proposal to adapt the library to the newest Homie convention version 👍 I have tested the changes with a NodeMCU board and the provided examples compile successfully! Anyway, review the changes carefully, please, I'm not a C++ guy.
Some things that could be added in a future PR:
Many thanks for all your amazing work and don't hesitate to criticize my code, feel free 😉
Best regards,
Aitor
PS: I have left all the individual commits in case you want to review them one by one, but I can squash them into a single one for the final merge.
PS2: related issues: #549, #467, #464