#!/usr/bin/env luvit --[[ lua-remote, Michal Kottman, 2013 MIT License Control your TV or HiFi using infrared remote control from the browser using LIRC. This application needs to be run using Luvit [1]. Requires that LIRC is listening for connection (by default on port 8765). lua- remote will start on the next port, so fire up http://localhost:8766/ in your browser, select the remote and you can click on any key to send the command immediately. You can also use curl/wget to fire the command on the URL: http://localhost:8766// Requirements: - Luvit [1] - LIRC [2] or WinLIRC [3] [1] http://luvit.io/ [2] http://www.lirc.org/ [3] http://winlirc.sourceforge.net/ --]] -- local LIRC_PORT = 8765 local http = require('http') local net = require('net') local string = require('string') local table = require('table') local url = require('url') -- http://lua-users.org/wiki/SplitJoin function string:split(sep) local sep, fields = sep or ":", {} local pattern = string.format("([^%s]+)", sep) self:gsub(pattern, function(c) fields[#fields+1] = c end) return fields end function getRemotes(req, res) local conn conn = net.createConnection(LIRC_PORT, 'localhost', function(err) if err then error(err) end local all = {} conn:on('data', function(data) all[#all+1] = data if data:match('END') then conn:done() end end) conn:on('error', function() res:writeHead(200, { ["Content-Type"] = "text/html", }) res:finish('Failed to connect to LIRC') end) conn:on('close', function() all = table.concat(all) all = all:split('\n') local remotes = {} if #all >= 7 and all[3] == 'SUCCESS' then for i=6,#all-1 do remotes[#remotes + 1] = all[i] end end res:writeHead(200, { ["Content-Type"] = "text/html", }) res:write('Remote control') if #remotes == 0 then res:write('No remotes available...') else res:write('
    ') for i=1,#remotes do res:write('
  1. '..remotes[i]..'
  2. ') end res:write('
') end res:finish('') end) conn:write('LIST\n') end) conn:on('error', function() res:writeHead(200, { ["Content-Type"] = "text/html", }) res:finish('Failed to connect to LIRC') end) end function getCommands(req, res, remote) local conn conn = net.createConnection(LIRC_PORT, 'localhost', function(err) if err then error(err) end local all = {} conn:on('data', function(data) all[#all+1] = data if data:match('END') then conn:done() end end) conn:on('close', function() all = table.concat(all) all = all:split('\n') local commands = {} if #all >= 7 and all[3] == 'SUCCESS' then for i=6,#all-1 do commands[#commands + 1] = all[i]:split(' ') end end res:writeHead(200, { ["Content-Type"] = "text/html", }) res:write( ''..remote..''.. ''.. '') if #commands == 0 then res:write('No commands available for ' .. remote .. '') else res:write('
    ') for _,c in ipairs(commands) do local url = '/'..remote..'/'..c[2] res:write([[
  1. ]]..c[2]..'
  2. ') end res:write('
') end res:finish('') end) conn:write('LIST ' .. remote .. '\n') end) conn:on('error', function() res:writeHead(200, { ["Content-Type"] = "text/html", }) res:finish('Failed to connect to LIRC') end) end function sendCommand(req, res, remote, command) local conn conn = net.createConnection(LIRC_PORT, 'localhost', function(err) if err then error(err) end conn:on('close', function() res:writeHead(200, { ["Content-Type"] = "text/plain", }) res:finish(command..' '..remote) end) conn:write('SEND_ONCE ' .. remote .. ' ' .. command .. '\n', function() conn:done() end) end) conn:on('error', function() res:writeHead(200, { ["Content-Type"] = "text/html", }) res:finish('Failed to connect to LIRC') end) end function app(req, res) print("Processing request for: " .. req.url) local u = url.parse(req.url) if u.pathname == '/' then getRemotes(req, res) else local path = u.pathname:split('/') if #path == 1 then getCommands(req, res, path[1]) elseif #path > 1 then sendCommand(req, res, path[1], path[2]) end end end local PORT = LIRC_PORT + 1 http.createServer(app):listen(PORT) print("Server listening at http://localhost:" .. PORT .. "/")