|
Hi there,
Few weeks ago, someone's asked if there were any Java handler for LNP. Here
we are ! There is one now. Including with this mail is the Java listing.
What to do
1) download the JVM
2) download java communication API from Sun (lets you drive a serial
port)(http://java.sun.com/products/javacomm/index.html)
3) create somewhere a directory named lnp
4) put the 3 files in it
5) compile them
6) create the documentation (javadoc lnp -d <the directory where you want
the doc to be>)
7) look at the exemple (LNPTester.java)
8) Here we are !
Please feel free to send me all the comments you may have (fabien@bergeret.com)
--------------------->first File : LNPManager.java
package lnp;
import java.util.*;
import java.net.*;
import java.io.*;
import javax.comm.*;
/**
* This class handles the whole LNP protocol.
* As soon as you create a new instance of this class, i.e. the first time
* you call the getInstance method, a new thread is created that keeps the IR
* tower awake. The tower sends then a 0 every 4th second.
* Example of use :<BR><CODE>
* LNPManager manager = LNPManager.getInstance("COM1");<BR>
* manager.addLNPListener(this);<BR>
* manager.integrityWrite("This is a test");</CODE><BR>
* History: <BR>
* 01/13/2001: 1st release date<BR>
* Problems known : <BR>
* - the manager receives its own packets<BR>
* - the manager can only handle one IR tower at a time<BR>
* - there is no simple way to stop the manager from keeping the IR tower
alive and
* from reading data from the IR tower, i.e. even when your main method is
finished, the
* JVM doesn't stop.
* @author Fabien Bergeret (fabien@bergeret.com).
* @version 1.0
*/
public final class LNPManager implements Runnable
{
/**
* Private constructor of the class.
* The constructor is private because this class implements the
* singleton pattern (i.e., to get an instance, you call the
* static method getInstance(). The method stats a new thread
* that keeps the IR tower awake.
* @param comPort the name of the serial port to which the IR tower is
connected.
*/
private LNPManager(String comPort)
{
listeners = new Vector();
openPort(comPort);
(new Thread(this)).start();
}
/**
* Static mlethod that return an instance of the current class.
* If no other instance exists, creates one. The class cannot handle two IR
* towers at that time. If you ever try to do so, it will lead to some
undefined behavior.
* @param comPort the name of the serial port to which the IR tower is
connected.
* @return a new instance of the class if no other instance was created, or
the last isntance
* used.
*/
public static LNPManager getInstance(String comPort)
{
if ( theInstance == null )
{
theInstance = new LNPManager(comPort);
}
return theInstance;
}
/**
* This class keeps the tower awake by sending a 0 every 4th second.
*/
private class WakeupThread implements Runnable
{
public WakeupThread(OutputStream out)
{
this.out = out;
(new Thread(this)).start();
}
public void run()
{
while(goOn)
{
try
{
out.write(0);
Thread.currentThread().sleep(4000);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
public void stop()
{
goOn = false;
}
private OutputStream out;
private boolean goOn = true;
}
/**
* This methods adds the parameter to the list of the listener to call
* when a new message (integrity or addressing) is received.
* At the current time, the LNPManager dispatches all the messages received,
* even if the listners don't have the corrct port number.
* @param listener the new object to call when a new message is received.
*/
public void addLNPListener(LNPListener listener)
{
listeners.addElement(listener);
}
/**
* Removes the parameter from the list of the listeners to call when a new
message is received.
* @param listener the object to remove from the list of the listeners to
call when a new message is received.
*/
public void removeLNPListener(LNPListener listener)
{
listeners.removeElement(listener);
}
/**
* Opens the serial port to which the IR tower is connected.
* This methods also sets some parameter to the serial port :
* baud rate : 2400, 8 databits, 1 stopbit, no parity.
* @param comPort the serial port to which the IR tower is connected.
*/
private void openPort(String comPort)
{
try
{
CommPortIdentifier id = CommPortIdentifier.getPortIdentifier(comPort);
IRTower = (SerialPort)id.open("LNP",200);
IRTower.setSerialPortParams(2400, IRTower.DATABITS_8, IRTower.STOPBITS_1,
IRTower.PARITY_NONE );
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* DO NOT CALL THIS METHOD DIRECTLY : it's public because it is the
implementation
* of a interface.
* When a new LNPMAnager is created, the constructor creates a new thread,
that calls this
* method.
* It starts a new wake up thread, and loops on what is received on the
serial port.
*/
public void run()
{
boolean goOn = true;
try
{
InputStream in = IRTower.getInputStream();
WakeupThread wakeUp = new WakeupThread(IRTower.getOutputStream());
while(goOn)
{
int lecture = in.read();
switch(lecture)
{
case 0xF0 :
integrityRead(in);
break;
case 0xF1 :
addressingRead(in);
break;
default :
}
}
wakeUp.stop();
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* Called by the read loop when a 0xF0 is read from the serial port.
* Reads the packet, checks the checksum, and (if ok) sends a event to
* all the listeners. If the checksum is wrong, sends a wrong checksum event
* to the listeners.
* @param in the InputStream from which to read the data.
*/
private void integrityRead(InputStream in)
{
try
{
int length = in.read();
byte [] buffer = new byte[length];
for ( int i = 0; i < length; i++ )
buffer[i]=(byte)in.read();
int checkSum = in.read();
if ( checkChecksum((byte)0xF0, (byte)length, buffer, (byte)checkSum) )
sendIntegrityEvent(buffer);
else
sendWrongChecksumEvent();
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* Sends a IntegrityEvent to all the listeners.
* @param buffer the buffer
*/
private void sendIntegrityEvent(byte [] buffer)
{
Enumeration enum = listeners.elements();
while(enum.hasMoreElements())
{
LNPListener courant = (LNPListener)enum.nextElement();
courant.integrityReceived(buffer);
}
}
/**
* Sends a WrongChecksumEvent to all the listeners.
*/
private void sendWrongChecksumEvent()
{
Enumeration enum = listeners.elements();
while(enum.hasMoreElements())
{
LNPListener courant = (LNPListener)enum.nextElement();
courant.wrongChecksumReceived();
}
}
/**
* Sends a WrongChecksumEvent to all the listeners.
* Extracts from, to and data informations from the buffer, and call the
* appropriate method of the interface.
* @param buffer The buffer containing the received data.
*/
private void sendAddressingEvent(byte [] buffer)
{
Enumeration enum = listeners.elements();
byte [] copy = new byte[buffer.length-2];
System.arraycopy(buffer,2,copy,0,copy.length);
while(enum.hasMoreElements())
{
LNPListener courant = (LNPListener)enum.nextElement();
courant.addressingReceived(copy,(byte)(buffer[0]&lnpPortMask),
(byte)(buffer[1]&lnpHostMask), (byte)(buffer[1]&lnpPortMask));
}
}
/**
* Called by run when a 0xF1 is received.
* Reads the length, the data, checks the checksum, sends an addressing event
* to the listeners if the checksum is Ok, a wrong checksum event otherwise.
* @param in the InputStream from which to read the data.
*/
private void addressingRead(InputStream in)
{
try
{
int length = in.read();
byte [] buffer = new byte[length];
for ( int i = 0; i < length; i++ )
buffer[i]=(byte)in.read();
int check = in.read();
if ( checkChecksum((byte)0xF1,(byte)length,buffer,(byte)check))
sendAddressingEvent(buffer);
else
sendWrongChecksumEvent();
}
catch(IOException e)
{
e.printStackTrace();
}
}
/**
* Sends a integrity packet containing the data of the parameter.
* @param data the data to send.
*/
public void integrityWrite(String data)
{
integrityWrite(data.getBytes());
}
/**
* Sends a integrity packet containing the data of the parameter.
* @param data the data to send.
*/
public void integrityWrite(byte [] data)
{
byte [] buffer = new byte[data.length+3];
buffer[0]=(byte)0xf0;
buffer[1]=(byte)data.length;
System.arraycopy(data,0,buffer,2,data.length);
buffer[data.length+2]= (byte)checksum(buffer,data.length+2);
logicalWrite(buffer);
}
/**
* Sends a addressing packet containing the data of the parameter.
* @param data the data to send.
* @param sourcePort the port number from which you send the data
* @param destHostId the host to which you send the data
* @param destPortId the port to which you send the data
*/
public void addressingWrite( String data , byte sourcePort, byte
destHostId, byte destPort)
{
addressingWrite(data.getBytes(),sourcePort, destHostId,destPort);
}
/**
* Sends a addressing packet containing the data of the parameter.
* @param data the data to send.
* @param sourcePort the port number from which you send the data
* @param destHostId the host to which you send the data
* @param destPortId the port to which you send the data
*/
public void addressingWrite( byte [] data, byte sourcePort, byte
destHostId, byte destPort)
{
byte [] buffer = new byte[data.length+5];
buffer[0]=(byte)0xf1;
buffer[1]=(byte)(data.length+2);
buffer[2]=(byte)((destHostId&lnpHostMask) | (destPort&lnpPortMask));
buffer[3]=(byte)((lnpHostAddress&lnpHostMask) | ( sourcePort &
lnpPortMask));
System.arraycopy(data,0,buffer,4,data.length);
buffer[data.length+4] = (byte)checksum(buffer,data.length+4);
logicalWrite(buffer);
}
/**
* Computes the checksum.
* @param data the data on which to perform the checksum
* @param length the length on which to perform the checksum
* @return the checksum
*/
private static int checksum( byte [] data, int length )
{
byte a = (byte)0xff;
byte b = (byte)0xff;
for (int i = 0; i < length; i++ )
{
a += data[i];
b += a;
}
return a + (b << 8);
}
/**
* Checks if the checksum is correct.
* @param firstByte 0xF0 or 0XF1, depending on the kind of packet
* @param length the length on which to check the checksum
* @param data the data on which to check the checksum
* @param checksum the received checksum
* @return true if the checksum is ok, false otherwise.
*/
private static boolean checkChecksum(byte firstByte, byte length, byte[]
data, byte checksum)
{
byte a = (byte)0xff;
byte b = (byte)0xff;
a+=firstByte;
b+=a;
a+=length;
b+=a;
for ( int i = 0 ; i < data.length; i++ )
{
a+=data[i];
b+=a;
}
int newChecksum = (byte)(a+(b<<8));
return (checksum == newChecksum);
}
/**
* Used to send a logical packet, i.e. a raw packet.
* Waits for the IR tower to be available, and sends the data to it.
* param data the data to send.
*/
private synchronized void logicalWrite(byte [] data)
{
try
{
/*for ( int i = 0; i < data.length; i++ )
{
System.out.println(data[i]);
}*/
if ( IRTower == null )
wait();
OutputStream out = IRTower.getOutputStream();
out.write(data);
out.flush();
}
catch(Exception e)
{
e.printStackTrace();
}
}
/**
* Sets the host address of the LNPManager.
* This method automatically applies the hostMask to the parameter.
* @param hostAddress : the address of the LNPManager.
*/
public void setHostAddress(int hostAddress)
{
lnpHostAddress = (byte)(hostAddress & lnpHostMask);
}
/**
* Contains the only instance of the LNPManager.
*/
private static LNPManager theInstance;
/**
* The lnpHostMask, 0xF0 by default
*/
private static final byte lnpHostMask = (byte)0xF0;
/**
* The lnpPortMask, 0x0F by default
*/
private static final byte lnpPortMask = (byte)(0xFF-lnpHostMask);
/**
* The hostAddress, which can be changed by calling setHostAddress, 0x10 by
default.
*/
private byte lnpHostAddress = (byte)0x10;
/**
* The Vector containing the listeners
*/
private Vector listeners;
/**
* The serial port to which the IRTower is connected
*/
private SerialPort IRTower;
/**
* The maximum size of a LNP packet
*/
private static final int MAX_SIZE = 256+3;
}
--------------------->second File : LNPListener.java
package lnp;
/**
* Interface that all classes interested by what is received by the IR tower
should implement.
* When an objet is interested by the events, it calls addLNPListener to the
LNPManager.
* When it's not longer interested, it calls removeLNPListener to the LNPManager.
* @author Fabien Bergeret (fabien@bergeret.com)
*/
public interface LNPListener
{
/**
* Method called by LNPManager when a new integrity packet is received, provided
* that the current object has subscribed to the LNPManager.
* @param buffer the data received
*/
public void integrityReceived(byte [] buffer);
/**
* Method called by LNPManager when a new addressing packet is received,
provided
* that the current object has subscribed to the LNPManager.
* @param buffer the data received
* @param toPort the port to which the data was sent
* @param fromHost the host that sent the data
* @param fromPort the port from which the data was sent.
*/
public void addressingReceived(byte [] buffer, byte toPort, byte fromHost,
byte fromPort);
/**
* Method called by LNPManager when a packet with a wrong checksum is
received, provided
* that the current object has subscribed to the LNPManager.
*/
public void wrongChecksumReceived();
}
--------------------->third and last File : LNPTester.java
package lnp;
/**
* Shows how to use the API of the LNPManager.
* @author Fabien Bergeret (fabien@bergeret.com)
*/
public class LNPTester implements LNPListener
{
/**
* Creates a new LNPTester.
*/
public static void main(String args[])
{
new LNPTester();
}
/**
* Gets the LNPManager connected with the COM1 port, sends a addressing
packet from
* port 9 to host 0, port 5, and subscribes to all incoming packets.
*/
public LNPTester()
{
LNPManager manager = LNPManager.getInstance("COM1");
manager.addressingWrite("Salut",(byte)9,(byte)0x0,(byte)5);
manager.addLNPListener(this);
}
/**
* Prints as a string the received integrity packet.
*/
public void integrityReceived(byte [] buffer)
{
System.out.println("Message received");
System.out.println(new String(buffer));
}
/**
* Prints as a string the received integrity packet, the destination port,
the source
* host and the source port.
*/
public void addressingReceived(byte [] buffer, byte toPort, byte fromHost,
byte fromPort)
{
System.out.println("Message received from "+fromHost+", "+fromPort+" to
"+toPort);
System.out.println(new String(buffer));
}
/**
* Prints an error message when a packet with a wrong checksum is received.
*/
public void wrongChecksumReceived()
{
System.out.println("Wrong checksum received");
}
}
--------------------->end of the mail
|
|
1 Message in This Thread:
- Entire Thread on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
|
|
|
|