123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 |
- const sm4 = require('./sm4.js');
- const common_vendor = require("../../../common/vendor.js");
- var wx = common_vendor.index
- var OBUNo = '';
- const key = '1A70B8BE26C994DA88F4712F5E60C738';
- var phoneRandom = '';
- var encrypDeviceRandom = '';
- var myDeviceId;
- // 蓝牙连接相关参数
- var Service, notifyCharacteristicsId, writeCharacteristicsId, readCharacteristicsId;
- //回调函数
- let CallBackInfo = null;
- let CallBackToQT = null;
- let CallBackInfoForconnected = null;
- var framNo = 0;
- var outDevices = new Array();
-
- //当前是第几条命令
- var currentCmdId = 0;
- //需要执行的命令总数
- var cmdTotal;
- //返回的命令数组;
- var outCmdArr = new Array();
- //输入的命令数组
- var inCmdArr = new Array();
- //命令类型
- var globalCmdType = '01';
- //复位状态:0未复位 1已复位
- var resetState = 0;
- var _res = {};
-
- //打开蓝牙适配器
- function openBle(filter, timeout, callback) {
-
- outDevices.splice(0, outDevices.length);
- uni.openBluetoothAdapter({
- success: function (res) {
- uni.startBluetoothDevicesDiscovery({
- services: ['FEE7'],
- success: function () {
- setTimeout(function () {
- uni.stopBluetoothDevicesDiscovery();
- uni.getBluetoothDevices({
- success: function (res) {
- res.devices.forEach((device) => {
- // 根据filter进行过滤
- if (device.name.indexOf(filter) == 0) {
- outDevices.push(device);
- }
- })
- callback(0, outDevices, "扫描成功");
- },
- fail: function (error) {
- callback(1, null, "扫描失败:" + error.errMsg);
- }
- })
- }, timeout)
- },
- fail: function (error) {
- callback(1, null, "扫描失败:" + error.errMsg);
- }
- })
- },
- fail: function (error) {
- callback(1, null, "扫描失败:" + error.errMsg);
- }
- })
- }
-
- function connectDevice(device, callback, callback2) {
-
- CallBackInfo = callback;
- CallBackInfoForconnected = callback2;
- myDeviceId = device.deviceId;
- uni.createBLEConnection({
- deviceId: myDeviceId,
- timeout: 3000,
- success: function (res) {
- uni.getBLEDeviceServices({
- deviceId: myDeviceId,
- success: function (res) {
- for (var a = 0; a < res.services.length; a++) {
- if ('0000FF00' == res.services[a].uuid.substr(0, 8)) {
- Service = res.services[a].uuid;
- }
- }
- uni.getBLEDeviceCharacteristics({
- deviceId: myDeviceId,
- serviceId: Service,
- success: function (res) {
- for (var i = 0; i < res.characteristics.length; i++) {
- let item = res.characteristics[i]
- if (item.properties.notify || item.properties.indicate) {
- if ('0000FF02' == item.uuid.substr(0, 8)) {
- notifyCharacteristicsId = item.uuid;
- }
- }
- if (item.properties.write) {
- if ('0000FF01' == item.uuid.substr(0, 8)) {
- writeCharacteristicsId = item.uuid;
- }
- } else if (item.properties.read) {
- if ('0000FF03' == item.uuid.substr(0, 8)) {
- readCharacteristicsId = item.uuid;
- }
- }
- }
- uni.notifyBLECharacteristicValueChange({
- state: true,
- deviceId: myDeviceId,
- serviceId: Service,
- characteristicId: notifyCharacteristicsId,
- success: function (res) {
- sendData(ass2001(), function (code) {
- if (code != 0) {
- _res.code = 1;
- _res.data = null;
- _res.msg = "连接失败:认证失败"
- CallBackInfo(_res);
- }
- })
- },
- fail: function (error) {
- _res.code = 1;
- _res.data = null;
- _res.msg = "连接失败:" + error.errMsg
- CallBackInfo(_res);
- }
- })
- },
- fail: function (error) {
- _res.code = 1;
- _res.data = null;
- _res.msg = "连接失败:" + error.errMsg
- CallBackInfo(_res);
- },
- })
- },
- fail: function (error) {
- _res.code = 1;
- _res.data = null;
- _res.msg = "连接失败:" + error.errMsg
- CallBackInfo(_res);
- }
- })
- },
- fail: function (error) {
- _res.code = 1;
- _res.data = null;
- _res.msg = "连接失败:" + error.errMsg
- CallBackInfo(_res);
- }
- })
-
- // 必须在这里的回调才能获取
- uni.onBLECharacteristicValueChange(function (characteristic) {
- var hex = Array.prototype.map.call(new Uint8Array(characteristic.value), x => ('00' + x.toString(16)).slice(-2)).join('');
- console.log('接收信息:' + hex);
- checkAndDistribution(hex);
- })
-
- uni.onBLEConnectionStateChange(function (res) {
- console.log('监听连接状态变化:');
- if (res.connected) {
- CallBackInfoForconnected(0, null, "监听连接成功");
- } else {
- resetState = 0;
- CallBackInfoForconnected(1, null, "监听到断开连接");
- }
- })
- }
-
- //断开与蓝牙外设的连接
- function disconnectDevice(callback) {
- resetState = 0;
- uni.closeBLEConnection({
- deviceId: myDeviceId,
- success: function (res) {
- uni.closeBluetoothAdapter({
- success: function (res) {
- var _res = {};
- _res.code = 0;
- _res.data = null;
- _res.msg = "断开成功";
- callback(_res);
- },
- fail: function (res) {
- var _res = {};
- _res.code = 1;
- _res.data = null;
- _res.msg = "断开失败:" + res.errMsg;
- callback(_res);
- }
- })
- },
- fail: function (res) {
- var _res = {};
- _res.code = 1;
- _res.data = null;
- _res.msg = "断开失败:" + res.errMsg;
- callback(_res);
- }
- })
- }
- ///////////////////////下面是util/////////////////////////
- /**
- * 发送数据
- */
- function sendData(cmd, callback) {
- console.log('发送信息:' + cmd);
- uni.writeBLECharacteristicValue({
- deviceId: myDeviceId,
- serviceId: Service,
- characteristicId: writeCharacteristicsId,
- value: strToBuff(cmd),
- success: function (res) {
- console.log('数据发送成功');
- callback(0);
- },
- fail: function (res) {
- console.log('数据发送失败');
- console.log(res);
- callback(1);
- }
- })
- }
-
- function hex2int(hex) {
- var len = hex.length,
- a = new Array(len),
- code;
- for (var i = 0; i < len; i++) {
- code = hex.charCodeAt(i);
- if (48 <= code && code < 58) {
- code -= 48;
- } else {
- code = (code & 0xdf) - 65 + 10;
- }
- a[i] = code;
- }
- return a.reduce(function (acc, c) {
- acc = 16 * acc + c;
- return acc;
- }, 0);
- }
-
-
- //命令转buffer
- function strToBuff(cmd) {
- let buffer = new ArrayBuffer(cmd.length / 2);
- let dataView = new Uint8Array(buffer);
- for (var a = 0; a < cmd.length / 2; a++) {
- dataView[a] = '0x' + cmd.substring(2 * a, 2 * a + 2);
- }
- return buffer
- }
-
- function ass2001() {
- OBUNo = '1122334455667788';
- phoneRandom = getRandom();
- console.log("phoneRandom:" + phoneRandom);
- var cmd = OBUNo + phoneRandom;
- return assbCmd("2001", cmd);
- }
-
- function ass2002() {
- var cmd = OBUNo + encrypDeviceRandom;
- return assbCmd("2002", cmd);
- }
-
- function ass2005() {
- var cmd = OBUNo;
- return assbCmd("2005", cmd);
- }
-
- function ass2006(option) {
- var cmd = OBUNo + option;
- return assbCmd("2006", cmd);
- }
-
- function channel(channelType, cmd, callback) {
- CallBackInfo = callback;
- sendData(ass200A(channelType, cmd), function (code) {
- if (code == 0) {} else {
- callback(1);
- }
- })
- }
-
- function transCmd(cmd, cmdtype, callback) {
- if (cmdtype == "10") {
- cmdtype = "01"
- }
- if (cmdtype == "20") {
- cmdtype = "02"
- }
- CallBackToQT = callback;
- currentCmdId = 0;
- cmdTotal = cmd.length;
- inCmdArr = cmd;
- outCmdArr.splice(0, outCmdArr.length);
- console.log("resetState" + resetState);
- if (resetState == 0) {
- globalCmdType = "03";
- channel("03", "", function (code, data, msg) {
- if (code == 0) {
- resetState = 1;
- globalCmdType = cmdtype;
- channel(cmdtype, cmd[0], function (code, data, msg) {
-
- });
- }
- });
- } else {
- globalCmdType = cmdtype;
- channel(cmdtype, cmd[0], function (code, data, msg) {
-
- });
- }
- }
-
- function channel2005(callback) {
- CallBackInfo = callback;
- sendData(ass2005(), function (code) {
- if (code == 0) {
- console.log(code);
- } else {
- console.log(code);
- callback(1);
- }
- })
- }
-
- function channel2006(cmd, callback) {
- CallBackInfo = callback;
- sendData(ass2006(cmd), function (code) {
- if (code == 0) {
- console.log(code);
- } else {
- console.log(code);
- callback(1);
- }
- })
- }
-
- function channelTLV(channelType, cmds, callback) {
- sendData(ass200A(channelType, cmd), function (code) {
- if (code == 0) {
- console.log(code);
- callback(0);
- } else {
- console.log(code);
- callback(1);
- }
- })
- }
-
- function ass200A(channelType, cmd) {
- var cmd = channelType + tenToHex(cmd.length / 2, 2) + cmd;
- return assbCmd("200A", cmd);
- }
-
- //获取16字节随机数
- function getRandom() {
- var result = '';
- for (var i = 0; i < 16; i++) {
- var tmp = Math.ceil((Math.random() * 255));
- tmp = (tmp.toString(16));
- if (tmp.length == 1) {
- tmp = "0" + tmp;
- }
- result += tmp;
- }
- return result.toUpperCase();
- }
- //组装命令
- function assbCmd(msgType, cmd) {
- var CmdId = 'AA55AA55';
- var nLength = tenToHex(8 + cmd.length / 2, 4);
- var data = CmdId + msgType + nLength + getFramNo() + '01' + cmd + getDate();
- var check = crc16(data, true);
- return data + check;
- }
-
- function getDate() {
- var date = new Date();
- return date.getFullYear().toString().substring(2, 4) + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds());
- }
-
- function pad2(n) {
- return n < 10 ? '0' + n : n
- }
-
- function getFramNo() {
- if (framNo == 2147483647) {
- framNo = 1;
- } else {
- framNo++;
- }
- return tenToHex(framNo, 8);
- }
- /**
- * 10to16
- * num 数字
- * len 想要的16进制长度
- */
- function tenToHex(num, len) {
- var hex = num.toString(16);
- var zero = '';
- for (var a = 0; a < len - hex.length; a++) {
- zero += '0';
- }
- return zero + hex
- }
-
- function strToByte(str) {
- var arr = [];
- for (var i = 0; i < str.length; i += 2) {
- arr.push(parseInt('0x' + str.substring(i, i + 2)));
- }
- return arr;
- };
-
- function bytesToHexString(bytes) {
- var hexStr = '';
- for (var i = 0; i < bytes.length; i++) {
- var hex = bytes[i].toString(16);
- if (hex.length == 1) {
- hex = "0" + hex;
- }
- hexStr += hex;
- }
- return hexStr.toUpperCase();
- }
-
- //crc16校验,传入要校验的字符串,返回计算的crc16结果
- function crc16(str) {
- var data = strToByte(str);
- var crc = 0x0000;
- for (var i = 0; i < data.length; i++) {
- crc = crc ^ (data[i] << 8);
- for (var j = 0; j < 8; j++) {
- if ((crc & 0x8000) != 0)
- crc = (crc << 1) ^ 0x8005;
- else
- crc = (crc << 1);
- }
- }
- crc = ((Math.pow(2, 32) + crc).toString(16));
- crc = crc.substring(crc.length - 4);
- return crc.toUpperCase();
- }
-
- function checkAndDistribution(data) {
- var cmd = data.substring(0, data.length - 4);
- var crc = data.substring(data.length - 4);
- if (crc.toUpperCase() == crc16(cmd)) {
- var head = data.substring(0, 8);
- if (head == "aa55aa55") {
- var type = data.substring(8, 12);
- switch (type) {
- case "3001":
- analysis3001(data);
- break;
- case "3002":
- analysis3002(data);
- break;
- case "3005":
- analysis3005(data);
- break;
- case "3006":
- analysis3006(data);
- break;
- case "300a":
- analysis300A(data);
- break;
- default:
- }
- } else {
- console.log("信息有误");
- }
- } else {
- console.log("信息CRC校验不通过");
- }
- }
-
- function analysis3001(data) {
- var length = hex2int(data.substring(12, 16));
- var cmd = data.substring(26, 26 + length * 2);
- var cmd1 = cmd.substring(0, 16);
- var cmd2 = cmd.substring(16, 48);
- var cmd3 = cmd.substring(48, 80);
- console.log("cmd2" + cmd2);
- OBUNo = cmd1;
- if (authCheck(phoneRandom, cmd2)) {
- // 认证通过
- encrypDeviceRandom = encryption(cmd3);
- sendData(ass2002(), function (code) {
- if (code != 0) {
- _res.code = 1;
- _res.data = null;
- _res.msg = "连接失败:2001认证失败"
- CallBackInfo(_res);
- }
- })
- } else {
- // 认证不通过
- _res.code = 1;
- _res.data = null;
- _res.msg = "连接失败:3001认证失败"
- CallBackInfo(_res);
- }
- }
-
- function analysis3002(data) {
- var length = hex2int(data.substring(12, 16));
- var cmd = data.substring(26, 26 + length * 2);
- var cmd1 = cmd.substring(0, 16);
- var cmd2 = cmd.substring(16, 18);
- if (cmd2 == "00") {
- _res.code = 0;
- _res.data = null;
- _res.msg = "连接成功"
- CallBackInfo(_res);
- } else {
- _res.code = 1;
- _res.data = null;
- _res.msg = "连接失败:认证失败"
- CallBackInfo(_res);
- }
- }
-
- function authCheck(random, data) {
- console.log("random" + random);
- console.log("data" + data);
- let decryptData = sm4.decrypt(strToByte(data), strToByte(key), {
- padding: 'none',
- output: 'array'
- }) // 解密,不使用 padding
-
- console.log("bytesToHexString(decryptData)" + bytesToHexString(decryptData));
-
- return bytesToHexString(decryptData) == random;
- }
-
- function encryption(data) {
- // 可以为 16 进制串或字节数组,要求为 128 比特
- let encryptData = sm4.encrypt(strToByte(data), strToByte(key), {
- padding: 'none'
- }) // 加密,默认输出 16 进制字符串
- return encryptData;
- }
-
- function analysis300A(data) {
- var length = hex2int(data.substring(12, 16));
- var cmd = data.substring(26, 26 + length * 2);
- var cmd1 = cmd.substring(0, 2);
- var cmd2 = cmd.substring(2, 4);
- var cmd3 = cmd.substring(4, 6);
- var cmd4 = cmd.substring(6, 6 + hex2int(cmd3) * 2);
- if (globalCmdType == '03') {
- CallBackInfo(0, cmd4, cmd4);
- } else {
- if (cmd4.substr(0, 2).toUpperCase() == "6C") {
- var cmd = inCmdArr[currentCmdId];
- channel(globalCmdType, cmd.substr(0, cmd.length - 2) + cmd4.substr(cmd4.length - 2), function (code, data, msg) {
-
- });
- } else {
-
- outCmdArr.push(cmd4);
- currentCmdId++;
- if (currentCmdId == cmdTotal) {
- var _res = {};
- _res.code = 0;
- _res.data = outCmdArr;
- _res.msg = "成功";
- CallBackToQT(_res);
- } else {
- channel(globalCmdType, inCmdArr[currentCmdId], function (code, data, msg) {});
- }
- }
-
- }
- }
-
- function analysis3005(data) {
- var length = hex2int(data.substring(12, 16));
- var cmd = data.substring(26, 26 + length * 2);
- CallBackInfo(0, cmd, cmd);
- }
-
- function analysis3006(data) {
- var length = hex2int(data.substring(12, 16));
- var cmd = data.substring(26, 26 + length * 2);
- CallBackInfo(0, cmd, cmd);
- }
-
- ///////////
- /**
- * 将方法暴露出来
- */
- module.exports = {
- openBle: openBle,
- disconnectDevice: disconnectDevice,
- connectDevice: connectDevice,
- transCmd: transCmd
- }
|