Lightsd: a daemon with a JSON-RPC API to control your bulbs

Thanks to lightsd I’ve been able to create “gesture” control for one of my lights with NodeMCU and Range sensor. If anyone is interested, here is how I’ve done it http://lab.ra100.net/control-lifx-nodemcu-and-range-sensor

2 Likes

@lopter I have been unable to build on the latest Raspbian builds, it just about finishes then fails at the end. I gave up sorry and don’t have the error written down but attempting on a new build on Pi 1 and 2 failed. I will try the 3 next but not sure when I will have time.

Oh! Can you copy/paste or attach error logs? Then I should be able to help.


@ra100, nice! I need to setup ready-to-install Debian/Ubuntu packages and/or, even better, actual repositories (which will also help @boxhead) .

I also need to add a method to adjust or set the brightness independently of the hue/saturation/temperature to make this kind of things easier. I actually wonder if such thing would be useful for another parameter than the brightness (in other words if lightsd should expose a generic method or only something for the brightness).

I’d recommend being able to change any subset of the HSBK components, while leaving the other components unchanged. (The same as what is possible in the Cloud API.)

I second that idea, I don’t think I’d use something like changing only hue right now, but it would be nice to can do that easily.

I will have to try and build again when I have some time to capture that for you. It isn’t an issue and I am not sure if anyone else has found the same problem. I will try again on the 3 as it is so much quicker.

1 Like

The secret key under your email address not available. Clearsign failed secret key not available.

That looks like an error from gnupg, not sure why you’re getting that. Are you building the package using the debuild command? If you’re using dpkg-buildpackage directly, you should be using the options -uc and -us. Do you happen to have the full log output including the commands (or sequence of commands) that led to that result?

Thanks

See your documentation.

Build instructions for Debian based systems (Ubuntu/Raspbian)
Note Those instructions have been tested on Debian Wheezy & Jessie.
Install the following packages:

apt-get install build-essential cmake libevent-dev git ca-certificates ipython3 fakeroot wget devscripts debhelper
Download and extract lightsd:

wget -O lightsd_1.1.2.orig.tar.gz https://github.com/lopter/lightsd/archive/1.1.2.tar.gz
tar -xzf lightsd_1.1.2.orig.tar.gz
cd lightsd-1.1.2
wget -O - https://github.com/lopter/lightsd/releases/download/1.1.2/dpkg-1.1.2.tar.gz | tar -xzf -
Build the package:

debuild

That is as far as I got. As to logs none are created that I saw.

I think this error can only happen at one of those commands:

apt-get install build-essential cmake libevent-dev git ca-certificates ipython3 fakeroot wget devscripts debhelper

or

debuild

Can you tell me which one of them is actually failing and maybe attach the entire log output? That will be helpful.

Thanks!

debuild.

There is no log that I know of it is just the screen results I see.

Sorry I should have said those were your instructions I followed up until the point it failed. The rest didn’t seem to have any issues before debuild

Alright, I’m not sure that error is critical, do you see the .deb packages being created? (If you are strictly following the build instructions, the packages will be created in the parent directory from where you run debuild, so you’ll have to do ls .. to check that out).

Otherwise you might wanna try to run debuild -uc -us instead of debuild and see if that gets rid of the error. The -uc and -us options prevent files from being cryptographically signed, we don’t need that here and we aren’t set-up for it.

Yeah, if debuild -uc -us doesn’t solve the issue, just copy-pasting the output might be helpful, I have a feeling that the ouput of the env command could be useful too. Since the forum isn’t configured to allow text files attachment, you might want to paste the output at pastie.org or something like it instead.

Thank you so much for your patience!

Uploads of txt files are now allowed. :wink:

1 Like

Thanks @lopter for the help. With the -uc -us options all went well.
I still know little about Linux but that’s why I have the Pi’s to learn, now I just have to get lightsd starting automatically and using a URL. Using your test Py worked well and nice and fast thanks.

1 Like

There is a hint in the documentation that this has been compiled on openbsd. Is this correct? I’m trying to do it on freebsd, but im running into problems very early in the build. Any help appreciated

/usr/home/krad/lightsd/lifx/broadcast.c:60:23: error: use of undeclared identifier ‘INADDR_BROADCAST’

I figure this is a linuxism?

Hello @krad,

This is correct, I don’t know if that’s a linuxism or a freebsdism, but the issue has been documented in GH-14. Adding an endian.h file under the compat/FreeBSD directory with the following content should get you going:

#pragma once

#include <sys/endian.h>

(c.f: this comment).

Let me know if that works!

I’ll hopefully release a fixed version of lightsd next month! It has been slow, but I have made some great progress on my continuous-integration setup which will greatly lower the bar for further development.

Hi all ! I’m having some troubles to get a response from lightsd with a Ruby client.

I tried two json-rpc clients library, then another very simple http request

require 'faraday'
conn = Faraday.new(:url => "http://192.168.1.10:4000") do |faraday|
  faraday.response :logger
  faraday.adapter Faraday.default_adapter
end

response = conn.post do |req|
  req.url '/'
  req.headers['Content-Type'] = 'application/json'
  req.body = '{ "jsonrpc": "2.0", "id": 1, "method": "get_light_state", "params": ["*"] }'
end

puts response.body

What I get is a “lightsd: client [::ffff:192.168.1.10]:65292: request too big or invalid”

I tried a request with the same Ruby code to a test json rpc server (http://gurujsonrpc.appspot.com/) and I got a response. What I’m doing wrong ?

Thanks

Hello @tactif,

lightsd doesn’t implement JSON-RPC over HTTP, none of the JSON-RPC library you will find on the Internet will work.

However, writing a JSON-RPC client that works with lightsd shouldn’t be too hard as the documentation covers it. You will find a small tutorial about it at the end of this page:

http://lightsd.readthedocs.io/en/latest/protocol.html

Let me know if that helps!

Ok ! I might have guessed this by myself :frowning: There is no statement in lightsd documentation about being http based… My bad !

So it’s JSON-RPC on top of TCP only ?

I tried with a slightly modified version of the python script you provided

import json
import socket
import uuid

READ_SIZE = 4096
ENCODING = "utf-8"

# Connect to lightsd, here using an Unix socket. The rest of the example is
# valid for TCP sockets too. Replace /run/lightsd/socket by the output of:
# echo $(lightsd --rundir)/socket
lightsd_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lightsd_socket.connect(('192.168.1.10', 4000))
lightsd_socket.settimeout(2)  # seconds

# Prepare the request:
request = json.dumps({
    "method": "get_light_state",
    "params": ["*"],
    "jsonrpc": "2.0",
    "id": str(uuid.uuid4()),
}).encode(ENCODING, "surrogateescape")

lightsd_socket.sendall(request)
response = bytearray()
while True:
    response += lightsd_socket.recv(READ_SIZE)
    try:
        json.loads(response.decode(ENCODING, "ignore"))
        break  # Decoding was successful, we have received everything.
    except Exception:
        continue  # Decoding failed, data must be missing.

response = response.decode(ENCODING, "surrogateescape")
print(json.loads(response))

And it worked… So I will try do to the same in Ruby

For the sake of eternity, this code proves that even with Ruby there is a controlled light at the end of the tunnel…

require 'socket'
require 'json'

READ_SIZE = 4096

s = TCPSocket.open('192.168.1.10', 4000)
request = {jsonrpc: "2.0", id: 1, method: 'get_light_state', params: ["*"]}.to_json.encode(Encoding::UTF_8)
s.write(request)
response = s.readpartial(READ_SIZE)
JSON.parse(response)["result"].each do |k,v|
  puts "#{k} -> #{v}"
end
s.close

Thank for your answer Louis !

1 Like