Last active
December 18, 2015 09:09
-
-
Save mkottman/5759847 to your computer and use it in GitHub Desktop.
Remote control your TV from the browser using Luvit / LIRC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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/<REMOTE>/<COMMAND> | |
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('<html><body><font color="red">Failed to connect to LIRC</font></body></html>') | |
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('<html><head><title>Remote control</title></head><body>') | |
if #remotes == 0 then | |
res:write('<b>No remotes available...</b>') | |
else | |
res:write('<ol>') | |
for i=1,#remotes do | |
res:write('<li><a href="/'..remotes[i]..'">'..remotes[i]..'</a></li>') | |
end | |
res:write('</ol>') | |
end | |
res:finish('</body>') | |
end) | |
conn:write('LIST\n') | |
end) | |
conn:on('error', function() | |
res:writeHead(200, { | |
["Content-Type"] = "text/html", | |
}) | |
res:finish('<html><body><font color="red">Failed to connect to LIRC</font></body></html>') | |
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( | |
'<html><head><title>'..remote..'</title>'.. | |
'<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>'.. | |
'</head><body>') | |
if #commands == 0 then | |
res:write('<b>No commands available for ' .. remote .. '</b>') | |
else | |
res:write('<ol>') | |
for _,c in ipairs(commands) do | |
local url = '/'..remote..'/'..c[2] | |
res:write([[<li><a href="#" onclick="jQuery.ajax(']]..url..[['); return false;">]]..c[2]..'</a></li>') | |
end | |
res:write('</ol>') | |
end | |
res:finish('</body>') | |
end) | |
conn:write('LIST ' .. remote .. '\n') | |
end) | |
conn:on('error', function() | |
res:writeHead(200, { | |
["Content-Type"] = "text/html", | |
}) | |
res:finish('<html><body><font color="red">Failed to connect to LIRC</font></body></html>') | |
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('<html><body><font color="red">Failed to connect to LIRC</font></body></html>') | |
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 .. "/") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# A simple runner for the remote which will update itself on exit/crash | |
while true; do | |
echo "Fetching latest version" | |
git pull | |
echo "Running server" | |
luvit remote.lua | |
echo "Sleeping for a bit" | |
sleep 0.1 | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment