a better KODI handler - gjniewenhuijse - 01.11.2017
How to make a handler that interacts with KODI.
Data can be send to kodi on port 9090 (or another port you configured) using a raw connection with putty.
My goal:
- send command to kodi, for example i can send this command: { "jsonrpc": "2.0", "id": 1, "method": "Application.SetVolume", "params": { "volume": 53 } }
- receive executed events from kodi, for example i receive this command: {"jsonrpc":"2.0","method":"GUI.OnScreensaverDeactivated","params":{"data":{"shuttingdown":false},"sender":"xbmc"}}
- receive commands from my lm/hl over udp and send them to kodi
I like to have this all in one handler. I have already a piece of code that works, but its to slow. It waits on udp command and that interrups my receiving events.
Maybe using copas or something solved the issue, but how?
kodiHandler("192.168.x.x","9090","12007")
Code: -- library
function kodiHandler(iServer,iPort,sendPort)
-- first call
if not ready then
require('socket')
require('json')
lastdatareceived = nil
ready = true
end
-- client connected
if connected then
while true do
char, err = client:receive(1)
-- error while receiving, closed socket
if err == 'closed' then
connected = false
sleep(1)
break
end
if char ~= nil then
lastdatareceived = os.time()
warningclosed = true
warningfailed = true
warningerrors = true
warningtimeou = true
table.insert(buffer, char)
tmpbuf = table.concat(buffer)
if ( json.pdecode(tmpbuf) ) then
data = tmpbuf
parse(data)
buffer = {}
end
else
now = os.time()
deltatime = now - lastdatareceived
end
-- receive incoming send requests
msg, ip, port = sendServer:receivefrom()
if msg then
-- send command
--log("send: "..msg)
client:send(msg)
end
--[[ clear not complete buffer
if deltatime > 10 and #buffer > 0 then
log( #buffer )
buffer = {}
lastdatareceived = os.time()
end
-]]
end
-- first call or previously disconnected
else
-- close previous connection when disconnected
if client then
client:close()
client = nil
end
if sendServer then
sendServer:close()
sendServer = nil
end
-- create tcp client
client = socket.tcp()
client:settimeout(5)
connected, err = client:connect(iServer, iPort)
-- connect ok, reset buffer
if connected then
lastdatareceived = os.time()
warningclosed = true
warningfailed = true
warningerrors = true
warningtimeou = true
--log('[KODI-client] connection ok: '..iServer)
buffer = {}
-- create udp server to receive incoming send requests
if not sendServer then
sendServer = socket.udp()
sendServer:setsockname('*', sendPort)
sendServer:settimeout(0.1)
end
sleep(5)
-- send initial command
--client:send( '{"jsonrpc": "2.0", "method": "Player.PlayPause", "params": { "playerid": 0 }, "id": 1}' )
-- error while connecting,
else
--log(err)
if warningfailed then log('[KODI-client] connection failed (conn): '.. err) end
warningfailed = false
sleep(5)
end
end
-- incoming command parser
function parse(data)
-- log other info, not mapped, if useful
--log("data received: "..data)
--log(json.pdecode(data))
end
end
RE: a better KODI handler - admin - 02.11.2017
Use this as a starting point, it uses non-blocking socket.select() so UDP won't interfere. The only blocking part is TCP re-connection. There's no need to close/open local UDP server each time.
Code: if not sockets then
require('socket')
clientip = '192.168.1.xx'
clientport = 9090
serverport = 12007
udpserver = socket.udp()
udpserver:setsockname('127.0.0.1', serverport)
udpserver:settimeout(0)
sockets = { udpserver }
function tcpconnect()
local tcpclient = socket.tcp()
tcpclient:settimeout(1)
if tcpclient:connect(clientip, clientport) then
tcpclient:settimeout(0)
else
tcpclient:close()
tcpclient = nil
os.sleep(1)
end
return tcpclient
end
function reconnect()
repeat
tcpclient = tcpconnect()
until tcpclient
sockets[ 2 ] = tcpclient
end
function errhandler()
tcpclient:close()
reconnect()
end
function clienthandler()
while true do
local char, err = tcpclient:receive(1)
if char then
...
else
if err == 'closed' then
errhandler()
end
break
end
end
end
function serverhandler()
local msg = udpserver:receive()
if tcpclient then
tcpclient:send(msg)
end
end
reconnect()
end
res = socket.select(sockets, nil, 1)
if res then
if res[ tcpclient ] then
clienthandler()
end
if res[ udpserver ] then
serverhandler()
end
end
RE: a better KODI handler - gjniewenhuijse - 06.11.2017
yes, that works great!
RE: a better KODI handler - gilles38 - 02.05.2019
Hi did you manage to have a feedback from Kodi ? for instance having a feedback when the film is finished to open the shutters and tun on the light etc ... ?
thanks
RE: a better KODI handler - gjniewenhuijse - 06.05.2019
(02.05.2019, 07:53)gilles38 Wrote: Hi did you manage to have a feedback from Kodi ? for instance having a feedback when the film is finished to open the shutters and tun on the light etc ... ?
thanks
edit this code and call a function in the main script:
Code: -- incoming command parser
function parse(data)
-- log other info, not mapped, if useful
--log("data received: "..data)
--log(json.pdecode(data))
end
RE: a better KODI handler - gilles38 - 07.05.2019
(06.05.2019, 15:27)gjniewenhuijse Wrote: (02.05.2019, 07:53)gilles38 Wrote: Hi did you manage to have a feedback from Kodi ? for instance having a feedback when the film is finished to open the shutters and tun on the light etc ... ?
thanks
edit this code and call a function in the main script:
Code: -- incoming command parser
function parse(data)
-- log other info, not mapped, if useful
--log("data received: "..data)
--log(json.pdecode(data))
end
thanks
I finally add an addon to Kodi called "callback" that allow you to launch script on a specific action in Kodi.
in my case it update a group address
|