You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

445 lines
16 KiB

5 years ago
  1. // Generated by P Bennett: Monday, 4 October 1999 at: 05:24:32 pm
  2. // Com Port Handler.
  3. // I have released this code as a guide only.
  4. // It will not run without the supporting classes.
  5. // It was origanally written to communicate with a development prototype
  6. // and runs under Slackware Linux Version 4 with Blackdown jdk1.1.7_v3
  7. // Green Threads and rxtx version 3.4 with Java Comms API V2.0
  8. // This thread is controlled by a thread that implements a queue
  9. // and methods for controlling the queue and allocating the resources (modems)
  10. // The modem used for development was a Siemens M20 Cellular modem.
  11. // The remote equipment dumped its data upon connection and then hangs up.
  12. // The protocol has changed somewhat now. (A Subset of HDLC)
  13. // I have added extra comments for your benefit.
  14. // It is free to use.
  15. // Just a quick note. I have no formal training therefor the programming techniques
  16. // may not be the best ones to use. However the technique I use has been developed
  17. // through experience and it seems to work for me.
  18. import java.util.*;
  19. import java.io.*;
  20. import gnu.io.*; //Comms Extensions
  21. /** Class To Talk To A GSM Cellular Modem, Dial an SNU and retrieve the data.
  22. * Uses Java Comm API 2.0
  23. * @author P Bennett
  24. * @version 1.0
  25. * @see SNServerIO
  26. * @see SNComThread
  27. */
  28. public class SNComHandler extends java.lang.Thread implements
  29. SerialPortEventListener {
  30. private static SNComThread comThread; // A reference back to the parent.
  31. private static SNLogger comLog; // Log handler
  32. private static SNConfig serverConfig; // Server Configuration object
  33. private String comName = "Nil"; // The com port name to use as in /dev/ttyS0
  34. private boolean process = false; // Process a request
  35. private String requestId = "Nil"; // Request ID
  36. private String num = "Nil"; // The phone number to dial
  37. private boolean running = true; // Make it go around
  38. private CommPortIdentifier portId; // Port Identifier
  39. private SerialPort serialPort = null; // Serial Port object
  40. private OutputStream outputStream = null; // The streams
  41. private InputStream inputStream = null;
  42. private String errMessage = ""; // An error message
  43. private boolean fatalErr = false; // Big problems call the emergency team :-(
  44. private boolean waitForInput = true; // Wait for incoming data
  45. /** Construct a new SNComHandler Object..
  46. * For initialising the array of Com Handlers.
  47. * @see SNComThread
  48. */
  49. public SNComHandler() {
  50. }
  51. /** Construct a new SNComHandler Object.
  52. * Created with the following parameters.
  53. * @param cThread The parent thread.
  54. * @param sLog The Logging object.
  55. * @param sConfig The server config object.
  56. * @param cName The Com Port name eg. /dev/ttyS0
  57. * @see SNLogger
  58. * @see SNConfig
  59. */
  60. public SNComHandler(SNComThread cThread, SNLogger sLog, SNConfig
  61. sConfig, String cName) throws NoSuchPortException {
  62. this.comThread = cThread; // Parent thread
  63. this.comLog = sLog; // Log object
  64. this.serverConfig = sConfig; // Config object
  65. this.comName = cName; // The com port name
  66. portId =
  67. (CommPortIdentifier)CommPortIdentifier.getPortIdentifier(this.comName);
  68. // Set up the ID
  69. this.comLog.log("Com Handler Initialised For " + comName); // Log start
  70. }
  71. /** Thread run method
  72. * Call unit num, when requested and
  73. * pass the recieved data back to
  74. * the parent thread que.
  75. */
  76. public void run() {
  77. // comLog.debugInfo("Com Handler Run Method Started For " + comName);
  78. int resetCount = 0; // Reset attempts
  79. int resetCount2 = 0; // And again. There must be a better way
  80. int resetCount3 = 0; // And again. of doing this!!!! They are all the same.
  81. while (running) { // While we are doin it.
  82. if (fatalErr) { // Big problems
  83. comThread.queRequest(requestId, errMessage, "Error"); // Tell the parent
  84. comLog.log(errMessage + " " + comName + " " + num); // Tell everyone
  85. num = "Nil"; // Reset some variables
  86. resetCount = 0; // The error resets process
  87. resetCount2 = 0; // Round we go again.
  88. resetCount3 = 0;
  89. fatalErr = false;
  90. }
  91. if (!process) { // Nothing to do
  92. try {
  93. Thread.sleep(500); // Have a sleep
  94. } catch (InterruptedException e) {}
  95. continue; // Round we go again.
  96. }
  97. comLog.debugInfo("**********We Are Processing***********");
  98. if (num.equals("Nil")) { // Can't dial Nil!
  99. try { // Just a catch never tested
  100. Thread.sleep(500); // Have a sleep
  101. } catch (InterruptedException e) {} // Prolly does not work as intended
  102. continue; // Round we go again.
  103. }
  104. comLog.debugInfo("**********Trying To Open Port***********");
  105. if (!openPort()) { // Try to open port
  106. closePort(); // Try to close it then
  107. try {
  108. Thread.sleep(500); // Have a sleep
  109. } catch (InterruptedException e) {}
  110. resetCount ++; // Up the counter
  111. //***************** 3 goes in serverconfig ************************8
  112. if (resetCount > 3) { // Check the counter
  113. process = false; // We got problems
  114. errMessage = "Error! Could Not Open Port";
  115. fatalErr = true; // We got big problems
  116. }
  117. continue; // Round we go to sort it out
  118. }
  119. comLog.debugInfo("**********Trying To Reset Modem***********");
  120. if (!reset()) { // We got the port now reset the modem
  121. try {
  122. Thread.sleep(500); // Have a sleep
  123. } catch (InterruptedException e) {}
  124. resetCount2 ++; // Up the counter
  125. //***************** 3 goes in serverconfig ************************8
  126. if (resetCount2 > 3) { // Check the counter
  127. process = false; // We got problems
  128. errMessage = "Error! Could Not Reset Modem";
  129. fatalErr = true; // We got big problems
  130. }
  131. continue; // Round we go to sort it out
  132. }
  133. comLog.debugInfo("**********Trying To Dial***********");
  134. if (!dial()) { // The modem reset OK now dial
  135. comLog.debugInfo("**********" + errMessage + "***********");
  136. try {
  137. Thread.sleep(500); // Have a sleep
  138. } catch (InterruptedException e) {}
  139. resetCount3 ++; // Up the count
  140. //***************** 3 goes in serverconfig ************************8
  141. if (resetCount3 > 2) { // Check the count
  142. process = false; // We got problems
  143. errMessage = "Error! Could Not Dial";
  144. fatalErr = true; // We got big problems
  145. }
  146. continue; // Round we go to sort it out
  147. }
  148. int numBytes = 0; // Number of bytes read from input
  149. byte[] readBuffer = new byte[20]; // Tmp Read buffer of 20 bytes
  150. String sReadBuff = ""; // Read Buffer
  151. boolean dLoop = true; // Loop
  152. while (dLoop) { // Wait for incoming data
  153. try {
  154. while (inputStream.available() > 0) { // While there is something to read
  155. numBytes = inputStream.read(readBuffer); // Get the bytes
  156. String tmpR = new String(readBuffer); // Set up a string
  157. sReadBuff += tmpR.substring(0, numBytes); // Add to read buffer
  158. }
  159. } catch (IOException e) {
  160. dLoop = false; // Problems
  161. process = false; // This has never occured
  162. }
  163. if (sReadBuff.indexOf("NO CARRIER") != -1) { // Test incoming data
  164. errMessage = ""; // Unit hangs up once it
  165. dLoop = false; // dumps its data
  166. } else if (sReadBuff.indexOf("ERROR") != -1) { // Check for error
  167. errMessage = "Error! Recieved Data Not Clean " + num + " " + comName;
  168. dLoop = false;
  169. } else if (sReadBuff.length() > 5000) { // Check for receive runnaway
  170. errMessage = "";
  171. dLoop = false;
  172. }
  173. }
  174. if (errMessage.equals("")) { // No error occured
  175. comThread.queRequest(requestId, sReadBuff, "Ready"); // Tell the parent the result
  176. comLog.log("Data Recieved " + " " + requestId + " " + num); // Log it
  177. System.out.println("*********" + sReadBuff + "*********"); // Raw Debug code
  178. } else {
  179. if (!fatalErr) { // Error
  180. comThread.queRequest(requestId, errMessage, "Error"); // Tell parent
  181. comLog.log(errMessage + " " + comName + " " + num); // Log
  182. System.out.println("*********" + errMessage + "*********"); // Raw debug
  183. }
  184. }
  185. closePort(); // Close the port
  186. resetCount = 0; // Reset the variables ready for next request
  187. resetCount2 = 0;
  188. resetCount3 = 0;
  189. num = "Nil";
  190. process = false;
  191. }
  192. }
  193. /** Open Com Port
  194. * @return true if succesfull
  195. */
  196. private boolean openPort() {
  197. if (serialPort == null) { // Set up serial port object if need be
  198. comLog.debugInfo("**********Open Port Routine***********");
  199. try {
  200. serialPort = (SerialPort) portId.open("SimpleReadApp", 2000); // Open serial port
  201. comLog.debugInfo("**********Port Open***********");
  202. } catch (PortInUseException e) {
  203. return false; // Hmm its in use
  204. }
  205. if (inputStream == null) { // Set up the input stream if need be
  206. try {
  207. inputStream = serialPort.getInputStream(); // Get the stream
  208. } catch (IOException e) {
  209. return false;
  210. }
  211. }
  212. if (outputStream == null) { // Set up the output stream if need be
  213. try {
  214. outputStream = serialPort.getOutputStream(); // Get the stream
  215. } catch (IOException e) {
  216. return false;
  217. }
  218. }
  219. try {
  220. serialPort.addEventListener(this); // Add the event listener
  221. } catch (TooManyListenersException e) {
  222. return false;
  223. }
  224. serialPort.notifyOnDataAvailable(true); // Set the port to notify on incoming data
  225. //********* Maybe this goes in serverconfig maybe on a per port basis
  226. // Set the port parameters
  227. try {
  228. serialPort.setSerialPortParams(19200, SerialPort.DATABITS_8,
  229. SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
  230. } catch (UnsupportedCommOperationException e) {
  231. return false;
  232. }
  233. }
  234. return true; // Everything went ok
  235. }
  236. /** Close Com Port. */
  237. private void closePort() {
  238. if (serialPort != null) { // Check that the serial port is not null
  239. serialPort.notifyOnDataAvailable(false); // Close down notification
  240. serialPort.removeEventListener(); // Remove the event listener
  241. if (inputStream != null) { // Check for null
  242. try {
  243. inputStream.close(); // Close it
  244. inputStream = null; // Clean up
  245. }
  246. catch (IOException e) {}
  247. }
  248. if (outputStream != null) { // Check for null
  249. try {
  250. outputStream.close(); // Close it
  251. outputStream = null; // Clean up
  252. }
  253. catch (IOException e) {}
  254. }
  255. serialPort.close(); // Close the serial port
  256. serialPort = null; // Clean up
  257. }
  258. }
  259. /** Reset The Modem
  260. * @return true if succesfull.
  261. */
  262. private boolean reset() {
  263. try {
  264. outputStream.write(new String("atz").getBytes()); // Send the modem atz
  265. outputStream.write((byte)0x0D); // And the other stuff
  266. outputStream.write((byte)0x0A); // <CR> <LF>
  267. } catch (IOException e) {
  268. return false;
  269. }
  270. int waitingCount = 0; // Heres another counter
  271. waitForInput = true; // We are waiting
  272. while (waitForInput) { // Yes we are
  273. try {
  274. Thread.sleep(100); // We have a little rest
  275. } catch (InterruptedException e) {}
  276. waitingCount ++; // We count
  277. //***************** 20 goes in serverconfig ************************
  278. if (waitingCount > 20) { // We have counted to much
  279. return false; // Could not reset
  280. }
  281. }
  282. int numBytes = 0; // Set up number of bytes read
  283. byte[] readBuffer = new byte[20]; // And a buffer
  284. String sReadBuff = ""; // And another buffer
  285. try {
  286. while (inputStream.available() > 0) {
  287. numBytes = inputStream.read(readBuffer); // Read from the port
  288. String tmpR = new String(readBuffer);
  289. sReadBuff += tmpR.substring(0, numBytes);
  290. }
  291. } catch (IOException e) {
  292. return false;
  293. }
  294. //********************Maybe for serverconfig
  295. if (sReadBuff.indexOf("OK") != -1) { // Test for OK response from modem
  296. try {
  297. Thread.sleep(1000); // We have another sleep to allow things
  298. } catch (InterruptedException e) {} // to settle
  299. return true;
  300. }
  301. return false; // We did not reset OK
  302. }
  303. /** Dial number requested
  304. * @return true if connected
  305. */
  306. private boolean dial() {
  307. try {
  308. comLog.debugInfo("**********" + num + "***********");
  309. outputStream.write(new String("atd").getBytes()); // Send atd
  310. outputStream.write(num.getBytes()); // And the number
  311. outputStream.write((byte)0x0D); // And the other stuff
  312. outputStream.write((byte)0x0A);
  313. } catch (IOException e) {
  314. errMessage = "Error! Could Not Write To Port ";
  315. comLog.debugInfo("**********Error Writing***********");
  316. return false; // Bad could not write
  317. }
  318. int waitingCount = 0; // We are counting again
  319. waitForInput = true; // Waiting
  320. while (waitForInput) {
  321. try {
  322. Thread.sleep(100); // Have a sleep
  323. } catch (InterruptedException e) {}
  324. waitingCount ++; // Counting
  325. //**************** For serverconfig ************************
  326. if (waitingCount > 200) { // Counted to much
  327. errMessage = "Error! Timed Out Waiting For Response";
  328. return false; // Timed out
  329. }
  330. }
  331. int numBytes = 0; // Set up for reading
  332. byte[] readBuffer = new byte[20]; // Youve seen it before
  333. String sReadBuff = ""; // The comments are getting thinner
  334. boolean dLoop = true; // No need to repeat
  335. while (dLoop) {
  336. try {
  337. while (inputStream.available() > 0) {
  338. numBytes = inputStream.read(readBuffer);
  339. String tmpR = new String(readBuffer);
  340. sReadBuff += tmpR.substring(0, numBytes); // We read it
  341. }
  342. if (sReadBuff.indexOf("NO CARRIER") != -1) { // Out of area
  343. errMessage = "Error! No Carrier";
  344. return false;
  345. } else if (sReadBuff.indexOf("BUSY") != -1) { // Busy
  346. errMessage = "Error! Busy"; // Who is ringing our units
  347. return false; // Maybe it is dialing out
  348. } else if (sReadBuff.indexOf("NO DIAL TONE") != -1) { // Bad no signal
  349. errMessage = "Error! No Dial Tone"; // Were has the ariel gone
  350. return false;
  351. } else if (sReadBuff.indexOf("OK") != -1) { // Hmm voice call no good
  352. errMessage = "Error! Voice Call";
  353. return false;
  354. } else if (sReadBuff.indexOf("CONNECT") != -1) { // Ah this is what we want
  355. return true; // Return true
  356. }
  357. } catch (IOException e) {
  358. errMessage = "Error! Could Not Read From Com Port";
  359. return false; // Bad but never happened yet
  360. }
  361. }
  362. errMessage = "Error! Invalid Data " + sReadBuff;
  363. return false; // Something has gone wrong
  364. }
  365. /** Serial Event Routine
  366. * Set waitForInput to false when data ready
  367. */
  368. public void serialEvent(SerialPortEvent event) {
  369. switch(event.getEventType()) {
  370. case SerialPortEvent.BI:
  371. case SerialPortEvent.OE:
  372. case SerialPortEvent.FE:
  373. case SerialPortEvent.PE:
  374. case SerialPortEvent.CD:
  375. case SerialPortEvent.CTS:
  376. case SerialPortEvent.DSR:
  377. case SerialPortEvent.RI:
  378. case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
  379. break;
  380. case SerialPortEvent.DATA_AVAILABLE:
  381. waitForInput = false; // We got incoming
  382. break; // Thats it for serial events
  383. }
  384. }
  385. /** Process Request To Call SNU.
  386. * Request that a call be made and the data
  387. * returned to the controlling thread.
  388. * @see SNComThread
  389. */
  390. public void processRequest(String req, String num) {
  391. requestId = req; // Set ID
  392. this.num = num; // Set the phone number
  393. process = true; // Make it go
  394. }
  395. /** Is Processing Call
  396. * @return true if thread is busy
  397. * @see SNComThread
  398. */
  399. public boolean isProcessing() {
  400. return process; // Are you busy
  401. }
  402. /** Is Processing This Q Id.
  403. * @param qID The ID to test for
  404. * @return true if the thread is processing qID
  405. * @see SNComThread
  406. */
  407. public boolean isProcessing(String qID) {
  408. return requestId.equals(qID); // Are you busy doing this job
  409. }
  410. }
  411. /* the following was added so the code will compile. Its not proper */
  412. class SNLogger
  413. {
  414. public void debugInfo(java.lang.String it)
  415. {
  416. }
  417. public void log(java.lang.String it)
  418. {
  419. }
  420. }
  421. class SNComThread
  422. {
  423. public void queRequest(java.lang.String a, java.lang.String b, java.lang.String c)
  424. {
  425. }
  426. }
  427. class SNConfig
  428. {
  429. }