Written some Osram Lightify support

Thanks for the heads up, I maybe doing something wrong but I don’t think the lib is Python 3 friendly.

" string = string + data
TypeError: Can’t convert ‘bytes’ object to str implicitly"

I remember bumping into this and another error because of changes between Python 2 and 3 which I fixed in my fork, so unless this gets fixed I think it means it’s a no go. Unless some one else can chime in with some useful information?

I’ve added a pull request for Andreas Neumeier’s fork here: https://github.com/aneumeier/python-lightify/pull/1 which should solve the python3 issues and also treat cases when luminosity is increased and the state is off and when luminosity is set to 0 and the state is on.

From what I see there is no need for set_onoff method as we can use set_luminance to turn the bulb on and off, this also allows us to use fade transitions for on/off.

I’ve also added the Osram Lightify component on my home-assistant fork here: https://github.com/olimpiurob/home-assistant/tree/osram_lightify which supports color temperature, fading(transition), rgb, brightness. All work is based on MindrustUK initial code here: https://github.com/MindrustUK/python-lightify with some improvements.

In order to test things out, you need to clone my home-assistant fork and install my for of python lightify that you can find here: https://github.com/olimpiurob/python-lightify change the lightify version to 1.0.3 here: https://github.com/olimpiurob/python-lightify/blob/master/lightify/init.py#L30 and install with python setup.py install in the root of the python-lightify.

There are still some quirks with the brightness, but haven’t had time to fix it and also, I only have one RGBW light to play with, that means that non RGBW bulbs and flexlight strips might not work at all.

The pull request for Andreas Neumeier’s fork has been merged and lightify 1.0.3 released on pypi. I have added a pull request for home-assistant here: https://github.com/home-assistant/home-assistant/pull/2170

Just updated to 0.21 today,

Looks like this is busted in some way:

Traceback (most recent call last): File "/usr/local/lib/python3.4/dist-packages/homeassistant/core.py", line 809, in job_handler func(arg) File "/usr/local/lib/python3.4/dist-packages/homeassistant/helpers/event.py", line 179, in pattern_time_change_listener action(now) File "/usr/local/lib/python3.4/dist-packages/homeassistant/helpers/entity_component.py", line 191, in _update_entity_states entity.update_ha_state(True) File "/usr/local/lib/python3.4/dist-packages/homeassistant/helpers/entity.py", line 145, in update_ha_state self.update() File "/usr/local/lib/python3.4/dist-packages/homeassistant/components/light/osramlightify.py", line 165, in update self.update_lights(no_throttle=True) File "/usr/local/lib/python3.4/dist-packages/homeassistant/util/__init__.py", line 289, in wrapper result = method(*args, **kwargs) File "/usr/local/lib/python3.4/dist-packages/homeassistant/util/__init__.py", line 289, in wrapper result = method(*args, **kwargs) File "/usr/local/lib/python3.4/dist-packages/homeassistant/components/light/osramlightify.py", line 67, in update_lights bridge.update_all_light_status() File "/home/hass/.homeassistant/deps/lightify/__init__.py", line 430, in update_all_light_status data = self.build_all_light_status(1) File "/home/hass/.homeassistant/deps/lightify/__init__.py", line 320, in build_all_light_status struct.pack("<B", flag) File "/home/hass/.homeassistant/deps/lightify/__init__.py", line 232, in build_global_command self.next_seq() struct.error: ubyte format requires 0 <= number <= 255

Anyone else found this? I haven’t had a proper chance to investigate my self yet.

Yeah, I’ve noticed the issue too. My guess is (and it’s just a guess now, as I didn’t have time to debug) that the connection fails at some point (usually a few hours after starting up HASS) and there is no mechanism for reconnecting(restarting hass and reinitializing the lightify bridge connection fixes the issue)

I was thinking of the lightify library and the way it is designed as it creates the connection when Lightify is instantiated, wouldn’t it be better if a connection is made each time you attempt to change/update/get state of the bulbs and then the socket be closed.

I don’t know much about network programming, but it would seem more efficient. I’d appreciate input here from someone that is more experienced in this matter.

I ended up disabling the following until I get round to having a proper look. This puts me roughly at the behavior and state of my previous code. It works fairly well since the update doesn’t change much as I don’t usually introduce new bulbs without a restart anyway.

def update(self): """Synchronize state with bridge.""" self.update_lights(no_throttle=True)

I was previously trying to do something along the lines of opening and closing the socket in lightify.py at every operation (read or write). Or at least having a catch condition that if it tries and can’t write it attempts to re-establish the connection. This was a problem I saw in my original code but as it happened so infrequently I just ended up having a Nagios job restart HASS until I get round to fixing it.

I’m not sure if there’s a more elegant way than try to read / write, fail, retry connection if that doesn’t work then generate an exception?

I’ve made some changes to the lightify library that should improve things. Still inneficient as it will re-connect if it fails to send data or receive, but it should work, at least it works if I unplug the bridge and plug it again without restarting hass.
The file is here: https://gist.github.com/olimpiurob/673659c93f5750a92498397333ddc775 and you just have to copy it over the old lightify’s __init__.py file, probably located in /usr/local/lib/python3.4/site-packages/lightify/. This should be further improved.
If it works, I guess I’ll just make another pull request as it is, as I seriously lack free time to properly fix this.

It turns out that the issue pops back up after a few hours.

So I finally got some time to look at this:

def build_basic_command(self, flag, command, group_or_light, data): length = 14 + len(data) try: result = struct.pack( "<H6B", length, flag, command, 0, 0, 0x7, self.next_seq() ) + group_or_light + data except TypeError: # Decode using cp437 for python3. This is not UTF-8 result = struct.pack( "<H6B", length, flag, command, 0, 0, 0x7, self.next_seq() ) + group_or_light + data.decode('cp437')

return result

Specifically:

" length, flag, command, 0, 0, 0x7, self.next_seq()

Will throw an struct.error range above 255.

This is due to: self.next_seq() incriminating beyond 255. I’m not sure how the sequence number impacts things at a protocol level, I need to do some more research.

For now I’ve bodged this as follows:

" length, flag, command, 0, 0, 0x7, 0 #self.next_seq()

I’ve got this on test for now so we’ll see how it goes.

So had this on test overnight, all appears to work:

Gist as follows: https://gist.github.com/MindrustUK/3af79d035dbbd26b4cc5f08b8d99a8e9

Overwrite : .homeassistant/deps/lightify/init.py as needed.

Haven’t had time to look at the sequence number in detail but this seems to fix the issue for now.

1 Like

Been testing this today, and seems to work well. :smiley: BUt its now giving this every 5 seconds:

16-07-07 23:40:13 lightify: Lightify Connecting…
16-07-07 23:40:18 lightify: Lightify Connecting…
16-07-07 23:40:23 lightify: Lightify Connecting…
16-07-07 23:40:28 lightify: Lightify Connecting…
16-07-07 23:40:33 lightify: Lightify Connecting… etc

I think some of the reconnect code added by Olimpiu Rob is creating this, I’ve not had the same happen to me but for some reason it’s constantly reconnecting to your gateway. I’ve noticed where he’s refactored / rewritten some of my original code he’s introduced some (personally) undesirable behavior (light luminosity not being preserved between on off states of the light) so I’ll need to look into that. I’ve not been able to re-create the disconnecting bug my self yet but my setup usually runs a few weeks / months before giving trouble (The gateway is fairly close to the wifi AP so think that helps).

Can you check and if available update your firmware via the official application? Long shot but never hurts to be on the latest version.

I haven’t seen the constant reconnect since last restart. I’m on the latest firmware, I just updated when I got a replacement unit (my first bulb died after a few weeks…). It might be related to the fact that I removed the bulb, and placed it in another lamp yesterday (without touching he gateway)…not sure. There is no signal issue for sure, my apt is too small for that :slight_smile:

I’ve also noticed that it doesn’t keep the dim state, like you mention… Sometimes the toggle also jumps back to the current state. If I turn it on, it just jumps back to off (and does nothing). On a second try, it works. This may be an issue with lightify, as I’ve seen that sometimes in the app as well.

:slight_smile:

Unfortunately I can’t find the time to debug and fix the issues described in this ticket at the current time. As soon as I can find the time I will do so if nobody finds a fix by then.
The problem described by kjell seems to be network related. Also, keeping the state of the light seems to be an issue with the lightify itself, as the app fails to keep state as well. I’ve noticed there are some sort of profiles that you can save, but they are available in the app itself, and they won’t work without the app.

Current python-lightify version is 1.0.3.
Where’s the latest version developed/committed? I only found version 1.0.2 in Github.

Andreas Neumeier seems to be packing / maintaining this at the following location:

Yeah, I forked the latest 1.0.4 and made a minor change so that light names now support utf-8. It works for me, I don’t know how well with others.

You fix works ok?

I was thinking how about just truncating self.next-seq() to ubyte? Maybe the field is there for differentiating different requests? If it cannot be truncated, what’s the point of having only one byte as counter?

I put % 256 to mine. Lets see how that works.

It’s been stable for a while now. There are still a bunch of other things that need fixed that I say I’ll get to every Sunday but haven’t gotten to it yet… Sounds like your fix maybe better, want to post a gist it might be useful for some other people watching the thread?

Not much code:
file : /usr/local/lib/python3.4/dist-packages/lightify/init.py

line 232 self.next_seq()
change to : self.next_seq() % 256

line 244 self.next_seq()
change to : self.next_seq() % 256

line 260 self.next_seq()
change to : self.next_seq() % 256

line 272 self.next_seq()
change to : self.next_seq() % 256

There’s three bytes before this counter : 0,0,7
Maybe they are just part of the counter?

But if there is many phones connecting to same lightify hub, are the counters synchronized? I don’t think so? Sounds too complicated. So my bet is it’s just something to keep different requests in some kind of order. Maybe there was some kind of rare error and with this counter it’s now 256x more rare?