Hyperion: Add brightness, HDMI and effect support#11543
Conversation
- added brightness support to dim the hyperion light - changed the "OFF" command to set the color to [0,0,0] after clearing all priorities. This is neccesary to keep the light turned off when an HDMI grabber is used for ambilight with hyperion. - added HDMI ambilight mode recognition and control. by setting the "hdmi_priority" in your "configuration.yaml" file (defaults to 880), home assistant will now be able to recognize when the hyperion light is in HDMI ambilight mode and will change its icon to an HDMI symbol and set the status to ON. Switching the hyperion light to HDMI ambilight mode can be done through the effect option (clears all priorities such that the HDMI grabber remains). - added effect support for the default effects of hyperion, a custom list can be defined in the "configuration.yaml" file by using the "effect_list" option.
- added brightness support to dim the hyperion light - changed the "OFF" command to set the color to [0,0,0] after clearing all priorities. This is neccesary to keep the light turned off when an HDMI grabber is used for ambilight with hyperion. - added HDMI ambilight mode recognition and control. by setting the "hdmi_priority" in your "configuration.yaml" file (defaults to 880), home assistant will now be able to recognize when the hyperion light is in HDMI ambilight mode and will change its icon to an HDMI symbol and set the status to ON. Switching the hyperion light to HDMI ambilight mode can be done through the effect option (clears all priorities such that the HDMI grabber remains). - added effect support for the default effects of hyperion, a custom list can be defined in the "configuration.yaml" file by using the "effect_list" option. - fixed some style issues with too long lines
- fixed some more indentation style issues
- yet more fixed visuel indent issues
- more visuel indents
- fixed invalid variable "A"
- remove unnececary brackets - specify specific exceptions
|
@tschmidty69 It seems like my code has passed all the checks. |
|
@tschmidty69 |
|
Read this page: https://home-assistant.io/developers/development_testing/ If you look at the CI testing check below you can see all it is doing is the same thing tox is doing but in the cloud as opposed to locally As far as getting it accepted, it just needs to be reviewed by one of the core team. It may take some time. One of the things they may ask you to do is to write tests for your component. |
|
@tschmidty69 thanks for the info. |
| self._hdmi_priority = hdmi_priority | ||
| self._default_color = default_color | ||
| self._rgb_color = [0, 0, 0] | ||
| self._rgb_mem = [0, 0, 0] |
There was a problem hiding this comment.
The "self._default_color" is used to set the color for the first time when hass is just booted. (after switching off again and switching on the color will be remembered and set to the previous value).
I changed this behaviour, in the previous (current) version the color is not remembered and after switching off and back on the color was reset to this default color.
I agree that this "self._default_color" is not perticularly nessesary because it is only used once after a reboot of hass, but I kept it because it was in the previous release and why not keep it.
The "self._rgb_color" and "self._rgb_mem" originate from the fact that Home Assistant and Hyperion use to diffrent definitions of RGB color. In Home Assistant an "RGB" color contains information about the Hue value (angle in the round color picker) and the saturation value (radius in the round color picker) but does not contain information about the brightness. Therefore in the HASS definition of "RGB" at least one of the values R, G or B is always 255 (exept when the light is off). The brightness is defined in a seperate value in home assistant.
However Hyperion uses the "true" RGB color definition: it contains the information about hue, saturation and brightness. Hyperion does not have any seprate brightness control. Therefore to set for instance a lower brighness pure blue color you simply sent [0,0,150] as RGB color.
It turns out Home Assistant misbehaved if i started to set self._rgb_color to values such as [0,0,150]. It wants a value of [0,0,255] for blue and then a brightness set to 150 to dim it. That is why I needed both values saved in memory. The "self._rgb_color" represents the HASS definition and "self._rgb_mem" is the Hyperion definition of RGB.
Furthermore when the light is turned off, the "self._rgb_color" is set to [0,0,0], therefore losing the information about the previous color. I wanted to store the previous color in memory "self._rgb_mem", so I can sent that color when the light is turend back on.
MartinHjelmare
left a comment
There was a problem hiding this comment.
Cache the argument in a local variable that you use when sending the json request. Don't change the instance attributes in the service methods. See below.
| self._rgb_color = self._default_color | ||
| self._rgb_mem = self._default_color | ||
| else: | ||
| self._rgb_color = self._rgb_mem |
There was a problem hiding this comment.
You should not change any state holding instance attributes in the service methods. Those will be updated in update after the service call, since this is a polling entity.
There was a problem hiding this comment.
I agree, I will update in a commit in a second
| self._rgb_color = self._rgb_mem | ||
|
|
||
| if ATTR_BRIGHTNESS in kwargs: | ||
| self._brightness = kwargs[ATTR_BRIGHTNESS] |
There was a problem hiding this comment.
I agree, I will update in a commit in a second
| self._brightness = kwargs[ATTR_BRIGHTNESS] | ||
|
|
||
| if ATTR_EFFECT in kwargs: | ||
| self._effect = kwargs[ATTR_EFFECT] |
There was a problem hiding this comment.
The Effect case is special, Hyperion takes to long to activate an effect and update its internal status. Therefore I experianced that when you activate an effect, Hyperion will start activating that effect, but imediatly HASS will ask for an update of the status, and because Hyperion is not yet done with activating the effect it will return a json staing that Hyperion is OFF. in the second time an update is requested by HASS the correct json response will be sent by Hyperion and the state will display correctly.
Therfore HASS behaved as followed: you turn on an effect, HASS will imediatly show the light is turned off, and a few seconds later HASS will show the light is turned on again and the correct effect is displayed.
This is super anying, therfore I have used "self._skip_check = True", this will cause the first update HASS requests imidiatly after you select an effect to be aborted. The second and following update requests will be done as usual. If some strange thing happed, HASS will always correct the state in the second update request, but I have not seen that this was necassary.
To display the correct Effect in HASS imediatly after you select an effect I do need to update the self._ properties in the special case of effects.
| self._effect = kwargs[ATTR_EFFECT] | ||
| if self._effect == 'HDMI': | ||
| self.json_request({'command': 'clearall'}) | ||
| self._icon = 'mdi:video-input-hdmi' |
There was a problem hiding this comment.
I disagree, see above: effect special case.
| if self._effect == 'HDMI': | ||
| self.json_request({'command': 'clearall'}) | ||
| self._icon = 'mdi:video-input-hdmi' | ||
| self._brightness = 255 |
There was a problem hiding this comment.
I disagree, see above: effect special case.
| self.json_request({'command': 'clearall'}) | ||
| self._icon = 'mdi:video-input-hdmi' | ||
| self._brightness = 255 | ||
| self._rgb_color = [125, 125, 125] |
There was a problem hiding this comment.
I disagree, see above: effect special case.
| 'priority': self._priority, | ||
| 'color': [0, 0, 0] | ||
| }) | ||
| self._rgb_color = [0, 0, 0] |
There was a problem hiding this comment.
I agree, I will update in a commit in a second
Proccesed the comments of @MartinHjelmare: home-assistant#11543 (review)
| if ATTR_EFFECT in kwargs: | ||
| self._skip_check = True | ||
| self._effect = kwargs[ATTR_EFFECT] | ||
| if self._effect == 'HDMI': |
There was a problem hiding this comment.
indentation contains mixed spaces and tabs
|
|
||
| if ATTR_EFFECT in kwargs: | ||
| self._skip_check = True | ||
| self._effect = kwargs[ATTR_EFFECT] |
There was a problem hiding this comment.
indentation contains tabs
indentation contains mixed spaces and tabs
unexpected indentation
TabError: inconsistent use of tabs and spaces in indentation
corrected tab instead of 4 spaces
|
@MartinHjelmare I have changed some of the things you requested, thanks for the feedback. The Effect case is special, Hyperion takes to long to activate an effect and update its internal status. Therefore I experianced that when you activate an effect, Hyperion will start activating that effect, but imediatly HASS will ask for an update of the status, and because Hyperion is not yet done with activating the effect it will return a json staing that Hyperion is OFF. in the second time an update is requested by HASS the correct json response will be sent by Hyperion and the state will display correctly. Therfore HASS behaved as followed: you turn on an effect, HASS will imediatly show the light is turned off, and a few seconds later HASS will show the light is turned on again and the correct effect is displayed. This is super anying, therfore I have used "self._skip_check = True", this will cause the first update HASS requests imidiatly after you select an effect to be aborted. The second and following update requests will be done as usual. If some strange thing happed, HASS will always correct the state in the second update request, but I have not seen that this was necassary. To display the correct Effect in HASS imediatly after you select an effect I do need to update the self._ properties in the special case of effects. The light itself does react imidiatly so the state schould be set imediatly, however Hyperion takes some time to update its own state and sent the correct response, but it does control the lights without delay. |
|
Yeah, that sounds ok, to me. 👍 |
|
@MartinHjelmare Could you then change the review such that the red "Changes requested" will disapear? Can the pull request now be merged, or does something else need to happen? |
| self._brightness = 255 | ||
| self._icon = 'mdi:lightbulb' | ||
| self._effect_list = effect_list | ||
| self._effect = 'none' |
There was a problem hiding this comment.
Fixed in new commit
| self._icon = 'mdi:lightbulb' | ||
| self._effect_list = effect_list | ||
| self._effect = 'none' | ||
| self._skip_check = False |
There was a problem hiding this comment.
Rename this to self._skip_update.
There was a problem hiding this comment.
Fixed in new commit
| if response['info']['activeLedColor'] == []: | ||
| self._rgb_color = [0, 0, 0] | ||
| # Get the active effect | ||
| if response['info']['activeEffects'] != []: |
There was a problem hiding this comment.
What's the aim of this check? Checking if it's not a list?
There was a problem hiding this comment.
the Json messages that HASS receives from Hyperion when the 'serverinfo' command is sent, contains a lot of information about the status of Hyperion in a dictonary.
It always contains the keys ['info']['activeEffects']. If Hyperion is not playing any effects like flashing the lights in all kind of ways or displaying rainbows etc. the ['info']['activeEffects'] contains an empty array: []. In that case the hyperion instance is doing something else like displaying a solid color (contained in the ['info']['activeLedColor'] key) or in ambilight mode (both ['info']['activeEffects'] and ['info']['activeLedColor'] are empty arrays and the ['info']['priorities'] key contains the specific priority for the HDMI grabber (or Kodi grabber)).
Therfore if the ['info']['activeEffects'] is not an empty array, it means that some kind of effect is playing. I will then try to retrive which effect is playing using the file-name of the script that is beeing played.
That check is thererefore ment to indicate if hyperion is playing an effect or not.
| self._effect = [x for x in self._effect_list | ||
| if s_name.lower() in x.lower()][0] | ||
| except (KeyError, IndexError): | ||
| self._effect = 'none' |
There was a problem hiding this comment.
Fixed in new commit
| else: | ||
| self._rgb_color = [0, 0, 0] | ||
| self._icon = 'mdi:lightbulb' | ||
| self._effect = 'none' |
There was a problem hiding this comment.
Fixed in new commit
| self._rgb_mem = [int(round(float(x)*255/self._brightness)) | ||
| for x in self._rgb_color] | ||
| self._icon = 'mdi:lightbulb' | ||
| self._effect = 'none' |
There was a problem hiding this comment.
Fixed in new commit
- changed 'none' to None - renamed "self._skip_check" to "self._skip_update"
changed checking if a list is empty from "list == []" to "not list"
|
@MartinHjelmare I adapted all the changes you requested Could you againg change the review such that the red "Changes requested" will disapear? |
|
The client library have no push function? |
|
I just noticed that I made a mistake in my last commit. However I need help with merging this fix. |
In the last commit the self._brightness has been removed and named brightness. However if the brightness is not in the current command this breaks the turn_on action because it is required for the cal_rgb. This fixes that by using the self._brightness if it is not in the current command. My last commit is alreay merged in this pull request: home-assistant#11543
Description:
This is neccesary to keep the light turned off when an HDMI grabber is used for ambilight with hyperion.
by setting the "hdmi_priority" in your "configuration.yaml" file (defaults to 880), home assistant will now be able to recognize when the hyperion light is in HDMI ambilight mode and will change its icon to an HDMI symbol and set the status to ON.
Related issue (if applicable): fixes #
Pull request in home-assistant.github.io with documentation (if applicable): home-assistant/home-assistant.io#4376
Example entry for
configuration.yaml(if applicable):Checklist:
If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
toxrun successfully. Your PR cannot be merged unless tests passREQUIREMENTSvariable (example).requirements_all.txtby runningscript/gen_requirements_all.py..coveragerc.If the code does not interact with devices:
toxrun successfully. Your PR cannot be merged unless tests pass