Skip to content
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

[boschshc] Add support for Light/Shutter Control II #16400

Merged
merged 17 commits into from
Mar 31, 2024

Conversation

david-pace
Copy link
Member

@david-pace david-pace commented Feb 12, 2024

Description

This PR adds support for another Bosch Smart Home device, namely Light/Shutter Control II. The device can either be configured as shutter control or as light control with two light switch circuits.

Testing

JAR Download for Testing

@david-pace david-pace added the enhancement An enhancement or new feature for an existing add-on label Feb 12, 2024
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.

Code looks good, thanks!
Left some comments, mainly documentation.

@david-pace
Copy link
Member Author

Hi @GerdZanker, @jlaur and @lsiepel, I would like to discuss the thing/channel modeling approach for this device with you.

We have the following situation: Bosch provides a device that can be configured either as a shutter control or a light switch with two light switch circuits. The shutter control configuration is straight-forward (one device, one thing type, corresponding channels).

However, when configured as two light switches, we see a parent device (it provides basic services such as communication quality and power metering) and two child devices, that represent the light switch circuits.

In my current implementation I have modeled it in the same way in openHAB. I introduced two different thing types, and the user sees three things. Here is an overview of the things and channels:

  • Light Control II (parent device)
    • system channel signal-strength indicating communication quality
    • channels power-consumption and energy-consumption for combined power metering
  • Light Switch 1 (this is a logical child device of the parent device)
    • system channel power-switch to control the light circuit
    • channel child-protection to control child protection (for each light switch circuit separately)
  • Light Switch 2 (this is a logical child device of the parent device)
    • system channel power-switch to control the light circuit
    • channel child-protection to control child protection (for each light switch circuit separately)

Currently the user sees three independent things in openHAB, but they belong to one single physical device. From a technical perspective, this is the most straight-forward mapping, but I'm aware that this might not be the most user-friendly one, since users might expect one thing per physical device. Indeed, @mike-bike who was so kind to test my code already mentioned that this might be counter-intuitive for users (see #14562 (comment)).

However, my rationale for separating the things was that the channel names are always the same this way. If we combined all these channels into one thing then we would need to "number" certain channels like this:

  • Light Control II (parent device)
    • system channel signal-strength indicating communication quality
    • channels power-consumption and energy-consumption for combined power metering
    • system channel power-switch-1 to control light circuit 1
    • system channel power-switch-2 to control light circuit 2
    • channel child-protection-1 to control child protection for light circuit 1
    • channel child-protection-2 to control child protection for light circuit 2

The problem is that this does not scale well. For example, if devices are released in the future that allow more switch circuits or even more complex / mixed configurations (like shutter controls, dimmers, relays, light switches freely configurable) then the channels would have to be configured in a dynamic way. If we keep the thing separation, we can use "thing composition" to model the configuration.

What would be your preferred way to model this device and possible future devices in terms of the openHAB model? Are dynamic channel configurations possible and would you prefer it in this case?

Also: the Light Control II device has the bridge as parent device. Is it possible to model deeper parent-child relations, such as the Light Switch being a child of Light Control II (and therefore a grandchild of the bridge)?

@david-pace david-pace added awaiting feedback work in progress A PR that is not yet ready to be merged labels Feb 13, 2024
@david-pace david-pace linked an issue Feb 13, 2024 that may be closed by this pull request
@jlaur
Copy link
Contributor

jlaur commented Feb 13, 2024

Also: the Light Control II device has the bridge as parent device. Is it possible to model deeper parent-child relations, such as the Light Switch being a child of Light Control II (and therefore a grandchild of the bridge)?

Yes, that is possible, and I would actually suggest to go with your first proposition of separate things, but make the parent Light Control II a bridge. The Netatmo binding is one example of having multiple levels:

  • account (logical bridge to reuse Netatmo cloud account across different weather stations)
    • weather station (physical device connected to Wi-Fi)
      • additional indoor module (physical battery-powered device with proprietary wireless connection to the weather station)
      • outdoor module
      • etc.

@mike-bike
Copy link

mike-bike commented Feb 14, 2024

I do not think, that Netatmo actually fits to the Bosch device. Netatmo (and Weather Service providers etc) support user defined multiple „devices“ e.g. weather channels or weather stations etc. There the "root" thing acting as bridge makes sense.
The Bosch device Light Control II is a well defined closed devise. It has 2 separate switches build into a fixed device. Even in future, if Bosch would provide more complex devices, they will have defined finite characteristics pending on the configuration. Having the Bosch root device act as bridge seems to me overkill.

Defined as Roller Shutter II it has:

  1. actual Power (W)
  2. cumulated Energy (Wh)
  3. Signal Strength
  4. Up
  5. Down
  6. Opening %
  7. Child protection
  8. plus addtl configuration items which may not be relevant for openHAB

Defined as Light Switch II it has:

  1. actual Power consumption (W)
  2. cumulated Energy (Wh)
  3. Signal Strength
  4. On/Off 1
  5. Child Protection 1
  6. automatic Timeout 1
  7. On/Off 2
  8. Child Protection 2
  9. automatic Timeout 2

Though, I do not have any idea about the implementation complexity to define dynamic channels, but to me it would make logical sense to have it as one thing.

Anyway, current setup works for me as well. I am happy about the support!

Thanks guys

Take care,
Michael

@lsiepel
Copy link
Contributor

lsiepel commented Feb 14, 2024

I must say that this is no simple choice. If you model it as the suggested parent/child, i must agree with @mike-bike it feels a bit overcomplicated.
From code perspective (re-use / composition) it suits good to have a parent child setup.
From user perspective; i bought one device and when i add it in openHAB it is represented as three Things. That's somewhat strange. That is also where it differs to the netatmo binding as those child Things are actual different hardware devices.

About the scalability: don't know if you expect future devices with 3+ circuits, but i would not make this (not yet existing) problem a big issue. And if a device with many more circuits is introduced, it can allways be modeled as a parent/child device.

Anyway, not making it easier here, but i would sugggest a more 'flat' structure of the Thing with numbered channels. Similar to how the z-wave binding handles a two button switch.

@david-pace
Copy link
Member Author

Thank you very much for your input @jlaur, @lsiepel and @mike-bike.

After having experimented with the parent/child model with two bridges, I am not really satisfied with the user experience. The Light Shutter Control II seems much harder to configure than the other devices although it's not really such a different device.

Bosch exposes it as parent device with two child devices on the technical level, but this does not mean that the user (or the user interface) has to be aware of this technical representation.

Maybe we can clarify the following before we proceed:

  • @mike-bike, can you tell us a bit about how this device is presented on the Bosch user interface (in the app)? Does it feel like one device or more like two devices? Does the user see anything related to the parent/child separation or does it rather feel like a single device that is configured?
  • Thanks for the hint with the two-button switch in the Z-Wave binding, @lsiepel. I will take a look at the thing type definition and the handler code once I find some time in order to find out whether this model is more suitable in our case.

After that we might have more context information to make a decision. Thank you all for your input and support 👍

@mike-bike
Copy link

mike-bike commented Feb 14, 2024

That's a good question. Interestingly it is shown as two devices in the Bosch App, there is no parent. Both devices do have the power consumption and energy as attributes. They both show the same consolidated values, but if a device is switched off, it shows power consumption 0 even though the other may consume power. If it is on, it shows the one consolidated value. The signal strengths is not visible in any of the Light Switch devices. It will only become an option if the device is configured as Roller Shutter.
That is an interesting alternative option (always a new way to look at things): two separate devices if configured as light switch and one device if configured as a roller shutter.

Please note, that I only can describe the visualization in the Bosch App and not the underlying software model. Similar view could be achieved in OpenHAB UI (e.g. by grouping) independent of the number of things.

(Edit: inline images removed. Happy to share via PM as needed)

@david-pace
Copy link
Member Author

@lsiepel I just tried to find the two-button z-wave switch, but I got lost because there are tons of thing definitions 😆 Could you please direct me to a relevant thing definition and the corresponding handler implementation?

@lsiepel
Copy link
Contributor

lsiepel commented Feb 16, 2024

t tried to find the two-button z-wave switch, but

I'm not familiair with the z-wave code. My suggestions was purely from functional perspective. It is one device, that has 2-buttons. They are modelled exactly as @mike-bike suggested, so i would suggest to create something like:
actual Power consumption (W)
cumulated Energy (Wh)
Signal Strength
On/Off 1
Child Protection 1
automatic Timeout 1
On/Off 2
Child Protection 2
automatic Timeout 2

How to construct those channels in code from the Bosch devices is beyond my knowledge about this device. But i don't think it would be that difficult for you.

@david-pace
Copy link
Member Author

After having thought about the different possibilities for some time I'm now also in favor of this model (one thing type, numbered channels). I will provide an implementation as soon as possible 👍

@jlaur, I hope that you are also OK with this approach since it's different from what you suggested previously.

@jlaur
Copy link
Contributor

jlaur commented Feb 16, 2024

@jlaur, I hope that you are also OK with this approach since it's different from what you suggested previously.

Definitely, it sounds like the best solution now when I have seen all arguments. 👍 My proposal was made when not knowing all details, and was mostly to confirm that multiple layers of bridges is possible and sometimes useful. I agree on the more flat structure for this particular case confined by specific hardware with exactly two switches.

@david-pace
Copy link
Member Author

I just finished an implementation with a single thing type and re-uploaded the JAR 👍

@mike-bike could you please download and test again? Note that it's important to delete all things and channels belonging to the old implementation, otherwise you might run into persistence / configuration issues. So the order should be

  1. delete all things and channels that have anything to do with Light Control II
  2. download and install JAR
  3. create a new Light Control II thing (in the best case the discovery will propose it, otherwise manually)
  4. test all channels

@mike-bike
Copy link

Done. Old channels and things deleted and new one identified as new thing activated. Items relinked.
It seems to be working ok. One thing with all channels. Switch changes reflected immediately in Bosch App and vice versa. Update to power consumption a bit delayed in openHAB due to update latency.
Will test a more tomorrow, but for now all is working fine.

Bildschirmfoto 2024-02-17 um 22 18 48 Bildschirmfoto 2024-02-17 um 22 59 09

Great work! Amazing, considering that you do not have that physical device available for testing!

Regards,
Michael

@david-pace
Copy link
Member Author

david-pace commented Feb 19, 2024

Thanks for testing again and for your feedback ❤️ That's really amazing considering the amount of code that was changed in the mean time 😉 I guess it does pay off to work with unit tests 😎

I'm working on code cleanups, some refactorings that are required now, maximizing unit test coverage and documentation. Will push some code soon. Stay tuned 👍

@david-pace david-pace removed the work in progress A PR that is not yet ready to be merged label Feb 19, 2024
@david-pace
Copy link
Member Author

david-pace commented Feb 19, 2024

I pushed my changes and the PR is open for code reviews again 👍

Note for the reviewers @lsiepel @jlaur and @GerdZanker: it might be easier to compare against main as opposed to the last commit that you reviewed, because commit 6 makes large parts of the code up to commit 5 obsolete.

@mike-bike I propose to wait until after the code reviews before the next (and hopefully last) test iteration. You need to test once more that all my refactorings worked and we might change the labels/identifiers (e.g. childId1, childId2) in the configuration. Nevertheless, I updated the JAR again in case you want to do intermediate tests anyways.

@mike-bike
Copy link

@mike-bike I propose to wait until after the code reviews before the next (and hopefully last) test iteration. You need to test once more that all my refactorings worked and we might change the labels/identifiers (e.g. childId1, childId2) in the configuration. Nevertheless, I updated the JAR again in case you want to do intermediate tests anyways.

Hi @david-pace, I will wait until advised. Happy to test when you are ready.

@david-pace david-pace added the work in progress A PR that is not yet ready to be merged label Feb 22, 2024
Signed-off-by: David Pace <dev@davidpace.de>
the i18n generator seems to behave incorrectly when entries are removed

Signed-off-by: David Pace <dev@davidpace.de>
Signed-off-by: David Pace <dev@davidpace.de>
Signed-off-by: David Pace <dev@davidpace.de>
Signed-off-by: David Pace <dev@davidpace.de>
Signed-off-by: David Pace <dev@davidpace.de>
Signed-off-by: David Pace <dev@davidpace.de>
@david-pace
Copy link
Member Author

I rebased everything on main and also suppressed the log entry Unknown deviceModel 'MICROMODULE_LIGHT_ATTACHED'! Please create a support request issue for this unknown device model..

@mike-bike please test again with the new JAR and let me know how the childDeviceIds arrays look (for both of your Light Control II devices) when you query the device list from the controller at /devices.

@mike-bike
Copy link

I rebased everything on main and also suppressed the log entry Unknown deviceModel 'MICROMODULE_LIGHT_ATTACHED'! Please create a support request issue for this unknown device model..

I cannot see any such log entry with the new JAR any longer. ==> Fixed!

@mike-bike please test again with the new JAR and let me know how the childDeviceIds arrays look (for both of your Light Control II devices) when you query the device list from the controller at /devices.

Deleted all items and things and loaded new JAR. Devices discovered and added to Inbox. I have added 1 device to the model and tested functionality:

  • switch-1 and switch-2 consistent with Bosch naming and wiring
  • switches and power meter working and in sync with Bosch app

For me it looks good!

Not sure what you mean by childDeviceIds arrays. Is this the result set from create request for https://192.168.2.61:8444/smarthome/devices ?

If so, please see snipped below. However, I could not find any of the additional logs you have mentioned earlier. No "sorting" or "successfully"...

I have loaded the following:
-rw-r--r-- 1 openhabian openhab 7073827 Feb 27 08:07 org.openhab.binding.boschshc-4.2.0-SNAPSHOT-shutter-control-2.jar
265 │ Active │ 80 │ 4.2.0.202402270706 │ openHAB Add-ons :: Bundles :: Bosch Smart Home Binding

Here the relevant extract from the log:
{"@type":"device","rootDeviceId":"64-da-a0-10-83-a7","id":"hdm:ZigBee:3425b4fffe3fcb04#3","deviceServiceIds":["PowerSwitch","ChildProtection","PowerSwitchProgram"],"manufacturer":"BOSCH","roomId":"hz_16","deviceModel":"MICROMODULE_LIGHT_ATTACHED","serial":"3425B4FFFE3FCB04","profile":"GENERIC","iconId":"icon_mm_light_generic","name":"taste 2","status":"AVAILABLE","parentDeviceId":"hdm:ZigBee:3425b4fffe3fcb04","childDeviceIds":[],"supportedProfiles":[]},{"@type":"device","rootDeviceId":"64-da-a0-10-83-a7","id":"hdm:ZigBee:3425b4fffe3fcb04#2","deviceServiceIds":["PowerSwitch","ChildProtection","PowerSwitchProgram"],"manufacturer":"BOSCH","roomId":"hz_16","deviceModel":"MICROMODULE_LIGHT_ATTACHED","serial":"3425B4FFFE3FCB04","profile":"GENERIC","iconId":"icon_mm_light_generic","name":"taste 1","status":"AVAILABLE","parentDeviceId":"hdm:ZigBee:3425b4fffe3fcb04","childDeviceIds":[],"supportedProfiles":[]}

2024-02-28 21:58:20.459 [TRACE] [rnal.discovery.ThingDiscoveryService] - Discovering device LightMM_3425b4fffe3fcb04

2024-02-28 21:58:20.461 [TRACE] [rnal.discovery.ThingDiscoveryService] - - details: id hdm:ZigBee:3425b4fffe3fcb04, roomId null, dev iceModel MICROMODULE_LIGHT_CONTROL

2024-02-28 21:58:20.462 [TRACE] [rnal.discovery.ThingDiscoveryService] - - got thingTypeID 'light-control-2' for deviceModel 'MICROM ODULE_LIGHT_CONTROL'

2024-02-28 21:58:20.464 [TRACE] [rnal.discovery.ThingDiscoveryService] - - got thingUID 'boschshc:light-control-2:192-168-2-61:hdm_ZigBee_3425b4fffe3fcb04' for device: 'Type device; RootDeviceId: 64-da-a0-10-83-a7; Id: hdm:ZigBee:3425b4fffe3fcb04; Device Service Ids: CommunicationQuality, PowerMeter, ElectricalFaults, SwitchConfiguration; Manufacturer: BOSCH; Room Id: null; Device Model: MICROMODULE_LIGHT_CONTROL; Serial: 3425B4FFFE3FCB04; Profile: GENERIC; Name: LightMM_3425b4fffe3fcb04; Status: AVAILABLE; Child Device Ids: hdm:ZigBee:3425b4fffe3fcb04#3, hdm:ZigBee:3425b4fffe3fcb04#2 '

2024-02-28 21:58:20.477 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'boschshc:light-control-2:192-168-2-61:hdm_ZigBee_3425b4fffe3fcb04' to inbox.

2024-02-28 21:58:20.481 [DEBUG] [rnal.discovery.ThingDiscoveryService] - Discovered device 'LightMM_3425b4fffe3fcb04' with thingTypeUID=boschshc:light-control-2:192-168-2-61:hdm_ZigBee_3425b4fffe3fcb04, thingUID=boschshc:light-control-2, id=hdm:ZigBee:3425b4fffe3fcb04, deviceModel=MICROMODULE_LIGHT_CONTROL

Please let me know if I can help any further.

PS: How do I get the code snippes into the browser window without breaking the lines whenever I paste from the terminal window?

@mike-bike
Copy link

@david-pace , correction! I did a restart after clearing the cache. After a while (the PI2 is soooo slooooow) I think I found what you were asking for (pls ignore the ugly formatting):

2024-02-28 22:54:01.932 [TRACE] [es.lightcontrol.LightControl2Handler] - Device validated and initialized: Type device; RootDeviceId: 64-da-a0-10-83-a7; Id: hdm:ZigBee:70ac08fffefead2d; Device Service Ids: PowerMeter, CommunicationQuality, ElectricalFaults, SwitchConfiguration; Manufacturer: BOSCH; Room Id: null; Device Model: MICROMODULE_LIGHT_CONTROL; Serial: 70AC08F FFEFEAD2D; Profile: GENERIC; Name: LightMM_70ac08fffefead2d; Status: AVAILABLE; Child Device Ids: hdm:ZigBee:70ac08fffefead2d#3, hdm :ZigBee:70ac08fffefead2d#2 2024-02-28 22:54:01.935 [DEBUG] [es.lightcontrol.LightControl2Handler] - Initializing child devices of Light Control II, child device IDs from device info: [hdm:ZigBee:70ac08fffefead2d#3, hdm:ZigBee:70ac08fffefead2d#2] 2024-02-28 22:54:01.937 [TRACE] [es.lightcontrol.LightControl2Handler] - Child device IDs for Light Control II after sorting: [hdm:ZigBee:70ac08fffefead2d#2, hdm:ZigBee:70ac08fffefead2d#3]

@david-pace
Copy link
Member Author

Hi @mike-bike, thank you so much for testing again 👍

You can paste code, log files etc. in so called fenced code blocks. Begin and end a block with triple backticks like this:

```
Code or logfile goes here
```

Thanks to your analysis we now know that the Smart Home Controller seems to list the child device IDs in a somewhat strange order. For both of your devices, we first get #3 and then #2:

  • Shutter Control II hdm:ZigBee:70ac08fffefead2d (Brunnen, Olivenbaum)
    • hdm:ZigBee:70ac08fffefead2d#3
    • hdm:ZigBee:70ac08fffefead2d#2
  • Shutter Control II hdm:ZigBee:3425b4fffe3fcb04 (the newer one wired for testing purposes)
    • hdm:ZigBee:3425b4fffe3fcb04#3
    • hdm:ZigBee:3425b4fffe3fcb04#2

It looks like #2 always corresponds to the physical Q1 pin and #3 to Q2. Since the implementation sorts the child device IDs, this association is guaranteed.

It looks like we could even hardcode the child device IDs to [parent device ID]#2 and [parent device ID]#3 but I propose to leave the code as it is and ask the controller for the child device IDs dynamically. There is no performance impact compared to the current release because we contact the controller anyway to get the device info (previously only to validate that the parent device ID is valid, now we also process the already parsed JSON result and check the child device IDs).

In this case I would say the code is open for code reviews again 😎

Thank you very much for your testing support @mike-bike ❤️

@david-pace david-pace removed awaiting feedback work in progress A PR that is not yet ready to be merged labels Feb 29, 2024
@david-pace
Copy link
Member Author

david-pace commented Mar 9, 2024

Note to the reviewers @GerdZanker, @jlaur and @lsiepel: I created two additional PRs on top of this one:

The other two PRs are much easier to review once this PR is merged, because otherwise all the commits from this PR will "clutter" the other PRs. I will therefore wait until this PR is reviewed and merged, then rebase the other ones, and then add you as reviewers.

It's not time-critical since we are not talking about bugfixes, but rather about functional enhancements and stability improvements through tests. I just wanted to let you know that this PR kind of "blocks" the other PRs and that I have prepared more code already 😎

Copy link
Contributor

@GerdZanker GerdZanker left a comment

Choose a reason for hiding this comment

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

Nice, to see this growing support of more and more devices. Thank you @david-pace

@jlaur
Copy link
Contributor

jlaur commented Mar 22, 2024

@lsiepel - it looks like your review is almost finished according to #16400 (review). Just checking if you will be able to finish your review, perhaps it just got off your radar? 😉 I had a brief look myself, and it looks nice and clean to me (as usual). 👍

@mike-bike
Copy link

Nice, to see this growing support of more and more devices. Thank you @david-pace

Hi Guys, I just opened another opportunity to grow even further: #16590 😀

Have a great weekend

Regards,
Michael

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.

LGTM, again very clean. Thanks!

@lsiepel lsiepel merged commit b77172c into openhab:main Mar 31, 2024
3 checks passed
@lsiepel lsiepel added this to the 4.2 milestone Mar 31, 2024
@david-pace david-pace deleted the 14562-light-shutter-control-2 branch March 31, 2024 12:09
lo92fr pushed a commit to lo92fr/openhab-addons that referenced this pull request Apr 30, 2024
* [boschshc] Add support for Shutter Control II (openhab#14562)
* add new channel type for child protection

Signed-off-by: David Pace <dev@davidpace.de>
adr001db pushed a commit to adr001db/openhab-addons that referenced this pull request May 12, 2024
* [boschshc] Add support for Shutter Control II (openhab#14562)
* add new channel type for child protection

Signed-off-by: David Pace <dev@davidpace.de>
Signed-off-by: Alexander Drent <Alex@Drent-ict.nl>
pgfeller pushed a commit to pgfeller/openhab-addons that referenced this pull request Sep 29, 2024
* [boschshc] Add support for Shutter Control II (openhab#14562)
* add new channel type for child protection

Signed-off-by: David Pace <dev@davidpace.de>
Signed-off-by: Patrik Gfeller <patrik.gfeller@proton.me>
joni1993 pushed a commit to joni1993/openhab-addons that referenced this pull request Oct 15, 2024
* [boschshc] Add support for Shutter Control II (openhab#14562)
* add new channel type for child protection

Signed-off-by: David Pace <dev@davidpace.de>
matchews pushed a commit to matchews/openhab-addons that referenced this pull request Oct 18, 2024
* [boschshc] Add support for Shutter Control II (openhab#14562)
* add new channel type for child protection

Signed-off-by: David Pace <dev@davidpace.de>
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[boschshc] Support for Light/Shutter Control II
5 participants