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

Fibaro light/rgbw controller brightness controls throwing exceptions, making the entity unusable #55386

Closed
rik-v opened this issue Aug 28, 2021 · 8 comments · Fixed by #56385
Closed

Comments

@rik-v
Copy link
Contributor

rik-v commented Aug 28, 2021

The problem

Main problem

Fibaro rgbw lights brightness control broken, will throw an exception about NoneType not being an integer

Expected behavior

Light works as intended and shows on/off, brightness and color controls*

Actual behavior

Light either does not function at all or will only operate the on/off and color functions*
thrown exception (excerpt): '>' not supported between instances of 'nonetype' and 'int'

*see details and gifs below for more clarity

Details:

Whilst setting up a new system we got to including the existing Fibaro stuff (which is running on an Home Center 3, latest software as of this writing, which is 5.080.x), however, this starts throwing exceptions regarding the brightness attribute.
Although the system did actually register the devices, we're not able to control them.
That is to say: sometimes it'll pop on and will give on/off and color controls, but it won't give brightness controls. Other times, it simply refuses to turn on at all.
In both cases, an exception gets thrown when the code tries to set the brightness level.
In all fairness, there's only one that I'll get to turn on, which is only because I've tinkered with it through the developer tools to "force" it's brightness value to 100, once I'd do that, I'd get on/off and color control (although it remains flaky, at best).

Now, in another location, we have similar setup, but on that location the entire setup works flawesly.
There's 2 differences on that location: 1) uses an HC3 Lite instead of a full-fledged HC3, 2) the Fibaro software version is 5.070.x, e.g. one minor lower.

What was tried to fix it

Now, I've tried the following things in an effort to fix the issue (none of them worked):

  • removed and re-added z-wave devices to the fibaro system
  • completely re-installed home assistant on a fresh sd-card and only setup fibaro (exact same result, only this time it didn't even register the devices)
  • bravely tried to debug home assistant on my local machine in an effort to find out what might cause this (no luck so far :( )

The exceptions

(this is the 'brightness-uncontrollable-exception')

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 451, in async_update_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 500, in _async_write_ha_state
    attr.update(self.state_attributes or {})
  File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 857, in state_attributes
    data[ATTR_BRIGHTNESS] = self.brightness
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 82, in brightness
    return scaleto255(self._brightness)
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 25, in scaleto255
    if value > 98:
TypeError: '>' not supported between instances of 'NoneType' and 'int'

(this is the 'cannot-be-added-to-system-exception')

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 382, in async_add_entities
    await asyncio.gather(*tasks)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 587, in _async_add_entity
    await entity.add_to_platform_finish()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 711, in add_to_platform_finish
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 464, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 500, in _async_write_ha_state
    attr.update(self.state_attributes or {})
  File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 857, in state_attributes
    data[ATTR_BRIGHTNESS] = self.brightness
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 82, in brightness
    return scaleto255(self._brightness)
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 25, in scaleto255
    if value > 98:
TypeError: '>' not supported between instances of 'NoneType' and 'int'

Pretty gifs and pictures for clarity :)

Note how the light will just "turn off again" (no, I did not click it again ;) it turns off by itself)
light_wont_turn_on

Here you can see the one light that actually gives on/off and color control, but the brightness control does not work.
light_on_no_bri_control

this is the debug logging that rolled out of that, note how it seems to constantly call "turn_on" even if the light is already on (this would happen if we'd move the brightness slider):
log_from_gifs

Personally I suspect Fibaro has changed something in their REST API which is causing these problems (since an older version of the same device does not have these issues), but I'm just not well versed enough in the home assistant code nor python to fix this myself :(
Could anyone help with this problem? (if anything is missing from the issue, please let me know so I can add it)

What is version of Home Assistant Core has the issue?

core-2021.8.8

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant OS

Integration causing the issue

Fibaro

Link to integration documentation on our website

https://www.home-assistant.io/integrations/fibaro/

Example YAML snippet

No response

Anything in the logs that might be useful for us?

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 451, in async_update_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 500, in _async_write_ha_state
    attr.update(self.state_attributes or {})
  File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 857, in state_attributes
    data[ATTR_BRIGHTNESS] = self.brightness
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 82, in brightness
    return scaleto255(self._brightness)
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 25, in scaleto255
    if value > 98:
TypeError: '>' not supported between instances of 'NoneType' and 'int'

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 382, in async_add_entities
    await asyncio.gather(*tasks)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 587, in _async_add_entity
    await entity.add_to_platform_finish()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 711, in add_to_platform_finish
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 464, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 500, in _async_write_ha_state
    attr.update(self.state_attributes or {})
  File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 857, in state_attributes
    data[ATTR_BRIGHTNESS] = self.brightness
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 82, in brightness
    return scaleto255(self._brightness)
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 25, in scaleto255
    if value > 98:
TypeError: '>' not supported between instances of 'NoneType' and 'int'

Additional information

No response

@probot-home-assistant
Copy link

fibaro documentation
fibaro source
(message by IssueLinks)

@rik-v
Copy link
Contributor Author

rik-v commented Aug 29, 2021

So, small update. Consider the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 451, in async_update_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 500, in _async_write_ha_state
    attr.update(self.state_attributes or {})
  File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 857, in state_attributes
    data[ATTR_BRIGHTNESS] = self.brightness
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 82, in brightness
    return scaleto255(self._brightness)
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 25, in scaleto255
    if value > 98:
TypeError: '>' not supported between instances of 'NoneType' and 'int'

So this happens when an 'update' (state) is triggered, device gets registered, etc. The reason this will happen must be that the SUPPORT_BRIGHTNESS flag is missing, if you'd consider the following code you can see that whenever the brightness property is requested, it will call scaleto255 which expects a value to just be there, but, because SUPPORT_BRIGHTNESS is not set the value is actually None, which will cause the exception:

# from components/fibaro/light.py
@property
def brightness(self):
    """Return the brightness of the light."""
    return scaleto255(self._brightness)

def scaleto255(value):
    """Scale the input value from 0-100 to 0-255."""
    # Fibaro has a funny way of storing brightness either 0-100 or 0-99
    # depending on device type (e.g. dimmer vs led)
    if value > 98: #<<<the offending code
        value = 100
    return max(0, min(255, ((value * 255.0) / 100.0)))
# from components/light/__init__.py
def state_attributes(self):
    """Return state attributes."""
    #... code shortened
    if color_mode in COLOR_MODES_BRIGHTNESS:
        data[ATTR_BRIGHTNESS] = self.brightness #<<< reason it fails
    elif supported_features & SUPPORT_BRIGHTNESS:
        # Backwards compatibility for ambiguous / incomplete states
        # Add warning in 2021.6, remove in 2021.10 <<< warning not in logs, so I'm assuming this code is not hit
        data[ATTR_BRIGHTNESS] = self.brightness

So, main question then: Why is the brightness-flag not set? Since this is a rgbw-controller, which obviously has brightness control.
The answer to that is: the supported_features does not get the 1 added to it because apparently something has changed within the Fibaro API for this: the interfaces reported no longer contains levelChange (obviously, that's weird, because these types of devices will support brightness settings...).
I've found this by doing some API calls towards Fibaro on a location that works (running HC3L v5.070.x) and the one that does not (running HC3 v5.080.x), on the former the response looks like this for an RGBW controller:

{
  "id": 59,
  "name": "Garden",
  "roomID": 221,
  "view": [
    {
      "assetsPath": "/assets/icon",
      "jsPath": "/dynamic-plugins/com.fibaro.colorController",
      "name": "com.fibaro.colorController",
      "translatesPath": "/dynamic-plugins/com.fibaro.colorController/i18n",
      "type": "ts"
    },
    {
      "assetsPath": "/assets/icon",
      "jsPath": "/dynamic-plugins/level-change",
      "name": "level-change",
      "translatesPath": "/dynamic-plugins/level-change/i18n",
      "type": "ts"
    }
  ],
  "type": "com.fibaro.FGRGBW442CC",
  "baseType": "com.fibaro.colorController",
  "enabled": true,
  "visible": true,
  "isPlugin": false,
  "parentId": 56,
  "viewXml": false,
  "configXml": false,
  "interfaces": [
    "levelChange",
    "light",
    "zwave",
    "zwaveAlarm",
    "zwaveMultiChannelAssociation",
    "zwaveProtection"
  ],
  "properties": {
    "pollingTimeSec": 0,
    "zwaveCompany": "Fibargroup",
    "zwaveInfo": "3,6,4",
    "zwaveVersion": "5.0",
    "RFProtectionState": 0,
    "RFProtectionSupport": 3,
    "alarmLevel": 0,
    "alarmType": 0,
    "categories": [
      "lights"
    ],
    "color": "255,98,0,0",
    "colorComponents": {},
    "configured": true,
    "currentProgram": 0,
    "currentProgramID": 0,
    "dead": false,
    "deadReason": "",
    "deviceControlType": 50,
    "deviceIcon": 15,
    "endPointId": 1,
    "isLight": true,
    "localProtectionState": 0,
    "localProtectionSupport": 5,
    "log": "",
    "logTemp": "",
    "manufacturer": "",
    "markAsDead": true,
    "model": "",
    "nodeId": 6,
    "parametersTemplate": 849,
    "productInfo": "1,15,9,2,16,0,5,0",
    "programsSortOrder": "1,2,3,4,5",
    "protectionExclusiveControl": 0,
    "protectionExclusiveControlSupport": false,
    "protectionState": 0,
    "protectionTimeout": 0,
    "protectionTimeoutSupport": false,
    "saveLogs": true,
    "serialNumber": "h'0000000000007b10",
    "state": false,
    "useTemplate": true,
    "userDescription": "",
    "value": 0
  },
  "actions": {
    "reconfigure": 0,
    "setColor": 1,
    "setColorComponents": 1,
    "setValue": 1,
    "startColorEnhancement": 1,
    "startColorFade": 1,
    "startLevelDecrease": 0,
    "startLevelIncrease": 0,
    "startProgram": 1,
    "stopColorChange": 1,
    "stopLevelChange": 0,
    "toggle": 0,
    "turnOff": 0,
    "turnOn": 0
  },
  "created": 1626628598,
  "modified": 1626628598,
  "sortOrder": 44
}

As you can see, this is roughly what the current HA code expects: it has levelChange in it's interfaces array, resulting in a correctly operation light with brightness control.
Funny thing though, this is a RGBW controller and the connected light-strip has got a white LED and the white channel is connected on the actual controller, but white control is not showing for any of the devices.
Although that's a separate issue, it has the same cause: the assumptions that give or don't give the entity white-level control don't match with the Fibaro API output. (it searches for setW in the actions array, but it's not there).

Now, the following is the Fibaro API output from the location running the HC3 with software version v5.080.x:

{
  "id": 101,
  "name": "L_Back",
  "roomID": 220,
  "view": [
    {
      "assetsPath": "/assets/icon",
      "jsPath": "/dynamic-plugins/com.fibaro.colorController",
      "name": "com.fibaro.colorController",
      "translatesPath": "/dynamic-plugins/com.fibaro.colorController/i18n",
      "type": "ts"
    }
  ],
  "type": "com.fibaro.FGRGBW442CC",
  "baseType": "com.fibaro.colorController",
  "enabled": true,
  "visible": true,
  "isPlugin": false,
  "parentId": 97,
  "viewXml": false,
  "configXml": false,
  "interfaces": [
    "light",
    "notification",
    "parameters",
    "zwave"
  ],
  "properties": {
    "pollingTimeSec": 0,
    "zwaveCompany": "Fibargroup",
    "zwaveInfo": "3,6,4",
    "zwaveVersion": "5.0",
    "categories": [
      "lights"
    ],
    "color": "255,63,0,0",
    "colorComponents": {
      "blue": 0,
      "green": 63,
      "red": 255,
      "warmWhite": 0
    },
    "configured": true,
    "currentProgram": 0,
    "currentProgramID": 0,
    "dead": false,
    "deadReason": "",
    "deviceControlType": 23,
    "deviceIcon": 15,
    "endPointId": 1,
    "isLight": true,
    "log": "",
    "logTemp": "",
    "manufacturer": "",
    "markAsDead": true,
    "model": "",
    "nodeId": 16,
    "parameterProvider": "zwave",
    "parametersTemplate": 0,
    "productInfo": "1,15,9,2,16,0,5,0",
    "programsSortOrder": "1,2,3,4,5",
    "saveLogs": true,
    "serialNumber": "",
    "state": false,
    "supportedNotifications": {
      "8": {
        "eventValues": {},
        "key": "blockScenes.notification.properties.8",
        "stateValues": {
          "over-current-status": {
            "key": "blockScenes.notification.properties.over-current-status",
            "values": {
              "0": {
                "key": "blockScenes.notification.properties.8.0",
                "saveToPanel": true
              },
              "6": {
                "key": "blockScenes.notification.properties.8.6",
                "saveToPanel": true
              }
            }
          }
        }
      },
      "9": {
        "eventValues": {},
        "key": "blockScenes.notification.properties.9",
        "stateValues": {
          "hw-status": {
            "key": "blockScenes.notification.properties.hw-status",
            "values": {
              "0": {
                "key": "blockScenes.notification.properties.9.0",
                "saveToPanel": true
              },
              "3": {
                "key": "blockScenes.notification.properties.9.3",
                "saveToPanel": true
              }
            }
          }
        }
      }
    },
    "useTemplate": true,
    "userDescription": "",
    "value": 0
  },
  "actions": {
    "reconfigure": 0,
    "setColor": 1,
    "setColorComponents": 1,
    "setValue": 1,
    "startColorEnhancement": 1,
    "startColorFade": 1,
    "startProgram": 1,
    "stopColorChange": 1,
    "toggle": 0,
    "turnOff": 0,
    "turnOn": 0
  },
  "created": 1629830995,
  "modified": 1629830995,
  "sortOrder": 30
}

In this case, the interfaces array does not contain the levelChange entry (for whatever reason...), and that's why it's throwing this exception.
Now, obviously, this being an RGBW controller, it will have brightness control (and like the previous example, it also white channel), so I'd say the assumptions as to when brightness is supported should change.
But that said, the current code - from the limited view that I've got now - shouldn't work for lights that actually do not have brightness control. The reason for that is that on multiple code paths it will request the brightness property, which in turn will try to execute the scaleto255 function which will fail because the actual value for _brightness gets set to None in the initializer. But again, that's kind of a separate issue.

So, to check this, I've changed the code locally to change the way it detects the capabilities. Code was changed to this:

#components/fibaro/light.py in __init__ (code truncated)
supports_dimming = (
    "levelChange" in fibaro_device.interfaces
    or supports_color #this change will enable brightness control
)
supports_white_v = (
    "setW" in fibaro_device.actions
    or fibaro_device.type == "com.fibaro.FGRGBW442CC" #this change enables white-level control
)

# Configuration can override default capability detection
if devconf.get(CONF_DIMMING, supports_dimming):
    self._supported_flags |= SUPPORT_BRIGHTNESS #the change causes this line and...
if devconf.get(CONF_COLOR, supports_color):
    self._supported_flags |= SUPPORT_COLOR
if devconf.get(CONF_WHITE_VALUE, supports_white_v):
    self._supported_flags |= SUPPORT_WHITE_VALUE #...this line to now get executed

And sure enough, when this was changed, the light gets detected properly, we get on/off, brightness, color and white level control!
And all of those functions are working fine, so besides the code that decides whether or not we get control over brihgtness and such, the code that actually controls is, is working fine.
light_brightness_and_white

@rik-v
Copy link
Contributor Author

rik-v commented Aug 29, 2021

Second update, confirmed that this exception is also breaking functionality for switch-like devices (such as a Fibaro Double Switch), these show up as "binary switch" however, if the property isLight is set to true (which it always is, afaik depends on the role and/or category set for the device in HC itself, so you can influence this behavior, if you have a switch and want to be able to use it, just make sure it does not have the light category and role), then this entity will not be added to the system, because it could not request the brightness property as you can see by the stacktrace below:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 382, in async_add_entities
    await asyncio.gather(*tasks)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 587, in _async_add_entity
    await entity.add_to_platform_finish()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 711, in add_to_platform_finish
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 464, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 500, in _async_write_ha_state
    attr.update(self.state_attributes or {})
  File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 857, in state_attributes
    data[ATTR_BRIGHTNESS] = self.brightness
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 82, in brightness
    return scaleto255(self._brightness)
  File "/usr/src/homeassistant/homeassistant/components/fibaro/light.py", line 25, in scaleto255
    if value > 98:
TypeError: '>' not supported between instances of 'NoneType' and 'int'

Now, if I forcibly add the levelChange interface to this object in Fibaro Home Center itself through its API, then it will work, as you can see by the gif below (this was after we added the interface and HA was able to add the device, so we could control it). Also note that - because it's just a switch - it does not show the brightness slider, which is correct (even though that interface is present in the device config)
However, when I changed two other switches with the same, none of them worked anymore and were showing brightness sliders. So the actual fix is to make sure that the isLight property becomes false.
In either case, this also shows us that it's not just RGBW like controllers that are 'broken', it's also stuff like switches, and who know, maybe even other things.
switch_no_level_ok

@rik-v
Copy link
Contributor Author

rik-v commented Aug 29, 2021

Workaround (for light devices that have the ability to set brightness): as a (very ugly, if I might add) workaround, if you run into this issue:

  • go to your Home Center interface and open the swagger interface from there (lower left corner).
  • Navigate to the devices API (the dropdown on the top right)
  • use the GET on device to get the config for a specific device (you'll need it's ID)
  • edit the config in some editor (VSCode ftw :)) and add the levelChange interface to the interfaces array
  • then copy the entire JSON, you'll need it for the update request
  • go back to swagger and use what you've copied as your request body for the PUT request to devices API (says "modify device" in the swagger description)

Once you've done that, you should at least get the basic functionality from the device in Home Assistant ;) (Beware though, this will only work for actual lights, not for switches, if you have this problem with a switch, make sure its isLight property is set to false, which you can do by making sure it is not assigned the role light and not assigned the category light)
Given, this is just a workaround and should definitely not be considered "OK" for the long term ;)

@rik-v
Copy link
Contributor Author

rik-v commented Oct 2, 2021

Bump. Waiting for PR to come through, waiting for maintainer to approve CI workflow?

@github-actions github-actions bot removed the stale label Oct 2, 2021
@Grubs
Copy link

Grubs commented Oct 2, 2021

Very keen to see this fixed too.

@rik-v
Copy link
Contributor Author

rik-v commented Nov 4, 2021

FYI, this was released in 2021.11.0, confirmed fixed as of that version :)

@Grubs
Copy link

Grubs commented Nov 4, 2021

I’ve been watching closely too. Confirming working here in 2021.10.7 too. Thanks again for your work.

@github-actions github-actions bot locked and limited conversation to collaborators Dec 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants