View Javadoc

1   package org.lsst.ccs.drivers.serial;
2   
3   import jssc.SerialPortException;
4   import jssc.SerialPortTimeoutException;
5   import org.lsst.ccs.drivers.commons.DriverException;
6   import org.lsst.ccs.drivers.commons.DriverTimeoutException;
7   
8   /**
9    * A serial port driver.
10   * 
11   * Currently implemented on top of JSSC.
12   * https://code.google.com/p/java-simple-serial-connector/
13   * 
14   * @author aubourg
15   * 
16   */
17  public class SerialPort {
18  
19      jssc.SerialPort portImpl;
20  
21      /**
22       * Constructor.
23       */
24      public SerialPort() {
25      }
26  
27      /**
28       * Constructor. Opens the port.
29       * 
30       * @param name
31       *            the os-dependant name of the port (eg /dev/ttyXX).
32       */
33      public SerialPort(String name) throws DriverException {
34          this();
35          openPort(name);
36      }
37  
38      /**
39       * Opens the port.
40       * 
41       * @param name
42       *            the os-dependant name of the port (eg /dev/ttyXX).
43       */
44      public void openPort(String name) throws DriverException {
45          if (portImpl != null)
46              throw new IllegalStateException("Device connection already open");
47          portImpl = new jssc.SerialPort(name);
48          try {
49              portImpl.openPort();
50          } catch (SerialPortException e) {
51              throw new DriverException("cannot open port", e);
52          }
53      }
54  
55      /**
56       * closes the port.
57       *
58       * @return whether or not the close was successful
59       */
60      public boolean closePort() throws DriverException {
61          try {
62              if (portImpl.closePort()) {
63                  portImpl = null;
64                  return true;
65              }
66              return false;
67          } catch (SerialPortException e) {
68              throw new DriverException("cannot close port", e);
69          }
70      }
71  
72      /**
73       * get the number of bytes available in the buffer (ie non blocking)
74       * 
75       * @return the number of bytes.
76       */
77      public int getInputBufferBytesCount() throws DriverException {
78          try {
79              return portImpl.getInputBufferBytesCount();
80          } catch (SerialPortException e) {
81              throw new DriverException("serial port error", e);
82          }
83      }
84  
85      /**
86       * read as many bytes as available without blocking.
87       * 
88       * @return the newly allocated byte array.
89       */
90      public byte[] readBytes() throws DriverException {
91          try {
92              return portImpl.readBytes();
93          } catch (SerialPortException e) {
94              throw new DriverException("serial port error", e);
95          }
96      }
97  
98      /**
99       * read bytes from the serial port. If not enough bytes are available might
100      * fail by throwing a TimeoutException after "timeout" milliseconds.
101      * 
102      * @param byteCount
103      *            the number of bytes to read
104      * @param timeout
105      *            milliseconds before failing on timeout
106      * @return the newly allocated byte array.
107      */
108     public byte[] readBytes(int byteCount, int timeout) throws DriverException {
109         try {
110             return portImpl.readBytes(byteCount, timeout);
111         } catch (SerialPortException e) {
112             throw new DriverException("serial port error", e);
113         } catch (SerialPortTimeoutException e) {
114             throw new DriverTimeoutException("serial port timeout", e);
115         }
116     }
117 
118     /**
119      * read a given number of bytes from the serial port.
120      * 
121      * @param byteCount
122      *            the number of bytes to read
123      * @return the newly allocated byte array.
124      */
125     public byte[] readBytes(int byteCount) throws DriverException {
126         try {
127             return portImpl.readBytes(byteCount);
128         } catch (SerialPortException e) {
129             throw new DriverException("serial port error", e);
130         }
131     }
132 
133     /**
134      * read all available bytes from the serial port, return as a String
135      * 
136      * @return the newly allocated String.
137      */
138     public String readString() throws DriverException {
139         try {
140             return portImpl.readString();
141         } catch (SerialPortException e) {
142             throw new DriverException("serial port error", e);
143         }
144     }
145 
146     /**
147      * read bytes from the serial port. If not enough bytes are available might
148      * fail by throwing a TimeoutException after "timeout" milliseconds.
149      * 
150      * @param byteCount
151      *            the number of bytes to read
152      * @param timeout
153      *            milliseconds before failing on timeout
154      * @return the newly allocated byte array.
155      */
156     public String readString(int byteCount, int timeout) throws DriverException {
157         try {
158             return portImpl.readString(byteCount, timeout);
159         } catch (SerialPortException e) {
160             throw new DriverException("serial port error", e);
161         } catch (SerialPortTimeoutException e) {
162             throw new DriverTimeoutException("serial port timeout", e);
163         }
164     }
165 
166     /**
167      * read bytes from the serial port.
168      * 
169      * @param byteCount
170      *            the number of bytes to read
171      * @param timeout
172      *            milliseconds before failing on timeout
173      * @return the newly allocated byte array.
174      */
175     public String readString(int byteCount) throws DriverException {
176         try {
177             return portImpl.readString(byteCount);
178         } catch (SerialPortException e) {
179             throw new DriverException("serial port error", e);
180         }
181     }
182 
183     /**
184      * set the flow control mode.
185      * 
186      * @param mask
187      *            bitfield
188      * 
189      *            0 : NONE
190      * 
191      *            1 : RTSCTS_IN
192      * 
193      *            2 : RTSCTS_OUT
194      * 
195      *            4 : XONXOFF_IN
196      * 
197      *            8 : XONXOFF_OUT
198      * 
199      * @return true if everything was ok.
200      */
201     public boolean setFlowControlMode(int mask) throws DriverException {
202         try {
203             return portImpl.setFlowControlMode(mask);
204         } catch (SerialPortException e) {
205             throw new DriverException("serial port error", e);
206         }
207     }
208 
209     /**
210      * Set the communication parameters
211      * 
212      * @param baudRate
213      *            baud rate (110, 300, 600, 1200, 4800, 9600, 14400, 19200,
214      *            38400, 57600, 115200, 128000, 256000)
215      * @param dataBits
216      *            data bits (5, 6, 7, 8)
217      * @param stopBits
218      *            stop bits (1, 2, 3 for 1.5)
219      * @param parity
220      *            parity (0 none, 1 odd, 2 even, 3 mark, 4 space)
221      * @return true if everything is ok
222      */
223     public boolean setParams(int baudRate, int dataBits, int stopBits,
224             int parity) throws DriverException {
225         try {
226             return portImpl.setParams(baudRate, dataBits, stopBits, parity);
227         } catch (SerialPortException e) {
228             throw new DriverException("serial port error", e);
229         }
230     }
231 
232     /**
233      * sends a single byte
234      * 
235      * @param singleByte the byte to send
236      * 
237      * @return whether everything was okay
238      */
239     public boolean writeByte(byte singleByte) throws DriverException {
240         try {
241             return portImpl.writeByte(singleByte);
242         } catch (SerialPortException e) {
243             throw new DriverException("serial port error", e);
244         }
245     }
246 
247     /**
248      * sends a byte array
249      * 
250      * @param buffer the byte array to send
251      *
252      * @return whether everything is okay
253      */
254     public boolean writeBytes(byte[] buffer) throws DriverException {
255         try {
256             return portImpl.writeBytes(buffer);
257         } catch (SerialPortException e) {
258             throw new DriverException("serial port error", e);
259         }
260     }
261 
262     /**
263      * sends a String as byte array
264      * 
265      * @param string the string to send
266      *
267      * @return whether everything is okay
268      */
269     public boolean writeString(String string) throws DriverException {
270         try {
271             return portImpl.writeString(string);
272         } catch (SerialPortException e) {
273             throw new DriverException("serial port error", e);
274         }
275     }
276 
277     /**
278      * sends a String + CR + LF as byte array
279      * 
280      * @param string the string to send
281      */
282     public void writeStringCRLF(String s) throws DriverException {
283         StringBuilder cmd = new StringBuilder(s);
284         cmd.append((char) 13);
285         cmd.append((char) 10);
286         writeString(cmd.toString());
287     }
288 
289     /**
290      * sends a String + LF as byte array
291      * 
292      * @param string the string to send
293      */
294     public void writeStringLF(String s) throws DriverException {
295         StringBuilder cmd = new StringBuilder(s);
296         cmd.append((char) 10);
297         writeString(cmd.toString());
298     }
299 
300 
301     /**
302      * sends a String + CR as byte array
303      * 
304      * @param string the string to send
305      */
306     public void writeStringCR(String s) throws DriverException {
307         StringBuilder cmd = new StringBuilder(s);
308         cmd.append((char) 13);
309         writeString(cmd.toString());
310     }
311 
312     /**
313      * reads a String until CR+LF occurs.
314      * 
315      * Default timeout of 1000 ms
316      *
317      * @return the read string (without the CRLF)
318      */
319     public String readUntilCRLF() throws DriverException {
320         return readUntilCRLF(1000);
321     }
322 
323     /**
324      * reads a String until LF occurs.
325      * 
326      * Default timeout of 1000 ms
327      *
328      * @return the read string (without the LF)
329      */
330     public String readUntilLF() throws DriverException {
331         return readUntilLF(1000);
332     }
333 
334     /**
335      * reads a String until "> " or "< " occurs. For Thorlabs Laser
336      * 
337      * Default timeout of 1000 ms
338      *
339      * @return the read string (without the "> " or "< ")
340      */
341     public String readUntilSUPSP() throws DriverException {
342         return readUntilSUPSP(1000);
343     }
344 
345     /**
346      * reads a String until "> " or "< " occurs, with explicit timeout
347      * 
348      * @param timeout
349      *            the timeout in ms
350      *
351      * @return the read string (without the "> " or "< ")
352      */
353     public String readUntilSUPSP(int timeout) throws DriverException {
354         StringBuilder buf = new StringBuilder();
355         while (true) {
356             byte[] b = readBytes(1, timeout);
357             if (b[0] == 62 || b[0] == 60) {
358                 byte sb = b[0];
359                 b = readBytes(1, timeout);
360                 if (b[0] == 32) {
361                     return buf.toString();
362                 }
363                 buf.append((char) sb);
364             }
365             buf.append((char) b[0]);
366         }
367     }
368 
369     /**
370      * reads a String until LF occurs, with explicit timeout
371      * 
372      * @param timeout
373      *            the timeout in ms
374      *
375      * @return the read string (without the LF)
376      */
377     public String readUntilLF(int timeout) throws DriverException {
378         StringBuilder buf = new StringBuilder();
379         while (true) {
380             byte[] b = readBytes(1, timeout);
381             if (b[0] == 10) {
382                return buf.toString();
383             }
384             buf.append((char) b[0]);
385         }
386     }
387 
388     /**
389      * reads a String until CR+LF occurs, with explicit timeout
390      * 
391      * @param timeout
392      *            the timeout in ms
393      *
394      * @return the read string (without the CRLF)
395      */
396     public String readUntilCRLF(int timeout) throws DriverException {
397         StringBuilder buf = new StringBuilder();
398         while (true) {
399             byte[] b = readBytes(1, timeout);
400             if (b[0] == 13) {
401                 byte sb = b[0];
402                 b = readBytes(1, timeout);
403                 if (b[0] == 10) {
404                     return buf.toString();
405                 }
406                 buf.append((char) sb);
407             }
408             buf.append((char) b[0]);
409         }
410     }
411 
412     /**
413      * Reads available data into a byte array.
414      * 
415      * @param buff
416      *            The buffer to receive the response data
417      * 
418      * @param offset
419      *            The offset to the first available byte in the buffer
420      * 
421      * @param timeout
422      *            the timeout in ms
423      *
424      * @return The number of bytes read
425      */
426     public int read(byte[] buff, int offset, int timeout)
427             throws DriverException {
428         byte[] data;
429         int leng = 0, count = getInputBufferBytesCount();
430         if (count == 0) {
431             if (timeout > 0) {
432                 data = readBytes(1, timeout);
433             } else {
434                 data = readBytes(1);
435             }
436             buff[offset++] = data[0];
437             leng = 1;
438             count = getInputBufferBytesCount();
439         }
440         if (offset + count > buff.length) {
441             count = buff.length - offset;
442         }
443         if (count > 0) {
444             data = readBytes(count);
445             System.arraycopy(data, 0, buff, offset, count);
446             leng += count;
447         }
448 
449         return leng;
450     }
451 
452 }