openLuup: Squeezebox

Since the thread has been quite for sometime I’m wondering if the last http.lua was pushed to the main repository on github and if the plugin is partially working. Just trying to make sure what files should I use from the thread’s investigation to get DLNA partially/working as I’m trying with the original files and is discovering 2 of my devices but it does not connect to any of them.

[hr]

Edit by moderator: see this post http://forum.micasaverde.com/index.php/topic,37661.msg298011.html#msg298011 for a proposed (simple) solution to this problem.

Firstly many thanks to akbooer for creating openLuup and @amg0 for ALTUI. I like the vera system (particularly with the great plugins from the community) but the stability leaves allot to be desired!

I am hoping to see if anyone has anyone had any luck getting the Squeezebox (2.1 Beta) to work under openLuup? I have the plugin installed and connected to squeezeserver however it is not creating the child devices.

No takers so far, apparently. Where is the source code code? I’ll take a look. Do you have a log from a system reload to check for errors?

I have added this to startup.lua for troubleshooting:

do – SqueezeBox
local dev = luup.create_device (‘’, ‘’, “SqueezeBox”, “D_SqueezeboxControl1.xml”, “I_SqueezeboxControl1.xml”) – create the device
luup.variable_set (“urn:micasaverde-com:serviceId:SqueezeBox1”, “serverIP”, “192.168.6.4”, dev) – set SqueezeBox Server IP address
end

Attached is the log.

I’m using the 2.1 plugin code from:

[url=http://forum.micasaverde.com/index.php/topic,30701.0.html]http://forum.micasaverde.com/index.php/topic,30701.0.html[/url]

I noticed a strange error in the cmd line on reboot per the attached. I reinstalled onto a vera 3 and the child devices are getting created after a couple of luup reloads.

Thanks,
Brendan

OK, that’s a bit worrying. It may be that the plugin is looking for compressed files, in whch case it won’t find them.

The log shows that the initial startup runs OK, then after two seconds its delayed startup code kicks in as it should. It successfully establishes a network connection to Squeezebox, and sends a couple of short messages, but then there’s a timeout.

I haven’t look at the source code yet, but thanks for the link.

I note that the code calls the script file:

GetNetworkState.sh ip_wan

Do you have that setup as per the openLuup User Guide?

Also, I see that the plugin has a debug mode. I would be good to get a log with that enabled.


Edit:

The two initial commands sent are:

	send_command ('listen 1')
	send_command ('player count ?')

…and it looks like the timeout happens because there is no received response from the second one.

Yes, I confirmed that /usr/bin/GetNetworkState.sh ip_wan is working from the AltUI Run Os Command although it is returning the openLuup Lan (not Wan) Address.

Attached is the log with debug enable on a new start and subsequent Luup reload. Thanks again for looking into this akbooer.

So this would seem to be a problem? Which implementation of the GetNetworkState.sh file are you using? I take it, the one with Lua code? If it’s returning the wrong value, then just hardwire the simpler version, returning the address you need.

Attached is the log with debug enable on a new start and subsequent Luup reload.

OK, so this tells us the same as before. A timeout after the second send.

You may need to reach out to the plugin developer on this one? I don’t have one of these devices and I’ve gone as far as I can on my own machine just simulating a response from the connected device.

[quote=“MountainAutomator, post:4, topic:192308”]I’m using the 2.1 plugin code from:

[url=http://forum.micasaverde.com/index.php/topic,30701.0.html]http://forum.micasaverde.com/index.php/topic,30701.0.html[/url][/quote]

I was reading the install guide on that post and noticed this:

To install the beta, (on either UI5 or UI7):

[ol][li]Please upgrade to the official 2.0 version from the app store if you have not done so already. [/li][/ol]

…and wondering if you actually downloaded the App Store version 2 files in the first place ?? I’ve done the download(s) and I don’t see any files that are not replaced by the beta version, so perhaps that instruction is out of date?

Nevertheless, have you tried the 2.0 version on its own?

...and wondering if you actually downloaded the App Store version 2 files in the first place ?? I've done the download(s) and I don't see any files that are not replaced by the beta version, so perhaps that instruction is out of date?

Nevertheless, have you tried the 2.0 version on its own?

No but I installed to an actual vera by just uploading the beta files so i think they are complete. I’ll do some more testing to make sure.

Which implementation of the GetNetworkState.sh file are you using? I take it, the one with Lua code? If it's returning the wrong value, then just hardwire the simpler version, returning the address you need.

Yes, currently using the lua code but I’ll try the hardcoded version to see if that changes anything.

Thanks,
Brendan

This is What the logs in /etc/cmh-ludl/LuaUPnP.log after the IP address and port has been set in the plugin:

I believe there is something being executed in L_SqueezeboxControl.lua while executing the function startup_delay() that is causing the error.

2016-03-01 21:15:11.295   luup.variable_set:5: 5.urn:micasaverde-com:serviceId:SqueezeBox1.connectStatus was: Refreshing... now: Running #hooks:0
2016-03-01 21:15:11.295   luup.io.write:5: message length: 25, bytes sent: 25, status: OK tcp{client}: 0x21c6eb8
2016-03-01 21:15:16.299   openLuup.io:5: timeout tcp{client}: 0x21c6eb8
2016-03-01 21:15:16.300   openLuup.server:: request completed (2103 bytes, 1 chunks, 46163 ms) tcp{client}: 0x20f97c8
2016-03-01 21:15:16.301   luup.io.write:5: message length: 25, bytes sent: 25, status: OK tcp{client}: 0x21c6eb8
2016-03-01 21:15:16.301   luup.io.write:5: message length: 9, bytes sent: 9, status: OK tcp{client}: 0x21c6eb8
2016-03-01 21:15:16.301   luup.io.write:5: message length: 15, bytes sent: 15, status: OK tcp{client}: 0x21c6eb8
2016-03-01 21:15:16.303   openLuup.io:5: timeout tcp{client}: 0x21c6eb8
2016-03-01 21:15:16.304   openLuup.io:5: timeout tcp{client}: 0x21c6eb8
2016-03-01 21:15:16.304   openLuup.io:5: timeout tcp{client}: 0x21c6eb8
2016-03-01 21:15:16.420   openLuup.server:: /data_request?id=lu_status2&output_format=json&DataVersion=884861376&Timeout=60&MinimumDelay=1500&_=1456884305823 tcp{client}: 0x20f97c8
2016-03-01 21:15:23.477   openLuup.server:: /favicon.ico tcp{client}: 0x22ce0e8
2016-03-01 21:15:23.477   openLuup.HTTP.FILE:: file not found:favicon.ico
2016-03-01 21:15:23.478   openLuup.server:: request completed (0 bytes, 0 chunks, 0 ms) tcp{client}: 0x22ce0e8

Any progress on this? It would be great if the squeezebox posts were split out into a separate thread


Edit by moderator: moved to separate thread.

I am bringing this thread back from the dead, as I want to offload my vera to openluup on a raspberry pi like machine.

I did quite a bit of debugging to understand what was going on with this, and the culprit seems to be the actual lua socks library that is the norm with openLuup. There seems to be an issue after the job scheduler selects the socket for reading and sends it to the incoming which performs a receive with protocol “cr” (reads from the socket until an end of line is found).

scheduler → local recvt = socket.select (list, nil, timeout) – wait for something to happen (but not for too long)
io->data, err = sock: receive “*l”
->timeout!

For the record, the sockets library in openLuup is

[code]local socket = require “socket”
return socket._VERSION or “unknown”

LuaSocket 3.0-rc1[/code]

the sockets library in my veralite is

test code:

[code]local socket = require “socket”
luup.log(socket._VERSION or “unknown”)
return true

LuaSocket 2.0.2[/code]

I’m going to check if the openLuup IO routine can be tweaked, or if I can get more debugging info from the lua sockets library by recompiling it with the DEBUG flag.

The socket library version is nothing to do with openLuup, but all to do with the version of the LuaSocket library actually installed in the Lua 5.1 configuration.

However, I feel this doesn’t have anything to do with that library, but with the “cr” protocol implementation in the openluup.io module.

In the code for that module you will find:

    -- From the LuaSocket documentation: 
    -- The line is terminated by a LF character (ASCII 10), optionally preceded by a CR character (ASCII 13). 
    -- The CR and LF characters are not included in the returned line. 
    -- In fact, all CR characters are ignored by the pattern. 
    data, err = sock: receive "*l"

In other words, the “cr” protocol is not correctly implemented, and the code would need to be modified to receive one character at a time and check explicitly for it. It just turns out that for all the other IP c-controlled devices I’ve used, the are all happy with the “crlf” protocol.

I do know that someone has modified this module for their own use for similar reasons, and will endeavour to chase that up. Alternatively, you’re more than welcome to recode it and share your findings.

From the luasocket documentation, it looks like cr or crlf are synonymous.

*l': reads a line of text from the socket. The line is terminated by a LF character (ASCII 10), optionally preceded by a CR character (ASCII 13). The CR and LF characters are not included in the returned line. In fact, all CR characters are ignored by the pattern. This is the default pattern;

I wonder if the squeezebox server sends Unicode characters, which might make it tricky to recognize a proper cr.

I’ll try to dump packets and see.

I compiled version 3 of the socket library to ensure that the issue wasn’t caused by a bug in the timeout implementation. It was worth a try…

I was successful in making the squeezebox plugin work in altui/openLuup!

Solution

Open device file D_SqueezeboxControl1.xml Add the following as a child node of <device></device> <protocol>crlf</protocol>

The file should be similar to this:

[code]<?xml version="1.0"?>


2
0


urn:schemas-micasaverde-com:device:SqueezeBox:1
SqueezeBox Controller
D_SqueezeboxControl1.json
crlf
1


urn:schemas-micasaverde-com:service:HaDevice:1
urn:micasaverde-com:serviceId:HaDevice1
S_HaDevice1.xml


urn:schemas-micasaverde-com:service:SqueezeBox:1
urn:micasaverde-com:serviceId:SqueezeBox1
S_SqueezeboxControl1.xml



I_SqueezeboxControl1.xml


[/code]

Explanation:
The issue wasn’t on the receive end, nor was it in the tcp stack, etc. It was actually caused by not terminating the command string sent to the squeezebox server, which in turn was buffering commands in a single line and never replying. This lead to the socket timing out in the end. After analyzing the io code under openLuup, the solution became obvious

local function send (sock, data, protocol) local eol = {cr = "\r", crlf = "\r\n"} -- TODO: 'stxetx' mode for write NOT currently supported local fmt = "message length: %s, bytes sent: %d, status: %s %s" if eol[protocol] then data = data .. eol[protocol] end local status, msg, last = sock: send (data) -- send the message _log (fmt: format (#data, status or last-1, msg or "OK", tostring(sock)), "luup.io.write") return status end

As it turns out, the Squeezebox plugin does not have a default protocol defined and therefore relies on ALTUI’s protocol during device load. As you might have guessed if you read up till this point, ALTUI’s default protocol is “cr”. Adding protocol “crlf” as the Squeezebox protocol means each command will get “\r\n” appended and will make the squeezebox reply back. There is no difference in implementation on the receiving end (there is no need as the lua socket ignores asccii 13 anyways).

I’m happy to report that with this simple change the Squeezebox plugin can be added to the list of compatible

Bonus points: test code which helped me diagnose. Note that each command is terminated with \n

socket = require('socket')

function sleep(n)
  print("sleeping "..n.." sec")
  os.execute("sleep " .. tonumber(n))
  print("done sleeping")
end


local ok, msg,sock2, recvt
sock, msg = socket.tcp ()
if sock then
  sock:settimeout (5)
  sock:setoption ("tcp-nodelay", true)    -- so that alternate read/write works as expected (no buffering)
  sock:setoption ("keepalive", true)      -- keepalive, thanks to @martynwendon for testing this solution
  ok, msg = sock:connect ('192.168.99.99', 9090)
end

sleep(1)
print(tostring(sock))
sock:send("listen 1\n")
sock:send("player count ?\n")
sleep(1) -- simulate some scheduler activity in openluup
recvt = socket.select ({sock}, nil, 0.5)  -- wait for something to happen (but not for too long)
while table.getn(recvt)>0  do
sleep(1) -- simulate some scheduler activity in openluup

  for _,sock2 in ipairs (recvt) do
    local data, err = sock: receive "*l"
    print ("socket_callback -> "..tostring(sock2) .. " data = " .. data .. " error = " .. (err or "?"))
  end
recvt = socket.select ({sock}, nil, 0.5)  -- wait for something to happen (but not for too long)
end
sock:close()

output

lua testsocket.lua sleeping 1 sec done sleeping tcp{client}: 0x307970 sleeping 1 sec done sleeping sleeping 1 sec done sleeping socket_callback -> tcp{client}: 0x307970 data = listen 1 error = ? sleeping 1 sec done sleeping socket_callback -> tcp{client}: 0x307970 data = player count 7 error = ?

can we mark the subject as RESOLVED and post the fix at the top?

Ah! Good catch! Kudos (and Karma) to you.

[u][b]Explanation:[/b][/u] The issue wasn't on the receive end, nor was it in the tcp stack, etc. It was actually caused by not terminating the command string sent to the squeezebox server, which in turn was buffering commands in a single line and never replying. [...] As it turns out, the Squeezebox plugin does not have a default protocol defined and therefore relies on ALTUI's protocol during device load. As you might have guessed if you read up till this point, ALTUI's default protocol is "cr". Adding protocol "crlf" as the Squeezebox protocol means each command will get "\r\n" appended and will make the squeezebox reply back. There is no difference in implementation on the receiving end (there is no need as the lua socket ignores asccii 13 anyways).

Actually, this is nothing to do with AltUI, but with the openLuup implementation (which, apparently, doesn’t conform to Vera’s behaviour in this case.) An alternative might be to add “crlf” as the default protocol in the absence of a defined one, although I must check to see what the Vera default is and whether no protocol is allowable (I think it should be, but I’m now curious as to why Vera handles this OK.)

can we mark the subject as RESOLVED and post the fix at the top?

I’ll see about that, but will anyway add a link to your post at the top of the thread.

Well, looking at the documentation for ‘protocol’ here: http://wiki.micasaverde.com/index.php/Luup_Plugins_ByHand#.3Cprotocol.3E, I see that ‘raw’ is explicitly required to ensure that no message terminators are used. There is no definition of the default, but it would seem from the experience here that it may well be ‘crlf’. I’m persuaded to make this the default, which would fix this problem without any changes to the device file.

Crlf might be the default for mios, but I haven’t checked. I had thought that openluup was getting a default from the altui implementation, but doing so would introduce a dependency.

I think a general default of crlf would potentially resolve or prevent similar CLI/telnet type implementations issues.

Thanks for spending time on openluup!

Next for me is to see if I can built an mqtt to mysensors plugin for openluup. I’d like to use some of my esp8266 and not rely on the nrf24l01 transport layer for a few devices.