/* * * Copyright (C) 2012-2014 R T Huitema. All Rights Reserved. * Web: www.42.co.nz * Email: robert@42.co.nz * Author: R T Huitema * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package nz.co.fortytwo.signalk.server; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import nz.co.fortytwo.signalk.util.ConfigConstants; import nz.co.fortytwo.signalk.util.Util; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.ProducerTemplate; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * A manager to monitor the USB tty ports. It dynamically adds/removes * ports as the USB devices are added/removed * * @author robert * */ public class SerialPortManager implements Runnable, Processor { private static Logger logger = LogManager.getLogger(SerialPortManager.class); private List<SerialPortReader> serialPortList = new CopyOnWriteArrayList<SerialPortReader>(); private boolean running = true; @SuppressWarnings("static-access") public void run() { // not running, start now. ProducerTemplate producer = CamelContextFactory.getInstance().createProducerTemplate(); producer.setDefaultEndpointUri(RouteManager.SEDA_INPUT); while (running) { // remove any stopped readers List<SerialPortReader> tmpPortList = new ArrayList<SerialPortReader>(); for (SerialPortReader reader : serialPortList) { if (!reader.isRunning()) { if(logger.isDebugEnabled())logger.debug("Comm port " + reader.getPortName() + " finished and marked for removal"); tmpPortList.add(reader); } if(logger.isDebugEnabled())logger.debug("Comm port " + reader.getPortName() + " currently running"); } serialPortList.removeAll(tmpPortList); //json array String portStr ="[\"/dev/ttyUSB0\",\"/dev/ttyUSB1\",\"/dev/ttyUSB2\"]"; portStr = Util.getConfigProperty(ConfigConstants.SERIAL_PORTS); portStr=portStr.replace("[", ""); portStr=portStr.replace("]", ""); portStr=portStr.replace("\"", ""); //now we have just comma delim text. String[] ports = portStr.split(","); for (String port:ports) { boolean portOk = false; try { //this doesnt work on windozy if(!SystemUtils.IS_OS_WINDOWS){ File portFile = new File(port); if (!portFile.exists()){ if(logger.isDebugEnabled())logger.debug("Comm port "+port+" doesnt exist"); continue; } } for (SerialPortReader reader : serialPortList) { if (StringUtils.equals(port, reader.getPortName())) { // its already up and running portOk = true; } } // if its running, ignore if (portOk){ if(logger.isDebugEnabled())logger.debug("Comm port " + port + " found already connected"); continue; } SerialPortReader serial = new SerialPortReader(); serial.setProducer(producer); //default 38400, then freeboard.cfg default, then freeboard.cfg per port int baudRate = Util.getConfigPropertyInt(ConfigConstants.SERIAL_PORT_BAUD); //get port name String portName = port; if(port.indexOf("/")>0){ portName=port.substring(port.lastIndexOf("/")+1); } if(Util.getConfigPropertyInt(ConfigConstants.SERIAL_PORT_BAUD+"."+portName)!=null){ baudRate = Util.getConfigPropertyInt(ConfigConstants.SERIAL_PORT_BAUD+"."+portName); } if(logger.isDebugEnabled())logger.debug("Comm port "+ConfigConstants.SERIAL_PORT_BAUD+"."+portName+" override="+Util.getConfigProperty(ConfigConstants.SERIAL_PORT_BAUD+"."+portName)); if(logger.isDebugEnabled())logger.debug("Comm port " + port + " found and connecting at "+baudRate+"..."); serial.connect(port, baudRate); if(logger.isDebugEnabled())logger.info("Comm port " + port + " found and connected"); serialPortList.add(serial); } catch (NullPointerException np) { logger.error("Comm port " + port + " was null, probably not found, or nothing connected"); } catch (purejavacomm.NoSuchPortException nsp) { logger.error("Comm port " + port + " not found, or nothing connected"); } catch (Exception e) { logger.error("Port " + port + " failed", e); } } // delay for 30 secs, we dont want to burn up CPU for nothing try { Thread.currentThread().sleep(10 * 1000); } catch (InterruptedException ie) { } } //finished, so clean up serialPortList.clear(); } /** * When the serial port is used to read from the arduino this must be called to shut * down the readers, which are in their own threads. */ public void stopSerial() { for (SerialPortReader serial : serialPortList) { if (serial != null) { serial.setRunning(false); } } running = false; } public void process(Exchange exchange) throws Exception { for (SerialPortReader serial : serialPortList) { if (serial != null) { serial.process(exchange); } } } }