Communicator.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*
  2. * To change this template, choose Tools | Templates
  3. * and open the template in the editor.
  4. */
  5. package camsucks;
  6. import gnu.io.*;
  7. import java.io.IOException;
  8. import java.io.InputStream;
  9. import java.io.OutputStream;
  10. import static java.lang.Thread.sleep;
  11. import java.util.Enumeration;
  12. import java.util.HashMap;
  13. /**
  14. * This class communicates with a serial com device
  15. * @author Henry Poon @ https://blog.henrypoon.com/
  16. * Changes by Roel: Removed all references to the GUI class from Henry Poon's original project.
  17. * Changed the event based serial read to a synchronised read after each write.
  18. * Added a Buffer for the serial read so that the read data can easily be accessed by other classes
  19. * Completely rewritten the writeData method so that it works with the GRID+ controller
  20. * Added some getters and setters for the buffer
  21. * added a getter for the portMap so that the controller and view can access it
  22. */
  23. public class Communicator {
  24. //for containing the ports that will be found
  25. private Enumeration ports = null;
  26. //map the port names to CommPortIdentifiers
  27. private HashMap portMap = new HashMap();
  28. //this is the object that contains the opened port
  29. private String selectedPort;
  30. private CommPortIdentifier selectedPortIdentifier = null;
  31. private SerialPort serialPort = null;
  32. //input and output streams for sending and receiving data
  33. private InputStream input = null;
  34. private OutputStream output = null;
  35. //just a boolean flag that i use for enabling
  36. //and disabling buttons depending on whether the program
  37. //is connected to a serial port or not
  38. private boolean bConnected = false;
  39. //the timeout value for connecting with the port
  40. final static int TIMEOUT = 2000;
  41. //some ascii values for for certain things
  42. final static int SPACE_ASCII = 32;
  43. final static int DASH_ASCII = 45;
  44. final static int NEW_LINE_ASCII = 10;
  45. //Buffer
  46. private int leng;
  47. private byte[] buffer;
  48. //a string for recording what goes on in the program
  49. String logText = "";
  50. /**
  51. *
  52. * @param selectedPort This parameter is the string name of the port the communicator object should connect to
  53. */
  54. public Communicator(String selectedPort) {
  55. this.selectedPort = selectedPort;
  56. }
  57. //search for all the serial ports
  58. //pre: none
  59. //post: adds all the found ports to a combo box on the GUI
  60. /**
  61. *
  62. * This method searches for COM ports on the system and saves their Identifier in the hashmap portMap with their name as key.
  63. *
  64. */
  65. public void searchForPorts() {
  66. ports = CommPortIdentifier.getPortIdentifiers();
  67. while (ports.hasMoreElements()) {
  68. CommPortIdentifier curPort = (CommPortIdentifier) ports.nextElement();
  69. //get only serial ports
  70. if (curPort.getPortType() == CommPortIdentifier.PORT_SERIAL) {
  71. getPortMap().put(curPort.getName(), curPort);
  72. }
  73. }
  74. //System.out.println(portMap);
  75. }
  76. //connect to the selected port in the combo box
  77. //pre: ports are already found by using the searchForPorts method
  78. //post: the connected comm port is stored in commPort, otherwise,
  79. //an exception is generated
  80. /**
  81. *This method opens the COM port with port parameters: Baudrate: 4800; databits: 8; Stopbit: 1; parity: none;
  82. */
  83. public void connect() {
  84. selectedPortIdentifier = (CommPortIdentifier) getPortMap().get(selectedPort);
  85. CommPort commPort = null;
  86. try {
  87. //the method below returns an object of type CommPort
  88. commPort = selectedPortIdentifier.open("TigerControlPanel", TIMEOUT);
  89. //the CommPort object can be casted to a SerialPort object
  90. serialPort = (SerialPort) commPort;
  91. serialPort.setSerialPortParams(4800, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
  92. //for controlling GUI elements
  93. setConnected(true);
  94. //logging
  95. logText = selectedPort + " opened successfully.";
  96. System.out.println(logText);
  97. //CODE ON SETTING BAUD RATE ETC OMITTED
  98. //XBEE PAIR ASSUMED TO HAVE SAME SETTINGS ALREADY
  99. } catch (PortInUseException e) {
  100. logText = selectedPort + " is in use. (" + e.toString() + ")";
  101. System.out.println(logText);
  102. } catch (Exception e) {
  103. logText = "Failed to open " + selectedPort + "(" + e.toString() + ")";
  104. System.out.println(logText);
  105. }
  106. }
  107. //open the input and output streams
  108. //pre: an open port
  109. //post: initialized intput and output streams for use to communicate data
  110. /**
  111. * This method initializes the serial IO stream,
  112. * after the init is complete the method sends an initialize command to the GRID+ controller
  113. * @return successful Boolean value which indicates whether the method was completed succesfuly
  114. */
  115. public boolean initIOStream() {
  116. //return value for whather opening the streams is successful or not
  117. boolean successful = false;
  118. try {
  119. //
  120. input = serialPort.getInputStream();
  121. output = serialPort.getOutputStream();
  122. writeData(0Xc0);
  123. successful = true;
  124. return successful;
  125. } catch (IOException e) {
  126. logText = "I/O Streams failed to open. (" + e.toString() + ")";
  127. System.out.println(logText);
  128. return successful;
  129. }
  130. }
  131. /**
  132. *This method disconnects the serial communication by first closing the serialPort and then closing the IOStreams
  133. *
  134. *
  135. */
  136. public void disconnect() {
  137. //close the serial port
  138. try {
  139. //serialPort.removeEventListener();
  140. serialPort.close();
  141. input.close();
  142. output.close();
  143. setConnected(false);
  144. logText = "Disconnected.";
  145. System.out.println(logText);
  146. } catch (IOException e) {
  147. logText = "Failed to close " + serialPort.getName() + "(" + e.toString() + ")";
  148. System.out.println(logText);
  149. }
  150. }
  151. /**
  152. * Returns true if the connection is open
  153. * False if closed
  154. * @return boolean value for the connection status
  155. */
  156. final public boolean getConnected() {
  157. return bConnected;
  158. }
  159. /**
  160. *Setter for the boolean value for the connection status
  161. * @param bConnected boolean value for the connection status
  162. */
  163. public void setConnected(boolean bConnected) {
  164. this.bConnected = bConnected;
  165. }
  166. //what happens when data is received
  167. //pre: serial event is triggered
  168. //post: processing on the data it reads
  169. /**
  170. * This method reads data from the input stream and puts it in a buffer
  171. * after the data is read the method waits 50 msec to make sure a new command doesn't follow up to quickly
  172. * This promotes stability in the program.
  173. *
  174. *
  175. */
  176. public void serialRead() throws InterruptedException {
  177. try {
  178. if (input.available() > 0) {
  179. try {
  180. setBuffer(new byte[1024]);
  181. setLeng(input.read(getBuffer()));
  182. // Debug.
  183. /*System.out.println("Length: " + getLeng());
  184. for (int itera = 0; itera < leng; itera++) {
  185. System.out.println("byte " + itera + ": " + Integer.toHexString(getBuffer(itera) & 0xFF));
  186. }*/
  187. } catch (Exception e) {
  188. logText = "Failed to read data. (" + e.toString() + ")";
  189. System.out.println(logText);
  190. }
  191. } else {
  192. logText = "Failed to read data. No data to read";
  193. //System.out.println(logText);
  194. }
  195. } catch (IOException e) {
  196. logText = "Failed to read data. (" + e.toString() + ")";
  197. System.out.println(logText);
  198. }
  199. //This prevents commands from being send too soon
  200. sleep(50);
  201. }
  202. //method that can be called to send data
  203. //pre: open serial port
  204. //post: data sent to the other device
  205. /**
  206. * This method sends a single byte command over the serial communication afterwards the method calls the read method
  207. * @param command a single byte command
  208. */
  209. public void writeData(int command) {
  210. try {
  211. output.write(command);
  212. sleep(20);
  213. serialRead();
  214. } catch (Exception e) {
  215. logText = "Failed to write data. (" + e.toString() + ")";
  216. System.out.println(logText);
  217. }
  218. }
  219. /**
  220. * This method sends a byte array command over the serial communication afterwards the method calls the read method
  221. * @param command an array of bytes as a command
  222. */
  223. public void writeData(byte[] command) {
  224. try {
  225. output.write(command);
  226. sleep(50);
  227. serialRead();
  228. } catch (Exception e) {
  229. logText = "Failed to write data. (" + e.toString() + ")";
  230. System.out.println(logText);
  231. }
  232. }
  233. /**
  234. * @return the leng
  235. */
  236. public int getLeng() {
  237. return leng;
  238. }
  239. /**
  240. * @param leng the leng to set
  241. */
  242. public void setLeng(int leng) {
  243. this.leng = leng;
  244. }
  245. /**
  246. * @return the buffer
  247. */
  248. public byte[] getBuffer() {
  249. return buffer;
  250. }
  251. /**
  252. *
  253. * @param i
  254. * @return The value of the buffer at i
  255. */
  256. public byte getBuffer(int i) {
  257. return buffer[i];
  258. }
  259. /**
  260. *
  261. * @return The second to last byte of the buffer
  262. */
  263. public byte getSecondToLast() {
  264. if (leng >= 2) {
  265. return buffer[leng - 2];
  266. } else {
  267. return 0;
  268. }
  269. }
  270. /**
  271. *
  272. * @return The last byte of the buffer
  273. */
  274. public byte getlast() {
  275. if (leng >= 2) {
  276. return buffer[leng - 1];
  277. } else {
  278. return 0;
  279. }
  280. }
  281. /**
  282. * @param buffer the buffer to set
  283. */
  284. public void setBuffer(byte[] buffer) {
  285. this.buffer = buffer;
  286. }
  287. /**
  288. * @return the portMap
  289. */
  290. public HashMap getPortMap() {
  291. return portMap;
  292. }
  293. }