Browse Source

软硬件绑定

zhangjie 4 years ago
parent
commit
0b09ec3147
53 changed files with 392 additions and 2 deletions
  1. BIN
      extra/artControl/ArtControl.exe
  2. BIN
      extra/artControl/D3Dcompiler_47.dll
  3. BIN
      extra/artControl/Qt5Core.dll
  4. BIN
      extra/artControl/Qt5Gui.dll
  5. BIN
      extra/artControl/Qt5Network.dll
  6. BIN
      extra/artControl/Qt5Svg.dll
  7. BIN
      extra/artControl/Qt5Widgets.dll
  8. BIN
      extra/artControl/bearer/qgenericbearer.dll
  9. BIN
      extra/artControl/bearer/qnativewifibearer.dll
  10. 2 0
      extra/artControl/config.ini
  11. BIN
      extra/artControl/iconengines/qsvgicon.dll
  12. BIN
      extra/artControl/imageformats/qdds.dll
  13. BIN
      extra/artControl/imageformats/qgif.dll
  14. BIN
      extra/artControl/imageformats/qicns.dll
  15. BIN
      extra/artControl/imageformats/qico.dll
  16. BIN
      extra/artControl/imageformats/qjpeg.dll
  17. BIN
      extra/artControl/imageformats/qsvg.dll
  18. BIN
      extra/artControl/imageformats/qtga.dll
  19. BIN
      extra/artControl/imageformats/qtiff.dll
  20. BIN
      extra/artControl/imageformats/qwbmp.dll
  21. BIN
      extra/artControl/imageformats/qwebp.dll
  22. BIN
      extra/artControl/images/LED_0.png
  23. BIN
      extra/artControl/images/LED_1.png
  24. BIN
      extra/artControl/images/tubiao.png
  25. BIN
      extra/artControl/libEGL.dll
  26. BIN
      extra/artControl/libGLESV2.dll
  27. BIN
      extra/artControl/libgcc_s_dw2-1.dll
  28. BIN
      extra/artControl/libstdc++-6.dll
  29. BIN
      extra/artControl/libwinpthread-1.dll
  30. BIN
      extra/artControl/opengl32sw.dll
  31. BIN
      extra/artControl/platforms/qwindows.dll
  32. BIN
      extra/artControl/translations/qt_ca.qm
  33. BIN
      extra/artControl/translations/qt_cs.qm
  34. BIN
      extra/artControl/translations/qt_de.qm
  35. BIN
      extra/artControl/translations/qt_en.qm
  36. BIN
      extra/artControl/translations/qt_fi.qm
  37. BIN
      extra/artControl/translations/qt_fr.qm
  38. BIN
      extra/artControl/translations/qt_he.qm
  39. BIN
      extra/artControl/translations/qt_hu.qm
  40. BIN
      extra/artControl/translations/qt_it.qm
  41. BIN
      extra/artControl/translations/qt_ja.qm
  42. BIN
      extra/artControl/translations/qt_ko.qm
  43. BIN
      extra/artControl/translations/qt_lv.qm
  44. BIN
      extra/artControl/translations/qt_ru.qm
  45. BIN
      extra/artControl/translations/qt_sk.qm
  46. BIN
      extra/artControl/translations/qt_uk.qm
  47. 23 0
      src/App.vue
  48. 2 0
      src/background.js
  49. 5 0
      src/plugins/env.js
  50. 332 0
      src/plugins/hardwareCheck.js
  51. 17 2
      src/store.js
  52. 10 0
      src/views/Login.vue
  53. 1 0
      vue.config.js

BIN
extra/artControl/ArtControl.exe


BIN
extra/artControl/D3Dcompiler_47.dll


BIN
extra/artControl/Qt5Core.dll


BIN
extra/artControl/Qt5Gui.dll


BIN
extra/artControl/Qt5Network.dll


BIN
extra/artControl/Qt5Svg.dll


BIN
extra/artControl/Qt5Widgets.dll


BIN
extra/artControl/bearer/qgenericbearer.dll


BIN
extra/artControl/bearer/qnativewifibearer.dll


+ 2 - 0
extra/artControl/config.ini

@@ -0,0 +1,2 @@
+[TCP_S_SerialNumber]
+TCP_S_SerialNumber=COM1

BIN
extra/artControl/iconengines/qsvgicon.dll


BIN
extra/artControl/imageformats/qdds.dll


BIN
extra/artControl/imageformats/qgif.dll


BIN
extra/artControl/imageformats/qicns.dll


BIN
extra/artControl/imageformats/qico.dll


BIN
extra/artControl/imageformats/qjpeg.dll


BIN
extra/artControl/imageformats/qsvg.dll


BIN
extra/artControl/imageformats/qtga.dll


BIN
extra/artControl/imageformats/qtiff.dll


BIN
extra/artControl/imageformats/qwbmp.dll


BIN
extra/artControl/imageformats/qwebp.dll


BIN
extra/artControl/images/LED_0.png


BIN
extra/artControl/images/LED_1.png


BIN
extra/artControl/images/tubiao.png


BIN
extra/artControl/libEGL.dll


BIN
extra/artControl/libGLESV2.dll


BIN
extra/artControl/libgcc_s_dw2-1.dll


BIN
extra/artControl/libstdc++-6.dll


BIN
extra/artControl/libwinpthread-1.dll


BIN
extra/artControl/opengl32sw.dll


BIN
extra/artControl/platforms/qwindows.dll


BIN
extra/artControl/translations/qt_ca.qm


BIN
extra/artControl/translations/qt_cs.qm


BIN
extra/artControl/translations/qt_de.qm


BIN
extra/artControl/translations/qt_en.qm


BIN
extra/artControl/translations/qt_fi.qm


BIN
extra/artControl/translations/qt_fr.qm


BIN
extra/artControl/translations/qt_he.qm


BIN
extra/artControl/translations/qt_hu.qm


BIN
extra/artControl/translations/qt_it.qm


BIN
extra/artControl/translations/qt_ja.qm


BIN
extra/artControl/translations/qt_ko.qm


BIN
extra/artControl/translations/qt_lv.qm


BIN
extra/artControl/translations/qt_ru.qm


BIN
extra/artControl/translations/qt_sk.qm


BIN
extra/artControl/translations/qt_uk.qm


+ 23 - 0
src/App.vue

@@ -4,3 +4,26 @@
     <router-view />
     <router-view />
   </div>
   </div>
 </template>
 </template>
+
+<script>
+export default {
+  name: "app",
+  data() {
+    return {};
+  },
+  computed: {
+    hardwareCheckResult() {
+      return this.$store.state.hardwareCheckResult;
+    }
+  },
+  watch: {
+    hardwareCheckResult(val) {
+      if (val.success) {
+        console.log("成功!");
+      } else {
+        console.error("失败!");
+      }
+    }
+  }
+};
+</script>

+ 2 - 0
src/background.js

@@ -6,6 +6,7 @@ import {
   /* installVueDevtools */
   /* installVueDevtools */
 } from "vue-cli-plugin-electron-builder/lib";
 } from "vue-cli-plugin-electron-builder/lib";
 import { closeEncryptCheck } from "./plugins/encryptProcess";
 import { closeEncryptCheck } from "./plugins/encryptProcess";
+import { stopConnect } from "./plugins/hardwareCheck";
 const isDevelopment = process.env.NODE_ENV !== "production";
 const isDevelopment = process.env.NODE_ENV !== "production";
 
 
 // Keep a global reference of the window object, if you don't, the window will
 // Keep a global reference of the window object, if you don't, the window will
@@ -49,6 +50,7 @@ function createWindow() {
 
 
 ipcMain.on("close-window", async () => {
 ipcMain.on("close-window", async () => {
   await closeEncryptCheck();
   await closeEncryptCheck();
+  stopConnect();
   app.quit();
   app.quit();
 });
 });
 
 

+ 5 - 0
src/plugins/env.js

@@ -63,6 +63,10 @@ function getEncryptPath() {
   return path.join(getExtraDir("encrypt"), "msyjencrypt.exe");
   return path.join(getExtraDir("encrypt"), "msyjencrypt.exe");
 }
 }
 
 
+function getHardwareCheckPath() {
+  return path.join(getExtraDir("artControl"), "ArtControl.exe");
+}
+
 /**
 /**
  *
  *
  * @param {String} pathContent 目录路径
  * @param {String} pathContent 目录路径
@@ -115,5 +119,6 @@ export {
   getImgDecodeTool,
   getImgDecodeTool,
   getFontPath,
   getFontPath,
   getEncryptPath,
   getEncryptPath,
+  getHardwareCheckPath,
   initConfigData
   initConfigData
 };
 };

+ 332 - 0
src/plugins/hardwareCheck.js

@@ -0,0 +1,332 @@
+import { getHardwareCheckPath } from "./env";
+const path = require("path");
+const net = require("net");
+const childProcess = require("child_process");
+
+// const isDevelopment = process.env.NODE_ENV !== "production";
+const hardwareCheckTool = getHardwareCheckPath();
+const hardwareCheckToolDir = path.dirname(hardwareCheckTool);
+// const HOST = "192.168.11.143";
+const HOST = "127.0.0.1";
+const PORT = "7013";
+const TIMESTAMP_BASE = "2000/01/01 00:00:00";
+
+let tcpClient = null;
+// 是否要停止硬件设备
+let needStartHardware = true;
+// 上位机软件进程
+let hardwareProcess = null;
+
+/**
+ * 十六进制字符转十进制数
+ * @param {String} str 十六进制字符
+ */
+function hexToInt(str) {
+  return parseInt(str, 16);
+}
+/**
+ * 十进制数转十六进制字符
+ * @param {Number} number 十进制数
+ */
+function intToHex(number) {
+  const hex = number.toString(16);
+  return hex.length < 2 ? `0` + hex : hex;
+}
+
+/**
+ * 分割字符串
+ * @param {String} str 字符串
+ * @param {Number} len 片段长度
+ */
+function splitStr(str, len = 2) {
+  let arrs = [];
+  let spinCount = Math.ceil(str.length / len);
+  for (let i = 0; i < spinCount; i++) {
+    arrs[i] = str.slice(i * len, (i + 1) * len);
+  }
+  return arrs;
+}
+
+/**
+ * 创建自定义crc16
+ * @param {Array} arr 数组
+ * @returns hex string
+ */
+function createCrc16(arr) {
+  let tcrc = 0xffff;
+  for (let i = 0, len = arr.length; i < len; i++) {
+    tcrc ^= "0x" + arr[i];
+    for (let j = 0; j < 8; j++) {
+      if (tcrc & 0x0001) {
+        tcrc >>= 1;
+        tcrc = tcrc & 0x7fff;
+        tcrc ^= 0xd164;
+      } else {
+        tcrc >>= 1;
+        tcrc = tcrc & 0x7fff;
+      }
+    }
+  }
+  tcrc ^= 0x7013;
+  tcrc = intToHex(tcrc);
+  return tcrc.slice(-2) + tcrc.slice(0, 2);
+}
+/**
+ * 创建解密自定义crc16
+ * @param {Array} arr 数组
+ * @returns hex string
+ */
+function createDecrytCrc16(arr) {
+  let tcrc = 0xffff;
+  for (let i = 0, len = arr.length; i < len; i++) {
+    tcrc ^= "0x" + arr[i];
+    for (let j = 0; j < 8; j++) {
+      if (tcrc & 0x0001) {
+        tcrc >>= 1;
+        tcrc = tcrc & 0x7fff;
+        tcrc ^= 0xc641;
+      } else {
+        tcrc >>= 1;
+        tcrc = tcrc & 0x7fff;
+      }
+    }
+  }
+  tcrc ^= 0x673d;
+  tcrc = intToHex(tcrc);
+  return tcrc.slice(-2) + tcrc.slice(0, 2);
+}
+
+function addCircle(num1, num2) {
+  const num = num1 + num2;
+  return num > 256 ? num - 256 : num;
+}
+
+function parseHardwareCode(content) {
+  return {
+    pre: content.slice(0, 2),
+    id: content.slice(2, 14),
+    timestamp: content.slice(14, 22),
+    code: content.slice(22, 34),
+    encryptTypeData: content.slice(34, 46),
+    customCrc16: content.slice(-4)
+  };
+}
+
+function getEncryptType(encryptTypeData) {
+  const total = splitStr(encryptTypeData).reduce(
+    (sum, num) => sum + hexToInt(num),
+    0
+  );
+  return total % 9;
+}
+
+function getEncryptNums(data, encryptType) {
+  const [n1, n2, n3, n4, n5, n6] = splitStr(data).map(num => hexToInt(num));
+  let encryptNums = [];
+  switch (encryptType) {
+    case 0:
+      encryptNums = [n1 + 3, n3 + 2, n2 + 7];
+      break;
+    case 1:
+      encryptNums = [n2 + 4, n4 + 4, n3 + 9];
+      break;
+    case 2:
+      encryptNums = [n3 + 5, n4 + 6, n2 + 1];
+      break;
+    case 3:
+      encryptNums = [n4 + 6, n5 + 0, n1 + 3];
+      break;
+    case 4:
+      encryptNums = [n5 + 7, n4 + 1, n2 + 5];
+      break;
+    case 5:
+      encryptNums = [n6 + 8, n1 + 3, n1 + 5];
+      break;
+    case 6:
+      encryptNums = [n2 + 9, n3 + 5, n1 + 3];
+      break;
+    case 7:
+      encryptNums = [n2 + 2, n6 + 7, n1 + 2];
+      break;
+    case 8:
+      encryptNums = [n4 + 1, n2 + 6, n2 + 1];
+      break;
+
+    default:
+      break;
+  }
+  return encryptNums;
+}
+
+function getDecryptCode(code, encryptNums) {
+  let ucTempMac = splitStr(code).map(num => hexToInt(num));
+  let ucCheckIdReturn = "";
+  ucTempMac[0] = addCircle(ucTempMac[0], encryptNums[0]);
+  ucTempMac[1] = addCircle(ucTempMac[1], encryptNums[0]);
+  ucCheckIdReturn = createDecrytCrc16(ucTempMac.map(num => intToHex(num)));
+  ucTempMac[2] = addCircle(ucTempMac[2], encryptNums[1]);
+  ucTempMac[3] = addCircle(ucTempMac[3], encryptNums[1]);
+  ucCheckIdReturn += createDecrytCrc16(ucTempMac.map(num => intToHex(num)));
+  ucTempMac[4] = addCircle(ucTempMac[4], encryptNums[2]);
+  ucTempMac[5] = addCircle(ucTempMac[5], encryptNums[2]);
+  ucCheckIdReturn += createDecrytCrc16(ucTempMac.map(num => intToHex(num)));
+  return ucCheckIdReturn;
+}
+
+function getAnswerCode(codes) {
+  const encryptType = getEncryptType(codes.encryptTypeData);
+  // console.log("encryptType:", encryptType);
+  const nums = getEncryptNums(codes.encryptTypeData, encryptType);
+  // console.log("EncryptNums:", nums);
+  const decryptCode = getDecryptCode(codes.code, nums);
+  // console.log("decryptCode:", decryptCode);
+  const answerCode = [codes.pre, codes.id, codes.timestamp, decryptCode].join(
+    ""
+  );
+  const checkCode = createCrc16(splitStr(answerCode));
+  // console.log(checkCode);
+
+  return [answerCode, checkCode].join("");
+}
+
+function checkTimestamp(timestamp) {
+  const time = hexToInt(timestamp);
+  const timeNow = new Date(time * 1000 + new Date(TIMESTAMP_BASE).getTime());
+  const now = new Date().getTime();
+
+  const deviation = 5000; // 5s范围内都是合法
+  return timeNow < now + deviation && timeNow > now - deviation;
+}
+
+//
+const checkToolIsStart = () => {
+  return new Promise((resolve, reject) => {
+    const cmd = process.platform === "win32" ? "tasklist" : "ps aux";
+    childProcess.exec(cmd, (err, stdout, stderr) => {
+      if (err) {
+        reject(err);
+        return;
+      }
+
+      const toolInfo = stdout.split("\n").find(line => {
+        return line.toLowerCase().includes("ArtControl.exe");
+      });
+      if (toolInfo) {
+        console.log(toolInfo);
+        resolve(toolInfo);
+      } else {
+        resolve("none");
+      }
+    });
+  });
+};
+
+const startHardwareCheckProcess = () => {
+  return new Promise((resolve, reject) => {
+    try {
+      hardwareProcess = childProcess.spawn(`${hardwareCheckTool}`, {
+        cwd: hardwareCheckToolDir
+      });
+      hardwareProcess.on("close", (code, signal) => {
+        console.log(`hardware machine over!${signal}`);
+      });
+      hardwareProcess.on("error", () => {
+        console.log(`hardware machine error!`);
+      });
+    } catch (error) {
+      reject(error);
+    }
+    // 检测工具是个持续进程,调用时无法获取进程开启成功信息。
+    // 目前延时2000ms处理。
+    setTimeout(() => {
+      resolve(true);
+    }, 2000);
+  });
+};
+
+const startHardwareCheckTool = async () => {
+  const res = await checkToolIsStart().catch(error => {
+    console.error(error);
+  });
+  if (!res) return Promise.reject("error");
+
+  if (res === "none") {
+    return startHardwareCheckProcess();
+  }
+  return Promise.resolve(true);
+};
+
+// tcp
+async function startConnect(resultCallback) {
+  // if (isDevelopment) {
+  //   return;
+  // }
+  const res = await startHardwareCheckTool().catch(error => {
+    console.error(error);
+    resultCallback({ success: false, type: "start", error });
+  });
+  if (!res) return;
+
+  stopConnect();
+
+  tcpClient = net.createConnection({
+    host: HOST,
+    port: PORT
+  });
+
+  tcpClient.on("connect", () => {
+    tcpClient.write(Buffer.from("efef", "hex"));
+    resultCallback({ success: true, type: "connect" });
+  });
+
+  tcpClient.on("data", data => {
+    if (!needStartHardware) return;
+
+    const content = data.toString("hex");
+    // console.log(content);
+    const codes = parseHardwareCode(content);
+    if (!checkTimestamp(codes.timestamp)) {
+      console.error("time error");
+      resultCallback({ success: false, type: "data", error: "超时" });
+      return;
+    }
+
+    const answerCode = getAnswerCode(codes);
+    // console.log(answerCode);
+    tcpClient.write(Buffer.from(answerCode, "hex"));
+    resultCallback({ success: true, type: "data" });
+  });
+
+  tcpClient.on("error", error => {
+    console.error(error);
+    resultCallback({ success: false, type: "connect", error });
+  });
+}
+
+function stopConnect() {
+  if (!tcpClient) return;
+  if (hardwareProcess) hardwareProcess.kill();
+  tcpClient.pause();
+  tcpClient.destroy();
+  tcpClient = null;
+}
+
+/**
+ * 控制硬件设备开关
+ * @param {Boolean} open 是否开启设备
+ */
+function swithHardware(open) {
+  needStartHardware = !!open;
+}
+
+function testParse(content) {
+  console.log(content);
+  // const customCrc16 = createCrc16(splitStr(content).slice(0, -2));
+  // console.log(customCrc16);
+  // const codes = parseHardwareCode(content);
+  const codes = parseHardwareCode(content);
+  const answerCode = getAnswerCode(codes);
+  console.log(answerCode);
+}
+
+export { startConnect, stopConnect, swithHardware, testParse };

+ 17 - 2
src/store.js

@@ -1,5 +1,6 @@
 import Vue from "vue";
 import Vue from "vue";
 import Vuex from "vuex";
 import Vuex from "vuex";
+import { startConnect, stopConnect } from "@/plugins/hardwareCheck";
 
 
 Vue.use(Vuex);
 Vue.use(Vuex);
 
 
@@ -8,14 +9,28 @@ import client from "./modules/client/store";
 
 
 export default new Vuex.Store({
 export default new Vuex.Store({
   state: {
   state: {
-    user: {}
+    user: {},
+    // 硬件检测结果
+    hardwareCheckResult: {}
   },
   },
   mutations: {
   mutations: {
     setUser(state, user) {
     setUser(state, user) {
       state.user = user;
       state.user = user;
+    },
+    setHardwareCheckResult(state, hardwareCheckResult) {
+      state.hardwareCheckResult = hardwareCheckResult;
+    }
+  },
+  actions: {
+    checkHardware({ commit }) {
+      startConnect(result => {
+        commit("setHardwareCheckResult", result);
+      });
+    },
+    stopHardware() {
+      stopConnect();
     }
     }
   },
   },
-  actions: {},
   modules: {
   modules: {
     client
     client
   }
   }

+ 10 - 0
src/views/Login.vue

@@ -104,6 +104,7 @@ export default {
     }
     }
   },
   },
   mounted() {
   mounted() {
+    this.closeHardware();
     this.$ls.clear();
     this.$ls.clear();
     this.initData();
     this.initData();
     this.tocCheckEncrypt();
     this.tocCheckEncrypt();
@@ -149,6 +150,7 @@ export default {
 
 
       this.$ls.set("user", data);
       this.$ls.set("user", data);
       this.$ls.set("organizationId", data.organizationId);
       this.$ls.set("organizationId", data.organizationId);
+      this.checkHardware();
       this.$store.commit("setUser", data);
       this.$store.commit("setUser", data);
       this.$store.commit("client/setClientConfig", {
       this.$store.commit("client/setClientConfig", {
         imageEncrypt: data.paramSetting.imageEncrypt,
         imageEncrypt: data.paramSetting.imageEncrypt,
@@ -164,6 +166,14 @@ export default {
       //   name: "PaperExport"
       //   name: "PaperExport"
       // });
       // });
     },
     },
+    // 软硬件绑定
+    checkHardware() {
+      return this.$store.dispatch("checkHardware");
+    },
+    closeHardware() {
+      return this.$store.dispatch("stopHardware");
+    },
+    // 加密狗
     tocCheckEncrypt() {
     tocCheckEncrypt() {
       this.exceptionIsConfirm = true;
       this.exceptionIsConfirm = true;
       this.loading = true;
       this.loading = true;

+ 1 - 0
vue.config.js

@@ -22,6 +22,7 @@ var config = {
           "extra/imagemagick/**",
           "extra/imagemagick/**",
           "extra/zxing/**",
           "extra/zxing/**",
           "extra/zxingA/**",
           "extra/zxingA/**",
+          "extra/artControl/**",
           "extra/database/org.rdb",
           "extra/database/org.rdb",
           "config.sample.json",
           "config.sample.json",
           "sense_shield_installer_pub_2.2.0.46331.exe"
           "sense_shield_installer_pub_2.2.0.46331.exe"