home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
73.56k stars 30.74k forks source link

Migrate the LIFX component to aiolifx #6435

Closed amelchio closed 7 years ago

amelchio commented 7 years ago

UPDATE: Please help me test a much improved LIFX platform!

Here is one way to do that:

Create a directory .homeassistant/custom_components/light and store this file as lifxtest.py:

https://raw.githubusercontent.com/amelchio/home-assistant/lifx-on-aiolifx/homeassistant/components/light/lifx.py

Disable your lifx platform and enable the test with this configuration:

light:
  - platform: lifxtest

Please comment with success as well as failure. Any reported bug that I can reproduce will be fixed.

----- Original post follows:

The HA LIFX component currently depends on liffylights. That library was originally spun off from HA but only saw one week of development. It has never been maintained and has at least a few prominent bugs:

The liffylights library is also missing support for new LIFX hardware (LIFX+ infrared bulbs and LIFX Z light strips) as well as the unofficial message type that allows effects such as flashing. This is holding back new features in HA.

In short, it is easier to replace liffylights than to fix it.

Accordingly, @keatontaylor started out on LIFXlocal, a brand new library that should work better than liffylights. However, LIFXlocal has seen even less development, with only one commit in the repository.

Enter LIFXlan. This library has existed since even before liffylights was created. It supports all LIFX hardware and all message types and it is actively maintained. It seems to be the natural choice for a LIFX library, except it currently only supports Python 2.

Rather than spending time on forking liffylights, fixing things and then publishing a successor that I have to maintain, I want to migrate HA to use LIFXlan. Actually, to see that my plan is viable, I mostly did the migration already: https://github.com/amelchio/home-assistant/tree/lifxlan – even with no improvements per se, things already work a bit better than with liffylights.

To complete my goal, I have to get Python 3 support into LIFXlan. I started that work as well: mclarkk/lifxlan#43

This issue is meant to track the progress in order to hopefully avoid duplication of effort.

keatontaylor commented 7 years ago

@amelchio, thank you for creating this issue. Regardless of the final route that is taken to update the LIFX library I want to outline some of what I consider requirements for any solution going forward and outline some of the changes I've made to the existing lifx component and associated library that has made my setup substantially more reliable.

As far as the LIFXLan library provided my @mclarkk it provides a very nice and well written high level API for communicating with the lights, but it doesn't provide the glue code needed work effectively with HA and in my opinion that glue code is substantially more important than the overall library used to format and send messages.

For this glue code to work effectively I feel it needs to provide the following:

For changes I've made to the current liffylights and lifx component on my own install, they are as follows.

  1. Added a check to prevent set_color from being sent if the on command was the only thing supplied.
  2. Changed the acknowledgement checking code in liffylights.py in line 137 from 3 to 2.
  3. Added the ability for liffylights to see broadcast messages from the bulbs.
  4. Added the ability for liffylights to update HA on power and color state messages.
  5. Removed code in lifx.py that would poll for device state. (this is not needed)
  6. Started using HA as a the sole source for messages to and from LIFX lights.

Overall the changes I made are to ensure that messages to lights are only for the purposes of changing light state and overall this has significantly improved the reliability of my lights and ultimately that is what I feel makes the biggest difference.

amelchio commented 7 years ago

@keatontaylor, thanks for popping in – I can agree with all of that and I was planning to implement most of the things that you mention, once we have a better base. That should fix a number of bugs. The glue is not HA specific and should be easy to add to another library with an active maintainer.

Is your work on liffylights/HA available, I did not manage to find it in any branch?

About the reduction in messages, did you see any actual problems due to the message frequency or is this more a matter of good taste, i.e. not sending unneeded messages?

I was contacted by @frawau and it turns out that a library based on asyncio and Python 3 already exists: https://github.com/frawau/aiolifx so that may be an even better path to follow. I will give it a try soon!

keatontaylor commented 7 years ago

@amelchio I can upload the liffylights and HA changes I've made to my github tomorrow morning. As for the reduction in messages, I absolutely see a significant decrease in issues as a result of sending fewer messages. My light, 12 in total, have had zero issues in just over two months after I reduced the number of messages to the light to only those that are needed. Especially improving the reliability of the Gen 1 bulbs.

The aiolifx library seems to borrow almost all the messaging code from LIFXLAN as far as I can tell, but has a lot of the code already in place to handle the glue code for HA. So it might be a better starting point. If you do get a codebase somewhere I'd be happy to help, and with my spring break coming up I should also have the time. :)

I'm excited to finally get this fixed and hopefully improve reliability for those of us using LIFX.

frawau commented 7 years ago

If I may

@keatontaylor[1], I have 10 gen 1 Lifx and I have been using aiolifx for 2-3 months, I think I saw 2 problems that quickly went away, with one bulb. I do suspect that using unicast and keeping the connection up is good for the reliability. Also, by using aiolifx in my "AutoBuddy" project, I am able to detect when a bulb comes back online without the need for discovery.

The messaging code is entirely from lifxlan, just modified for Python 3, I did not see the point of reinventing the wheel. There is just one difference in the API for the "pulse"command.

Try the test program, just hit return quickly and you'll be able to get a sense as to how fast it will discover your Lifx.

@amelchio I'll see how I can get it on PyPi.

Cheers, François

On Monday, 6 March 2017 00:36:15 ICT Keaton Taylor wrote:

@amelchio[2] I can upload the liffylights and HA changes I've made to my github tomorrow morning. As for the reduction in messages, I absolutely see a significant decrease in issues as a result of sending fewer messages. My light, 12 in total, have had zero issues in just over two months after I reduced the number of messages to the light to only those that are needed. Especially improving the reliability of the Gen 1 bulbs. The aiolifx library seems to borrow almost all the messaging code from LIFXLAN as far as I can tell, but has a lot of the code already in place to handle the glue code for HA. So it might be a better starting point. If you do get a codebase somewhere I'd be happy to help, and with my spring break coming up I should also have the time. :) I'm excited to finally get this fixed and hopefully improve reliability for those of us using LIFX. —You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub[3], or mute the thread[4].[5]


[1] https://github.com/keatontaylor [2] https://github.com/amelchio [3] https://github.com/home-assistant/home-assistant/issues/ 6435#issuecomment-284333259 [4] https://github.com/notifications/unsubscribe-auth/ AORvqQAFYqqZgbZ3wHKZPBz4TF3uKfkaks5ri8V_gaJpZM4MTgc8 [5] https://github.com/notifications/beacon/AORvqd1PLMWJ-R1uve1gMmemfki5rO6Pks5ri8V_gaJpZM4MTgc8.gif

keatontaylor commented 7 years ago

@frawau, I took a look at your example CLI program and probed around with wireshark a bit to look at the messages being sent. Everything looks good with the exception of the number of messages being sent during initial discovery. Things like wifi info, etc can be retrieved when they're called upon, not during the initial discovery. If the library itself asks for this information on discovery I'd ask it to be removed and only retrieve the bare minimum of what we need from the bulbs.

Ideally, simply GetService as a broadcast and Get (light message) will be sufficient to get the mac address, label, service port, IP, along with the current power, brightness, etc from the bulb.

Also, UDP is stateless, the connection does not remain open as UDP has no concept of an ongoing connection.

Otherwise everything looks very good and is extremely speedy.

amelchio commented 7 years ago

@keatontaylor It seems we agree that aiolifx is the way to go, that's great. If nothing unexpected turns up (in the code or in my life), I can probably do the conversion this week.

frawau commented 7 years ago

@keatontaylor [1]All those messages are requested by the test program only. Check the "register" method.

UDP is stateless... silly me I know that, I meant to say that I am using a slow heartbeat....

Cheers, François

On Monday, 6 March 2017 01:52:24 ICT Keaton Taylor wrote:

@frawau[2], I took a look at your example CLI program and probed around with wireshark a bit to look at the messages being sent. Everything looks good with the exception of the number of messages being sent during initial discovery. Things like wifi info, etc can be retrieved when they're called upon, not during the initial discovery. If the library itself asks for this information on discovery I'd ask it to be removed and only retrieve the bare minimum of what we need from the bulbs. Ideally, simply GetService as a broadcast and Get (light message) will be sufficient to get the mac address, label, service port, IP, along with the current power, brightness, etc from the bulb. Also, UDP is stateless, the connection does not remain open as UDP has no concept of an ongoing connection. Otherwise everything looks very good and is extremely speedy. —You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub[3], or mute the thread[4].[5]


[1] https://github.com/keatontaylor [2] https://github.com/frawau [3] https://github.com/home-assistant/home-assistant/issues/ 6435#issuecomment-284350272 [4] https://github.com/notifications/unsubscribe-auth/AORvqUnFRjrKbhu_d-_BOjTJb5WxEkOpks5ri9dYgaJpZM4MTgc8 [5] https://github.com/notifications/beacon/AORvqVkDsvg0k2w-Uua8tv6Ejd89tOSBks5ri9dYgaJpZM4MTgc8.gif

frawau commented 7 years ago

@amelchio It's on PyPi. Let me know if it works for you.[1]

Regard, François

On Monday, 6 March 2017 02:01:01 ICT Anders Melchiorsen wrote:

@keatontaylor[2] It seems we agree that aiolifx is the way to go, that's great. If nothing unexpected turns up (in the code or in my life), I can probably do the conversion this week. —You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub[3], or mute the thread[4].[5]


[1] https://github.com/amelchio [2] https://github.com/keatontaylor [3] https://github.com/home-assistant/home-assistant/issues/ 6435#issuecomment-284352312 [4] https://github.com/notifications/unsubscribe-auth/ AORvqWbRByImG5MeYdugY1jZHLKSQYXIks5ri9ldgaJpZM4MTgc8 [5] https://github.com/notifications/beacon/ AORvqaV4loxV5no_8_0I6nri5O6S40rgks5ri9ldgaJpZM4MTgc8.gif

arsaboo commented 7 years ago

@amelchio Looking forward to this 👍

amelchio commented 7 years ago

@frawau It works 👌. To be used with Home Assistant, though, aiolifx must be backported to support Python 3.4, see https://home-assistant.io/developers/asyncio_misc/

@keatontaylor It seems that polling is actually needed in order to catch changes made outside of Home Assistant. This could for example be with the smartphone app, a physical wall switch or the native schedules. Do you agree or did I miss something?

frawau commented 7 years ago

@amelchio[1] Really? It works ;) To support 3.4 I would think that all you have to do is change any async/await into @asyncio.coroutine/yield from. From the top of my head that should be it and it only involves 2 methods fire_sending and try_sending, 4 lines in total. (Ooops I should have followed the link before writting that ;))

Can you check if that works ? ( I don't have python3.4 currently ( I used the strech repos to get my "Jessies" up to speed ) Then we can find a way to make that "official" in Pypi.

Indeed you need to poll for status every now and then to get other apps induced changes. I did look a bit (not too hard) and all I could find is the bulb sending a StateInfo message after booting, that the reason of the ' if "State"' bit in datagram_received and also why it can quickly find (around 15 secs) the bulbs that were offline without the need for discovery. That should take care of the physical switch bit.

Cheers, François

On Tuesday, 7 March 2017 00:59:37 ICT Anders Melchiorsen wrote:

@frawau[2] It works 👌. To be used with Home Assistant, though, aiolifx must be backported to support Python 3.4, see https://home-assistant.io/developers/asyncio_misc/ [3] @keatontaylor[4] It seems that polling is actually needed in order to catch changes made outside of Home Assistant. This could for example be with the smartphone app, a physical wall switch or the native schedules. Do you agree or did I miss something? —You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub[5], or mute the thread[6].[7]


[1] https://github.com/amelchio [2] https://github.com/frawau [3] https://home-assistant.io/developers/asyncio_misc/ [4] https://github.com/keatontaylor [5] https://github.com/home-assistant/home-assistant/issues/ 6435#issuecomment-284661122 [6] https://github.com/notifications/unsubscribe-auth/ AORvqdN1oQ_r4u60D_ZrHXGy-0Nt67Biks5rjRx5gaJpZM4MTgc8 [7] https://github.com/notifications/beacon/ AORvqV3asc5s8oWnMg3tKlpEVx_TwRXOks5rjRx5gaJpZM4MTgc8.gif

keatontaylor commented 7 years ago

@amelchio, polling is extremely messy for the following example.

I.E - You turn off lights with a transition say 10 seconds, the bulbs respond with an acknowledgement and ideally HA will see the bulbs as immediately off, which I think is the preferred behavior, since ultimately that is the command that was sent to the bulbs. If during that 10 seconds a polling event occurs, HA will be updated with whatever the brightness level, etc the bulb is currently in during the polling. So for example if the polling occurs at second 5 in the 10 second off transition, polling will report to HA that the bulb is at 50% brightness. If say polling occurs every 10 seconds then we will have 5 seconds of HA not knowing what the state of the bulb is.

The solution to this problem is tricky, because we need to decide if we're going to prioritize HA being "more" correct in what the actual state of the bulbs are, or if we're going to allow apps outside HA to muck around with light state.

In my own testing I went the route of only allowing HA to control the lights, this means that HA is always correct in what state the lights are in, after a transition completes.

Overall the best compromise may be to have something within the library that polls lights on a given interval, but pausing polling for particular bulbs that are in a transition, then resume normal polling when it is complete.

A bad solution, in my opinion, would be ignoring acknowledgements all together and polling the lights more frequently, like once a second, but I am almost 100% confident that would result in the lights becoming unresponsive, etc.

In a perfect world, the lights themselves would broadcast changes regardless of the app being used to control them, so that HA could just capture the broadcasts, and in some cases, like updating lights from the web API they do, but from the LIFX app, they do not.

Let me know what your opinions are on this. I feel it is a crucial decision to be made that has the largest impact on lifx light reliability.

amelchio commented 7 years ago

Okay, I pushed an initial aiolifx version now: https://github.com/amelchio/home-assistant/tree/aiolifx

I am learning Python as I go so the code may have some issues. Especially the asyncio stuff has me kind of confused and googling.

Anyway, everything seems to work much better than before. I think it fixes #3604, #4589, #5158 and #6245.

@frawau I also do not have Python 3.4 handy but if it is just a few lines then we can surely find a way to get that handled. Kudos on aiolifx, it's a pleasure to use.

@keatontaylor I think polling is fine in that situation. Yes, there are some inconsistencies during transitions but the polling will make sure that they are resolved eventually. The smartphone app works the same way and it's rarely an issue. Give it another chance, I believe your bad experiences are mostly due to liffylights, not so much the LIFX bulbs.

keatontaylor commented 7 years ago

@amelchio, if that is the case we need a somewhat high polling rate. Maybe 5 seconds or something. If the state of the bulb is the same as the last state we should not send callbacks to HA to ensure the core thread isn't being flooded with updates. Also, we may want to reconsider some of the code in the lifx component.

Here is the scenario that will result in a bad experience:

Currently the lifx component will not turn on lights that it thinks are already on. So in the case of some external device like the lifx bulb turns the light off, HA will not be able to turn it back on until the next polling even completes. We can remove the check and send the on command to the bulbs regardless of the known state, but that would mean something like a brightness change would send the 'on' command and the brightness change command each time.

This is compounded by the inability for the YAML code in HA to effectively check some state of the bulb and perform no action if it is in a current state. Like the following code.

  action:
    - service_template: >
        {% if is_state('input_boolean.sleeping', 'off') %}
          homeassistant.turn_on
        {% else %}
          homeassistant.turn_off
        {% endif %}
      entity_id: light.bedroom_lamp
      data:
        transition: 0

In the case above, the service template must provide either on or off, you cannot say neither. So commands like these if the code wasn't in place in the component to ignore state changes when the light was already in that state could flood the light with off or on messages when it is already off/on.

I suppose we could ask for a light state message before we send a command to the lights to ensure that the new state we want is different from the old one, but in networks with high latency that would likely increase the time it takes to turn on/off a bulb beyond what would be reasonable for the user.

keatontaylor commented 7 years ago

At bare minimum I would like a configuration option for polling frequency so that it may be turned off it HA is the only thing communicating with the lights.

frawau commented 7 years ago

Hi Guys,

For what it's worth, here is how I would handle your "polling" problem... Again I am not at all familiar with HA, but I think it would work.

Inside the Lifx component, you have a fast heartbeat element (hb), say every 5 secs. Each light has its own cycle, which is an integer (polling freq/ hb freq) each time the hb is fired, all the cycles are decreased by 1, when it reaches 0 the polling message is actually sent and the cycle is reset. Whenever a command with a duration is sent, you set that light cycle so it it will poll right after the command is done.

I think that that could work and is not too difficult to implement.

Just my 2 cents.

Regards, François

On Tuesday, 7 March 2017 17:15:23 ICT Keaton Taylor wrote:

At bare minimum I would like a configuration option for polling frequency so that it may be turned off it HA is the only thing communicating with the lights. —You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub[1], or mute the thread[2].[3]


[1] https://github.com/home-assistant/home-assistant/issues/ 6435#issuecomment-284914755 [2] https://github.com/notifications/unsubscribe-auth/ AORvqdgfJVwbXxA8ZQhR4DBM1uBSUtpCks5rjgErgaJpZM4MTgc8 [3] https://github.com/notifications/beacon/AORvqd-VebgXuaFtmgy6Zb_1JWuh5Lk7ks5rjgErgaJpZM4MTgc8.gif

keatontaylor commented 7 years ago

@frawau seems like a reasonable solution.

amelchio commented 7 years ago

@keatontaylor Why don't you test out my branch. I have tried to address almost all of your concerns so I would be happy to see you actually break it 😃

It is true that HA needs a way to set a color without affecting the power state (and vice versa), for example for Flux. However, that is a generic issue so let us keep that discussion out of this LIFX cleanup.

keatontaylor commented 7 years ago

@amelchio, I already found something I don't like. :)

Your lifx.py code simply sets the HA state of the bulb to the state that is requested without receiving an acknowledgement from the bulb. So there is no verification that the state actually changed to what we want, and instead you seem to be relying solely on polling. This certainly works, but also has its own fair share of issues associated with it.

Also could you explain to me what the block updates code is for?

amelchio commented 7 years ago

There may be a more elegant way to do this but the most elegant way has the problem of not actually working.

The ACK just says that the packet was received, it does not tell us that the transition has completed or even started. But the ACK is not ignored: if it does not show up, "unregister" is called and the bulb is set as unavailable.

The "block_updates" code is to avoid the UI glitch where the power toggle would temporarily jump back right after being clicked. The bulb is slow to react and setting a state followed by requesting the current state can return the old state, even though it is about to change.

Unfortunately, this "set" followed by "get" is exactly what HA always does. So I assume success for two seconds, allowing potential retransmits to complete and the bulb to handle the set request. At this point the "get" is made, ensuring that the state machine is properly updated.

keatontaylor commented 7 years ago

Hmm, I'll have to give this more thought on what may be best, but in the meantime take a look at how the liffylights code does it.

frawau commented 7 years ago

I am just curious.... How often do you see that happening? (No ACK) In my environment I almost never see that. In any case, you could change DEFAULT_TIMEOUT and DEFAULT_ATTEMPTS to find a combination that works for you. I did tinker with that a bit before settling on the current values.

And now for something completely different. Do you have a flic (https://flic.io/) component in HA? Because I have a aioflic lib you might be interested in. (although I am waiting for them to update their bit)

Cheers, François

On Wednesday, 8 March 2017 01:44:14 ICT Anders Melchiorsen wrote:

The ACK just says that the packet was received, it does not tell us that the transition has completed or even started. But the ACK is not ignored: if it does not show up, "unregister" is called and the bulb is set as unavailable.

amelchio commented 7 years ago

@frawau I did not yet run it long enough to tell. Until now I mostly saw missing ACKs when toggling the wall switch on purpose. I do have one bulb that seems to unregister every now and then. I will have to keep an eye on that but it is an outdoor lamp and I suspect that it is actually checking out.

Just to be clear, Home Assistant is not my project. I am just a new user trying to get it working with my lights. So the Flic button is not in my personal area of interest, sorry.

mclarkk commented 7 years ago

Just an FYI for future projects, lifxlan has been updated to support both Python 2 and Python 3, thanks in large part to @frawau! It was way past due. I just released the newest version on PyPI. Best of luck on the HA project!

amelchio commented 7 years ago

@mclarkk that's great, thanks for your good work on LIFX support.

@frawau I now confirmed that the bulb that is frequently being unregistered by aiolifx cannot be ping'ed during the outage. So it seems to be a problem with my connectivity and not an issue with aiolifx 👍

amelchio commented 7 years ago

@keatontaylor @arsaboo @Charliedean @brianjking @petersandersen @issacg

Hi guys. If you feel like it, please test my new LIFX platform. I put instructions at the top of this #6435 issue. (I picked your handles from issues that I think my work fixes.)

arsaboo commented 7 years ago

@amelchio Thanks....trying it now. It does not start, I see the following in my logs:

Mar 10 20:54:53 raspberrypi hass[1314]: File "/home/hass/.homeassistant/custom_components/light/lifxtest.py", line 214
Mar 10 20:54:53 raspberrypi hass[1314]: ^
Mar 10 20:54:53 raspberrypi hass[1314]: SyntaxError: only named arguments may follow *expression
arsaboo commented 7 years ago

I removed the * on that line and then it works. Will test it out more.

amelchio commented 7 years ago

@arsaboo Thanks, that was a 3.5-ism, so I guess you are running on Python 3.4? I fixed it now.

keatontaylor commented 7 years ago

I'll take a look asap. Probably on Sunday. :)

arsaboo commented 7 years ago

Working well so far. Let me know if there is anything specific that we want to test.

arsaboo commented 7 years ago

I did a side-by-set testing of the current lifx component and lifxtest. The difference is day and night. Lifxtest is super responsive - the status updates in less than a second when turning the lights on and in less than 2-3 seconds when turning them off. On the lifx component, it almost takes forever to update (easily more than 30 seconds). Would love to see a PR soon just for the speed alone.

Quick question: Is there any way to add random, color loop, or any other effects?

arsaboo commented 7 years ago

Also, see these errors in the logs every time I turn on/off the lights:

17-03-11 11:44:15 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/lib/python3.4/asyncio/tasks.py", line 237, in _step
    result = next(coro)
  File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/core.py", line 1001, in _event_to_service_call
    yield from service_handler.func(service_call)
  File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/components/light/__init__.py", line 249, in async_handle_light_service
    yield from light.async_turn_on(**params)
  File "/usr/lib/python3.4/asyncio/coroutines.py", line 141, in coro
    res = func(*args, **kw)
  File "/home/hass/.homeassistant/custom_components/light/lifxtest.py", line 225, in async_turn_on
    self.block_updates()
  File "/home/hass/.homeassistant/custom_components/light/lifxtest.py", line 178, in block_updates
    self.blocker = asyncio.ensure_future(self.update_later())
AttributeError: 'module' object has no attribute 'ensure_future'
17-03-11 11:44:23 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/lib/python3.4/asyncio/tasks.py", line 237, in _step
    result = next(coro)
  File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/core.py", line 1001, in _event_to_service_call
    yield from service_handler.func(service_call)
  File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/components/light/__init__.py", line 251, in async_handle_light_service
    yield from light.async_turn_off(**params)
  File "/usr/lib/python3.4/asyncio/coroutines.py", line 141, in coro
    res = func(*args, **kw)
  File "/home/hass/.homeassistant/custom_components/light/lifxtest.py", line 239, in async_turn_off
    self.block_updates()
  File "/home/hass/.homeassistant/custom_components/light/lifxtest.py", line 178, in block_updates
    self.blocker = asyncio.ensure_future(self.update_later())
AttributeError: 'module' object has no attribute 'ensure_future'
amelchio commented 7 years ago

@arsaboo Thank you, that is very valuable feedback! I have pushed a new version which I think fixes the error in your log. Maybe I should install Python 3.4 myself to better see those things .

There is not anything specific to test. This first step is for bug fixes as well as improved reliability and response times. The only new feature is that lights are set as "unavailable" when turned off at the wall switch.

I want to use LIFX for notifications so I do plan to add at least a flash effect. I don't know about color cycling, it has to run on the server (not the bulb) so it is a bit of work to implement.

arsaboo commented 7 years ago

@amelchio Cool....those errors are gone with the fix.

Color cycling will be cool to have, but I guess that is not an immediate requirement. Something to work on after we have the basics ready 😉

arsaboo commented 7 years ago

Just updated to 0.40 and now I see a few of these in my logs:

17-03-11 18:23:40 ERROR (MainThread) [homeassistant.core] Error doing job: Exception in callback _SelectorDatagramTransport._read_ready()
Traceback (most recent call last):
  File "/usr/lib/python3.4/asyncio/events.py", line 120, in _run
    self._callback(*self._args)
  File "/usr/lib/python3.4/asyncio/selector_events.py", line 932, in _read_ready
    self._protocol.datagram_received(data, addr)
  File "/home/hass/.homeassistant/deps/aiolifx/aiolifx34.py", line 111, in datagram_received
    callb(self,response)
  File "/home/hass/.homeassistant/custom_components/light/lifxtest.py", line 90, in ready
    self.hass.async_add_job(self.async_add_devices([entity]))
  File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/core.py", line 195, in async_add_job
    elif is_callback(target):
  File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/core.py", line 80, in is_callback
    return '_hass_callback' in func.__dict__
AttributeError: 'NoneType' object has no attribute '__dict__'
17-03-11 18:23:40 ERROR (MainThread) [homeassistant.core] Error doing job: Exception in callback _SelectorDatagramTransport._read_ready()
Traceback (most recent call last):
  File "/usr/lib/python3.4/asyncio/events.py", line 120, in _run
    self._callback(*self._args)
  File "/usr/lib/python3.4/asyncio/selector_events.py", line 932, in _read_ready
    self._protocol.datagram_received(data, addr)
  File "/home/hass/.homeassistant/deps/aiolifx/aiolifx34.py", line 111, in datagram_received
    callb(self,response)
  File "/home/hass/.homeassistant/custom_components/light/lifxtest.py", line 90, in ready
    self.hass.async_add_job(self.async_add_devices([entity]))
  File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/core.py", line 195, in async_add_job
    elif is_callback(target):
  File "/srv/hass/hass_venv/lib/python3.4/site-packages/homeassistant/core.py", line 80, in is_callback
    return '_hass_callback' in func.__dict__
AttributeError: 'NoneType' object has no attribute '__dict__'
keatontaylor commented 7 years ago

@amelchio, color cycling can run on the bulb with the setwaveform command as part of the lifxlan and by proxy the aiolifx library.

amelchio commented 7 years ago

@arsaboo Thanks again! I pushed another fix.

amelchio commented 7 years ago

@keatontaylor that only does one color change (what I called a flash effect). I believe you have to string several of those together to get some nice cycling effects.

keatontaylor commented 7 years ago

Ah, I see. Still we should have pulse/blink implemented via set waveform.

arsaboo commented 7 years ago

This has been working very reliably for me....may not be a bad idea to get the initial implementation in. Simpler the PR, faster it will be approved 😉

keatontaylor commented 7 years ago

@arsaboo very true.

arsaboo commented 7 years ago

@amelchio Regarding the cycling effects, instead of specifying the colors as you suggest in your previous comment, wondering if it will be easier to just use random colors.

amelchio commented 7 years ago

@arsaboo Can you describe the effects you are looking for in more detail? Incidentally, I hope to submit the PR on the initial implementation today but I do expect a fair amount of spanking in review as I am new to Home Assistant as well as Python.

arsaboo commented 7 years ago

@amelchio All the more reason to submit a simpler code :wink:

I am essentially looking for a random color cycling that can be used in case of parties (something similar to color loop in Hue). The effects that LIFX runs on the phone use lot of battery. It will be nice to have something similar/close that can be run independently.

amelchio commented 7 years ago

@arsaboo It uses a lot of battery because it is a lot of work and that would have to be implemented again in Home Assistant :). I don't know how Hue does things, hence the request to elaborate. I was wondering whether it could be done already today with a (somewhat complicated) HA script.

Personally, I would love an effect that could simulate a TV set to a burglar passing by the house.

arsaboo commented 7 years ago

@amelchio A script should be fine. As long as we can specify the colors (see example here) and the transition interval, we should be fine.

issacg commented 7 years ago

Sorry I haven't had a moment to look at this yet, but wanted to add that I'm very grateful for your work regardless 👍

Charliedean commented 7 years ago

Working perfectly over here, I have just replaced the lifx.py until next release. Loving the responsiveness and smoothness 👍

mihalski commented 7 years ago

Thank you!

I will be testing this tonight. I have been a very angry man since getting over 20 Lifx lights and being tortured by their unreliability.

Hopefully this can bring a little joy back into my life!