scanCommon.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. import { Message } from 'element-ui';
  2. // 定义 WebSocket 和扫描客户端的通信模块
  3. const scanCommon = {
  4. // 扫描客户端WebSocket 服务器地址
  5. url: 'ws://127.0.0.1:9999',//扫描端口9999 图片服务端口9998
  6. // WebSocket 实例
  7. ws: null,
  8. // 当前客户端连接状态
  9. isOnline:false,
  10. isScanned:false,//是否有扫描仪 是否可以扫描
  11. // 心跳定时器
  12. timerPing: null,
  13. timerClose: null,
  14. connectionInterval:null,//监听连接状态变化的定时器
  15. // 心跳间隔时间(单位:毫秒)
  16. intervalPing: 10000, // 每隔10秒发送一次ping
  17. intervalClose: 5000, // 等待5秒未收到pong则判定断开
  18. isManuallyStopped:false,//是否手动停止,防止重复连接
  19. /**
  20. * 初始化 WebSocket 连接
  21. * @param {Function} callback - 接收扫描结果的回调函数
  22. */
  23. init(callback) {
  24. // Message({
  25. // type: 'success',
  26. // message: '扫描程序正在启动,请稍后……'
  27. // });
  28. try {
  29. this.ws = new WebSocket(this.url);
  30. } catch (error) {
  31. // console.error('WebSocket 初始化失败:', error);
  32. Message({
  33. type: 'error',
  34. message: '无法初始化 WebSocket 连接,请检查网络设置',
  35. duration: 5000
  36. });
  37. // if (callback) callback({ success: false, message: 'WebSocket 初始化失败' });
  38. return;
  39. }
  40. /**
  41. * WebSocket 连接建立成功时触发
  42. */
  43. this.ws.onopen = () => {
  44. this.isOnline = true;
  45. // 添加状态检查
  46. if (this.ws && this.ws.readyState === WebSocket.OPEN) {
  47. this.ws.send("client connect success");
  48. } else {
  49. // console.warn('WebSocket 尚未就绪,延迟发送消息');
  50. setTimeout(() => {
  51. if (this.ws && this.ws.readyState === WebSocket.OPEN) {
  52. this.ws.send("client connect success");
  53. }
  54. }, 500); // 延迟发送,等待连接真正建立
  55. }
  56. this.startHeartbeat(); // 启动心跳检测
  57. };
  58. /**
  59. * 接收到服务端消息时触发
  60. * @param {MessageEvent} evt - WebSocket 返回的消息事件对象
  61. */
  62. this.ws.onmessage = (evt) => {
  63. // console.log("打印扫描仪返回的 evt:", evt.data);
  64. if(evt.data!=null)
  65. {
  66. if (evt.data === "ping")
  67. {
  68. this.send("pong"); // 回复 pong
  69. } else if (evt.data === "pong")
  70. {
  71. // 收到 pong 不做处理
  72. } else {
  73. // try {
  74. const objectData = JSON.parse(evt.data);
  75. console.log("处理扫描结果的objectData:", objectData);
  76. if(objectData!=null)
  77. {
  78. if (objectData.code === 200)
  79. {
  80. if(objectData.action=='connectMessage')
  81. {
  82. Message({
  83. type: 'success',
  84. message: '客户端连接成功……'
  85. });
  86. }
  87. else if(objectData.action=='getScannerList')
  88. {
  89. //获取扫描仪结果
  90. // console.log("打印扫描仪返回的 objectData:", objectData);
  91. if(objectData.data.length>0)
  92. {
  93. //有扫描仪连接
  94. this.isScanned=true;
  95. Message({
  96. type: 'success',
  97. message: '扫描仪连接成功……'
  98. });
  99. }
  100. else
  101. {
  102. //没有扫描仪连接
  103. this.isScanned=false;
  104. }
  105. }
  106. else
  107. {
  108. callback(objectData); // 可选:通过回调函数返回扫描结果
  109. }
  110. }
  111. else if (objectData.code === 509)
  112. {
  113. // Message({
  114. // type: 'error',
  115. // message: '扫描仪未连接,请检查网络设置'
  116. // });
  117. callback(objectData); // 可选:通过回调函数返回扫描结果
  118. } else if (objectData.code === 502)
  119. {
  120. // Message({
  121. // type: 'error',
  122. // message: '未检测到纸张或卡纸'
  123. // });
  124. callback(objectData); // 可选:通过回调函数返回扫描结果
  125. // this.ws.close(); // 关闭链接
  126. }
  127. }
  128. // } catch (error) {
  129. // console.error("解析消息失败:", error);
  130. // }
  131. }
  132. }
  133. this.resetHeartbeat(); // 重置心跳
  134. };
  135. /**
  136. * WebSocket 连接关闭时触发
  137. */
  138. this.ws.onclose = () => {
  139. // console.log("连接关闭");
  140. // if(callback) callback({success: false, message: '客户端已关闭!'})
  141. this.handleOffline();
  142. };
  143. /**
  144. * WebSocket 发生错误时触发
  145. * @param {Event} evt - 错误事件对象
  146. */
  147. this.ws.onerror = (evt) => {
  148. // console.error("WebSocket 错误:", evt);
  149. // Message({
  150. // type: 'error',
  151. // message: 'WebSocket 发生错误,请检查扫描仪是否运行正常'
  152. // });
  153. // if(callback) callback({success: false, message: '客户端未启动!'})
  154. // console.log("扫描客户端未启动");
  155. this.isOnline=false;
  156. this.ws.close();
  157. };
  158. },
  159. /**
  160. * 发送消息给 WebSocket 服务端
  161. * @param {string} data - 要发送的消息内容
  162. */
  163. send(data) {
  164. if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
  165. // Message({
  166. // type: 'error',
  167. // message: '请确认扫描客户端是否已经启动',
  168. // duration: 5000
  169. // });
  170. return;
  171. }
  172. try {
  173. // console.log("发送数据:" + data);
  174. this.ws.send(data);
  175. } catch (e) {
  176. // console.error("发送数据失败:", e);
  177. Message({
  178. type: 'error',
  179. message: '发送数据失败,请检查连接状态',
  180. duration: 5000
  181. });
  182. }
  183. },
  184. /**
  185. * 启动心跳机制
  186. */
  187. startHeartbeat() {
  188. this.timerPing = setTimeout(() => {
  189. if (this.ws && this.ws.readyState === WebSocket.OPEN) {
  190. this.send("ping"); // 发送心跳 ping
  191. this.timerClose = setTimeout(() => {
  192. if (this.ws) {
  193. this.ws.close(); // 若长时间无响应,主动断开连接
  194. }
  195. this.isOnline = false;
  196. this.handleOffline(); // 处理离线逻辑
  197. }, this.intervalClose);
  198. }
  199. }, this.intervalPing);
  200. },
  201. /**
  202. * 重置心跳定时器
  203. */
  204. resetHeartbeat() {
  205. clearTimeout(this.timerPing);
  206. clearTimeout(this.timerClose);
  207. this.startHeartbeat(); // 重新启动心跳
  208. },
  209. /**
  210. * 停止 WebSocket 连接并清除所有定时器
  211. */
  212. stop() {
  213. // 清除心跳定时器
  214. clearTimeout(this.timerPing);
  215. clearTimeout(this.timerClose);
  216. // 清除连接状态监听定时器
  217. this.stopWatchingConnection();
  218. // 关闭 WebSocket 连接
  219. if (this.ws) {
  220. this.ws.onclose = () => {}; // 移除原有 onclose 处理
  221. this.ws.close(); // 主动关闭连接
  222. this.ws = null;
  223. }
  224. // 标记为手动停止,防止后续自动重连
  225. this.isManuallyStopped = true;
  226. // 重置连接状态
  227. this.isOnline = false;
  228. // console.log('WebSocket 已被手动停止');
  229. },
  230. /**
  231. * 处理设备离线逻辑,尝试自动重连
  232. */
  233. handleOffline() {
  234. // 如果是手动停止,则不再尝试重连
  235. if (this.isManuallyStopped) {
  236. return;
  237. }
  238. // console.log("客户端未开启,尝试重新连接...");
  239. // Message({
  240. // type: 'warning',
  241. // message: '扫描仪已断开连接,尝试重新连接...',
  242. // duration: 3000
  243. // });
  244. // console.log("当前连接状态",this.isOnline);
  245. this.isOnline=false;
  246. // 延迟尝试重连
  247. setTimeout(() => {
  248. if (!this.isOnline && !this.isManuallyStopped) {
  249. this.init(); // 重新初始化连接
  250. }
  251. }, this.intervalClose * 2);
  252. },
  253. /**
  254. * 检查客户端是否已连接
  255. * @returns {boolean}
  256. */
  257. isClientConnected() {
  258. return this.ws && this.ws.readyState === WebSocket.OPEN;
  259. },
  260. /**
  261. * 监听连接状态变化
  262. * @param {Function} callback - 回调函数,接收 isOnline 布尔值参数
  263. */
  264. watchConnection(callback) {
  265. if (this.connectionInterval) {
  266. clearInterval(this.connectionInterval); // 防止重复启动
  267. }
  268. const checkStatus = () => {
  269. const isOnline = this.isClientConnected();
  270. //调用检测扫描仪指令
  271. if(isOnline)
  272. {
  273. // console.log("开始检测扫描仪状态",this.isScanned);
  274. // console.log("开始检查客户端状态",isOnline);
  275. if(this.isScanned)
  276. {
  277. //有扫描仪连接 就不发送指令了
  278. }
  279. else
  280. {
  281. //没有扫描仪连接 实时发送指令获取状态
  282. let json={
  283. action:'getScannerList',//获取扫描仪信息
  284. };
  285. // console.log("发送指令获取扫描仪信息",json);
  286. this.ws.send(JSON.stringify(json));
  287. }
  288. callback(isOnline);//告诉网页 客户端打开状态
  289. }
  290. else
  291. {
  292. callback(false);//告诉网页 连接已经断开
  293. }
  294. };
  295. checkStatus(); // 立即执行一次
  296. this.connectionInterval = setInterval(checkStatus, 3000); // 每3秒检测一次
  297. },
  298. /**
  299. * 停止监听连接状态
  300. */
  301. stopWatchingConnection() {
  302. if (this.connectionInterval) {
  303. clearInterval(this.connectionInterval);
  304. this.connectionInterval = null;
  305. }
  306. }
  307. };
  308. export default scanCommon;