Greetings all, I am interested in deploying a MINA application on an embedded device that supports both serial and network communications. In the FAQs, it says the Java Comm API is on its way, and I was just wondering how far along this implementation is. If this is something that I need to implement, could anyone give me pointers on where to start. It appears that the logical approach I would take, would be to create a SerialPortConnector that implements the IoConnector interface? The problem I see with that is that all the connect methods in the IoConnector interface contain a SocketAddress in the signature.
I have a Mina server sending everything read on the serialport to the TCP/IP connections and everything read on the TCP/IP side to the serial connection.
Actualy there is a lot of change undergoing in Sun Java comm API & RXTX and I wanted to see how it's going to evolve before implementing full serial support for MINA.
Here an example on how to start it :
SerialTCPServer serialServ=new SerialTCPServer();
serialServ.addSerialPort(9001,new SerialSocketAddress("/dev/ttyS0",38400,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE));
serialServ.addSerialPort(9002,new SerialSocketAddress("/dev/ttyS1",2400,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE));
serialServ.addSerialPort(9003,new SerialSocketAddress("/dev/ttyS2",9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_EVEN));
serialServ.addSerialPort(9004,new SerialSocketAddress("/dev/ttyS3",9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE));
serialServ.start();
BTW it's dependant of my reconnectionFilters & JMX patches, you can find it in JIRa or simply delete the references.
Hope it helps, contact me if any questions,
Julien
/* * Created on 24 févr. 2005 * */ package archean.serial; import java.net.SocketAddress;
/** * @author Julien Vermillard - Archean * a serial port address * defined by it name and parameters (bauds, data bits, stop bits and parity) */ public class SerialSocketAddress extends SocketAddress { /** * Default <code>serialVersionUID</code> */ private static final long serialVersionUID = 1L; private String name; private int bauds; private int dataBits; private int stopBits; private int parity; /** * @param name port name (OS identifiant) * @param bauds baud rate * @param dataBits amount of data bits * @param stopBits stop bits * @param parity parity check * @see javax.comm.SerialPort for constants */ public SerialSocketAddress(String name, int bauds, int dataBits, int stopBits, int parity) { super(); this.name = name; this.bauds = bauds; this.dataBits = dataBits; this.stopBits = stopBits; this.parity = parity; } /** * @return Returns the bauds. */ public int getBauds() { return bauds; } /** * @return Returns the dataBits. */ public int getDataBits() { return dataBits; } /** * @return Returns the name. */ public String getName() { return name; } /** * @return Returns the parity. */ public int getParity() { return parity; } /** * @return Returns the stopBits. */ public int getStopBits() { return stopBits; } }
/* * Created on 25 févr. 2005 * */ package archean.serial; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.management.ManagementFactory; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.Enumeration; import java.util.TooManyListenersException; import javax.comm.CommPortIdentifier; import javax.comm.PortInUseException; import javax.comm.SerialPort; import javax.comm.SerialPortEvent; import javax.comm.SerialPortEventListener; import javax.comm.UnsupportedCommOperationException; import javax.management.JMException; import javax.management.MBeanServer; import javax.management.ObjectName; import org.apache.log4j.Logger; import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoAcceptor; import org.apache.mina.common.IoHandler; import org.apache.mina.common.IoSession; import org.apache.mina.transport.socket.nio.SocketAcceptor; import archean.Startable; import archean.util.mina.SessionManager; /** * @author Julien Vermillard - Archean * a TCP server echoing communication from a Serial port of the computer (COMM1/2/3 on windows, /dev/ttySX on Linux) * * */ public class SerialTCPEchoer implements Startable, SerialPortEventListener { private int port; private SerialSocketAddress serialPortAddress; private OutputStream outputStream; private InputStream inputStream; private SerialPort serialPort; private ArrayList<IoSession> sessions = new ArrayList<IoSession>(); private Logger logger; public SerialTCPEchoer(int port, SerialSocketAddress serialPort) { this.port = port; this.serialPortAddress = serialPort; logger = Logger.getLogger("SerialPort["+serialPort.getName()+":"+port+"]"); } /** * @see archean.Startable#start() */ public void start() { // start serial port configuration CommPortIdentifier portId; Enumeration portList = CommPortIdentifier.getPortIdentifiers(); int i=0; while (portList.hasMoreElements()) { i++; portId = (CommPortIdentifier) portList.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { logger.debug("serial port discovered :"+portId.getName()); if (portId.getName().equals(serialPortAddress.getName())) { try { logger.info("Port found : " + portId.getName()); serialPort = (SerialPort) portId.open( "SerialTCPEchoer", 2000); serialPort.setSerialPortParams(serialPortAddress.getBauds(),serialPortAddress.getDataBits(), serialPortAddress.getStopBits(),serialPortAddress.getParity()); /*serialPort.setInputBufferSize(8); serialPort.setOutputBufferSize(8); */ outputStream = serialPort .getOutputStream(); inputStream = serialPort.getInputStream(); serialPort.notifyOnDataAvailable(true); serialPort.addEventListener(this); } catch (PortInUseException e) { e.printStackTrace(); } catch (UnsupportedCommOperationException e1) { e1.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (TooManyListenersException e) { e.printStackTrace(); } } } } logger.debug(i+" port scanned."); // start TCP server // Create a TCP/IP acceptor IoAcceptor acceptor; try { acceptor = new SocketAcceptor(); // Add thread pool filter // MINA runs in a single thread if you don't add this filter. //acceptor.addFilter(IoHandlerFilter.MAX_PRIORITY, threadPoolFilter); // Bind acceptor.bind(new InetSocketAddress(port), new EchoProtocolHandler()); logger.info("Listening on port " + port); } catch (IOException e) { logger.error("Exception while opening tcp port",e); e.printStackTrace(); } } /** * @see archean.Startable#stop() */ public void stop() { // stop serial port serialPort.close(); } private class EchoProtocolHandler implements IoHandler { public void sessionOpened(IoSession session) { logger.info(session.getRemoteAddress()+" connected"); sessions.add(session); } public void sessionCreated(IoSession session) throws Exception { // JMX instrumentation try { SessionManager sessMgr=new SessionManager(session); MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ObjectName name = new ObjectName("archean.serial:type=SessionManager,name="+serialPort.toString().replace(':','/')); mbs.registerMBean(sessMgr, name); } catch (JMException e) { logger.error("JMX Exception : ",e); } } public void sessionClosed(IoSession session) { logger.info(session.getRemoteAddress()+" disconnected"); try { MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); ObjectName name = new ObjectName("archean.serial:type=SessionManager,name="+serialPort.toString().replace(':','/')); mbs.unregisterMBean(name); } catch (JMException e) { logger.error("JMX Exception : ",e); } sessions.remove(session); } public void sessionIdle(IoSession session, IdleStatus status) { // TODO : IDLE what to do ? } public void exceptionCaught(IoSession session, Throwable cause) { logger.error(Thread.currentThread().getName() + ' ' + session.getRemoteAddress() + ": EXCEPTION",cause); session.close(); } public void messageReceived(IoSession session, Object message) throws Exception { ByteBuffer rb=(ByteBuffer)message; // Write the received data back to remote peer ByteBuffer wb = ByteBuffer.allocate(rb.remaining()); wb.put(rb); wb.flip(); byte[] buf = new byte[wb.remaining()]; wb.get(buf); try { outputStream.write(buf); outputStream.flush(); } catch (IOException e) { logger.error("ERROR while writing bytes",e); } } public void messageSent(IoSession session, Object message) throws Exception { // TODO Auto-generated method stub } } private byte[] readBuffer = new byte[100]; /** * @see javax.comm.SerialPortEventListener#serialEvent(javax.comm.SerialPortEvent) */ public void serialEvent(SerialPortEvent event) { switch (event.getEventType()) { case SerialPortEvent.DATA_AVAILABLE: try { while (inputStream.available() > 0) { int numBytes = inputStream.read(readBuffer); ByteBuffer b = ByteBuffer.allocate(numBytes); b.put(readBuffer, 0, numBytes); b.flip(); for (IoSession s : sessions) { s.write(b); } } } catch (IOException e) { } break; default: break; } } }
/* * Created on 25 févr. 2005 * */ package archean.serial; import java.util.ArrayList; import archean.Startable; /** * @author Julien Vermillard - Archean * */ public class SerialTCPServer implements Startable { private ArrayList<SerialTCPEchoer> echoers = new ArrayList<SerialTCPEchoer>(); private boolean started=false; public SerialTCPServer() { } public void start() { for(SerialTCPEchoer e:echoers) { e.start(); } started=true; } public void stop() { for(SerialTCPEchoer e:echoers) { e.stop(); } started=false; } public void addSerialPort(int port,SerialSocketAddress addr) { SerialTCPEchoer echoer=new SerialTCPEchoer(port,addr); echoers.add(echoer); if(started) echoer.start(); } }
smime.p7s
Description: S/MIME cryptographic signature