/* * Copyright 2011-16 Fraunhofer ISE * * This file is part of OpenMUC. * For more information visit http://www.openmuc.org * * OpenMUC is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenMUC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenMUC. If not, see <http://www.gnu.org/licenses/>. * */ package org.openmuc.framework.driver.iec62056p21; import java.io.IOException; import java.util.List; import java.util.concurrent.TimeoutException; import org.openmuc.framework.config.ArgumentSyntaxException; import org.openmuc.framework.config.DeviceScanInfo; import org.openmuc.framework.config.DriverInfo; import org.openmuc.framework.config.ScanException; import org.openmuc.framework.config.ScanInterruptedException; import org.openmuc.framework.driver.spi.ConnectionException; import org.openmuc.framework.driver.spi.DriverDeviceScanListener; import org.openmuc.framework.driver.spi.DriverService; import org.openmuc.j62056.Connection; import org.openmuc.j62056.DataSet; import org.osgi.service.component.annotations.Component; @Component public final class Iec62056Driver implements DriverService { private final static DriverInfo info = new DriverInfo("iec62056p21", // id // description "This driver can read meters using IEC 62056-21 Mode C.", // device address "Synopsis: <serial_port>\nExamples: /dev/ttyS0 (Unix), COM1 (Windows)", // parameters "N.A.", // channel address "Synopsis: <data_set_id>", // device scan settings "Synopsis: <serial_port> [-e] [-d <baud_rate_change_delay>]\nExamples for <serial_port>: /dev/ttyS0 (Unix), COM1 (Windows)\n-e = enable handling of echos caused by optical tranceivers\n-d <baud_rate_change_delay> = delay of baud rate change in ms. Default is 0. USB to serial converters often require a delay of up to 250ms."); @Override public DriverInfo getInfo() { return info; } @Override public void scanForDevices(String settings, DriverDeviceScanListener listener) throws UnsupportedOperationException, ArgumentSyntaxException, ScanException, ScanInterruptedException { String[] args = settings.split("\\s+", 0); if (args.length < 1 || args.length > 4) { throw new ArgumentSyntaxException( "Less than one or more than four arguments in the settings are not allowed."); } String serialPortName = ""; boolean echoHandling = false; int baudRateChangeDelay = 0; for (int i = 0; i < args.length; i++) { if (args[i].equals("-e")) { echoHandling = true; } else if (args[i].equals("-d")) { i++; if (i == args.length) { throw new ArgumentSyntaxException("No baudRateChangeDelay was specified after the -d parameter"); } try { baudRateChangeDelay = Integer.parseInt(args[i]); } catch (NumberFormatException e) { throw new ArgumentSyntaxException("Specified baudRateChangeDelay is not an integer."); } } else { serialPortName = args[i]; } } if (serialPortName.isEmpty()) { throw new ArgumentSyntaxException("The <serial_port> has to be specified in the settings"); } Connection connection = new Connection(serialPortName, echoHandling, baudRateChangeDelay); try { connection.open(); } catch (IOException e) { throw new ScanException(e); } try { List<DataSet> dataSets = connection.read(); String deviceSettings; if (echoHandling) { if (baudRateChangeDelay > 0) { deviceSettings = "-e -d " + baudRateChangeDelay; } else { deviceSettings = "-e"; } } else { if (baudRateChangeDelay > 0) { deviceSettings = "-d " + baudRateChangeDelay; } else { deviceSettings = ""; } } listener.deviceFound(new DeviceScanInfo(serialPortName, deviceSettings, dataSets.get(0).getId().replaceAll("\\p{Cntrl}", ""))); } catch (IOException e) { e.printStackTrace(); throw new ScanException(e); } catch (TimeoutException e) { e.printStackTrace(); throw new ScanException(e); } finally { connection.close(); } } @Override public void interruptDeviceScan() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public org.openmuc.framework.driver.spi.Connection connect(String deviceAddress, String settings) throws ArgumentSyntaxException, ConnectionException { boolean echoHandling = false; int baudRateChangeDelay = 0; if (!settings.equals("")) { String[] args = settings.split("\\s+"); if (args.length > 2) { throw new ArgumentSyntaxException("More than two arguments in the settings are not allowed."); } for (int i = 0; i < args.length; i++) { if (args[i].equals("-e")) { echoHandling = true; } else if (args[i].equals("-d")) { i++; if (i == args.length) { throw new ArgumentSyntaxException( "No baudRateChangeDelay was specified after the -d parameter"); } try { baudRateChangeDelay = Integer.parseInt(args[i]); } catch (NumberFormatException e) { throw new ArgumentSyntaxException("Specified baudRateChangeDelay is not an integer."); } } else { throw new ArgumentSyntaxException("Found unknown argument in settings: " + args[i]); } } } Connection connection = new Connection(deviceAddress, echoHandling, baudRateChangeDelay); try { connection.open(); } catch (IOException e) { throw new ConnectionException("Unable to open local serial port: " + deviceAddress, e); } try { connection.read(); } catch (IOException e) { connection.close(); throw new ConnectionException("IOException trying to read meter: " + deviceAddress + ": " + e.getMessage(), e); } catch (TimeoutException e) { e.printStackTrace(); throw new ConnectionException("Read timed out: " + e.getMessage()); } return new Iec62056Connection(connection); } }