Le vendredi 19 mai 2006 à 10:46 -0400, Gaston, Brian a écrit :
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();
	}
}

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to