/** * Copyright (c) 2010-2016 by the respective copyright holders. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.binding.benqprojector.internal.transport; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import gnu.io.NRSerialPort; /** * Implement the serial based transport for communicating with a Benq projector * * @author Kristian Larsson (kll) * @since 1.8.0 */ public class BenqProjectorSerialTransport implements BenqProjectorTransport { private static final Logger logger = LoggerFactory.getLogger(BenqProjectorSerialTransport.class); /** * Serial device to use */ private String serialDevice = ""; // TODO: what should default be? private int serialSpeed = 57600; private NRSerialPort serialPort = null; private PrintWriter projectorWriter = null; private BufferedReader projectorReader = null; private boolean retryAttempt = false; private boolean serialConnect() { logger.debug("Running connection setup"); try { logger.debug("Setting up socket connection to " + this.serialDevice); this.serialPort = new NRSerialPort(this.serialDevice, this.serialSpeed); this.serialPort.connect(); this.projectorReader = new BufferedReader(new InputStreamReader(this.serialPort.getInputStream())); this.projectorWriter = new PrintWriter(this.serialPort.getOutputStream(), true); logger.debug("Serial connection setup successfully!"); return true; } catch (Exception e) { logger.error("Unable to connect to device: " + this.serialDevice, e); } return false; } @Override public boolean setupConnection(String connectionParams) { boolean setupOK = false; if (this.serialPort == null) { /* parse connection paramters in the format device:speed */ String[] deviceIdParts = connectionParams.split(":"); if (deviceIdParts.length == 1) { logger.debug("Using default speed: " + this.serialSpeed); this.serialDevice = deviceIdParts[0]; } else if (deviceIdParts.length == 2) { this.serialDevice = deviceIdParts[0]; this.serialSpeed = Integer.parseInt(deviceIdParts[1]); } else { return false; } setupOK = this.serialConnect(); } else { logger.debug("Port is already setup"); } return setupOK; } @Override public void closeConnection() { try { this.serialPort.disconnect(); } catch (Exception e) { logger.error("Trying to close socket resulted in IO exception: " + e.getMessage()); } this.serialPort = null; } @Override public String sendCommandExpectResponse(String cmd) { String respStr = ""; String tmp; if (this.projectorWriter != null) { this.projectorWriter.printf("%s", cmd); logger.debug("Sent command '" + cmd.replace("\r", "") + "'"); try { tmp = this.projectorReader.readLine(); while (tmp != null) { if (tmp.startsWith("*") == true && tmp.endsWith("#")) { /* got response */ logger.debug("Response: '" + tmp + "'"); respStr = tmp; break; } tmp = this.projectorReader.readLine(); } } catch (Exception e) { logger.error("IO Exception while reading response from projector: " + e.getMessage()); if (retryAttempt == false) { this.closeConnection(); if (this.serialConnect()) { logger.debug("Reconnect successful - retrying transmission"); /* set flag to stop us ending up here again and so avoid infinite recursion */ retryAttempt = true; sendCommandExpectResponse(cmd); } else { logger.error("Attempt to reconnect after IOException failed: " + e.getMessage()); } /* reset flag */ retryAttempt = false; } } } else { logger.debug("Not sending command to projector as connection is not setup yet."); } return respStr; } }