Java tutorial
/** * Copyright (c) 2014,2018 Contributors to the Eclipse Foundation * * See the NOTICE file(s) distributed with this work for additional * information regarding copyright ownership. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0 * * SPDX-License-Identifier: EPL-2.0 */ package org.eclipse.smarthome.binding.lirc.internal.connector; import java.io.BufferedReader; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.binding.lirc.internal.LIRCResponseException; import org.eclipse.smarthome.binding.lirc.internal.messages.LIRCButtonEvent; import org.eclipse.smarthome.binding.lirc.internal.messages.LIRCResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Stream reader to parse LIRC output into messages * * @author Andrew Nagle */ public class LIRCStreamReader extends Thread { private final Logger logger = LoggerFactory.getLogger(LIRCStreamReader.class); private static final Pattern EVENT_PATTERN = Pattern.compile("^([a-f0-9]+)\\s([a-f0-9]+)\\s(.+)\\s(.+)$"); private InputStream in; private boolean interrupted = false; private BufferedReader reader; private LIRCConnector connector; public LIRCStreamReader(LIRCConnector connector, InputStream in) { this.connector = connector; this.in = in; } @Override public void interrupt() { interrupted = true; super.interrupt(); } @Override public void run() { reader = new BufferedReader(new InputStreamReader(in)); String line; String responseText = ""; while (!interrupted) { try { line = reader.readLine(); if (line == null) { throw new EOFException("lost connection"); } else { logger.trace("Received message: {}", line); Matcher m = EVENT_PATTERN.matcher(line); if (m.matches()) { String code = m.group(1); String repeatsHex = m.group(2); String button = m.group(3); String remote = m.group(4); int repeats = Integer.parseInt(repeatsHex, 16); LIRCButtonEvent buttonMessage = new LIRCButtonEvent(remote, button, repeats, code); connector.sendButtonToListeners(buttonMessage); } else { if ("BEGIN".equals(line)) { responseText = ""; } else if ("END".equals(line)) { processResponse(responseText); responseText = null; } else { responseText += line + "\n"; } } } } catch (InterruptedIOException e) { Thread.currentThread().interrupt(); logger.error("Interrupted via InterruptedIOException"); } catch (EOFException e) { logger.error("Lost connection to LIRC server", e); connector.sendErrorToListeners(e.getMessage()); this.interrupt(); } catch (IOException e) { if (!interrupted) { logger.error("Reading from socket failed", e); connector.sendErrorToListeners(e.getMessage()); } } catch (LIRCResponseException e) { logger.error("Invalid message received", e); } } IOUtils.closeQuietly(reader); } private void processResponse(String responseText) throws LIRCResponseException { String[] parts = responseText.split("\n"); String command = parts[0]; boolean success = true; int dataLength = 0; String[] data = null; if (parts.length > 1) { if ("SUCCESS".equals(parts[1]) || "ERROR".equals(parts[1])) { success = "SUCCESS".equals(parts[1]); } else { throw new LIRCResponseException("Malformed response"); } } if (parts.length > 2) { if ("DATA".equals(parts[2]) && parts.length > 3) { dataLength = Integer.parseInt(parts[3]); } else { throw new LIRCResponseException("Malformed response"); } } if (parts.length > 4) { data = Arrays.copyOfRange(parts, 4, parts.length); if (data.length != dataLength) { throw new LIRCResponseException(String.format( "Data does not match expected length. Expected: %s, Got: %s", dataLength, data.length)); } } LIRCResponse response = new LIRCResponse(command, success, data); connector.sendMessageToListeners(response); } }