Java tutorial
/******************************************************************************* * Copyright (c) 2014 Transcends, LLC. * This program 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 2 of the * License, or (at your option) any later version. This program 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 this program; if not, * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. * http://www.gnu.org/licenses/gpl-2.0.html *******************************************************************************/ /** * */ package org.rifidi.edge.adapter.alien; import java.io.IOException; import java.util.BitSet; import java.util.HashSet; import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.rifidi.edge.adapter.alien.autonomous.AlienAutonomousSensorSession; import org.rifidi.edge.adapter.alien.commandobject.AlienCommandObjectWrapper; import org.rifidi.edge.adapter.alien.commandobject.AlienGetCommandObject; import org.rifidi.edge.adapter.alien.gpio.AlienGPIOSession; import org.rifidi.edge.adapter.alien.gpio.messages.TextIOListMessageParsingStrategy; import org.rifidi.edge.api.SessionStatus; import org.rifidi.edge.notification.NotifierService; import org.rifidi.edge.sensors.AbstractCommandConfiguration; import org.rifidi.edge.sensors.AbstractSensor; import org.rifidi.edge.sensors.ByteMessage; import org.rifidi.edge.sensors.CannotExecuteException; import org.rifidi.edge.sensors.Command; import org.rifidi.edge.sensors.TimeoutCommand; import org.rifidi.edge.sensors.sessions.AbstractPollIPSensorSession; import org.rifidi.edge.sensors.sessions.MessageParsingStrategyFactory; /** * A session that connects to an Alien9800Reader * * @author Jochen Mader - jochen@pramari.com * @author Kyle Neumeier - kyle@pramari.com * */ public class Alien9800ReaderSession extends AbstractPollIPSensorSession implements AlienCommandConstants { /** Logger for this class. */ private static final Log logger = LogFactory.getLog(Alien9800ReaderSession.class); /** Username for connecting to the reader. */ private final String username; /** Password for connecting to the reader. */ private final String password; /** Each command needs to be terminated with a newline. */ public static final String NEWLINE = "\n"; /** Welcome string. */ public static final String WELCOME = "Alien"; /** Service used to send out notifications */ private volatile NotifierService notifierService; /** The FACTORY_ID of the reader this session belongs to */ private final String readerID; private AlienAutonomousSensorSession autonomousSession; private AlienGPIOSession gpiosession; /** * * Constructor * * @param sensor * @param id * The FACTORY_ID of the session * @param host * The IP to connect to * @param port * The port to connect to * @param notifyPort * The port to use as a autonomous notify port * @param reconnectionInterval * The wait time between reconnect attempts * @param maxConAttempts * The maximum number of times to try to connect * @param username * The Alien username * @param password * The Alien password * @param destination * The JMS destination for tags * @param template * The JSM template for tags * @param notifierService * The service for sending client notifications * @param readerID * The FACTORY_ID of the reader that created this session * @param commands * A thread safe set containing all available commands */ public Alien9800ReaderSession(AbstractSensor<?> sensor, String id, String host, int port, int notifyPort, int ioStreamPort, int reconnectionInterval, int maxConAttempts, String username, String password, NotifierService notifierService, String readerID, Set<AbstractCommandConfiguration<?>> commands) { super(sensor, id, host, port, reconnectionInterval, maxConAttempts, commands); this.username = username; this.password = password; this.notifierService = notifierService; this.readerID = readerID; this.autonomousSession = new AlienAutonomousSensorSession(sensor, "1", notifierService, notifyPort, 15, new HashSet<AbstractCommandConfiguration<?>>()); this.gpiosession = new AlienGPIOSession(sensor, "2", ioStreamPort, new TextIOListMessageParsingStrategy()); } /* * (non-Javadoc) * * @seeorg.rifidi.edge.core.sensors.base.AbstractIPSensorSession# * getMessageParsingStrategyFactory() */ @Override public MessageParsingStrategyFactory getMessageParsingStrategyFactory() { return new AlienMessageParsingStrategyFactory(); } /* * (non-Javadoc) * * @see org.rifidi.edge.sensors.SensorSession#connect() */ @Override public void connect() throws IOException { super.connect(); Thread autoSessionThread = new Thread(new Runnable() { @Override public void run() { try { autonomousSession.connect(); } catch (IOException ex) { logger.warn("Cannot start Autonomous Session " + autonomousSession); } } }); autoSessionThread.start(); final Alien9800ReaderSession interactiveSession = this; Thread gpioSessionThread = new Thread(new Runnable() { @Override public void run() { try { gpiosession.initialize(interactiveSession); gpiosession.connect(); } catch (CannotExecuteException e) { e.printStackTrace(); logger.warn("Cannot connect Alien GPIO Session: " + gpiosession); } catch (IOException e) { e.printStackTrace(); logger.warn("Cannot connect Alien GPIO Session: " + gpiosession); } } }); gpioSessionThread.start(); } /* * (non-Javadoc) * * @see * org.rifidi.edge.core.readers.impl.AbstractIPReaderSession#onConnect() */ @Override public boolean onConnect() throws IOException { logger.debug("getting the welcome response"); try { String welcome = new String(receiveMessage().message); logger.debug("welcome message: " + welcome); if (welcome == null || !welcome.contains(Alien9800ReaderSession.WELCOME)) { logger.fatal("SensorSession is not an alien sensorSession: " + welcome); return false; } else if (welcome.toLowerCase().contains("busy")) { logger.error("SensorSession is busy: " + welcome); return false; } else { logger.debug("SensorSession is an alien. Hoo-ray!"); } logger.debug("sending username"); sendMessage(new ByteMessage( (Alien9800ReaderSession.PROMPT_SUPPRESS + username + Alien9800ReaderSession.NEWLINE) .getBytes())); logger.debug("getting the username response"); receiveMessage(); logger.debug("sending the password. "); sendMessage(new ByteMessage( (Alien9800ReaderSession.PROMPT_SUPPRESS + password + Alien9800ReaderSession.NEWLINE) .getBytes())); logger.debug("recieving the password response"); String authMessage = new String(receiveMessage().message); if (authMessage.contains("Invalid")) { logger.warn("Incorrect Password"); return false; } } catch (TimeoutException ex) { logger.warn("Timeout when logging in"); throw new IOException(ex); } return true; } /* * (non-Javadoc) * * @see * org.rifidi.edge.sensors.sessions.AbstractIPSensorSession#disconnect * () */ @Override public void disconnect() { try { super.disconnect(); } catch (Exception e) { } try { this.autonomousSession.disconnect(); } catch (Exception e) { } try { this.gpiosession.disconnect(); } catch (Exception e) { } } /* * (non-Javadoc) * * @seeorg.rifidi.edge.core.sensors.sessions.AbstractIPSensorSession# * getKeepAliveCommand() */ @Override protected Command getKeepAliveCommand() { /** * The Alien uptime command sends a 'get uptime' command to the alien * reader. If it gets no response within 10 seconds, it assumes the * reader has gone away and restarts the session. */ return new TimeoutCommand("Alien Keep Alive") { @Override public void execute() throws TimeoutException { // the message to send String message = PROMPT_SUPPRESS + "get " + COMMAND_UPTIME + NEWLINE; try { // send the message to the reader sendMessage(new ByteMessage(message.getBytes())); // wait for a response receiveMessage(); } catch (IOException e) { // Ignore } } }; } /* * (non-Javadoc) * * @see * org.rifidi.edge.sensors.sessions.AbstractIPSensorSession#sendMessage * (org.rifidi.edge.sensors.messages.ByteMessage) */ @Override public void sendMessage(ByteMessage message) throws IOException { super.sendMessage(message); } /* * (non-Javadoc) * * @see * org.rifidi.edge.core.readers.impl.AbstractReaderSession#setStatus(org * .rifidi.edge.core.api.SessionStatus) */ @Override protected void setStatus(SessionStatus status) { super.setStatus(status); // TODO: Remove this once we have aspectJ notifierService.sessionStatusChanged(this.readerID, this.getID(), status); } /* * (non-Javadoc) * * @see * org.rifidi.edge.core.readers.impl.AbstractReaderSession#killComand(java * .lang.Integer) */ @Override public void killComand(Integer id) { super.killComand(id); // TODO: Remove this once we have aspectJ notifierService.jobDeleted(this.readerID, this.getID(), id); } /* * (non-Javadoc) * * @see org.rifidi.edge.sensors.SensorSession#submit(java.lang.String, * long, java.util.concurrent.TimeUnit) */ @Override public Integer submit(String commandID, long interval, TimeUnit unit) { Integer retVal = super.submit(commandID, interval, unit); // TODO: Remove this once we have aspectJ try { notifierService.jobSubmitted(this.readerID, this.getID(), retVal, commandID, (interval > 0L)); } catch (Exception e) { // make sure the notification doesn't cause this method to exit // under any circumstances logger.error(e); } return retVal; } /** * This method sets the External Output high for the given ports * * @param ports * The ports to set high */ public void setOutputPort(BitSet ports) { int value = 0; for (int i = 0; i < 8; i++) { int bit = 0; if (ports.size() > i + 1) bit = ports.get(i) ? 1 : 0; value = value | bit << i; } if (value > 255) { throw new IllegalArgumentException("No more than 8 ports allowed"); } ((Alien9800Reader) this.getSensor()).setExternalOutput(value); ((Alien9800Reader) this.getSensor()).applyPropertyChanges(); } /** * This method tests if a given input port is high * * @param port * @return * @throws CannotExecuteException */ public boolean testInputPort(int port) throws CannotExecuteException { int external = getExternalInput(); // create a mask by bitshifting 1 port number of bits int mask = 1 << port; // if the mask AND the bitmap returned from the alien reader is // greater than 1, then the bit specified by 'port' is high return (external & mask) > 0; } /** * helper method that sends a 'get externalInput' command to the reader. It * blocks until the response returns * * @return the External Input * @throws CannotExecuteException */ public int getExternalInput() throws CannotExecuteException { LinkedBlockingQueue<AlienCommandObjectWrapper> commandObj = new LinkedBlockingQueue<AlienCommandObjectWrapper>(); commandObj.add(new AlienCommandObjectWrapper(Alien9800Reader.PROP_EXTERNAL_INPUT, new AlienGetCommandObject(COMMAND_EXTERNAL_INPUT))); boolean executed = ((Alien9800Reader) this.getSensor()).applyPropertyChanges(commandObj, true); if (executed) { return ((Alien9800Reader) this.getSensor()).getExternalInput(); } else { throw new CannotExecuteException("The GPI command may not have executed"); } } /** * This method flashes the given output ports high for a given amount of * time. This method executes in a separate thread, so it returns * immediately. * * @param ports * The ports to set to high * @param finalPorts * The configuration of the ports after the flashes are done * @param timeOn * The time in seconds to set the ports high * @param timeOff * The time in seconds to set the port low * @param repeat * The number of times to reapeat the flashes. * @throws CannotExecuteException */ public void flashOutput(final BitSet ports, final BitSet finalPorts, final int timeOn, final int timeOff, final int repeat) throws CannotExecuteException { Thread t = new Thread(new Runnable() { @Override public void run() { try { setOutputPort(new BitSet()); for (int i = 0; i < repeat; i++) { setOutputPort(ports); Thread.sleep(timeOn * 1000); setOutputPort(new BitSet()); Thread.sleep(timeOff * 1000); } setOutputPort(finalPorts); } catch (InterruptedException e) { logger.warn("Could not complete flash output"); Thread.currentThread().interrupt(); } catch (Exception e) { logger.warn("Could not complete flash output"); } } }); t.start(); } /* * (non-Javadoc) * * @see * org.rifidi.edge.sensors.sessions.AbstractIPSensorSession#toString() */ @Override public String toString() { return super.toString() + ", " + autonomousSession + "," + gpiosession; } }