Millheat local API development questions

The id looks like something unique, isn‘t it including the MAC Address ? If so, extract it from the string and use it as representation property. No additional query needed.
It also seems to include the device type (modular), which could be used for the Thing type.

I already parse the id to get the MAC address - I’m not contacting the device to get the MAC address during discovery. That’s not where the problem lies.

The problem is that if the same device already is defined as a Thing using a .things file, OH must have the time to start the binding and the binding to contact the device and get the MAC address before discovery “discovers” the same device.

Regarding the “modular” part, sadly I have no idea where “modular” comes in - it’s not the model name and for all I know, all their devices could be called “modular” in mDNS. It is a panel heater, which is what I need to know the Thing type, but as I don’t know how the mDNS broadcasts from other models look, I still don’t know exactly how this logic must look.

What I have done for now is to get the MAC address from id and Thing type using name and then make it log the info for any Mill devices it comes across that does not fit the information as “I know it”. This will hopefully make it relatively easy to get the mDNS details from other types of devices from users.

I don’t understand your problem. If the device is configured in .things file with the id parameter and you define that id parameter as presentation property, it should simply be identified as existing and not popup in inbox. That‘s how all bindings work, you can have a look at Shelly binding for exsmple.

The “id parameter”, the MAC address, is NOT in the .things file. The IP address/hostname is. Thus, once OH starts, the binding must contact the Thing and query the MAC address before it is “registered” as the presentation property. Most of the time, this works just fine, but sometimes it seems that the discovery happens before the binding can fetch the MAC address, and the same device ends up in the inbox.

It should be part of the config parameters, UI and .things file.
This will prevent the same thing showing up in inbox as duplicate if you also set it as representation property.
This will also prevent the need to query the device for its MAC adress and then see it already exists.
Other bindings do the same, having MAC Address and IP Address as config parameters and also MAC Address as representation property.

Then I’d say that the design is somewhat problematic. There is no easy way for the user to get the MAC address of the device up front, if that is to be entered in the config. But, it’s easy for the binding to get it, after the device has been contacted.

As I already said, this works fine most of the time, but a slight “grace period” after startup before doing the discovery would be helpful. That said, if the device is offline when OH starts, the same issue could arise when the device came online if the discovery happened to take place before the binding polled it to discover that it was online.

Ideally, the auto discovery should wait at least one “poll interval” before acting on a new found device. But, I don’t know if there’s any way to tell the framework that I want to do that. It probably isn’t. I could just pause the thread I get from MDNSDiscoveryService for a while before answering, that could work, but it would be crude and I don’t know where the thread comes from or if it holds any locks (I could figure that out by debugging of course). I just isn’t the way I would like to do it.

I could make “my own” DiscoveryService that mimics MDNSDiscoveryService but that caches the results for a while before querying the participans, but it feels redundant to have two services that monitors mDNS events.

My question was if there was a “common solution” for this, because I imagined that a lot of devices needs to be queried for their MAC address before it is known. But, I think I’m starting to understand now that this isn’t the case - maybe that’s one of the reasons why file-based Things are “frowned upon” by some. If the Thing is managed and created by automatic discovery, of course it’s not problem to storre the MAC address as part of the configuration. But, when you create it manually, either managed or file-based, it is a problem to have to register the MAC address.

Users can check the router config for that.
Before being usable in openHAB, the device needs to join the WiFi….

No, discovery has to be part of binding intialisation, whereas scheduled polling is part of the Thing handler.
You can update config parameters in the Thing handler, but this should not be used for static things like MAC Address.

Edit: Most vendor Apps show device Information, could the id be found there ?
How does a user get the devices IP Address?

IF they have a router that they control (many ISPs provide routers that the users themselves don’t control) and IF they know how to do this, they certainly can. They can also use other tools like arp to find it, but I’d say that this complicated things quite a bit for the users just to “work around” an issue that could be handled by OH. That said, users could also add the device to the “ignore list” if it keeps being rediscovered. Still not ideal IMO.

I’m not sure I follow you here. The discovery seems to happen at “random times”, probably it happens when the device broadcasts its mDNS details - which the device does at some interval. So, I don’t understand why it “has” to be part of the binding initialization. It wouldn’t hurt if the the device showed up in the inbox a few seconds later - if that means that users don’t have to handle the MAC address manually.

I do update config parameters from the binding, but I don’t think those are stored. I don’t update the config parameters that are defined in the thing-types.xml file, I only update those that the binding create dynamically. Since using managed Things isn’t possible from Eclipse, I can’t really verify that the config parameters I create aren’t stored, but that has been my assumption the whole time. That’s kind of the point of having “dynamic parameters” as I see it.

I don’t keep the MAC address as a config parameter at all though, I keep it as a property. You can use either config parameters or properties as “representation properties”. But, for all I know, the properties might be stored as well if the Thing is managed.

If the properties are stored, this problem only applies to file-based Things. Managed Things will then “know” their MAC address when OH starts as soon as they have been contacted by the binding once.

I’d guess that would be highly “app” dependent - but as MAC addresses are usually considered “low level details”, my guess is that many would not show them. In any case, my goal by using a LAN based binding is that people should not have to use “vendor apps” and cloud stuff.

Discovery services are setup at binding init and also include background discovery. Therefore it will check periodically if a new device with the defined MDNS string/service is being found.
If you do not want to use the MAC Address as representation property, it‘s your choice but a bad design.

Indeed, when checking the JSONDB after creating a managed Thing with this binding, I find that both configuration parameters and properties created dynamically have been stored. It wasn’t what I thought/imagined, and I’m not sure if it’s desirable in this case, but it “solves” the MAC address issue for managed Things. So, the problem only exists for file-based things.

I never said that I don’t want to use it as the representation property, I said I didn’t want to make the users enter it manually.

But, as it turns out, the “issue” I’m seeing will only exist for file-based Things, and since that is already considered “undesirable” I guess it’s not the end of the world if users that use file-based definitions will have to add them to the “ignore” list - OR of course they could specify the MAC address as a property in the .things file and it wouldn’t happen.

Ok, I might have been a bit unclear, sorry.
Yes, the issue will only exist for file based configs. You define whatever config parameter will be stored in the db when creating the discovery result and later on the Thing. So managed configs will not have to mess with MAC and/or IP Addresses, the will be stored without user interaction.

There is a somewhat related issue here:

…which is discussed further here:

I’m not saying that this is a big problem for this binding, I guess file-based Things are relatively rare, but I think the design of the discovery mechanism isn’t ideal. The idea that the binding and discovery should “live different lives” will cause practical problems. I think it would be better if for example the discovery service registered what it found, and that the binding could fetch and process the “discoveries” what it was ready. But, I’ll manage… I just think there’s room for improvement here.

Well, that‘s what it does.
Your Binding registers as a MDNS discovery participant, telling the core discovery service what devices it should be notified of. This is done by the MDNS service string.
When a new device announces itself on the network, core discovery service will notify your discovery implemrntation about a new device. Your Binding will then create a new discovery result and put a new thing into inbox, unless it could be identified as aleady existing. This will also work with .things files if they contain a config parameter that is used as representation property in the discovery service.
This way it was possible to create a suggestion service for new devices where Bindings are not installed. All it needed was just some information from the Binding discovery implementations.

As far as I can tell, it skips the important step of letting the binding wait until it’s ready before having to provide a discovery result. If the binding returns a null discovery result because the binding isn’t ready, I don’t see a way to “reprocess” that same discovery at a later stage, when the binding is ready. I don’t know if just holding on to the thread asking for the discovery result is nice behavior, it certainly doesn’t feel nice to do. So, the binding has to reply when it is asked, whether it has collected the information it needs or not. That’s what I think is “problematic”, that the binding can’t instead process this when it is ready to do so.

Why couldn’t bindings be able to “take” these suggestions if they match their criteria at a later stage and process them, turning them from “suggestions” to “real discoveries”?

Because the Binding is not installed at this time, therefore openHAB suggests to install it :wink:

Don’t understand you. If you don’t explicitly avoid background discovery, core service will inform your binding on the „next cycle“ about the devices found.

Ok, forget it, I was referring to “Thing suggestions”, not “binding suggestion”. But, it’s not important. What I tried to say was that these discovery results could be kept until some binding “claimed them” by creating a discovery result. That way, the bindings could process the results at a time of its choosing.

That is interesting if it’s true, but doesn’t correspond with my testing. When debugging, I seem to get two “discoveries” rapidly after each other, and then nothing later. I guess I’ll have to look more into how this actually works then. Because, if the “cycles” aren’t too far apart, just waiting for the next one would be a somewhat acceptable solution.

AFAIK, you can manually trigger a scan after Binding init is finished.
My Wemo Binding needs a special UPnP scan, which I trigger manually.

I’ve looked at the Wemo discovery, and to be honest, I don’t understand how WemoDiscoveryService is used at all. There’s a lot I don’t understand about OSGi still, but from what I can see, WemoDiscoveryParticipant which implements UpnpDiscoveryParticipant is used by UpnpDiscoveryService - not WemoDiscoveryService.

It seems to me that the “limitations” I’m complaining about aren’t in AbstractDiscoveryService but in MDNSDiscoveryService and in particular with the Participant construct. Since the MDNSDiscoveryParticipant doesn’t extend the MDNSDiscoveryService itself, and doesn’t even provide access to the discovery service instance, you’re very limited in what you can do when implementing MDNSDiscoveryParticipant. That said, there might be “magic” OSGi ways to do things that I don’t know how to.