GithubHelp home page GithubHelp logo

Comments (20)

ThomDietrich avatar ThomDietrich commented on August 28, 2024 2

I do agree, that announcing unit, datatype and range of one property should be standardized in the homie convention. In fact I feel like this would be one of the important details of a convention thriving to become a discoverable IoTs-on-MQTT convention.
I would choose another approach than defining a mixed string, which is both hard to parse and easy to mistake and on top of that does not use what MQTT has to offer.

My proposal:

  • Currently all device properties of one device are announced using the topics
    homie/device-id/$...
  • Similarly all node properties of one node are announced using the topics
    homie/device-id/node-id/$...
  • Consequently all "property properties" of one property could be announced using the topics
    homie/device-id/node-id/property-id/$...

Side note: Using the word "properties" in this context might have been a bad idea...

Property properties Description
$name pretty name (optional)
$settable true or false. true: Property can be set using the .../property-id/set topic
$unit A string representing the unit of the property, e.g. "degree Celsius", "kW", ""
$datatype integer, float, boolean, string, enum, ....
$range from:to or ON,OFF,UNDEF or regex: ^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$
$valid default: "true" or empty. Set to "false" to indicate that this property is not updated currently. (Might be important because of retained messages. Just an example for further possibilities)

The table above is just an example and open for discussion.


Additionally I would suggest to introduce for completeness:

  • homie/device-id/$nodes
  • homie/device-id/node-id/$properties (already defined)
  • homie/device-id/node-id/property-id/$attributes

from convention.

marvinroger avatar marvinroger commented on August 28, 2024 1

I would even replace the [] with (), to differentiate ranges and data types:

homie/686f6d6965/ledstrip/$properties → led[1-3]:settable(enum:true,false)

from convention.

marvinroger avatar marvinroger commented on August 28, 2024 1

Okay, let's recap with a sample environment device.

Sample

Device properties

homie/686f6d6965/$homie → 2.1.0
homie/686f6d6965/$online → true
homie/686f6d6965/$name → Bedroom environment device
homie/686f6d6965/$localip → 192.168.0.10
homie/686f6d6965/$mac → A1:B2:C3:D4:E5:F6
homie/686f6d6965/$nodes → temperature,weather
homie/686f6d6965/$stats/uptime → 12
homie/686f6d6965/$stats/signal → 72
homie/686f6d6965/$stats/interval → 6
homie/686f6d6965/$fw/name → Firmware
homie/686f6d6965/$fw/version → 1.0.0
homie/686f6d6965/$fw/checksum → 6057f13c496ecf7fd777ceb9e79ae285
homie/686f6d6965/$implementation → esp8266
homie/686f6d6965/$implementation/foo → bar

Node properties (and property properties)

temperature node

homie/686f6d6965/temperature/$type → temperature
homie/686f6d6965/temperature/$properties → degrees

homie/686f6d6965/temperature/degrees/$settable → false
homie/686f6d6965/temperature/degrees/$unit → Celcius
homie/686f6d6965/temperature/degrees/$datatype → float
homie/686f6d6965/temperature/degrees/$range → -10:50
homie/686f6d6965/temperature/degrees/$valid (to be clarified)

weather node

homie/686f6d6965/temperature/$type →  weather
homie/686f6d6965/temperature/$properties → condition

homie/686f6d6965/temperature/condition/$settable → false
homie/686f6d6965/temperature/condition/$unit →
homie/686f6d6965/temperature/condition/$datatype → enum
homie/686f6d6965/temperature/condition/$range → sunny,cloudy,windy,rainy,stormy,foggy,showy
homie/686f6d6965/temperature/condition/$valid (to be clarified)

I like this approach.

Range for each datatypes

  • integer, float: from:to e.g. -23:45
  • boolean: none
  • enum: a,b,c and , escaped by doubling ,,
  • string: either none or size:min-max (e.g. size:1-3) or regex:^[A-Fa-f0-9]{32}$

I am not sure about the $valid and homie/device-id/node-id/property-id/$attributes topics. Can you clarify their purpose?

from convention.

ThomDietrich avatar ThomDietrich commented on August 28, 2024 1

Hey @marvinroger great to get in touch with you ;)

Your examples look great to me!

After going through all possible use cases, I realized that the $valid property is not meaningful. A property not valid will simply not be announced via $properties and a retained message can be deleted in that case.

You can also ignore homie/device-id/node-id/property-id/$attributes. It was supposed the be the analogy of $nodes but a property doesn't have sub-elements like the node has properties.


The discovery process

The whole idea behind this definition is to make a device discoverable. How would the discovery actually be implemented?

  1. The discovery service doesn't know the device-id of new devices
    -> Will it need to subscribe to homie/+/$online or similar?
  2. Next it will subscribe to homie/device-id/$..., including $nodes
  3. Next it will subscribe to homie/device-id/node-id/$... for all nodes, including $properties
  4. Lastly it will subscribe to homie/device-id/node-id/property/$... for all properties

It might be beneficial to provide a better way to solve step 1.

Steps 2,3,4 are only possible if all messages are retained messages. Otherwise, this will create a race condition.

Would you agree with this description? Is anything missing? @Kwave ?


If you want to go forward with this approach, maybe it would be good to choose a new word besides "properties". Topics starting with "$" could be called "attributes" for example.

Best Regards!

from convention.

marvinroger avatar marvinroger commented on August 28, 2024 1

@ThomDietrich it's a pleasure too, sorry for the long response time, I was busy with school!

Great then. For everyone who read this, please use the +1 and -1 GitHub reactions so we can get your feedback. And of course, feel free to comment if you would like to enter the discussion!


For the discovery, I've taken a different approach for one of my projects (see https://github.com/INTECH-RGB/homie-dashboard/blob/master/server/lib/bridges/mqtt-infrastructure.js).

Let's imagine you have the representation of your infrastructure in a structure (JSON for the example):

{}

Basically, we subscribe to homie/#. The problem is we receive the messages with no specific order. Imagine we receive a homie/686f6d6965/temperature/degrees/$datatype → float. We would parse the topic and know that we are receiving the datatype attribute of the degrees property from the temperature node of the 686f6d6965 device. We see the device does not exist in the representation, so we would add it:

{
  "686f6d6965": {
    "nodes": {}
  }
}

Then, we would see that the node does not exist, that the property does not exist, and so on... To end up with:

{
  "686f6d6965": {
    "nodes": {
      "temperature": {
        "properties": {
          "degrees": {
            "datatype": "float"
          }
        }
      }
    }
  }
}

And a device is considered discovered when all required information are populated in the representation. I hope you get the idea?

from convention.

marvinroger avatar marvinroger commented on August 28, 2024

I do agree!

Your suggestion handles the following:

  • Enums
  • Integer ranges

What about strings (which can be anything, not only enums), floats, more specific types like colors (255,255,255) etc.?

I would rather define data types. Each data types could have optional parameters (like min, max...). Something like:

homie/686f6d6965/switch/$properties → on:settable[enum:true,false]
homie/686f6d6965/temperature/$properties → temperature:settable[integer:60,100]

What do you think?

from convention.

sd-zhang avatar sd-zhang commented on August 28, 2024

Good thinking with data types. I completely agree with what you suggested.

Strings should be relatively simple to handle. For example, setting a color using predefined names can be done like this:
homie/686f6d6965/ledstrip/$properties → led[1-3]:settable(string)
homie/686f6d6965/ledstrip/led_1/set ← red

Multivariable settings are slightly tougher, but I think using a separator should be able to handle it, like so:
homie/686f6d6965/ledstrip/$properties → led[1-3]:settable(integer: 0,255; 0, 255; 0,255)

This would indicate that there are three settable integers for this property, each within the range [0, 255]. The color can be set like this:
homie/686f6d6965/ledstrip/led_1/set ← 0, 127, 255

from convention.

gorootde avatar gorootde commented on August 28, 2024

I've implemented the Openhab 2 Homie binding, that is why I also came across this point @ThomDietrich. It's rather difficult to map the properties to datatypes - or even a meaningful UI representation. Your suggestion would allow to do so.

from convention.

ThomDietrich avatar ThomDietrich commented on August 28, 2024

@Kwave I've taken a quick look at your feature branch. Would you agree, that it would be beneficial if another "Property property" would be $category holding one of the defined ESH channel categories. $settable already covers Accessible Mode and the exact ESH Item type to use can probably be derived from $unit+$datatype+$range.
What do you think?

from convention.

gorootde avatar gorootde commented on August 28, 2024

@ThomDietrich I'am not sure if data representation should be part of the homie specification. It depends on how you define the term "Node":

  1. If "Homie-Node" is defined as a sensor that is connected to a "Homie-Device", we definitely need the $category topic filled with the ESH channel category. We even need much more topics to indicate whether the sensor is "online" (works as expected) and so on.
  2. If "Homie-Node" is defined as a property of the "Homie-Device" with some additional meta information (e.g. the temperature example in the convention), you don't need any additional topics at all. The $type topic may contain the ESH category, whereas the unit and other meta-information are transported via subtopics.

However I'am much more attracted by the $-meta information solution than overloading the $properties topic with complicated syntax (which is not very mqtt'ish). Adding [] or () to the property list introduces a structure to the message, instead of using the already present mechanism to structure topics.

from convention.

ThomDietrich avatar ThomDietrich commented on August 28, 2024

Hello @Kwave,
My suggestion was not directly aimed at ESH but rather follows along the idea to make the Homie Convention base for fully discoverable devices. Defining the "category" of a property might help discovering systems like ESH/OH to configure and present properties (i.e. items in ESH/OH) in the desired way. Hence it might be beneficial to additionally/optionally add "$category" to the "Property properties" example.

I'am not sure if data representation should be part of the homie specification.

If the abstraction is (as in this case) high enough, I do not see any issue with that. Remember, that I asked you if your OH binding would benefit from the category. If that is not the case, we can just as well leave it out.

It would be great to hear some thoughts from @marvinroger. How do you feel about the presented approach and how realistic is an implementation in that direction?

Best Regards! Thomas

from convention.

ThomDietrich avatar ThomDietrich commented on August 28, 2024

Get it, like it ;)
Reminds me of the approach taken here.

Makes me speculate if it might be easier to streamline everything a bit to begin with. How would you feel about all the above (all $attributes), but serialized in one message?

home/$announce{"686f6d6965": {"$online": "true", "$nodes": {"temperature", "weather"}, ...}}

from convention.

marvinroger avatar marvinroger commented on August 28, 2024

It would not help. A discovery service must be able to discover devices even after the devices are powered up. So "one-shot" announces on homie/$announce would not work, the messages would need to be retained on homie/{deviceid}/$announce topics. But then, the problem remains: the retained messages might arrive out-of-order, so nothing guarantees that the announces will arrive before every other messages, making announces useless.

from convention.

ThomDietrich avatar ThomDietrich commented on August 28, 2024

Oh, you are totally right with the first part! Of course each device needs it's own retained topic (I would suggest to turn it around).

I did not get the second part of your argument though. The one retained message on homie/$announce/686f6d6965 would contain all "attributes" needed to instantly fully "discover" one device. No need to listen to any other topic for that. The discovery service simply needs to subscribe to homie/$announce/+. It will get to know all previously registered as well as new devices instantly.

All the above assumes, that the goal here is to make all variables and capabilities of on device known through an announcement process upon mqtt connection rather than step by step while its operation...

from convention.

marvinroger avatar marvinroger commented on August 28, 2024

Oh okay, I thought you wanted to keep the current structure of the messages, only announcing through $announce the nodes and properties (not the attributes), so a discovery service could map a device knowing all its nodes and properties, before populating with actual Homie attributes.

You said earlier, and I totally agree with that:

I would choose another approach than defining a mixed string, which is both hard to parse and easy to mistake and on top of that does not use what MQTT has to offer

Your suggestion was basically to exploit the potential of MQTT by making use of semantic topics rather that one "fit-it-all" topic. Your JSON based announce does not follow this approach. Moreover, JSON is pretty costly in terms of memory needed on micro-controllers (ESP8266 for example) which is why we avoided any JSON in the payloads.

from convention.

ThomDietrich avatar ThomDietrich commented on August 28, 2024

JSON is pretty costly in terms of memory needed on micro-controllers

Excellent point.
Yes I'm still convinced of the MQTT hierarchy approach. However, for transparency I thought it would only be fair to mention the other possibilities. At the end of the day the goal should be to allow discovery services to have full knowledge about the capabilities of a device in a deterministic way (I believe we do agree? 😉). One full JSON message would accomplish that, so would a set of nested topics messages as we've discussed before.

I thought you wanted to keep the current structure of the messages, only announcing through $announce the nodes and properties (not the attributes), so a discovery service could map a device knowing all its nodes and properties, before populating with actual Homie attributes.

Not necessarily. This is a mixture of both. It's not a full description and needs further messages to make a full discovery possible. Do you see any benefits in this?

This is a very interesting discussion! -Thomas

from convention.

ThomDietrich avatar ThomDietrich commented on August 28, 2024

@marvinroger you want me to recap and post an updated definition? I think we've settled all the open questions.

from convention.

marvinroger avatar marvinroger commented on August 28, 2024

@ThomDietrich my bad once again, I am currently looking for an internship in Paris and it takes a lot of time!

Yes, please go ahead! And if anybody has other advices, let's discuss. 😉

from convention.

gorootde avatar gorootde commented on August 28, 2024

@marvinroger @ThomDietrich I've created a Pull Request that sums up the discussed items. Please comment in the PR if I did get anything wrong.

from convention.

marvinroger avatar marvinroger commented on August 28, 2024

As the @Kwave's PR implements a lot of what was being discussed here, let's continue in #28

from convention.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.