handler.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. 'use strict'
  2. import { ipcRenderer } from 'electron';
  3. import SerialPort from 'serialport';
  4. const serials = {};
  5. const ids = ipcRenderer.sendSync('windowsid', 'already');
  6. /* ************ Functions ************ */
  7. /**
  8. * Parse a incoming a list of messages of ports, & divide into two parts, based
  9. * on connected boards.
  10. * @param {Array} list A list of messages of ports
  11. * @returns {Object} A object which contains two arrays
  12. */
  13. function parsePorts(list) {
  14. let result = { boards: [], wifi: [] };
  15. list.forEach(val => {
  16. let mf = val.manufacturer;
  17. if (mf) {
  18. // if (mf.indexOf('Arduino') > -1)
  19. // result.boards.push(val);
  20. if (mf.indexOf('ftdi') > -1)
  21. result.wifi.push(val);
  22. }
  23. });
  24. return result;
  25. }
  26. /**
  27. * Handle error, & send error back to the previous process.
  28. * @param {Error} err Incoming error
  29. * @param {string} event Event name
  30. * @param {Array<string|number>} data Data to send
  31. * @returns {void} void
  32. */
  33. function errorHandler(err, event, sid = '', data = []) {
  34. ipcRenderer.sendTo(ids[0], 'error', err, event, sid, data);
  35. return;
  36. }
  37. /**
  38. * Handle list event & return a set of messages of connected boards.
  39. * @returns {void} void
  40. */
  41. function listHandler() {
  42. SerialPort.list()
  43. .then(result => {
  44. let res = parsePorts(result);
  45. ipcRenderer.sendTo(ids[0], 'result_list', res);
  46. })
  47. .catch(err => errorHandler(err, 'list'));
  48. return;
  49. }
  50. /**
  51. * Handle open command, & receive messages from board.
  52. * @param {string} sid Socket's id
  53. * @param {string} comName Name of port
  54. * @param {number} baudRate Number of baud rate
  55. * @returns {void} void
  56. */
  57. function openHandler(e, sid, comName, baudRate = 9600) {
  58. const serial = new SerialPort(comName, { baudRate: baudRate }, err => {
  59. if (!err) {
  60. ipcRenderer.sendTo(ids[0], 'result_open', sid, comName, baudRate);
  61. serial.on('readable', () => {
  62. let str = serial.read();
  63. str instanceof Buffer ? str = str.toString('utf-8') : '';
  64. ipcRenderer.sendTo(ids[0], 'message', sid, str);
  65. })
  66. serials[sid] = serial;
  67. } else
  68. errorHandler(err, 'open', sid);
  69. });
  70. return;
  71. }
  72. /**
  73. * Handle close command, & close the communication.
  74. * @param {string} sid Socket's id
  75. * @returns {void} void
  76. */
  77. function closeHandler(e, sid) {
  78. const serial = serials[sid];
  79. if (serial && serial.isOpen)
  80. serial.close(err => {
  81. if (!err) {
  82. delete serials[sid];
  83. ipcRenderer.sendTo(ids[0], 'result_close', sid)
  84. } else
  85. errorHandler(err, 'close', sid);
  86. return;
  87. });
  88. }
  89. /**
  90. * Handle send command, & send a message to board.
  91. * @param {string} sid Socket's id
  92. * @param {string} msg Incoming message
  93. * @param {string} postfix Postfix of sending message
  94. * @returns {void} void
  95. */
  96. function sendHandler(e, sid, msg, postfix = '') {
  97. const serial = serials[sid];
  98. if (serial && serial.isOpen) {
  99. if (postfix === 'nl')
  100. postfix = '\n';
  101. else if (postfix === 'cr')
  102. postfix = '\r';
  103. else if (postfix === 'blc')
  104. postfix = '\n\r';
  105. msg += postfix;
  106. serial.write(msg, 'utf-8', e => console.warn(e));
  107. }
  108. return;
  109. }
  110. /**
  111. * Handle update command, & update the communication to a specific
  112. * baud rate.
  113. * @param {string} sid Socket's id
  114. * @param {number} baudRate Baud rate to update to
  115. * @returns {void} void
  116. */
  117. function updateHandler(e, sid, baudRate) {
  118. const serial = serials[sid];
  119. if (serial && serial.isOpen) {
  120. serial.update({ baudRate: baudRate }, err => {
  121. err ?
  122. errorHandler(err, 'update', sid, [baudRate]) :
  123. ipcRenderer.sendTo(ids[0], 'result_update', sid, baudRate);
  124. });
  125. }
  126. return;
  127. }
  128. /**
  129. * Parse a incoming a list of messages of ports, & compare with list map, &
  130. * check if it's get new boards connected.
  131. * @param {Array<string>} map An array with comNames
  132. * @returns {void} void
  133. */
  134. function detectListChange(map) {
  135. SerialPort.list()
  136. .then(result => {
  137. let is_changed = false, comNames = [], res = { boards: [], wifi: [] };
  138. result.forEach(val => {
  139. if (val.manufacturer) {
  140. if (val.manufacturer.toLocaleLowerCase().indexOf('ftdi') > -1)
  141. res.wifi.push(val);
  142. // else if (val.manufacturer.toLocaleLowerCase().indexOf('silicon') > -1)
  143. // res.wifi.push(val);
  144. comNames.push(val.comName);
  145. }
  146. });
  147. if (comNames.length !== map.length)
  148. is_changed = true;
  149. else {
  150. for (let i = 0; i < comNames.length; i++)
  151. if (map.indexOf(comNames[i]) < 0) {
  152. is_changed = true;
  153. break;
  154. }
  155. }
  156. if (is_changed) {
  157. ipcRenderer.sendTo(ids[0], 'result_list', res);
  158. map.length = 0;
  159. comNames.forEach(val => {
  160. map.push(val);
  161. });
  162. }
  163. })
  164. .catch(err => errorHandler(err, 'list'));
  165. return;
  166. }
  167. /**
  168. * Run detectListChange function every 3 secs.
  169. * @returns {void} void
  170. */
  171. function loopDetectListChange() {
  172. let listMap = [];
  173. setInterval(() => {
  174. detectListChange(listMap);
  175. }, 3000);
  176. }
  177. // ------ bind functions to ipcRenderer's events ------ //
  178. ipcRenderer.on('handle_list', listHandler);
  179. ipcRenderer.on('handle_open', openHandler);
  180. ipcRenderer.on('handle_close', closeHandler);
  181. ipcRenderer.on('handle_send', sendHandler);
  182. ipcRenderer.on('handle_update', updateHandler);
  183. ipcRenderer.on('disconnect', sid => {
  184. const serial = serials[sid];
  185. serial ? delete serials[sid] : '';
  186. return;
  187. });
  188. loopDetectListChange();