This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

a better KODI handler
#1
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? Smile

kodiHandler("192.168.x.x","9090","12007")
Code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
-- 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
Reply
#2
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:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
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
Reply
#3
yes, that works great!
Reply
#4
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
Reply
#5
(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:
123456
-- incoming command parser   function parse(data)     -- log other info, not mapped, if useful     --log("data received: "..data)     --log(json.pdecode(data))   end
Reply
#6
(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:
123456
-- incoming command parser   function parse(data)     -- log other info, not mapped, if useful     --log("data received: "..data)     --log(json.pdecode(data))   end

thanks Wink

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 Smile
Reply


Forum Jump: