修改过页面
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.

882 lines
27 KiB

1 year ago
  1. const serial = chrome.serial;
  2. var showDebugLog = false;
  3. var SerialConnection = function() {
  4. this.connectionId = -1;
  5. this.boundOnReceive = this.onReceive.bind(this);
  6. this.boundOnReceiveError = this.onReceiveError.bind(this);
  7. this.onConnect = new MyEvent();
  8. this.onReceive = new MyEvent();
  9. this.onError = new MyEvent();
  10. this.recvBuffer = new Uint8Array(8*1024);
  11. this.recvView = new DataView(this.recvBuffer.buffer);
  12. this.recvCursor = 0;
  13. this.bitrate = 57600;
  14. };
  15. SerialConnection.prototype.onConnectComplete = function(connectionInfo) {
  16. if (!connectionInfo) {
  17. if (chrome.runtime.lastError != undefined) {
  18. logln('chrome.serial.connect error: ' + chrome.runtime.lastError.message);
  19. }
  20. return;
  21. }
  22. this.connectionId = connectionInfo.connectionId;
  23. chrome.serial.onReceive.addListener(this.boundOnReceive);
  24. chrome.serial.onReceiveError.addListener(this.boundOnReceiveError);
  25. this.onConnect.dispatch();
  26. };
  27. SerialConnection.prototype.onReceive = function(receiveInfo) {
  28. if (receiveInfo.connectionId !== this.connectionId) {
  29. return;
  30. }
  31. this.recvBuffer.set(new Uint8Array(receiveInfo.data), this.recvCursor);
  32. this.recvCursor += receiveInfo.data.byteLength;
  33. //console.log(buf2hex(receiveInfo.data));
  34. if (this.recvCursor < 6) {
  35. return;
  36. }
  37. this._dispathReceiveData();
  38. };
  39. SerialConnection.prototype.clearRecvData = function() {
  40. this.recvCursor = 0;
  41. this.recvBuffer.fill(0);
  42. }
  43. SerialConnection.prototype._dispathReceiveData = function() {
  44. var dLen = this.recvView.getUint16(7);
  45. if (this.recvCursor < dLen + 9) {
  46. return;
  47. }
  48. var dataBuffer = new Uint8Array(dLen + 9);
  49. dataBuffer.set(this.recvBuffer.subarray(0, dLen + 9));
  50. if (showDebugLog) {
  51. logln("recv: " + buf2hex(dataBuffer.buffer));
  52. }
  53. var realCrc = calcCRC(dataBuffer, 6, dLen + 7);
  54. var crc = dataBuffer[dLen+7] * 256 + dataBuffer[dLen+8];
  55. if (crc != realCrc) {
  56. logln("invalid crc " + crc + " ,real= " + realCrc);
  57. }else {
  58. var packet = new Packet().fromDataBuffer(dataBuffer);
  59. this.onReceive.dispatch(packet);
  60. }
  61. if (this.recvCursor > dLen + 9) {
  62. dataBuffer = new Uint8Array(this.recvCursor - dLen - 6);
  63. dataBuffer.set(this.recvBuffer.subarray(dLen + 9, this.recvCursor));
  64. this.recvBuffer.fill(0);
  65. this.recvBuffer.set(dataBuffer);
  66. this.recvCursor -= dLen + 9;
  67. this._dispathReceiveData();
  68. }else {
  69. this.recvCursor = 0;
  70. this.recvBuffer.fill(0);
  71. }
  72. }
  73. SerialConnection.prototype.onReceiveError = function(errorInfo) {
  74. if (errorInfo.connectionId === this.connectionId) {
  75. this.onError.dispatch(errorInfo.error);
  76. }
  77. };
  78. SerialConnection.prototype.update = function(conf, cb) {
  79. if (!this.connectionId) {return;}
  80. serial.update(this.connectionId, conf, cb);
  81. }
  82. SerialConnection.prototype.connect = function(path, bitrate=57600) {
  83. this.clearRecvData();
  84. this.bitrate = bitrate;
  85. serial.connect(path, { bitrate: this.bitrate },this.onConnectComplete.bind(this))
  86. };
  87. SerialConnection.prototype.send = function(packet) {
  88. if (this.connectionId < 0) {
  89. throw 'Invalid connection';
  90. }
  91. var data = packet.getDataBuffer();
  92. if (showDebugLog) {
  93. logln("send: " + buf2hex(data));
  94. }
  95. serial.send(this.connectionId, data, function() {});
  96. };
  97. SerialConnection.prototype.disconnect = function() {
  98. if (this.connectionId < 0) {
  99. throw 'Invalid connection';
  100. }
  101. serial.disconnect(this.connectionId, function() {});
  102. };
  103. ////////////////////////////////////////////////////////
  104. ////////////////////////////////////////////////////////
  105. function logln(msg) {
  106. var buffer = document.querySelector('#buffer');
  107. buffer.innerHTML += msg + '<br/>';
  108. var msgEnd = document.querySelector('#msg_end');
  109. msgEnd.scrollIntoView();
  110. }
  111. function log(msg) {
  112. var buffer = document.querySelector('#buffer');
  113. buffer.innerHTML += msg;
  114. var msgEnd = document.querySelector('#msg_end');
  115. msgEnd.scrollIntoView();
  116. }
  117. function buf2hex(buffer) {
  118. return '0x' + Array.prototype.map.call(new Uint8Array(buffer), x => ('0x00' + x.toString(16)).slice(-2)).join(' 0x');
  119. }
  120. function calcCRC(buffer, start, end) {
  121. var crc = 0;
  122. for (var i = start; i < end; i++) {
  123. crc += buffer[i] & 0xff;
  124. }
  125. return crc & 0xffff;
  126. }
  127. const PacketTypeCmd = 0x01;
  128. const PacketTypeData = 0x02;
  129. const PacketTypeDataEnd = 0x08;
  130. const PacketTypeCmdResp = 0x07;
  131. const PacketTypeDataResp = 0x09;
  132. var Packet = function(data=new Uint8Array([0x35]), dataLen=1, type=PacketTypeCmd) {
  133. this.dataBuffer = new Uint8Array(512);
  134. this.dataBuffer.set([0xEF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF]);
  135. this.type = type;
  136. this.dataLen = dataLen;
  137. this.data = data;
  138. this.result = 0;
  139. }
  140. Packet.prototype.setCmd = function(cmd) {
  141. this.type = PacketTypeCmd;
  142. this.data = Uint8Array.of(cmd);
  143. this.dataLen = 1;
  144. }
  145. Packet.prototype.getDataBuffer = function () {
  146. var dataView = new DataView(this.dataBuffer.buffer);
  147. dataView.setUint8(6, this.type);
  148. var len = this.dataLen + 2;
  149. dataView.setUint16(7, len);
  150. this.dataBuffer.set(this.data, 9);
  151. var crc = calcCRC(this.dataBuffer, 6, this.dataLen + 9);
  152. dataView.setUint16(9 + this.dataLen, crc);
  153. return new Uint8Array(this.dataBuffer.buffer, 0, this.dataLen + 11);
  154. }
  155. Packet.prototype.fromDataBuffer = function(buffer) {
  156. this.dataBuffer.set(buffer);
  157. var dataView = new DataView(this.dataBuffer.buffer);
  158. this.type = dataView.getUint8(6);
  159. var len = dataView.getUint16(7);
  160. this.dataLen = len - 2;
  161. this.data = new Uint8Array(buffer.buffer, 9, this.dataLen);
  162. if (this.type == PacketTypeCmdResp) {
  163. this.result = this.data[0];
  164. }
  165. return this;
  166. }
  167. ////////////////////////////////////////////////////////
  168. ////////////////////////////////////////////////////////
  169. var curDevice = null;
  170. function tryHandshake(device) {
  171. return new Promise((resolve, reject) =>{
  172. logln("try handshake with " + device.path);
  173. var connection = new SerialConnection();
  174. var isValidDevice = 0;
  175. device.bitrate = 57600;
  176. connection.onConnect.addListener(function() {
  177. logln("device " + device.path + " connected");
  178. connection.send(new Packet());
  179. });
  180. connection.onReceive.addListener(function(packet) {
  181. if (packet.type == PacketTypeCmdResp && packet.result == 0) {
  182. isValidDevice = 1;
  183. connection.disconnect();
  184. resolve(1)
  185. }
  186. });
  187. connection.connect(device.path, device.bitrate);
  188. setTimeout(() => {
  189. if (isValidDevice) {
  190. }else {
  191. device.bitrate = 115200;
  192. connection.update({
  193. bitrate: device.bitrate
  194. }, (result) => {
  195. if (result) {
  196. connection.send(new Packet());
  197. setTimeout(() => {
  198. connection.disconnect();
  199. if (!isValidDevice) {
  200. resolve(0);
  201. }
  202. }, 500);
  203. }else {
  204. connection.disconnect();
  205. resolve(0);
  206. }
  207. })
  208. }
  209. }, 500);
  210. })
  211. }
  212. async function checkDevices(devices) {
  213. for (var device of devices) {
  214. logln("found device, path = " + device.path);
  215. var res = await tryHandshake(device);
  216. if (res) {
  217. curDevice = device;
  218. logln("found valid device " + device.path);
  219. break;
  220. }
  221. }
  222. }
  223. ////////////////////////////////////////////////////////
  224. var EnrollSchedule = function(device, enrollCount=6, callback=((err=null, step=0, state=0, data=null)=>{}), timeout = 60 * 1000) {
  225. this.step = 0;
  226. this.enrollCount = enrollCount;
  227. this.callback = callback;
  228. this.device = device;
  229. this.connection = null;
  230. this.timeout = timeout;
  231. this.timeoutFlag = 0;
  232. this.responseTime = 1000;
  233. this.responseTimeout = 0;
  234. this.responseCallback = null;
  235. this.canceled = false;
  236. }
  237. const STATE_WAIT_FINGER_DOWN = 1;
  238. const STATE_WAIT_FINGER_LEAVE = 2;
  239. const STATE_FINGER_DOWN = 3;
  240. const STATE_FINGER_LEAVE = 4;
  241. const STATE_EXTRACT_TEMPLATE = 5;
  242. const STATE_DOWNLOAD_TEMPLATE = 6;
  243. const STATE_EXTRACT_TEMPLATE_FAIL = 100;
  244. const STATE_EXTRACT_TEMPLATE_DIRTY = 101;
  245. const STATE_EXTRACT_TEMPLATE_POINTS_FEW = 102;
  246. const STATE_EXTRACT_TEMPLATE_MERGE_FAIL = 103;
  247. const ErrorReceiveDataErr = 1;
  248. const ErrorEnrollTimeout = 2;
  249. const ErrorDeviceNotFound = 3;
  250. const ErrorEmptyFail = 4;
  251. function printError(err) {
  252. logln( "enroll err with code: " + err);
  253. }
  254. EnrollSchedule.prototype.start = async function() {
  255. this.step = 0;
  256. this.canceled = false;
  257. try {
  258. await this._connect();
  259. if(this.canceled) { return this._disConnect(); }
  260. var ret = await this._sendAndWaitRecvCmd(0x0d);
  261. if (ret == 0x11) {
  262. throw ErrorEmptyFail;
  263. }
  264. while(this.step < this.enrollCount) {
  265. this.step += 1;
  266. ret = await this._enrollOne(this.step);
  267. if (ret) {
  268. let stateErr = STATE_EXTRACT_TEMPLATE_FAIL;
  269. if(ret == 0x06) {
  270. stateErr = STATE_EXTRACT_TEMPLATE_DIRTY;
  271. }else if (ret == 0x07) {
  272. stateErr = STATE_EXTRACT_TEMPLATE_POINTS_FEW;
  273. }else if (ret == 0x0a) {
  274. stateErr = STATE_EXTRACT_TEMPLATE_MERGE_FAIL;
  275. }
  276. this.callback(null, this.step, stateErr, null);
  277. this.step -= 1;
  278. }
  279. if(this.canceled) { return this._disConnect(); }
  280. }
  281. logln("receive tempalte");
  282. this.callback(null, this.step, STATE_DOWNLOAD_TEMPLATE, null);
  283. var ret = await this._mergeTemplate();
  284. if(this.canceled) { return this._disConnect(); }
  285. var recvBuffer = await this._receiveTemplate();
  286. if(this.canceled) { return this._disConnect(); }
  287. this.callback(null, this.step, 0, recvBuffer);
  288. }catch(e) {
  289. this.callback(e, this.step, 0, null);
  290. }
  291. this._disConnect();
  292. }
  293. EnrollSchedule.prototype._mergeTemplate = function() {
  294. return this._sendAndWaitRecvCmd(0x05);
  295. }
  296. EnrollSchedule.prototype._receiveTemplate = function() {
  297. return new Promise((resolve, reject) => {
  298. var that = this;
  299. var data = Uint8Array.of(0x08, 0x01);
  300. var packet = new Packet(data, 2);
  301. var recvDataLen = 4 * 1024 * 1024;
  302. var recvData = new Uint8Array(recvDataLen);
  303. var recvDataCursor = 0;
  304. var resetTimeoutCheck = function() {
  305. if (that.responseTimeout) {
  306. clearTimeout(that.responseTimeout);
  307. }
  308. that.responseTimeout = setTimeout(() => {
  309. var dummy = new Packet();
  310. that.connection.send(dummy);
  311. that.responseTimeout = setTimeout(() => {
  312. reject(ErrorReceiveDataErr);
  313. }, that.responseTime);
  314. }, that.responseTime);
  315. }
  316. this.responseCallback = (packet) => {
  317. resetTimeoutCheck();
  318. if (packet.type == PacketTypeCmdResp) {
  319. }else if (packet.type == PacketTypeData || packet.type == PacketTypeDataEnd) {
  320. if (recvDataCursor + packet.dataLen < recvDataLen) {
  321. recvData.set(packet.data, recvDataCursor);
  322. recvDataCursor += packet.dataLen;
  323. }else {
  324. if (that.responseTimeout) {
  325. clearTimeout(that.responseTimeout);
  326. }
  327. reject("recv buffer full");
  328. }
  329. }
  330. if (packet.type == PacketTypeDataEnd) {
  331. if (that.responseTimeout) {
  332. clearTimeout(that.responseTimeout);
  333. }
  334. resolve(recvData.slice(0, recvDataCursor));
  335. }
  336. }
  337. this.connection.send(packet);
  338. resetTimeoutCheck();
  339. });
  340. }
  341. EnrollSchedule.prototype._sendAndWaitRecvCmd = function(cmd) {
  342. return new Promise((resolve, reject) =>{
  343. var packet = new Packet();
  344. packet.setCmd(cmd);
  345. this._sendAndWaitRecv(packet).then(packet => {
  346. if (packet.type == PacketTypeCmdResp) {
  347. resolve(packet.result);
  348. }
  349. }).catch(err => {
  350. reject(err);
  351. });
  352. });
  353. }
  354. EnrollSchedule.prototype._enrollOne = async function(step) {
  355. var down = false;
  356. var leave = false;
  357. var isTimeout = false;
  358. this.timeoutFlag = setTimeout(() => {
  359. if (!down) {
  360. isTimeout = true;
  361. }
  362. }, this.timeout);
  363. //wait finger leave
  364. logln("wait leave")
  365. this.callback(null, this.step, STATE_WAIT_FINGER_LEAVE, null);
  366. while (leave == false && !isTimeout) {
  367. if(this.canceled) { return; }
  368. leave = !(await this.captureOne());
  369. }
  370. this.callback(null, this.step, STATE_FINGER_LEAVE, null);
  371. if (isTimeout) {
  372. throw ErrorEnrollTimeout;
  373. }
  374. this.callback(null, this.step, STATE_WAIT_FINGER_DOWN, null);
  375. //wait finger down
  376. logln("wait down")
  377. while (!down && !isTimeout) {
  378. if(this.canceled) { return; }
  379. down = await this.captureOne();
  380. }
  381. if (isTimeout) {
  382. throw ErrorEnrollTimeout;
  383. }
  384. this.callback(null, this.step, STATE_FINGER_DOWN, null);
  385. logln("finger down step = " + step);
  386. if(this.canceled) { return; }
  387. this.callback(null, this.step, STATE_EXTRACT_TEMPLATE, null);
  388. var ret = await this.extractOne(step);
  389. if (ret != 0) {
  390. logln("extract tempate err " + ret);
  391. return ret;
  392. }
  393. return 0;
  394. }
  395. EnrollSchedule.prototype.extractOne = function(step) {
  396. return new Promise((resolve, reject) =>{
  397. var data = Uint8Array.of(0x02, step);
  398. var packet = new Packet(data, 2);
  399. this._sendAndWaitRecv(packet).then(packet => {
  400. if (packet.type == PacketTypeCmdResp) {
  401. resolve(packet.result);
  402. }
  403. }).catch(err => {
  404. reject(err);
  405. });
  406. });
  407. }
  408. EnrollSchedule.prototype.captureOne = function() {
  409. return new Promise((resolve, reject) => {
  410. var packet = new Packet();
  411. packet.setCmd(0x01);
  412. this._sendAndWaitRecv(packet).then(packet => {
  413. if (packet.type == PacketTypeCmdResp) {
  414. resolve(packet.result == 0);
  415. }
  416. }).catch(err => {
  417. reject(err);
  418. });
  419. });
  420. }
  421. EnrollSchedule.prototype._sendAndWaitRecv = function(packet) {
  422. return new Promise((resolve, reject) => {
  423. var that = this;
  424. this.responseCallback = (packet) => {
  425. if (packet.type == PacketTypeCmdResp) {
  426. if (that.responseTimeout) {
  427. clearTimeout(that.responseTimeout);
  428. that.responseTimeout = 0;
  429. }
  430. if (packet.result == 0x01) {
  431. reject(ErrorReceiveDataErr);
  432. }else {
  433. resolve(packet);
  434. }
  435. }
  436. }
  437. this.connection.send(packet);
  438. this.responseTimeout = setTimeout(() => {
  439. that.connection.send(packet);
  440. this.responseTimeout = setTimeout(() => {
  441. reject(ErrorReceiveDataErr);
  442. }, this.responseTime);
  443. }, this.responseTime);
  444. });
  445. }
  446. EnrollSchedule.prototype._resolvePacket = function(packet) {
  447. if (this.responseCallback) {
  448. this.responseCallback(packet);
  449. }
  450. }
  451. EnrollSchedule.prototype._connect = function() {
  452. return new Promise((resolve, reject) => {
  453. var that = this;
  454. this.connection = new SerialConnection();
  455. this.connection.onConnect.addListener(function() {
  456. logln("device " + that.device.path + " connected");
  457. resolve();
  458. });
  459. this.connection.onReceive.addListener(function(packet) {
  460. that._resolvePacket(packet);
  461. });
  462. this.connection.connect(this.device.path, this.device.bitrate);
  463. setTimeout(() => {
  464. reject("connect timeout");
  465. }, 500);
  466. });
  467. }
  468. EnrollSchedule.prototype._disConnect = function() {
  469. if (this.connection) {
  470. this.connection.disconnect();
  471. this.connection = null;
  472. }
  473. if (this.responseTimeout) {
  474. clearTimeout(this.responseTimeout);
  475. this.responseTimeout = 0;
  476. }
  477. if (this.timeoutFlag) {
  478. clearTimeout(this.timeoutFlag);
  479. this.timeoutFlag = 0;
  480. }
  481. }
  482. EnrollSchedule.prototype.stop = function() {
  483. this.canceled = true;
  484. }
  485. var enrollSchedule = null;
  486. var tempData = null;
  487. function startEnroll(enrollCount=6, timeout=10*1000, cb) {
  488. if (!curDevice) {
  489. logln("device not found");
  490. cb.call(null, {
  491. err: ErrorDeviceNotFound
  492. }, 0, null);
  493. return;
  494. }
  495. enrollSchedule = new EnrollSchedule(curDevice, enrollCount, (err, step, state, data) => {
  496. if (err) {
  497. printError(status.err);
  498. }
  499. if(cb) {
  500. cb.call(null, {
  501. err: err,
  502. state: state,
  503. step: step,
  504. data: data
  505. });
  506. }
  507. if (data) {
  508. tempData = data;
  509. }
  510. }, timeout);
  511. logln("start enroll");
  512. enrollSchedule.start();
  513. }
  514. function stopEnroll() {
  515. if (enrollSchedule) {
  516. enrollSchedule.stop();
  517. enrollSchedule = null;
  518. }
  519. }
  520. ////////////////////////////////////////////////////////
  521. //test
  522. EnrollSchedule.prototype.sleep = function(time) {
  523. return new Promise((resolve, reject) => {
  524. setTimeout(() => {
  525. resolve();
  526. }, time);
  527. });
  528. }
  529. EnrollSchedule.prototype.downloadTemplate = async function(data) {
  530. var cmdData = Uint8Array.of(0x09, 0x02);
  531. var packet = new Packet(cmdData, 2);
  532. this.connection.send(packet);
  533. await this.sleep(1000);
  534. var dataLength = data.length;
  535. var packetLen = 256;
  536. var sendCursor = 0;
  537. var sendLen = 0;
  538. var sendType = PacketTypeData;
  539. logln("downloading");
  540. while (sendCursor < dataLength) {
  541. sendLen = (dataLength-sendCursor > packetLen) ? packetLen : (dataLength-sendCursor);
  542. sendType = (dataLength-sendCursor > packetLen) ? PacketTypeData : PacketTypeDataEnd;
  543. var sendData = new Uint8Array(data.buffer, sendCursor, sendLen);
  544. var dataPack = new Packet(sendData, sendLen, sendType);
  545. this.connection.send(dataPack);
  546. console.log("send "+ sendLen)
  547. log('.');
  548. sendCursor += sendLen;
  549. await this.sleep(100);
  550. }
  551. cmdData = Uint8Array.of(0x06, 0x02, 0x00, 0x03);
  552. packet = new Packet(cmdData, 4);
  553. this.connection.send(packet);
  554. logln('.');
  555. await this.sleep(500);
  556. }
  557. async function downloadTemplate() {
  558. if (!curDevice) {
  559. var err = "device not found";
  560. logln(err);
  561. return;
  562. }
  563. if (!tempData) {
  564. var err = "please enroll";
  565. logln(err);
  566. return;
  567. }
  568. var enroll = new EnrollSchedule(curDevice);
  569. try {
  570. await enroll._connect();
  571. await enroll.downloadTemplate(tempData);
  572. logln("download complete");
  573. }catch(err) {
  574. logln("download err: " + err);
  575. }
  576. await enroll._disConnect();
  577. }
  578. async function matchTemplate() {
  579. if (!curDevice) {
  580. var err = "device not found";
  581. logln(err);
  582. return;
  583. }
  584. var enroll = new EnrollSchedule(curDevice);
  585. try {
  586. await enroll._connect();
  587. await enroll._enrollOne(1);
  588. var packData = Uint8Array.of(0x04, 0x01, 0x00, 0x03, 0x00, 0x03);
  589. var packet = new Packet(packData, 6);
  590. await new Promise((resolve, reject) =>{
  591. enroll._sendAndWaitRecv(packet).then(packet => {
  592. if (packet.type == PacketTypeCmdResp) {
  593. if(packet.result) {
  594. logln("match fail");
  595. }else {
  596. logln("match success score " + (packet.data[3] * 256 + packet.data[4]));
  597. }
  598. resolve();
  599. }
  600. }).catch(err => {
  601. reject("match err: " + err);
  602. });
  603. })
  604. }catch(err) {
  605. logln("download err: " + err);
  606. }
  607. await enroll._disConnect();
  608. }
  609. ////////////////////////////////////////////////////////
  610. ////////////////////////////////////////////////////////
  611. function disableAll() {
  612. document.querySelector("#enroll").disabled = true;
  613. document.querySelector("#down").disabled = true;
  614. document.querySelector("#match").disabled = true;
  615. document.querySelector("#refresh").disabled = true;
  616. document.querySelector("#export").disabled = true;
  617. document.querySelector("#import").disabled = true;
  618. }
  619. function enableAll() {
  620. document.querySelector("#enroll").disabled = false;
  621. document.querySelector("#down").disabled = false;
  622. document.querySelector("#match").disabled = false;
  623. document.querySelector("#refresh").disabled = false;
  624. document.querySelector("#export").disabled = false;
  625. document.querySelector("#import").disabled = false;
  626. }
  627. var server = null;
  628. onload = function() {
  629. document.querySelector('#show-log').checked = showDebugLog;
  630. document.querySelector('#show-log').onchange = function(e) {
  631. showDebugLog = e.target.checked;
  632. }
  633. document.querySelector('#enroll').onclick = function(e) {
  634. if (e.currentTarget.innerText == "Enroll") {
  635. e.currentTarget.innerText = "Stop";
  636. startEnroll(6, 10* 1000, (status) => {
  637. console.log(status.step);
  638. if (status.err) {
  639. console.log(status.err);
  640. }
  641. if (status.err || status.data) {
  642. document.querySelector('#enroll').innerText = "Enroll";
  643. }
  644. if (status.data) {
  645. // console.log(data);
  646. // console.log(buf2hex(data.buffer));
  647. }
  648. });
  649. }else {
  650. e.currentTarget.innerText = "Enroll";
  651. stopEnroll();
  652. }
  653. }
  654. document.querySelector('.msg').style="height:" + (window.innerHeight - 70) + "px";
  655. chrome.serial.getDevices((devices) => {
  656. checkDevices(devices);
  657. });
  658. document.querySelector("#down").onclick = async function(e) {
  659. disableAll();
  660. try {
  661. await downloadTemplate();
  662. }catch(err) {
  663. logln("download err: " + err);
  664. }
  665. enableAll();
  666. }
  667. document.querySelector("#match").onclick = async function(e) {
  668. disableAll();
  669. try {
  670. await matchTemplate();
  671. }catch(err) {
  672. logln("match err: " + err);
  673. }
  674. enableAll();
  675. }
  676. document.querySelector("#refresh").onclick = function(e) {
  677. disableAll();
  678. chrome.serial.getDevices(async function(devices) {
  679. try {
  680. await checkDevices(devices);
  681. }catch (e) {
  682. console.log(e)
  683. }
  684. enableAll();
  685. });
  686. }
  687. document.querySelector("#export").onclick = function(e) {
  688. if (!tempData) {
  689. logln("please enroll");
  690. return;
  691. }
  692. let reader = new FileReader();
  693. reader.onload = function(eve) {
  694. if (eve.target.readyState == FileReader.DONE)
  695. {
  696. let a = document.createElement('a');
  697. a.download = "mafp_template.bin";
  698. a.href = this.result;
  699. a.click();
  700. }
  701. }
  702. reader.readAsDataURL(new Blob([tempData]));
  703. }
  704. document.querySelector("#import").onclick = function(e) {
  705. let fileInput = document.querySelector("#import-file");
  706. fileInput.value = "";
  707. fileInput.click();
  708. }
  709. document.querySelector("#import-file").onchange = function(e) {
  710. let files = e.target.files;
  711. if (files && files.length) {
  712. let reader = new FileReader();
  713. reader.onload = async function(ev) {
  714. if (ev.total == 4096) {
  715. tempData = new Uint8Array(this.result);
  716. disableAll();
  717. try {
  718. await downloadTemplate();
  719. }catch(err) {
  720. logln("download err: " + err);
  721. }
  722. enableAll();
  723. }else {
  724. logln("invalid file length " + ev.total);
  725. }
  726. }
  727. reader.readAsArrayBuffer(files[0]);
  728. }
  729. }
  730. const port = 9897;
  731. if (http.Server && http.WebSocketServer) {
  732. server = new http.Server();
  733. var wsServer = new http.WebSocketServer(server);
  734. server.listen(port);
  735. logln("ws socket server listen at " + port);
  736. var connectedSocket = null;
  737. wsServer.addEventListener('request', function(req) {
  738. if (connectedSocket) {
  739. req.reject();
  740. return;
  741. }
  742. console.log('Client connected');
  743. var socket = req.accept();
  744. connectedSocket = socket;
  745. socket.addEventListener('message', function(e) {
  746. var reqData = JSON.parse(e.data);
  747. if (reqData.cmd == "enrollStart") {
  748. startEnroll(reqData.config.enrollCount,
  749. reqData.config.enrollTimeout,
  750. (status) =>{
  751. var resp = {
  752. err: status.err ? status.err : "",
  753. state: status.state ? status.state : 0,
  754. step: status.step
  755. }
  756. if (status.data) {
  757. resp.data = Array.from(status.data);
  758. }
  759. connectedSocket.send(JSON.stringify(resp));
  760. });
  761. }else if (reqData.cmd == "enrollCancel") {
  762. stopEnroll();
  763. }
  764. });
  765. socket.addEventListener('close', function() {
  766. connectedSocket = null;
  767. stopEnroll();
  768. console.log('Client disconnected');
  769. if (chrome.runtime.lastError != undefined) {
  770. console.log(chrome.runtime.lastError.message);
  771. }
  772. });
  773. return true;
  774. });
  775. }
  776. };
  777. onresize = function(e) {
  778. document.querySelector('.msg').style="height:" + (e.currentTarget.innerHeight - 70) + "px";
  779. document.querySelector('#msg_end').scrollIntoView();
  780. }