![]() |
|
a better KODI handler - Printable Version +- LogicMachine Forum (https://forum.logicmachine.net) +-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1) +--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8) +--- Thread: a better KODI handler (/showthread.php?tid=1074) |
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
endRE: 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
endRE: 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 ... ? 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))
endRE: 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 ![]() 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
|