Closed mihalski closed 8 years ago
Hello Michal,
Thank you for giving a chance to lightsd!
This error most likely means lightsd is already running, but I don't have enough context to be sure about that. To help you as effectively as possible could you tell me the process you've followed to setup lightsd? The output of those two commands will also be helpful:
systemctl status lightsd
lsof -i :56700
Both commands need to be run as root, the first one will tell us if lightsd was already started by systemd and the second one (which needs the lsof [1] package to be installed) will tell us what's using lightsd/LIFX's address and port.
Any question, let me know!
Cheers – Louis
Hi,
Thanks for your response.
I'll start with the outpput of the two commands:
homepi:~ $ sudo systemctl -l status lightsd
● lightsd.service - LIFX WiFi smart bulbs control service
Loaded: loaded (/usr/lib/systemd/system/lightsd.service; disabled)
Active: failed (Result: start-limit) since Mon 2016-10-24 15:36:02 AEST; 15h ago
Process: 10044 ExecStart=/usr/bin/lightsd -t -v warning -s %t/lightsd/socket -c %t/lightsd/pipe (code=exited, status=1/FAILURE)
Main PID: 10044 (code=exited, status=1/FAILURE)
Oct 24 15:36:02 homepi systemd[1]: lightsd.service: main process exited, code=exited, status=1/FAILURE
Oct 24 15:36:02 homepi systemd[1]: Unit lightsd.service entered failed state.
Oct 24 15:36:02 homepi lightsd[10044]: [ERR] lightsd: can't setup lightsd: Address already in use
Oct 24 15:36:02 homepi systemd[1]: lightsd.service holdoff time over, scheduling restart.
Oct 24 15:36:02 homepi systemd[1]: Stopping LIFX WiFi smart bulbs control service...
Oct 24 15:36:02 homepi systemd[1]: Starting LIFX WiFi smart bulbs control service...
Oct 24 15:36:02 homepi systemd[1]: lightsd.service start request repeated too quickly, refusing to start.
Oct 24 15:36:02 homepi systemd[1]: Failed to start LIFX WiFi smart bulbs control service.
Oct 24 15:36:02 homepi systemd[1]: Unit lightsd.service entered failed state.
pi@homepi:~ $ sudo lsof -i :56700
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
hass 10235 homeassistant 7u IPv4 901286 0t0 UDP *:56700
pi@homepi:~ $
So that certainly explains why it's not starting, but I have no idea what Home Assistant is doing with that port.. Is it a default JSON-RPC port perhaps? Also doesn't explain why I couldn't start it on another port, but that could just be user error on my part.
I installed lightsd originally by downloading the current version using the git command and building my own debian package as per the documentation. Then I discovered that you had new release candidate packages available do I downloaded the deb file, purged my personally built package and installed yours.
pi@homepi:~ $ dpkg -l lightsd
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-====================-===============-===============-=============================================
ii lightsd 1.2.0~rc.4-1 armhf Centralized daemon to control your LIFX bulbs
Assuming lightsd can do everything I desire (and it seems like it should) I hope to eventually stumble my way to integrating it with Home Assistant (the LIFX support in that has frustrated me GREATLY).
Regards, Michal
Yes, homeassistant and lightsd are conflicting here:
Listening on UDP port 56700 is part of the LIFX LAN protocol [1], and both homeassistant and lightsd cannot use it at the same time.
I think you need to look for a way to disable homeassistant's LIFX integration so it doesn't bind on udp/56700, that will allow you to run both lightsd and homeassistant at the same time. Otherwise you can simply stop homeassistant, it's probably not what you're looking for, but that will allow you to try lightsd.
I'm happy to read you're interested in integrating lightsd with homeassistant! I wrote a Python 3.5 client for lightsd on top of asyncio [2] and typing [3], which might be of interest. I haven't done a good job at releasing my work lately, but that client will end-up on PyPI before the end of the year.
Best – Louis
[1] https://lan.developer.lifx.com/docs/workflow-diagrams#discovery [2] https://docs.python.org/3/library/asyncio.html [3] https://docs.python.org/3/library/typing.html
Thank you for your very informative response.
It was just the LIFX lights "platform" in Home Assistant that was using that port. I took it out of the configuration and now lightsd is running happily.
I must admit that I am certainly not skilled in any programming languages and my current job doesn't really allow me much time to invest in learning one, but I do reasonably well with basic examples such as:
Those two examples would probably make clear to me how to interpret the documentation and let me start messing around.
Are you aware of any other sources of information and examples with regards to lightsd? I've found nothing with google.
Regards, Michal
lightsd doesn't make use of HTTP, so curl cannot be used to send commands. lightsd uses JSON-RPC right over TCP, which is unconventional, but simpler from my point of view.
You'll find some documentation about how to use lightsd here: http://lightsd.readthedocs.io/en/latest/index.html. Since you already have lightsd running successfully you can jump right into the "First steps" section, you'll see that it covers the systemd commands we already used here and will get you running with two examples: one using only shell commands and one in Python (I recommend you install the ipython3 [1] package to run the Python example).
Once you've got the examples running the real stuff is in the "The lights daemon protocol", that section also covers how to write a client for lightsd (i.e., a curl replacement for lightsd). But hopefully, you'll find the examples easy enough to tinker with and you won't need to rewrite a full client nor miss curl too much.
The only sources of information about lightsd that I know of are: here, the docs that I linked, and this thread on the LIFX forum [2]. I can't wait to spend some time on adding to and improving the documentation.
Any question, let me know!
Cheers – Louis
[1] https://packages.debian.org/jessie/ipython3 [2] https://community.lifx.com/t/lightsd-a-daemon-with-a-json-rpc-api-to-control-your-bulbs/
I'd like to say that your responses are in general pretty fantastic (the footnotes are a great touch). However the link to the LIFX developer Zone doesn't seem to be working. In fact the Developer Zone seems to be down?
And with regards to the documentation and the example, because of my lack of familiarity with JSON I think I'm missing something.. If I am starting from the position of not knowing how many lights there are or what their names are, how do I get a list? It SEEMS to me from the documentation like you MUST know the names of the lights to do anything. Am I misunderstanding?
Regards, Michal
And I think I've stumbled into the answer:
pi@homepi:~ $ sudo /usr/share/lightsd/examples/lightsc.py
Connecting to lightsd@unix:///run/lightsd/socket
Python 3.4.2 (default, Oct 19 2014, 13:31:11)
Type "copyright", "credits" or "license" for more information.
IPython 2.3.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
Connected to unix:///run/lightsd/socket, use the variable c to interact with your bulbs:
>>> r = c.get_light_state("*")
>>> r
In [1]: bulbs = {b["label"]: b for b in c.get_light_state("*")["result"]}
In [2]: bulbs
Out[2]:
{'Office Floor Lamp': {'_lifx': {'wifi': {'firmware_version': '101.62'},
'gateway': {'url': 'tcp://[::ffff:192.168.1.9]:56700',
'site': '4c:49:46:58:56:32',
'latency': 0},
'addr': 'd0:73:d5:14:1d:c8',
'mcu': {'firmware_version': '1.13'}},
'_model': 'Color 1000',
'_vendor': 'LIFX',
'tags': [],
'label': 'Office Floor Lamp',
'hsbk': [216, 0, 0.239993, 3540],
'power': False},
'Family Room Floor Lamp': {'_lifx': {'wifi': {'firmware_version': '101.62'},
'gateway': {'url': 'tcp://[::ffff:192.168.1.16]:56700',
'site': '4c:49:46:58:56:32',
'latency': 0},
'addr': 'd0:73:d5:13:e5:c3',
'mcu': {'firmware_version': '1.13'}},
'_model': 'White 800',
'_vendor': 'LIFX',
'tags': [],
'label': 'Family Room Floor Lamp',
'hsbk': [0, 0, 1, 2500],
'power': False},
'Bedroom Bedside Lamp': {'_lifx': {'wifi': {'firmware_version': '101.62'},
'gateway': {'url': 'tcp://[::ffff:192.168.1.45]:56700',
'site': '4c:49:46:58:56:32',
'latency': 0},
'addr': 'd0:73:d5:14:14:26',
'mcu': {'firmware_version': '1.13'}},
'_model': 'Color 1000',
'_vendor': 'LIFX',
'tags': [],
'label': 'Bedroom Bedside Lamp',
'hsbk': [0, 0, 0.18999, 3215],
'power': False},
'Office Ceiling Light': {'_lifx': {'wifi': {'firmware_version': '101.62'},
'gateway': {'url': 'tcp://[::ffff:192.168.1.51]:56700',
'site': '4c:49:46:58:56:32',
'latency': 0},
'addr': 'd0:73:d5:12:21:f3',
'mcu': {'firmware_version': '1.13'}},
'_model': 'White 800',
'_vendor': 'LIFX',
'tags': [],
'label': 'Office Ceiling Light',
'hsbk': [0, 0, 0.203128, 4515],
'power': False},
'Living Room Lamp': {'_lifx': {'wifi': {'firmware_version': '101.62'},
'gateway': {'url': 'tcp://[::ffff:192.168.1.12]:56700',
'site': '4c:49:46:58:56:32',
'latency': 0},
'addr': 'd0:73:d5:12:1c:5f',
'mcu': {'firmware_version': '1.13'}},
'_model': 'White 800',
'_vendor': 'LIFX',
'tags': [],
'label': 'Living Room Lamp',
'hsbk': [0, 0, 0.98999, 2500],
'power': False}}
In [3]:
Is this the right way of getting a list of available lights (along with their details)?
Regards, Michal
EDIT: While I'm at it, I'm curious if you have you adopted, developed or found any particular naming convention for your lights? I've encountered the problem that you either have to be too descriptive (Bedroom Bedside Lamp doesn't roll off the tongue when you're sleepy and asking Alexa to turn it off) or you run into problems with multiple Floor Lamp/Table Lamp/Ceiling Light/etc which cannot benefit from the context of your location when trying to control them.
Thank you for the kind words!!
Yes, that is the right way of getting a list of available lights with their details! I'm sure you'll wrap your head around JSON [1] very fast, it's just a way to represent basic data types —numbers, character strings, list and key/value pairs (aka, JSON objects, maps or dictionaries)— in a standard textual form. JSON is effectively a data serialization format [2] (And JSON-RPC is built on top of this format).
Yes, knowing the names (labels) of your lights matters. For lightsd the name of a light is a "target", on which you can do different things such as changing its color, turn it on or off and so on. But you can also use tags (which is the legacy way to group lights together in the LIFX protocol [3]) and * (a shortcut for "all lights") to target lights [4].
If anything, stupid, arbitrary and short names has been the convention for naming my lights. Then I have some more useful tags (groups) such as "#kitchen", "#br" (bedroom), "#tower" (all the lights in some Ikea thing) or "#ceilings". I think it comes down to a personal preference, just one thing to keep in mind: don't name two lights the same name to group them together, use a tag for that.
Finally, I don't recommend you run lightsc.py with sudo (i.e., as the privileged user root), you should just add the "pi" user to the lightsd group, this will give your "pi" user access to lightsd's UNIX socket:
sudo gpasswd -a pi lightsd
Log out and back in as the pi user; the groups
command should now list you lightsd membership. (This is actually in the docs but we skipped that part 🙃).
Best – Louis
[1] http://www.json.org/ [2] https://en.wikipedia.org/wiki/Serialization [3] And the only one lightsd support, which seems to be fine seems LIFX has maintained backward compatibility (ty!), though groups made with tags don't show up in their mobile apps anymore. [4] http://lightsd.readthedocs.io/en/latest/protocol.html#targeting-bulbs
I notice that all the LIFX LAN protocol implementations use port 56700. Is this necessary? Is there a way to have multiple implementations running concurrently on the same ip address? ie homebridge-lifx-lan and lightsd for example?
I'm starting to feel like there should be a LIFX LAN proxy that everything connects to :/
Regards, Michal
The protocol specifies udp/56700, implementations have to follow it. Only one application at the same time can bind to a given port/ip address pair. It would be interesting to check if the bulbs would actually reply to traffic not coming from 56700 (so you could bind on something else than udp/56700), but I don't really have an incentive to spend time on this.
lightsd can be used as a proxy to the LIFX bulbs: it's effectively a single point of control for all your bulbs and allows network separation. A "true" proxy would speak the LIFX LAN protocol on both sides, but I don't think such implementation is a good idea since LIFX has moved to a model where one bulb equals one IP address.
homebridge speaking to lightsd is probably a better way to go?
I fear I may not have enough time and/or may be a bit too stupid to get this working. I've trying to get lightsc.sh working and I've set the correct pipe and added the pi user to the lightsd group (and logged out and back in) but for the life of me I can't get it to work.
For example:
pi@homepi:~ $ lightsc_make_request power_on ${*:-'["Office Floor Lamp","Office Ceiling Light"]'}
{
"jsonrpc": "2.0",
"method": "power_on",
"params": [["Office Floor Lamp","Office Ceiling Light"]],
"id": "wh2jbLC2WnY="
}
But the same thing in the python client works:
In [1]: c.power_on(["Office Floor Lamp","Office Ceiling Light"])
Out[1]:
{'result': True,
'id': '493e1f45-c9a8-4e0d-a908-12289486fa6b',
'jsonrpc': '2.0'}
I'm just looking for an easy way to to be able to control lightsd from the command line with separate commands (or batches of commands) so that I can get it working in the interim while I try to figure out how to use it properly.
tl;dr: what you meant is lightsc power_on ${*:-'["Office Floor Lamp","Office Ceiling Light"]'}
, which can be further simplified into lightsc power_on '["Office Floor Lamp","Office Ceiling Light"]'
.
As the documentation explains (here [1]); the lightsc_make_request
shell function is meant for batching multiple JSON-RPC requests together: it outputs a request but doesn't send it to lightsd. The idea is to call lightsc_make_request
multiple times, surround that output with [
and ]
(to make it a JSON list) and send all of that down lightsd's pipe, e.g:
tee $(lightsc_get_pipe) <<EOF
[
$(lightsc_make_request power_on "Office Floor Lamp"),
$(lightsc_make_request power_on "Office Ceiling Light")
]
EOF
Also notice how the two commands are separated by a coma (again, to make it a proper JSON list).
If we don't care about batching (and we never do when we only have one command to execute) just use the lightsc
shell function; this will do what you meant:
lightsc power_on ${*:-'["Office Floor Lamp","Office Ceiling Light"]'}
Finally, if you want to demystify that ${*:-…}
notation you may want to read about "Parameter Expansion" and "Special Parameters" in your shell manual (which man $(basename ${SHELL})
should display to you). Otherwise you can just skip it:
lightsc power_on '["Office Floor Lamp","Office Ceiling Light"]'
Hope this helps!
[1] http://lightsd.readthedocs.io/en/latest/first-steps.html#using-lightsc-sh
@mihalski, I'm closing this, if you have more questions contact me and/or create a thread on the LIFX forum (I still piggy-back on their forum, since lightsd doesn't have one).
Thank you for trying/using lightsd!
Hi,
I've found lightsd due to my contempt for how poorly all the other solutions (such as the integrated LIFX support in Home Assistant) perform. It seemed to me like this project was trying to solve all the problems that plagued those implementations.
However, when I try to start lightsd (whether directly or through the startup scripts) I get the error:
[ERR] lightsd: can't setup lightsd: Address already in use
Any ideas as to what might cause this? It's not complaining about the port (of which I have tried many), but the address.. I've tried 0.0.0.0, 127.0.0.1 and my wlan0 ip (as well as not specifying at all as is the default with the startup script).
FWIW I'm running Raspbian Jessie on a Raspberry Pi 3.
Regards, Michal