Skip to content

Conversation

@MikeTheTux
Copy link
Contributor

@MikeTheTux MikeTheTux commented Aug 30, 2025

[automower] Implement individual Things for configuration dependent items

This PR implements individual openHAB Things for configuration-dependent Automower items (WorkAreas and StayoutZones) to avoid ordering issues when the mower configuration changes. Instead of using consecutive channel naming, each item now gets its own Thing with a unique ID based on the Automower's configuration.

  • Adds new Thing types for StayoutZones and WorkAreas with individual handlers
  • Removes dynamic channel creation in favor of separate Things with dedicated channels
  • Updates discovery service to automatically discover and create Things for zones and work areas

In addition, following improvements are implemented / issues are fixed:

  • Background Discovery Service implemented
  • Fixed issue, where bridge could require an entire polling cycle to go ONLINE
  • Fixed issue, where handleCommand() for CHANNEL_WORKAREA_ENABLED and CHANNEL_WORKAREA_CUTTING_HEIGHT was mixed up
  • Channel Naming and Refactoring (lower-case-hyphen)
  • Support of channel refresh command

@MikeTheTux MikeTheTux added the work in progress A PR that is not yet ready to be merged label Aug 30, 2025
@MikeTheTux MikeTheTux marked this pull request as draft August 30, 2025 20:40
Signed-off-by: Michael Weger <[email protected]>
@MikeTheTux MikeTheTux requested a review from Copilot August 30, 2025 20:45

This comment was marked as outdated.

Signed-off-by: Michael Weger <[email protected]>
Signed-off-by: Michael Weger <[email protected]>
Signed-off-by: Michael Weger <[email protected]>
Signed-off-by: Michael Weger <[email protected]>
@MikeTheTux MikeTheTux marked this pull request as ready for review September 4, 2025 17:47
@MikeTheTux MikeTheTux added enhancement An enhancement or new feature for an existing add-on and removed work in progress A PR that is not yet ready to be merged labels Sep 4, 2025
@MikeTheTux MikeTheTux requested a review from Copilot September 4, 2025 17:48

This comment was marked as outdated.

Signed-off-by: Michael Weger <[email protected]>
Signed-off-by: Michael Weger <[email protected]>
@MikeTheTux
Copy link
Contributor Author

@lsiepel This is the PR for the improvement that I was mentioning in #18630 (comment)

Could you please have a look?

@MikeTheTux MikeTheTux requested a review from lsiepel September 4, 2025 18:57
Signed-off-by: Michael Weger <[email protected]>
Copy link
Contributor

@lsiepel lsiepel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for creating the follow-up PR. I left some comments to look at. I have not seen a milestone release date yet, but it should not be long. Let's see if we can get this in.

@MikeTheTux
Copy link
Contributor Author

Thanks for creating the follow-up PR. I left some comments to look at. I have not seen a milestone release date yet, but it should not be long. Let's see if we can get this in.

I'll try to be reactive in order to bring the changes into next release. This would avoid one additional breaking update.

@MikeTheTux
Copy link
Contributor Author

I did some testing from OH5.0.1 to this version. Some channel updates of static channels have been missed and are now added via ab0c995.

The binding still throws errors. These come from the channels who have been created with the old binding version and are no longer there / or with changed type in the new binding version.

Do I need to write code in the new binding, searching and deleting orphan channels?
Or shall I change the update instruction: re-add thing?

@lsiepel
Copy link
Contributor

lsiepel commented Sep 17, 2025

e binding still throws errors. These come from the channels who have been created with the old binding version and are no longer there / or with changed type in the new binding version.

If you have some examples i can offer better guidances. But in general, it will be best to remove channels that are not there anymore, but where missed from previous upgrade instructions.

Same applies to changed channel type's, but i would expect if those are part of previosu upgrade instructions that they fail.

Do not alter previous ugprade instructions, only if a blocking issue occurs and prevents to complete the instruction at all, remaining the thing stuck upgrading.

@MikeTheTux
Copy link
Contributor Author

There are some channels in the automower thing, that have been created dynamically (in code) based on certain conditions in thing version 1 & 2.
With thing version 3, the conditions for generating these channels change, as well as the channel-uid (e.g. changed group name).

Static update instruction in update.xml will not do the job. I need to write code that is deleting channels that are no longer valid in thing version 3.
image

image

Adding this kind of code comes with the drawback that the migration code is part of the binding implementation and needs to maintained forever as a consequence.

@lsiepel
Copy link
Contributor

lsiepel commented Sep 18, 2025

In zwavejs binding, i solved this by:

  1. creating a list of channels on Thing initialize
  2. a: add all missing channels to the Thing
  3. b: remove all channels that are orphaned

This ensures that i do not need to keep track of versions or whatever. looping those channels is an ultra minor step. I hope we do not need to have 'in code' upgrade instructions that we need to maintain for years.

@MikeTheTux
Copy link
Contributor Author

  • creating a list of channels on Thing initialize

  • a: add all missing channels to the Thing

  • b: remove all channels that are orphaned

That makes sense. I've implemented already something similar in

@MikeTheTux
Copy link
Contributor Author

I'm still struggling with the upgrade from v1 (OH5.0.1) to v3:

  • automower thing init runs in 120s timeout
2025-09-19 07:45:09.199 [WARN ] [core.thing.internal.ThingManagerImpl] - Channel types or config descriptions for thing 'automower:automower:asdf-jkloe' are missing in the respective registry for more than 120s. In case it does not happen immediately after an upgrade, it should be fixed in the binding.
2025-09-19 07:45:09.218 [ERROR] [.update.UpdateChannelInstructionImpl] - Failed to create channel 'automower:automower:asdf-jkloe:message#msg-timestamp' because channel type 'automower:messageTimeType' could not be found.
2025-09-19 07:45:09.219 [ERROR] [.update.UpdateChannelInstructionImpl] - Failed to create channel 'automower:automower:asdf-jkloe:message#msg-code' because channel type 'automower:messageCodeType' could not be found.
2025-09-19 07:45:09.220 [ERROR] [.update.UpdateChannelInstructionImpl] - Failed to create channel 'automower:automower:asdf-jkloe:message#msg-text' because channel type 'automower:messageType' could not be found.
2025-09-19 07:45:09.221 [ERROR] [.update.UpdateChannelInstructionImpl] - Failed to create channel 'automower:automower:asdf-jkloe:message#msg-severity' because channel type 'automower:messageSeverityType' could not be found.
2025-09-19 07:45:09.221 [ERROR] [.update.UpdateChannelInstructionImpl] - Failed to create channel 'automower:automower:asdf-jkloe:message#msg-gps-position' because channel type 'automower:messagePositionType' could not be found.
2025-09-19 07:45:09.222 [ERROR] [.update.UpdateChannelInstructionImpl] - Failed to create channel 'automower:automower:asdf-jkloe:command#start_in_work_area' because channel type 'automower:startInWorkArea' could not be found.
2025-09-19 07:45:09.226 [INFO ] [core.thing.internal.ThingManagerImpl] - Updating 'automower:automower:asdf-jkloe' from version 1 to 3
2025-09-19 07:45:09.294 [WARN ] [core.thing.internal.ThingManagerImpl] - Failed to normalize configuration for new thing during update 'automower:automower:asdf-jkloe': {thing/channel=Type description automower:workAreaIdType for automower:automower:asdf-jkloe:status#work-area-id not found, although we checked the presence before.}

There does exist an update channel instructions for the msg channels:

<update-channel id="msg-timestamp" groupIds="message">
<type>automower:message-time-type</type>
</update-channel>
<update-channel id="msg-code" groupIds="message">
<type>automower:message-code-type</type>
</update-channel>
<update-channel id="msg-text" groupIds="message">
<type>automower:message-type</type>
</update-channel>
<update-channel id="msg-severity" groupIds="message">
<type>automower:message-severity-type</type>
</update-channel>
<update-channel id="msg-gps-position" groupIds="message">
<type>automower:message-position-type</type>
</update-channel>

@lsiepel
Copy link
Contributor

lsiepel commented Sep 19, 2025

I installed the native binding in the latest snapshot, added the automower, and linked the msg-timestamp channel. Since I don’t have a bridge (or device), it doesn’t go online, but everything looks fine. The thing type version is 2.

I then removed the binding, dropped in the jar from this PR, and the thing/channel updated as expected:

2025-09-19 10:11:21.779 [WARN ] [core.thing.internal.ThingManagerImpl] - Channel types or config descriptions for thing 'automower:automower:cfbb90f8fe' are missing in the respective registry for more than 120s. In case it does not happen immediately after an upgrade, it should be fixed in the binding.
2025-09-19 10:11:21.780 [INFO ] [core.thing.internal.ThingManagerImpl] - Updating 'automower:automower:cfbb90f8fe' from version 2 to 3

I noticed your mower thing is still at version 1. The channel type that fails was introduced in v2, so it looks like the thing does not upgrade from v1 to v2.

Maybe related to https://github.com/openhab/openhab-addons/pull/18630/files#r2207150423

@MikeTheTux
Copy link
Contributor Author

I noticed your mower thing is still at version 1. The channel type that fails was introduced in v2, so it looks like the thing does not upgrade from v1 to v2.

I’m currently testing the upgrade path from v1 to v3, since this is likely the most common scenario for users on the stable release.

From my perspective, the update process seems problematic:

  1. In binding v1, there is no msg-timestamp channel or automower:messageTimeType type.
  2. In <instruction-set targetVersion="2">, a new channel msg-timestamp with type automower:messageTimeType is added.
  3. In <instruction-set targetVersion="3">, the same channel is updated to use type automower:message-time-type.
  4. openHAB reports that the v2 type automower:messageTimeType is missing, which makes sense because v3 only provides the new type automower:message-time-type.

How does openHAB core handle multiple sequential updates? If it processes updates in order (1 → 2 → 3), this will always cause issues like this, since intermediate channel types may not exist in the final binding version.

While the resulting error could be ignored, it’s tied to a 120s timeout:

During this timeout, the Thing remains "Not Yet Ready." Furthermore any channel update in code (via thingBuilder.withChannels(channelList)) occurs after the timeout only.

In summary, upgrading from v1 to v3 results in log errors, a 120s timeout, and additional delay (cycle time) before the binding goes ONLINE. After that, everything works as expected.

Is this normal and accepted behavior, or am I missing something?

@lsiepel
Copy link
Contributor

lsiepel commented Sep 19, 2025

How does openHAB core handle multiple sequential updates? If it processes updates in order (1 → 2 → 3), this will always cause issues like this, since intermediate channel types may not exist in the final binding version.

They are processed in order, not directly to the final version. Exactly to prevent the case you describe.

I wonder if you can test the upgrade from v1 to v2 and check if the msg-timestamp with type automower:messageTimeType is added as expected and the thing type version is actuall set to 2.

The 120s timeout is because it cannot find the thing type and waits before it is added to the thingtypeprovider, but you are not using that provider, so it waits until the timout. That is just a side effect of the upgrade failing.

@MikeTheTux
Copy link
Contributor Author

MikeTheTux commented Sep 19, 2025

I wonder if you can test the upgrade from v1 to v2

Successfully tested the update from v1 to v2 to v3:
image

org.openhab.binding.automower-5.0.2-v1.jar:
2025-09-19 17:27:41.182 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'automower:automower:asdf-jkloe' to inbox.
org.openhab.binding.automower-5.0.2-v2.jar:
2025-09-19 17:31:50.222 [WARN ] [core.thing.internal.ThingManagerImpl] - Channel types or config descriptions for thing 'automower:automower:asdf-jkloe' are missing in the respective registry for more than 120s. In case it does not happen immediately after an upgrade, it should be fixed in the binding.
2025-09-19 17:31:50.252 [INFO ] [core.thing.internal.ThingManagerImpl] - Updating 'automower:automower:asdf-jkloe' from version 1 to 2
org.openhab.binding.automower-5.0.2-v3.jar
2025-09-19 17:35:31.638 [WARN ] [core.thing.internal.ThingManagerImpl] - Channel types or config descriptions for thing 'automower:automower:asdf-jkloe' are missing in the respective registry for more than 120s. In case it does not happen immediately after an upgrade, it should be fixed in the binding.
2025-09-19 17:35:31.651 [INFO ] [core.thing.internal.ThingManagerImpl] - Updating 'automower:automower:asdf-jkloe' from version 2 to 3
2025-09-19 17:35:31.686 [WARN ] [core.thing.internal.ThingManagerImpl] - Failed to normalize configuration for new thing during update 'automower:automower:asdf-jkloe': {thing/channel=Type description automower:calendarTaskStartType for automower:automower:asdf-jkloe:calendartask#01-task-start not found, although we checked the presence before.}

No msg-timestamp issue in this case.

But an warning regarding the dynamic channels when updating to v3:
Thing.initialize() is called after the 01-task-start warning. In Thing.initialize() dynamically created, orphan channels like 01-task-start are removed. To late for the warning after the first init during update. Due to the clean-up of orphan channels, the warning is gone in a subsequent init.

When going incremental from v1 to v2 to v3:

  • 3 Warnings incl. 2 times the 120s delay during init

When going directly from v1 to v3:

  • 6 Errors
  • 1 Warning incl. the 120s delay during init

They are processed in order, not directly to the final version. Exactly to prevent the case you describe.

When going in order from v1 to v3, the first update from v1 to v2 will always create the 6 Errors, as in the present Binding (org.openhab.binding.automower-5.0.2-v3.jar), the CamelCase channel types (e.g. automower:messageTimeType) are no longer present.

Regardless of the log entries, the binding is functional and operating without further warnings after the update.

@lsiepel
Copy link
Contributor

lsiepel commented Sep 20, 2025

We can probably merge this as is, in the end the binding works as expected. Nevertheless i wonder why these upgrades give issues. Maybe @jlaur can share his thoughts on this.

@MikeTheTux
Copy link
Contributor Author

Yes, let's get it merged.

@bern77, I compiled an OH5.0.2 version of these latest changes.
Would you like to give it a try? On the last PR you had quite some good feedback.
org.openhab.binding.automower-5.0.2-SNAPSHOT.jar.zip

@bern77
Copy link
Contributor

bern77 commented Sep 22, 2025

Thanks, I'll give it a try! But most likely not before Sunday... I'll keep you posted on any findings!

@bern77
Copy link
Contributor

bern77 commented Sep 30, 2025

Thanks, I'll give it a try! But most likely not before Sunday... I'll keep you posted on any findings!

Sorry, it's a bit busy at the moment... I tried to take your snapshot for a spin, but ran into the old issue of getZones() not getting any results from the API:

2025-09-30 19:23:29.071 [WARN ] [mmon.WrappedScheduledExecutorService] - Scheduled runnable ended with an exception:
java.lang.NullPointerException: Cannot invoke "org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.StayOutZones.getZones()" because the return value of "org.openhab.binding.automower.internal.rest.api.automowerconnect.dto.MowerData.getStayOutZones()" is null
        at org.openhab.binding.automower.internal.bridge.AutomowerBridgeHandler.pollAutomowers(AutomowerBridgeHandler.java:183) ~[?:?]
        at org.openhab.binding.automower.internal.things.AutomowerHandler.poll(AutomowerHandler.java:358) ~[?:?]
        at org.openhab.binding.automower.internal.things.AutomowerHandler.completeInitAsync(AutomowerHandler.java:248) ~[?:?]
        at org.openhab.binding.automower.internal.things.AutomowerHandler.lambda$3(AutomowerHandler.java:237) ~[?:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) ~[?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?]
        at java.lang.Thread.run(Thread.java:1583) [?:?]

Obviously, I've not received any response from Husqvarna on my ticket but that would have been quite a suprise anyway.

So I fell back to a 5.1.0 snapshot from end of July, which works for me...

@MikeTheTux
Copy link
Contributor Author

but ran into the old issue of getZones() not getting any results from the API:

Thanks for giving it a try and sorry that you have to report a similar problem again.
Unfort. we still lack good regression tests. Therefore I'm very thankful for your test feedback.

Can you please have a second try on this update?
org.openhab.binding.automower-5.0.2-SNAPSHOT-v2.jar.zip

Signed-off-by: Michael Weger <[email protected]>
@bern77
Copy link
Contributor

bern77 commented Oct 1, 2025

Can you please have a second try on this update? org.openhab.binding.automower-5.0.2-SNAPSHOT-v2.jar.zip

Thanks for the fix - I've installed the new snapshot, now bringe + thing go online smoothly. I'll keep an eye on it and report any findings!

@MikeTheTux
Copy link
Contributor Author

Can you please have a second try on this update? org.openhab.binding.automower-5.0.2-SNAPSHOT-v2.jar.zip

Thanks for the fix - I've installed the new snapshot, now bringe + thing go online smoothly. I'll keep an eye on it and report any findings!

Big thanks! Please be aware, that with this version individual Things for WorkAreas (and Stayout Zones - that you do not have) are needed.

@bern77
Copy link
Contributor

bern77 commented Oct 1, 2025

Big thanks! Please be aware, that with this version individual Things for WorkAreas (and Stayout Zones - that you do not have) are needed.

Thanks, that's a good hint indeed - I've updated my config accordingly! Way better design this way 😊

@lsiepel
Copy link
Contributor

lsiepel commented Oct 1, 2025

I'll monitor this PR, please report when all is green.

@bern77
Copy link
Contributor

bern77 commented Oct 4, 2025

I'll keep an eye on it and report any findings!

In the log I see the following warning every now and then:

2025-10-04 10:00:00.541 [WARN ] [.core.thing.binding.BaseThingHandler] - Handler AutomowerHandler of thing automower:automower:amconnect3:<id> tried accessing its bridge although the handler was already disposed.
2025-10-04 10:00:00.541 [WARN ] [.core.thing.binding.BaseThingHandler] - Handler AutomowerHandler tried updating the thing status although the handler was already disposed.

@MikeTheTux
Copy link
Contributor Author

I'll keep an eye on it and report any findings!

In the log I see the following warning every now and then:

2025-10-04 10:00:00.541 [WARN ] [.core.thing.binding.BaseThingHandler] - Handler AutomowerHandler of thing automower:automower:amconnect3:<id> tried accessing its bridge although the handler was already disposed.
2025-10-04 10:00:00.541 [WARN ] [.core.thing.binding.BaseThingHandler] - Handler AutomowerHandler tried updating the thing status although the handler was already disposed.

My explanation is that the issue was caused by the first, failing upgrade attempt of the binding.
The binding ran into the exception, resources (e.g. the discovery service) have not been cleaned up.

Can you confirm that ...

  • ... the error logging started already after the first failing update?
  • ... the error is gone, once you restart openHAB?

@bern77
Copy link
Contributor

bern77 commented Oct 5, 2025

Can you confirm that ...

  • ... the error logging started already after the first failing update?
  • ... the error is gone, once you restart openHAB?

Yes, I think you're right. The error appeared after the upgrade and since I restarted earlier today is hasn't appeared anymore.

@MikeTheTux
Copy link
Contributor Author

MikeTheTux commented Oct 6, 2025

I'll monitor this PR, please report when all is green.

@lsiepel: let's merge. I will not have any further input as my mower went into winter break.

@bern77: thx for your testing efforts. Please reach out to me, if you have any further finding.

@lsiepel lsiepel merged commit e375b93 into openhab:main Oct 10, 2025
2 checks passed
@lsiepel lsiepel added this to the 5.1 milestone Oct 10, 2025
DrRSatzteil pushed a commit to DrRSatzteil/openhab-addons that referenced this pull request Oct 11, 2025
…tems (openhab#19268)

* split automower stayout zones and work areas into individual things/AutomowerCommand.java

Signed-off-by: Michael Weger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement An enhancement or new feature for an existing add-on (potentially) not backward compatible

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants