Part I: Server
Contents
All the IR servers/tools that I found were either bloated or did not provide the functionality that I required. I had created a web server in Java a couple years ago so I made a branch and modified it for my singular purpose.
Disclaimer: I used to be a software engineer (a lifetime ago) – my code these days is not nearly as eloquent or efficient as it could be. To be frank, I wanted a functional piece of equipment quickly that my wife could use effectively and appreciate – and selfishly, not to be seen as “just playing on my computer”.
public static void main(String[] args) { if(args.length > 0){ for(int i = 0; i < args.length; i++) { switch(args[i]){ case "-path": //required: path to www path = args[i+1]; break; case "-port": //optional: default 9000 port = parseInt(args[i+1]); break; case "-allowremote": //optional allowRemote = true; break; } } } httpServer = new SimpleHttpServer(); httpServer.Start(port, allowRemote); }
void Start(int port, boolean allowRemote) { try { if(!allowRemote) server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), port), 0); else { System.out.println("CAUTION: SERVER IS ALLOWING REMOTE CONNECTIONS!"); server = HttpServer.create(new InetSocketAddress(port), 0); } System.out.println("Universal Remote Backend started (" + port + ")"); server.createContext("/", new Handlers.RootHandler()); server.createContext("/IR", new Handlers.IRHandler()); server.createContext("/status", new Handlers.StatusHandler()); server.start(); } catch (IOException e) { e.printStackTrace(); } }Below is the handler code for file requests to the web server.
public static class RootHandler implements HttpHandler { @Override public void handle(HttpExchange he) throws IOException { String fileName = he.getRequestURI().getPath(); File file = new File(Main.path + fileName).getCanonicalFile(); if (!file.isFile()) { // Object does not exist or is not a file: reject with 404 error. String response = "404 (Not Found)\n"; he.sendResponseHeaders(404, response.length()); OutputStream os = he.getResponseBody(); os.write(response.getBytes()); he.close(); os.close(); } else { // Object exists and is a file: accept with response code 200. String mime = MimeTypes.getMimeType(FilenameUtils.getExtension(fileName)); he.sendResponseHeaders(200, file.length()); byte[] bytearray = new byte[(int) file.length()]; FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis); bis.read(bytearray, 0, bytearray.length); OutputStream os = he.getResponseBody(); os.write(bytearray, 0, bytearray.length); fis.close(); bis.close(); he.close(); os.close(); } } }The following code creates the handler for POST calls for IR commands. It also includes the logic to handle device status – it will be covered in Part III – HMI.
public static class IRHandler implements HttpHandler{ public void handle(HttpExchange he) throws IOException { InputStreamReader isr = new InputStreamReader(he.getRequestBody(), "utf-8"); BufferedReader br = new BufferedReader(isr); String query = br.readLine(); Map<String, String> parameters = parseQueryString(query); String response = ""; String key = ""; String cmd = ""; Main.currentActivity = parameters.get("mac"); ArrayList <Map.Entry <String,String>> commands = parseMacro(parameters.get("commands").replace("\"", "")); for(int i = 0; i < commands.size(); i++){ key = commands.get(i).getKey(); cmd = commands.get(i).getValue(); if(cmd.equals("KEY_POWER")){ switch(key){ case "Projector": Main.ProjectorStatus = (Main.ProjectorStatus) ? false : true; break; case "Receiver": Main.ReceiverStatus = (Main.ReceiverStatus) ? false : true; break; case "XBOX": Main.XboxStatus = (Main.XboxStatus) ? false : true; break; case "Cox": Main.CoxStatus = (Main.CoxStatus) ? false : true; break; default: break; } } response += (!key.equals("delay")) ? sendIR("SEND_ONCE", key, cmd) : ""; } OutputStream os = he.getResponseBody(); he.sendResponseHeaders(200, response.length()); os.write(response.getBytes()); he.close(); os.close(); } }Below is the code that executes the irsend command that is package with the LIRC: Linux Infrared Remote Control package. Getting the remotes programmed will be covered in Part II: IR Blaster.
public static String sendIR(String type, String device, String key){ String response = ""; try { Process p = Runtime.getRuntime().exec("irsend " + type + " " + device + " " + key); BufferedReader in = new BufferedReader( new InputStreamReader(p.getInputStream())); String line = null; while ((line = in.readLine()) != null) { System.out.println(line); response += line + "\n"; } } catch (IOException e) { e.printStackTrace(); } return response; }