zigpy / zha-device-handlers

ZHA device handlers bridge the functionality gap created when manufacturers deviate from the ZCL specification, handling deviations and exceptions by parsing custom messages to and from Zigbee devices.
Apache License 2.0
768 stars 702 forks source link

[Device Support Request] Bosch Light/shutter control II (BMCT-SLZ) #2518

Open sopelt opened 1 year ago

sopelt commented 1 year ago

Problem description

This device looks like an interesting choice for roller/shutter control. After pairing it via code (as it needs this route to succeed) it is detected as RBSH-MMS-ZB-EU. The issue is that the device has to modes: lights (2 separate relays for switching lights) or shutter (the firmware prevents both relays being switched on at the same time and allows for shutter-specific settings like timings). Without setting this mode both options (a cover and two lights) are detected but seem non-functional.

Solution description

Looking at this code I have a basic idea of what value needs to be written to the manufacturer specific cluster to set the mode I am interested in but I have no experience writing quirks. If someone could point me to a quirk with a similar use case (most stuff looks quite okay out of the box but a man. spec. cluster needs to be mapped to two specific settable values) I would love to see what I manage to get together.

Device signature

Device signature ```json { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4617, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0202", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0102", "0x0702", "0x0b04", "0x0b05", "0xfca0" ], "output_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xfca0" ], "output_clusters": [] }, "3": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xfca0" ], "output_clusters": [] } }, "manufacturer": "Bosch", "model": "RBSH-MMS-ZB-EU", "class": "zigpy.device.Device" } ```

Diagnostic information

Diagnostic information ```json { "home_assistant": { "installation_type": "Home Assistant OS", "version": "2023.8.1", "dev": false, "hassio": true, "virtualenv": false, "python_version": "3.11.4", "docker": true, "arch": "aarch64", "timezone": "Europe/Vienna", "os_name": "Linux", "os_version": "6.1.21-v8", "supervisor": "2023.08.1", "host_os": "Home Assistant OS 10.4", "docker_version": "23.0.6", "chassis": "embedded", "run_as_root": true }, "custom_components": {}, "integration_manifest": { "domain": "zha", "name": "Zigbee Home Automation", "after_dependencies": [ "onboarding", "usb" ], "codeowners": [ "@dmulcahey", "@adminiuga", "@puddly" ], "config_flow": true, "dependencies": [ "file_upload" ], "documentation": "https://www.home-assistant.io/integrations/zha", "iot_class": "local_polling", "loggers": [ "aiosqlite", "bellows", "crccheck", "pure_pcapy3", "zhaquirks", "zigpy", "zigpy_deconz", "zigpy_xbee", "zigpy_zigate", "zigpy_znp" ], "requirements": [ "bellows==0.35.8", "pyserial==3.5", "pyserial-asyncio==0.6", "zha-quirks==0.0.102", "zigpy-deconz==0.21.0", "zigpy==0.56.4", "zigpy-xbee==0.18.1", "zigpy-zigate==0.11.0", "zigpy-znp==0.11.4" ], "usb": [{ "vid": "10C4", "pid": "EA60", "description": "*2652*", "known_devices": [ "slae.sh cc2652rb stick" ] }, { "vid": "1A86", "pid": "55D4", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus v2" ] }, { "vid": "10C4", "pid": "EA60", "description": "*sonoff*plus*", "known_devices": [ "sonoff zigbee dongle plus" ] }, { "vid": "10C4", "pid": "EA60", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*tubeszb*", "known_devices": [ "TubesZB Coordinator" ] }, { "vid": "1A86", "pid": "7523", "description": "*zigstar*", "known_devices": [ "ZigStar Coordinators" ] }, { "vid": "1CF1", "pid": "0030", "description": "*conbee*", "known_devices": [ "Conbee II" ] }, { "vid": "10C4", "pid": "8A2A", "description": "*zigbee*", "known_devices": [ "Nortek HUSBZB-1" ] }, { "vid": "0403", "pid": "6015", "description": "*zigate*", "known_devices": [ "ZiGate+" ] }, { "vid": "10C4", "pid": "EA60", "description": "*zigate*", "known_devices": [ "ZiGate" ] }, { "vid": "10C4", "pid": "8B34", "description": "*bv 2010/10*", "known_devices": [ "Bitron Video AV2010/10" ] } ], "zeroconf": [{ "type": "_esphomelib._tcp.local.", "name": "tube*" }, { "type": "_zigate-zigbee-gateway._tcp.local.", "name": "*zigate*" }, { "type": "_zigstar_gw._tcp.local.", "name": "*zigstar*" }, { "type": "_slzb-06._tcp.local.", "name": "slzb-06*" } ], "is_built_in": true }, "data": { "ieee": "**REDACTED**", "nwk": 57174, "manufacturer": "Bosch", "model": "RBSH-MMS-ZB-EU", "name": "Bosch RBSH-MMS-ZB-EU", "quirk_applied": false, "quirk_class": "zigpy.device.Device", "manufacturer_code": 4617, "power_source": "Mains", "lqi": 188, "rssi": -53, "last_seen": "2023-08-09T11:27:24", "available": true, "device_type": "Router", "signature": { "node_descriptor": "NodeDescriptor(logical_type=, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=, mac_capability_flags=, manufacturer_code=4617, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)", "endpoints": { "1": { "profile_id": "0x0104", "device_type": "0x0202", "input_clusters": [ "0x0000", "0x0003", "0x0004", "0x0005", "0x0102", "0x0702", "0x0b04", "0x0b05", "0xfca0" ], "output_clusters": [ "0x000a", "0x0019" ] }, "2": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xfca0" ], "output_clusters": [] }, "3": { "profile_id": "0x0104", "device_type": "0x0100", "input_clusters": [ "0x0003", "0x0004", "0x0005", "0x0006", "0xfca0" ], "output_clusters": [] } }, "manufacturer": "Bosch", "model": "RBSH-MMS-ZB-EU" }, "active_coordinator": false, "entities": [{ "entity_id": "light.bosch_rbsh_mms_zb_eu_light", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "light.bosch_rbsh_mms_zb_eu_light_2", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "sensor.bosch_rbsh_mms_zb_eu_power_factor", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "sensor.bosch_rbsh_mms_zb_eu_active_power", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "sensor.bosch_rbsh_mms_zb_eu_instantaneous_demand", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "sensor.bosch_rbsh_mms_zb_eu_summation_delivered", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "cover.bosch_rbsh_mms_zb_eu_cover", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "select.bosch_rbsh_mms_zb_eu_start_up_behavior", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "select.bosch_rbsh_mms_zb_eu_start_up_behavior_2", "name": "Bosch RBSH-MMS-ZB-EU" }, { "entity_id": "button.bosch_rbsh_mms_zb_eu_identify", "name": "Bosch RBSH-MMS-ZB-EU" } ], "neighbors": [ ], "routes": [ ], "endpoint_names": [{ "name": "WINDOW_COVERING_DEVICE" }, { "name": "ON_OFF_LIGHT" }, { "name": "ON_OFF_LIGHT" } ], "user_given_name": null, "device_reg_id": "", "area_id": null, "cluster_details": { "1": { "device_type": { "name": "WINDOW_COVERING_DEVICE", "id": 514 }, "profile_id": 260, "in_clusters": { "0x0000": { "endpoint_attribute": "basic", "attributes": { "0x0009": { "attribute_name": "generic_device_type", "value": 255 }, "0x0004": { "attribute_name": "manufacturer", "value": "Bosch" }, "0x0005": { "attribute_name": "model", "value": "RBSH-MMS-ZB-EU" } }, "unsupported_attributes": {} }, "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0102": { "endpoint_attribute": "window_covering", "attributes": { "0x0007": { "attribute_name": "config_status", "value": 3 }, "0x0008": { "attribute_name": "current_position_lift_percentage", "value": 0 }, "0x0009": { "attribute_name": "current_position_tilt_percentage", "value": 0 }, "0x0017": { "attribute_name": "window_covering_mode", "value": 0 } }, "unsupported_attributes": { "0x0015": { "attribute_name": "acceleration_time_lift" } } }, "0x0702": { "endpoint_attribute": "smartenergy_metering", "attributes": { "0x0000": { "attribute_name": "current_summ_delivered", "value": 0 }, "0x0302": { "attribute_name": "divisor", "value": 100 }, "0x0400": { "attribute_name": "instantaneous_demand", "value": 0 }, "0x0306": { "attribute_name": "metering_device_type", "value": 0 }, "0x0301": { "attribute_name": "multiplier", "value": 1 }, "0x0200": { "attribute_name": "status", "value": 0 }, "0x0303": { "attribute_name": "summation_formatting", "value": 42 }, "0x0300": { "attribute_name": "unit_of_measure", "value": 0 } }, "unsupported_attributes": { "0x0100": { "attribute_name": "current_tier1_summ_delivered" }, "0x0102": { "attribute_name": "current_tier2_summ_delivered" }, "0x0104": { "attribute_name": "current_tier3_summ_delivered" }, "0x0304": { "attribute_name": "demand_formatting" }, "0x0106": { "attribute_name": "current_tier4_summ_delivered" }, "0x0108": { "attribute_name": "current_tier5_summ_delivered" }, "0x010a": { "attribute_name": "current_tier6_summ_delivered" } } }, "0x0b04": { "endpoint_attribute": "electrical_measurement", "attributes": { "0x0605": { "attribute_name": "ac_power_divisor", "value": 1 }, "0x0604": { "attribute_name": "ac_power_multiplier", "value": 1 }, "0x050b": { "attribute_name": "active_power", "value": 0 }, "0x0000": { "attribute_name": "measurement_type", "value": 1 } }, "unsupported_attributes": { "0x0300": { "attribute_name": "ac_frequency" }, "0x0601": { "attribute_name": "ac_voltage_divisor" }, "0x0302": { "attribute_name": "ac_frequency_max" }, "0x0603": { "attribute_name": "ac_current_divisor" }, "0x0602": { "attribute_name": "ac_current_multiplier" }, "0x0505": { "attribute_name": "rms_voltage" }, "0x0600": { "attribute_name": "ac_voltage_multiplier" }, "0x0507": { "attribute_name": "rms_voltage_max" }, "0x0508": { "attribute_name": "rms_current" }, "0x050a": { "attribute_name": "rms_current_max" }, "0x0403": { "attribute_name": "power_divisor" }, "0x050d": { "attribute_name": "active_power_max" }, "0x050f": { "attribute_name": "apparent_power" }, "0x0400": { "attribute_name": "ac_frequency_multiplier" }, "0x0401": { "attribute_name": "ac_frequency_divisor" }, "0x0402": { "attribute_name": "power_multiplier" } } }, "0x0b05": { "endpoint_attribute": "diagnostic", "attributes": {}, "unsupported_attributes": {} }, "0xfca0": { "endpoint_attribute": "manufacturer_specific", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": { "0x000a": { "endpoint_attribute": "time", "attributes": {}, "unsupported_attributes": {} }, "0x0019": { "endpoint_attribute": "ota", "attributes": {}, "unsupported_attributes": {} } } }, "2": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 }, "0x4003": { "attribute_name": "start_up_on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xfca0": { "endpoint_attribute": "manufacturer_specific", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} }, "3": { "device_type": { "name": "ON_OFF_LIGHT", "id": 256 }, "profile_id": 260, "in_clusters": { "0x0003": { "endpoint_attribute": "identify", "attributes": {}, "unsupported_attributes": {} }, "0x0004": { "endpoint_attribute": "groups", "attributes": {}, "unsupported_attributes": {} }, "0x0005": { "endpoint_attribute": "scenes", "attributes": {}, "unsupported_attributes": {} }, "0x0006": { "endpoint_attribute": "on_off", "attributes": { "0x0000": { "attribute_name": "on_off", "value": 0 }, "0x4003": { "attribute_name": "start_up_on_off", "value": 0 } }, "unsupported_attributes": {} }, "0xfca0": { "endpoint_attribute": "manufacturer_specific", "attributes": {}, "unsupported_attributes": {} } }, "out_clusters": {} } } } } ```
sopelt commented 1 year ago

Using zha-toolkit I was able to initialize the device to "shutter mode" by sending the relevant value (0x01) to the custom cluster (0xfca0):

service: zha_toolkit.attr_write
data:
  ieee: ...
  manf: 0x1209
  endpoint: 1
  cluster: 0xfca0
  attribute: 0x0000
  attr_type: 0x30
  attr_val: 0x01

This enables basic shutter operation (up, down, stop) but I have yet to look at calibrating the times etc.

sopelt commented 1 year ago

Sticking with poking it with zha-toolkit one can set the calibration_closing_time (attribute 0x0002 ... similarly 0x0003 for opening) e.g. to 10s (encoded as 10s * 10 = 100 = 0x64 in hex)

service: zha_toolkit.attr_write
data:
  ieee: ...
  manf: 0x1209
  endpoint: 1
  cluster: 0xfca0
  attribute: 0x0002
  attr_type: 0x23
  attr_val: 0x64

So this should allow basic operation for many scenarios. I have yet to try to set the different shutter types or tilt angles. As far as I understand settings like the device type, calibration times should be handled directly in homeassistant-core similar to startup behavior. I could not find any traces for configuration for shutters and am thinking of exposing them through a quirk for now to at least be able to set them through HAs UI/services/blueprints for now. Any pointers towards existing work in that direction would be appreciated.

sopelt commented 1 year ago

I put together a prototypical quirk that allows setting the device type, switch type and shutter calibration times. This should enable basic operation as a shutter without zha-toolkit.

Feedback welcome ;)

image

peterreimer commented 1 year ago

Hi, thank you for this quirk. I have this switch installed and finally recognized by ZHA, but it does not respond to any action in home assistant. I managed to install your quirk but i do not understand how to set the type to light switch. I have two lights connected. Any hints for a home assistant newbie?

sopelt commented 1 year ago

Hi @peterreimer

I am assuming the basic pairing via the QR code worked and the device shows up but the roller/light controls do nothing? This would be because of the "split personality" of being a light/shutter device and you first need to set the mode of the device itself. When navigating to the device in HA it should look something like

image

The dots and manage zigbee device

image

should bring you to the clusters view:

image

after choosing BoschLightShutterControlII as the cluster and device_type as the attribute you can hit read to see the initial type which will be something like undefined which is why the device refuses to act at all.

Changing the type to DeviceType.Light and writing the attribute should give you independent operation of the two relays to control your lights.

image

peterreimer commented 1 year ago

Hi @sopelt, that worked. Thank you for the detailed explanation. To get the pairing right took me also a while. The qr code on the switch was a long string containing both the IEEE Address and the installation code. Only when i found the little sticker in the box i figured out which value has to go into which field of the zha.permit tool. Now that i works i might get a second unit and use it as shutter control. Thanks again, Peter

sopelt commented 1 year ago

You're welcome. Yeah, the "join via code experience" is not great yet but I would assume that will be handled soon through QR scan + vendor code format support in the home assistant app as the devices using it seem to increase in numbers lately... How "split personality devices" like this one can be better supported out of the box and in a generic way - no idea ;)

Hedda commented 1 year ago

FYI, check out the discussion here about Bosch Twinguard (8750001213 smoke detector) which might be related -> https://github.com/zigpy/zha-device-handlers/issues/2561

Also not sure if related this(?) but FYI; noticed @promasu has submitted PR to "Add support for Bosch QR-codes for zha.permit"

https://github.com/home-assistant/core/pull/102427

https://github.com/home-assistant/home-assistant.io/pull/29459

https://github.com/home-assistant/core/pull/102427/commits/3a753de25a4bd420ad4aa04a86733f3f92d66f59

    # Bosch
    r"""
        ^RB01SG
        [0-9a-fA-F]{34}
        ([0-9a-fA-F]{16}) # IEEE address
        DLK
        ([0-9a-fA-F]{36}) # install code
        $
    """,
promasu commented 1 year ago

My change was only for converting the qr-codes from the battery lid etc from the bosch devices to the ieee address and install code used by the zha.allow service. This has nothing to do with device recognition or the handling of the install codes in general. Just what happens with the user input on the zha.permit page. I even think my change is not live with the current version (10.5) of Home Assistant, at least not according to the changelog

Hedda commented 1 year ago

My change was only for converting the qr-codes from the battery lid etc from the bosch devices to the ieee address and install code used by the zha.allow service. This has nothing to do with device recognition or the handling of the install codes in general. Just what happens with the user input on the zha.permit page. I even think my change is not live with the current version (10.5) of Home Assistant, at least not according to the changelog

@promasu Ah, but your QR-code PR/patch probably is related to this other discussion about Bosch Twinguard here, or? -> https://github.com/zigpy/zha-device-handlers/issues/2561

promasu commented 1 year ago

My change was only for converting the qr-codes from the battery lid etc from the bosch devices to the ieee address and install code used by the zha.allow service. This has nothing to do with device recognition or the handling of the install codes in general. Just what happens with the user input on the zha.permit page. I even think my change is not live with the current version (10.5) of Home Assistant, at least not according to the changelog

@promasu Ah, but your QR-code PR/patch probably is related to this other discussion about Bosch Twinguard here, or? -> https://github.com/zigpy/zha-device-handlers/issues/2561

Not really I think. It's more to make life easy with putting in the qr instead of typing down two long strings

peterreimer commented 1 year ago

Apparently i also have to set the switch_type. The default seems to be undefinded, but than i could only control the lights with home assistant, but not with the physical wall switch. Setting the switch_type to SwitchType.Rocker_Switch solved this and now everything works as expected.

ring0r commented 9 months ago

Apparently i also have to set the switch_type. The default seems to be undefinded, but than i could only control the lights with home assistant, but not with the physical wall switch. Setting the switch_type to SwitchType.Rocker_Switch solved this and now everything works as

Hi,

thanks for your message. I have a similar problem with the Bosch Controller II and I want to use it for my roller blinds via Zigbee2mqtt.

I also have the problem that some attributes are not recognized during pairing, but the biggest problem is that I can no longer use the wall switches.

Where can I change the settings as you did?

Thanks in advance!

peterreimer commented 9 months ago

i did this in the "Manage Zigbee Device" Dialog. The way to get there is described by @sopelt earlier in this threat grafik But you say you use zigbee2mqtt, so this is probably not the right place for you to ask since this solution is for ZHA.

Hedda commented 9 months ago

I want to use it for my roller blinds via Zigbee2mqtt.

ZHA Device Handlers (also known as ZHA Quirks) have nothing to do with Zigbee2MQTT, instead these are only for the native Zigbee Home Automation that is built into Home Assistant as a core component, see -> https://www.home-assistant.io/integrations/zha/

Darkmelman commented 6 months ago

@sopelt Ho, thank you for your quirk. The topic was absolutely new for me and i can't get it to work. I paired the Bosch Licht-/Rolladensteuerung ii with my HA ZHA but it's not using the quirk and i can't figure out why.

I edited the configuration.yaml, checked the config, restarted HA und repaired but it's not using the quirk. Maybe you have an idea.

Thanks in advance!

github-actions[bot] commented 6 days ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.