SERIAL SERVER

By Dan O'Sullivan

SerialServer relays bytes back and forth from an internet socket connection to a hardware serial port. It is sort of like an ethernet to RS232 converter. This is especially useful for software like Flash which has an easy time making socket connections and a hard time making serial connections. This will allow you to connect to a device with a serial port or a USB port that you can turn into an RS232 port with an adapter, or a bluetooth connection (might require a bluetooth dongle on your machine and some bluetooth control panel settings) to software that makes socket conections. For example you can connectsensors and actuators on a microcontroller (sample code from my European office) to something that like Flash or software on a cell phone.

You can see the source here

Installation:

Application:

You can download this as an application called ss6.jar. You might get lucky and it will run when you double click on it, otherwise run it by in a command or console window by typing "java -jar ss6.jar".

Applet:

Try this applet It uses the java plugin which is probably already installed. Unfortunately this probably will not work off the bat because most machines will not have the files for java to use serial communication installed (see the next section). This applet also asks for permission to get past sandbox security (serial not permitted in a browser), you will have to trust me and say okay.

Comm Classes:

There is a good chance your java bits are all installed okay. The only thing that is a bit unusual to be already installed is the files for that allow java to talk serial. You have to get those from www.rxtx.org and put them in a special place. Within rxtx there are two flavors. Get the one " For use WITHOUT Sun's CommAPI (namespace gnu.io)". Whatever you use for serial classes, you will know you have them installed when you stop get something like "ClassDef not found" or "Unsatisfied Link" in the Sun Java Console..

Until recently I would send people to http://java.sun.com/products/javacomm/ to download the files from sun for windows . They seem to have upgraded or something but now you can only get files for solaris. They should still work if you can get them (you can still get them here).

You should follow the installation instructions but basically there are a couple of files that need to be placed where your java virtual machine can see them:

Installation on a PC

  1. Read the readme because these instructions may not be up to date
  2. Download the files and expand them.
  3. comm.jar or RXTXcomm.jar goes in c:\...jre\lib\ext\
  4. win32com.dll or rxtxSerial.dll goes in c:\...jre\bin\


Sun has another file javax.comm.properties goes in c:\...jre\lib\ but you don't need that for the rxtx. Also ignore the parrallel dll from rxtx.

The typical gotcha: The "..." in my filenames is where your plugin's java runtime is. On my machine the ... is at C:\Program Files\Java\j2re1.4.1_02\ but you may have many java runtimes (jre) some of them buried in development kits (jdk) or (sdk) installed all over your machine. YOu can see which Java you are using with Java -version or look in the Sun Java Console of your browser for something like "Java(TM) Plug-in: Version 1.4.....". If worse comes to worse put these files in all the lib, lib\ext and bin directories of all your java runtimes. Make sure you put them in the lib and bin folder with the JRE folder.

Installation on a Mac:

  1. Download and e xpand the files. In unix you can expand the files gunzip rxtx-2.1-7pre17.tar.gz and then take the resulting file and say tar -xvf rxtx-2.1-7pre17.tar On a PC use something like WinZip for expanding the file.
  2. Search deep into the separated file directory for these files "libSerial.jnilib" and "RXTXcomm.jar" and place them into /Library/Java/Extensions/.
  3. You may have to run this script on a mac if you get a complaint about serial port busy.

Installation on Linux:

I supsect you will put the same files as you did for the Mac into the similar folder that you used for the PC but I don't really know. One gotcha is that you may need to use the "noverify" option when you go to run it.

Installation on other platforms: http://republika.pl/mho/java/comm/

Parameters:

If you want to save having to adjust the ports and baud rate manually with the pulldown menus, you can send them to the application or the applet as the parameters, Baud, SerialPort, and SocketPort.

Sub0ForChar is a parameter that is particularly useful for connecting to flash. Flash will not process incoming data until it is appended with a 0 character. It is more common in the Serial realm to append trasmissions with a carriage return (ascii 13) or a line feed (ascii 10) or both. If you are connecting Flash to a proprietary box where you don't have enough control to add the 0 character, then you can use this parameter to set which character to substitute with the character 0 for Flashes benefit.

SerialDriver is a parameter that you might have to set if you have both the sun and the rxtx drivers installed and you want to use the sun drivers. you would use the word "sun" for the value of this parameter. If you have only one installed it should find that and use it. If you have both and you do not specify with this parameter it will use the rxtx drivers.

Passing Parameters to an Application: 
java -jar ss.jar SerialPort:COM1 Baud:4800 SocketPort:9005 Sub0ForChar:10 SerialDriver:Sun
Passing Parameters to an Applet:  

PARAM NAME="Baud" VALUE="9600"
PARAM NAME="SerialPort" VALUE="COM1"
PARAM NAME="SocketPort" VALUE="9001"
PARAM NAME= "Sub0ForChar" VALUE="10"

PARAM NAME= "SerialDriver" VALUE="Sun"

Testing:

You can troubleshoot this thing by connecting to the socket side using telnet. This allows you to eliminate all the problems you might be having in your flash or shockwave code. You you would connect by running "telnet localhost 9000" in a command window.

On the serial side you can connect your serial port to another serial port (perhaps on the same machine) using a "null modem adapter" from Radio Shack. Then you can use simple telnet-like programs like "hyperterm" (comes with windows) or "zterm" you can find it for the mac to eliminate all the problems you might be having with your serial device.

Flash Tips:

Flashes XML Socket (don't ask me why they call it an XML socket you don't have to send XML) wants you to put a 0 character at the end of all your bytes to mark the end of transmission. This means that you cannot send a byte worth zero, only bytes 1-255 (remember to add something to getPins which tend to be 0 or 1). On the bright side, this can be handy if you are recieving multiple bytes. Basically the "onData" callback will not happen until it gets a zero byte which you can send at the end of all the data bytes to signify that they have all arrived. Flash will also append a zero byte with each call to the send method so on the serial device side, you will have to either ignore the zero character or use it as a demiliter as just described. In any case the SerialServer generally just passes the zero bytes back and forth without prejudice unless you use the Sub0ForChar parameter in which case it substitutes a 0 character every time it sees the character you specify with this parameter. For sending binary numbers you might look into the String.fromCharCode() command. Here is some very boring code from this fla or swf that you can just paste into the first frame of an emply flash movie.

createSocket ();

function createSocket () {
	_root.createTextField("inputlabel",4,50,100,50,20);
	inputlabel.text = "Input:";
	_root.createTextField("outputlabel",5,50,300,50,20);
	outputlabel.text = "Output:";
	_root.createTextField("inputer",3,100,100,200,20);
	_root.createTextField("outputer",2,100,300,200,20);
	outputer.type = "input";
	outputer.border = true;
	inputer.border = true;
	serialServer = new XMLSocket ();
	trace ("made it" + serialServer);
	//127.0.0.1 is the same as "localhost" ie an alias to your local machine
	//it is concievable to that you would want to connect from another machine and you would change this
	serialServer.connect ("127.0.0.1", 9001);
	serialServer.onConnect = function (success) {
		trace ("connected " + success);
		serialServer.send ("HOWDY FROM FLASH" + new Date().toString());
	};
	serialServer.onClose = function () {
		trace ("closed");
	};
	serialServer.onData = function (data) {
		trace ("incoming" + data);
		inputer.text = inputer.text + data;
	};
	outputer.onChanged = function () {
		serialServer.send (outputer.text);
		trace ("output" + outputer.text);
		outputer.text = "";
	};
}

Here is some code fla swf for recieving the values of three sensors AS TEXT from a microcontroller and sending back the mouse position

     createSocket ();    

 //Here is some code for recieving the values of three sensors from a microcontroller and sending back the mouse position:
   function createSocket () {
   myThing = _root.attachMovie("circle","thing",1);
   myThing._y = 200;
   
   serialServer = new XMLSocket ();
   trace ("made it" + serialServer);
   //127.0.0.1 is the same as "localhost" ie an alias to your local machine
   //it is concievable to that you would want to connect from another machine and you would change this
   serialServer.connect ("127.0.0.1", 9001);
   serialServer.onConnect = function (success) {
   trace ("connected " + success);
   serialServer.send("A");
   //serialServer.send ("HOWDY FROM FLASH" + new Date().toString());
   };
   serialServer.onClose = function () {
   trace ("closed");
   };
   serialServer.onData = gotSomething ;
   }
   
   function gotSomething(datar) {
   //trace (datar + "incoming " + datar.length + " " + datar.charCodeAt(0) + " " + datar.charCodeAt(1) + " " + datar.charCodeAt(2));
 parts = datar.split(",")
 if(parts.length >= 3){
   myThing._x = number(parts[2]); //scale it up from 1-255 to stage witht
   myThing._alpha = number(parts[1]); //scale it down from 1-255 to 0-100
   myThing._width = 50 + number(parts[0])*50
   myThing._height = 50 + number(parts[0])*50
   }
   mousePos = _root._xmouse;
   serialServer.send(String.fromCharCode(mousePos));
}

This Might talk to a program like this on a pic

DEFINE OSC 4
DEFINE ADC_BITS 8
   DEFINE ADC_CLOCK 3
   DEFINE ADC_SAMPLEuS 20
   lightVar var byte
   potVaR VAR BYTE
   switchVar var byte
   inByte var byte
   extraFlashByte var byte
   input portb.7 
   serout2 portc.6, 16468, [65]

main:
   switchVar = portb.7 + 65 'make it readable
   adcin 0, potvar
   adcin 2, lightvar
   serout2 portc.6, 16468, [DEC lightVar,44,DEC potVar, 44, DEC switchVar, 0]
serin2 portc.7, 16468, [inbytem,extraFlashByte] 
     
   Pulsout portd.0, inByte //turn the servo motor
   PAUSE 10
goto main

or a program like this on a BX

   dim invar as byte
   dim extraFlashChar as byte
   dim outvar as byte
   dim variableResistor as integer
   dim variableResistor2 as integer
   dim pulsewidth as integer
   dim pos as single
   
 'set up a buffer
 dim inputBuffer(1 To 20) as byte
 dim outputBuffer(1 To 20) as byte
 dim outputString as string
Sub main()
   call openQueue(inputBuffer,20)
   call openQueue(outputBuffer,20)
   'set up the port
   call defineCom3(13, 11, bx1000_1000) 
   call openCom(3,9600,inputBuffer,outputBuffer) '9600 baud
   debug.print "start"
do 'deal with one variable resistor and send it 
   variableResistor = getADC(15)

'deal with another variable resistor and send it 
 variableResistor2 = getADC(17)
   'debug.print cStr(variableResistor) 'determine that I get numbers 180 -580
'deal with the switch and send it 
 outvar = getPin(8) 
   'so you don't send 0 (the nasty null char) or 1 but 65 or 66, "A" or "B"
   outputString = cstr(outvar)& chr(44)&cstr(variableResistor)& chr(44)&cstr(variableResistor2)
   call putQueueStr(outputBuffer,outputString)
   extraFlashChar = 0
   call putQueue(outputBuffer,extraFlashChar,1)
   'debug.print outputString
   'get something back and use that to turn the motor
   call getQueue(inputBuffer,invar,1) 'program stops until it hears something
   call getQueue(inputBuffer,extraFlashChar,1) 'program stops until it hears something
   'debug.print "got" 
   pos = cSng(invar)* 0.000006
   call pulseout(10,pos,1)
   call delay(0.02)
loop 
   End Sub
   

You can see the source here