From 1851e76b7bdde02739ef56df48c53ef05edb6b6c Mon Sep 17 00:00:00 2001 From: walson_8 <459788263@qq.com> Date: Sun, 12 Sep 2021 15:27:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E8=93=9D=E7=89=99?= =?UTF-8?q?=E9=80=9A=E4=BF=A1=E4=BE=8B=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 33 ++ app.json | 16 + app.wxss | 10 + miniprogram_npm/eventemitter2/index.js | 800 +++++++++++++++++++++++++++++ miniprogram_npm/eventemitter2/index.js.map | 1 + pages/asyntest/asyntest.js | 191 +++++++ pages/asyntest/asyntest.json | 3 + pages/asyntest/asyntest.wxml | 18 + pages/asyntest/asyntest.wxss | 28 + pages/index/index.js | 212 ++++++++ pages/index/index.json | 3 + pages/index/index.wxml | 41 ++ pages/index/index.wxss | 41 ++ pages/lanyatest/lanyatest.js | 637 +++++++++++++++++++++++ pages/lanyatest/lanyatest.json | 3 + pages/lanyatest/lanyatest.wxml | 29 ++ pages/lanyatest/lanyatest.wxss | 28 + pages/logs/logs.js | 18 + pages/logs/logs.json | 4 + pages/logs/logs.wxml | 6 + pages/logs/logs.wxss | 8 + project.config.json | 74 +++ sitemap.json | 7 + utils/btls/ble.js | 59 +++ utils/btls/bleHandler.js | 296 +++++++++++ utils/btls/error.js | 44 ++ utils/btls/tools.js | 481 +++++++++++++++++ utils/global.js | 6 + utils/long.js | 8 + utils/util.js | 153 ++++++ 30 files changed, 3258 insertions(+) create mode 100644 app.js create mode 100644 app.json create mode 100644 app.wxss create mode 100644 miniprogram_npm/eventemitter2/index.js create mode 100644 miniprogram_npm/eventemitter2/index.js.map create mode 100644 pages/asyntest/asyntest.js create mode 100644 pages/asyntest/asyntest.json create mode 100644 pages/asyntest/asyntest.wxml create mode 100644 pages/asyntest/asyntest.wxss create mode 100644 pages/index/index.js create mode 100644 pages/index/index.json create mode 100644 pages/index/index.wxml create mode 100644 pages/index/index.wxss create mode 100644 pages/lanyatest/lanyatest.js create mode 100644 pages/lanyatest/lanyatest.json create mode 100644 pages/lanyatest/lanyatest.wxml create mode 100644 pages/lanyatest/lanyatest.wxss create mode 100644 pages/logs/logs.js create mode 100644 pages/logs/logs.json create mode 100644 pages/logs/logs.wxml create mode 100644 pages/logs/logs.wxss create mode 100644 project.config.json create mode 100644 sitemap.json create mode 100644 utils/btls/ble.js create mode 100644 utils/btls/bleHandler.js create mode 100644 utils/btls/error.js create mode 100644 utils/btls/tools.js create mode 100644 utils/global.js create mode 100644 utils/long.js create mode 100644 utils/util.js diff --git a/app.js b/app.js new file mode 100644 index 0000000..bc308f3 --- /dev/null +++ b/app.js @@ -0,0 +1,33 @@ +// app.js + +import { globalData } from "./utils/global"; +const EventEmitter2 = require("./miniprogram_npm/eventemitter2/index").EventEmitter2; +const emitter = new EventEmitter2(); + +App({ + onLaunch() { + // 展示本地存储能力 + const logs = wx.getStorageSync('logs') || [] + logs.unshift(Date.now()) + wx.setStorageSync('logs', logs) + + + // 登录 + wx.login({ + success: res => { + // 发送 res.code 到后台换取 openId, sessionKey, unionId + } + }) + }, + + globalData: Object.assign( + { + ble: "",//全局蓝牙实例 + emitter: emitter, //全局订阅函数 + blueStatus: false, + userInfo: null + }, + globalData + ), + +}) diff --git a/app.json b/app.json new file mode 100644 index 0000000..ed74964 --- /dev/null +++ b/app.json @@ -0,0 +1,16 @@ +{ + "pages":[ + "pages/asyntest/asyntest", + "pages/lanyatest/lanyatest", + "pages/index/index", + "pages/logs/logs" + ], + "window":{ + "backgroundTextStyle":"light", + "navigationBarBackgroundColor": "#fff", + "navigationBarTitleText": "Weixin", + "navigationBarTextStyle":"black" + }, + "style": "v2", + "sitemapLocation": "sitemap.json" +} diff --git a/app.wxss b/app.wxss new file mode 100644 index 0000000..06c6fc9 --- /dev/null +++ b/app.wxss @@ -0,0 +1,10 @@ +/**app.wxss**/ +.container { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: space-between; + padding: 200rpx 0; + box-sizing: border-box; +} diff --git a/miniprogram_npm/eventemitter2/index.js b/miniprogram_npm/eventemitter2/index.js new file mode 100644 index 0000000..47b5419 --- /dev/null +++ b/miniprogram_npm/eventemitter2/index.js @@ -0,0 +1,800 @@ +module.exports = (function() { +var __MODS__ = {}; +var __DEFINE__ = function(modId, func, req) { var m = { exports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; }; +var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = { exports: {} }; __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); if(typeof m.exports === "object") { __MODS__[modId].m.exports.__proto__ = m.exports.__proto__; Object.keys(m.exports).forEach(function(k) { __MODS__[modId].m.exports[k] = m.exports[k]; var desp = Object.getOwnPropertyDescriptor(m.exports, k); if(desp && desp.configurable) Object.defineProperty(m.exports, k, { set: function(val) { __MODS__[modId].m.exports[k] = val; }, get: function() { return __MODS__[modId].m.exports[k]; } }); }); if(m.exports.__esModule) Object.defineProperty(__MODS__[modId].m.exports, "__esModule", { value: true }); } else { __MODS__[modId].m.exports = m.exports; } } return __MODS__[modId].m.exports; }; +var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } }; +var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; }; +__DEFINE__(1585827830357, function(require, module, exports) { +/*! + * EventEmitter2 + * https://github.com/hij1nx/EventEmitter2 + * + * Copyright (c) 2013 hij1nx + * Licensed under the MIT license. + */ +;!function(undefined) { + + var isArray = Array.isArray ? Array.isArray : function _isArray(obj) { + return Object.prototype.toString.call(obj) === "[object Array]"; + }; + var defaultMaxListeners = 10; + + function init() { + this._events = {}; + if (this._conf) { + configure.call(this, this._conf); + } + } + + function configure(conf) { + if (conf) { + this._conf = conf; + + conf.delimiter && (this.delimiter = conf.delimiter); + this._maxListeners = conf.maxListeners !== undefined ? conf.maxListeners : defaultMaxListeners; + + conf.wildcard && (this.wildcard = conf.wildcard); + conf.newListener && (this._newListener = conf.newListener); + conf.removeListener && (this._removeListener = conf.removeListener); + conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak); + + if (this.wildcard) { + this.listenerTree = {}; + } + } else { + this._maxListeners = defaultMaxListeners; + } + } + + function logPossibleMemoryLeak(count, eventName) { + var errorMsg = '(node) warning: possible EventEmitter memory ' + + 'leak detected. ' + count + ' listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.'; + + if(this.verboseMemoryLeak){ + errorMsg += ' Event name: ' + eventName + '.'; + } + + if(typeof process !== 'undefined' && process.emitWarning){ + var e = new Error(errorMsg); + e.name = 'MaxListenersExceededWarning'; + e.emitter = this; + e.count = count; + process.emitWarning(e); + } else { + console.error(errorMsg); + + if (console.trace){ + console.trace(); + } + } + } + + function EventEmitter(conf) { + this._events = {}; + this._newListener = false; + this._removeListener = false; + this.verboseMemoryLeak = false; + configure.call(this, conf); + } + EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property + + // + // Attention, function return type now is array, always ! + // It has zero elements if no any matches found and one or more + // elements (leafs) if there are matches + // + function searchListenerTree(handlers, type, tree, i) { + if (!tree) { + return []; + } + var listeners=[], leaf, len, branch, xTree, xxTree, isolatedBranch, endReached, + typeLength = type.length, currentType = type[i], nextType = type[i+1]; + if (i === typeLength && tree._listeners) { + // + // If at the end of the event(s) list and the tree has listeners + // invoke those listeners. + // + if (typeof tree._listeners === 'function') { + handlers && handlers.push(tree._listeners); + return [tree]; + } else { + for (leaf = 0, len = tree._listeners.length; leaf < len; leaf++) { + handlers && handlers.push(tree._listeners[leaf]); + } + return [tree]; + } + } + + if ((currentType === '*' || currentType === '**') || tree[currentType]) { + // + // If the event emitted is '*' at this part + // or there is a concrete match at this patch + // + if (currentType === '*') { + for (branch in tree) { + if (branch !== '_listeners' && tree.hasOwnProperty(branch)) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+1)); + } + } + return listeners; + } else if(currentType === '**') { + endReached = (i+1 === typeLength || (i+2 === typeLength && nextType === '*')); + if(endReached && tree._listeners) { + // The next element has a _listeners, add it to the handlers. + listeners = listeners.concat(searchListenerTree(handlers, type, tree, typeLength)); + } + + for (branch in tree) { + if (branch !== '_listeners' && tree.hasOwnProperty(branch)) { + if(branch === '*' || branch === '**') { + if(tree[branch]._listeners && !endReached) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], typeLength)); + } + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i)); + } else if(branch === nextType) { + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+2)); + } else { + // No match on this one, shift into the tree but not in the type array. + listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i)); + } + } + } + return listeners; + } + + listeners = listeners.concat(searchListenerTree(handlers, type, tree[currentType], i+1)); + } + + xTree = tree['*']; + if (xTree) { + // + // If the listener tree will allow any match for this part, + // then recursively explore all branches of the tree + // + searchListenerTree(handlers, type, xTree, i+1); + } + + xxTree = tree['**']; + if(xxTree) { + if(i < typeLength) { + if(xxTree._listeners) { + // If we have a listener on a '**', it will catch all, so add its handler. + searchListenerTree(handlers, type, xxTree, typeLength); + } + + // Build arrays of matching next branches and others. + for(branch in xxTree) { + if(branch !== '_listeners' && xxTree.hasOwnProperty(branch)) { + if(branch === nextType) { + // We know the next element will match, so jump twice. + searchListenerTree(handlers, type, xxTree[branch], i+2); + } else if(branch === currentType) { + // Current node matches, move into the tree. + searchListenerTree(handlers, type, xxTree[branch], i+1); + } else { + isolatedBranch = {}; + isolatedBranch[branch] = xxTree[branch]; + searchListenerTree(handlers, type, { '**': isolatedBranch }, i+1); + } + } + } + } else if(xxTree._listeners) { + // We have reached the end and still on a '**' + searchListenerTree(handlers, type, xxTree, typeLength); + } else if(xxTree['*'] && xxTree['*']._listeners) { + searchListenerTree(handlers, type, xxTree['*'], typeLength); + } + } + + return listeners; + } + + function growListenerTree(type, listener) { + + type = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + + // + // Looks for two consecutive '**', if so, don't add the event at all. + // + for(var i = 0, len = type.length; i+1 < len; i++) { + if(type[i] === '**' && type[i+1] === '**') { + return; + } + } + + var tree = this.listenerTree; + var name = type.shift(); + + while (name !== undefined) { + + if (!tree[name]) { + tree[name] = {}; + } + + tree = tree[name]; + + if (type.length === 0) { + + if (!tree._listeners) { + tree._listeners = listener; + } + else { + if (typeof tree._listeners === 'function') { + tree._listeners = [tree._listeners]; + } + + tree._listeners.push(listener); + + if ( + !tree._listeners.warned && + this._maxListeners > 0 && + tree._listeners.length > this._maxListeners + ) { + tree._listeners.warned = true; + logPossibleMemoryLeak.call(this, tree._listeners.length, name); + } + } + return true; + } + name = type.shift(); + } + return true; + } + + // By default EventEmitters will print a warning if more than + // 10 listeners are added to it. This is a useful default which + // helps finding memory leaks. + // + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + + EventEmitter.prototype.delimiter = '.'; + + EventEmitter.prototype.setMaxListeners = function(n) { + if (n !== undefined) { + this._maxListeners = n; + if (!this._conf) this._conf = {}; + this._conf.maxListeners = n; + } + }; + + EventEmitter.prototype.event = ''; + + + EventEmitter.prototype.once = function(event, fn) { + return this._once(event, fn, false); + }; + + EventEmitter.prototype.prependOnceListener = function(event, fn) { + return this._once(event, fn, true); + }; + + EventEmitter.prototype._once = function(event, fn, prepend) { + this._many(event, 1, fn, prepend); + return this; + }; + + EventEmitter.prototype.many = function(event, ttl, fn) { + return this._many(event, ttl, fn, false); + } + + EventEmitter.prototype.prependMany = function(event, ttl, fn) { + return this._many(event, ttl, fn, true); + } + + EventEmitter.prototype._many = function(event, ttl, fn, prepend) { + var self = this; + + if (typeof fn !== 'function') { + throw new Error('many only accepts instances of Function'); + } + + function listener() { + if (--ttl === 0) { + self.off(event, listener); + } + return fn.apply(this, arguments); + } + + listener._origin = fn; + + this._on(event, listener, prepend); + + return self; + }; + + EventEmitter.prototype.emit = function() { + if (!this._events && !this._all) { + return false; + } + + this._events || init.call(this); + + var type = arguments[0]; + + if (type === 'newListener' && !this._newListener) { + if (!this._events.newListener) { + return false; + } + } + + var al = arguments.length; + var args,l,i,j; + var handler; + + if (this._all && this._all.length) { + handler = this._all.slice(); + if (al > 3) { + args = new Array(al); + for (j = 0; j < al; j++) args[j] = arguments[j]; + } + + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + handler[i].call(this, type); + break; + case 2: + handler[i].call(this, type, arguments[1]); + break; + case 3: + handler[i].call(this, type, arguments[1], arguments[2]); + break; + default: + handler[i].apply(this, args); + } + } + } + + if (this.wildcard) { + handler = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handler, ns, this.listenerTree, 0); + } else { + handler = this._events[type]; + if (typeof handler === 'function') { + this.event = type; + switch (al) { + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + default: + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + handler.apply(this, args); + } + return true; + } else if (handler) { + // need to make copy of handlers because list can change in the middle + // of emit call + handler = handler.slice(); + } + } + + if (handler && handler.length) { + if (al > 3) { + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + } + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + handler[i].call(this); + break; + case 2: + handler[i].call(this, arguments[1]); + break; + case 3: + handler[i].call(this, arguments[1], arguments[2]); + break; + default: + handler[i].apply(this, args); + } + } + return true; + } else if (!this._all && type === 'error') { + if (arguments[1] instanceof Error) { + throw arguments[1]; // Unhandled 'error' event + } else { + throw new Error("Uncaught, unspecified 'error' event."); + } + return false; + } + + return !!this._all; + }; + + EventEmitter.prototype.emitAsync = function() { + if (!this._events && !this._all) { + return false; + } + + this._events || init.call(this); + + var type = arguments[0]; + + if (type === 'newListener' && !this._newListener) { + if (!this._events.newListener) { return Promise.resolve([false]); } + } + + var promises= []; + + var al = arguments.length; + var args,l,i,j; + var handler; + + if (this._all) { + if (al > 3) { + args = new Array(al); + for (j = 1; j < al; j++) args[j] = arguments[j]; + } + for (i = 0, l = this._all.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + promises.push(this._all[i].call(this, type)); + break; + case 2: + promises.push(this._all[i].call(this, type, arguments[1])); + break; + case 3: + promises.push(this._all[i].call(this, type, arguments[1], arguments[2])); + break; + default: + promises.push(this._all[i].apply(this, args)); + } + } + } + + if (this.wildcard) { + handler = []; + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + searchListenerTree.call(this, handler, ns, this.listenerTree, 0); + } else { + handler = this._events[type]; + } + + if (typeof handler === 'function') { + this.event = type; + switch (al) { + case 1: + promises.push(handler.call(this)); + break; + case 2: + promises.push(handler.call(this, arguments[1])); + break; + case 3: + promises.push(handler.call(this, arguments[1], arguments[2])); + break; + default: + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + promises.push(handler.apply(this, args)); + } + } else if (handler && handler.length) { + handler = handler.slice(); + if (al > 3) { + args = new Array(al - 1); + for (j = 1; j < al; j++) args[j - 1] = arguments[j]; + } + for (i = 0, l = handler.length; i < l; i++) { + this.event = type; + switch (al) { + case 1: + promises.push(handler[i].call(this)); + break; + case 2: + promises.push(handler[i].call(this, arguments[1])); + break; + case 3: + promises.push(handler[i].call(this, arguments[1], arguments[2])); + break; + default: + promises.push(handler[i].apply(this, args)); + } + } + } else if (!this._all && type === 'error') { + if (arguments[1] instanceof Error) { + return Promise.reject(arguments[1]); // Unhandled 'error' event + } else { + return Promise.reject("Uncaught, unspecified 'error' event."); + } + } + + return Promise.all(promises); + }; + + EventEmitter.prototype.on = function(type, listener) { + return this._on(type, listener, false); + }; + + EventEmitter.prototype.prependListener = function(type, listener) { + return this._on(type, listener, true); + }; + + EventEmitter.prototype.onAny = function(fn) { + return this._onAny(fn, false); + }; + + EventEmitter.prototype.prependAny = function(fn) { + return this._onAny(fn, true); + }; + + EventEmitter.prototype.addListener = EventEmitter.prototype.on; + + EventEmitter.prototype._onAny = function(fn, prepend){ + if (typeof fn !== 'function') { + throw new Error('onAny only accepts instances of Function'); + } + + if (!this._all) { + this._all = []; + } + + // Add the function to the event listener collection. + if(prepend){ + this._all.unshift(fn); + }else{ + this._all.push(fn); + } + + return this; + } + + EventEmitter.prototype._on = function(type, listener, prepend) { + if (typeof type === 'function') { + this._onAny(type, listener); + return this; + } + + if (typeof listener !== 'function') { + throw new Error('on only accepts instances of Function'); + } + this._events || init.call(this); + + // To avoid recursion in the case that type == "newListeners"! Before + // adding it to the listeners, first emit "newListeners". + if (this._newListener) + this.emit('newListener', type, listener); + + if (this.wildcard) { + growListenerTree.call(this, type, listener); + return this; + } + + if (!this._events[type]) { + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + } + else { + if (typeof this._events[type] === 'function') { + // Change to array. + this._events[type] = [this._events[type]]; + } + + // If we've already got an array, just add + if(prepend){ + this._events[type].unshift(listener); + }else{ + this._events[type].push(listener); + } + + // Check for listener leak + if ( + !this._events[type].warned && + this._maxListeners > 0 && + this._events[type].length > this._maxListeners + ) { + this._events[type].warned = true; + logPossibleMemoryLeak.call(this, this._events[type].length, type); + } + } + + return this; + } + + EventEmitter.prototype.off = function(type, listener) { + if (typeof listener !== 'function') { + throw new Error('removeListener only takes instances of Function'); + } + + var handlers,leafs=[]; + + if(this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + } + else { + // does not use listeners(), so no side effect of creating _events[type] + if (!this._events[type]) return this; + handlers = this._events[type]; + leafs.push({_listeners:handlers}); + } + + for (var iLeaf=0; iLeaf 0) { + recursivelyGarbageCollect(root[key]); + } + if (Object.keys(obj).length === 0) { + delete root[key]; + } + } + } + recursivelyGarbageCollect(this.listenerTree); + + return this; + }; + + EventEmitter.prototype.offAny = function(fn) { + var i = 0, l = 0, fns; + if (fn && this._all && this._all.length > 0) { + fns = this._all; + for(i = 0, l = fns.length; i < l; i++) { + if(fn === fns[i]) { + fns.splice(i, 1); + if (this._removeListener) + this.emit("removeListenerAny", fn); + return this; + } + } + } else { + fns = this._all; + if (this._removeListener) { + for(i = 0, l = fns.length; i < l; i++) + this.emit("removeListenerAny", fns[i]); + } + this._all = []; + } + return this; + }; + + EventEmitter.prototype.removeListener = EventEmitter.prototype.off; + + EventEmitter.prototype.removeAllListeners = function(type) { + if (type === undefined) { + !this._events || init.call(this); + return this; + } + + if (this.wildcard) { + var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); + var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0); + + for (var iLeaf=0; iLeaf 0 &&\n tree._listeners.length > this._maxListeners\n ) {\n tree._listeners.warned = true;\n logPossibleMemoryLeak.call(this, tree._listeners.length, name);\n }\n }\n return true;\n }\n name = type.shift();\n }\n return true;\n }\n\n // By default EventEmitters will print a warning if more than\n // 10 listeners are added to it. This is a useful default which\n // helps finding memory leaks.\n //\n // Obviously not all Emitters should be limited to 10. This function allows\n // that to be increased. Set to zero for unlimited.\n\n EventEmitter.prototype.delimiter = '.';\n\n EventEmitter.prototype.setMaxListeners = function(n) {\n if (n !== undefined) {\n this._maxListeners = n;\n if (!this._conf) this._conf = {};\n this._conf.maxListeners = n;\n }\n };\n\n EventEmitter.prototype.event = '';\n\n\n EventEmitter.prototype.once = function(event, fn) {\n return this._once(event, fn, false);\n };\n\n EventEmitter.prototype.prependOnceListener = function(event, fn) {\n return this._once(event, fn, true);\n };\n\n EventEmitter.prototype._once = function(event, fn, prepend) {\n this._many(event, 1, fn, prepend);\n return this;\n };\n\n EventEmitter.prototype.many = function(event, ttl, fn) {\n return this._many(event, ttl, fn, false);\n }\n\n EventEmitter.prototype.prependMany = function(event, ttl, fn) {\n return this._many(event, ttl, fn, true);\n }\n\n EventEmitter.prototype._many = function(event, ttl, fn, prepend) {\n var self = this;\n\n if (typeof fn !== 'function') {\n throw new Error('many only accepts instances of Function');\n }\n\n function listener() {\n if (--ttl === 0) {\n self.off(event, listener);\n }\n return fn.apply(this, arguments);\n }\n\n listener._origin = fn;\n\n this._on(event, listener, prepend);\n\n return self;\n };\n\n EventEmitter.prototype.emit = function() {\n if (!this._events && !this._all) {\n return false;\n }\n\n this._events || init.call(this);\n\n var type = arguments[0];\n\n if (type === 'newListener' && !this._newListener) {\n if (!this._events.newListener) {\n return false;\n }\n }\n\n var al = arguments.length;\n var args,l,i,j;\n var handler;\n\n if (this._all && this._all.length) {\n handler = this._all.slice();\n if (al > 3) {\n args = new Array(al);\n for (j = 0; j < al; j++) args[j] = arguments[j];\n }\n\n for (i = 0, l = handler.length; i < l; i++) {\n this.event = type;\n switch (al) {\n case 1:\n handler[i].call(this, type);\n break;\n case 2:\n handler[i].call(this, type, arguments[1]);\n break;\n case 3:\n handler[i].call(this, type, arguments[1], arguments[2]);\n break;\n default:\n handler[i].apply(this, args);\n }\n }\n }\n\n if (this.wildcard) {\n handler = [];\n var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n searchListenerTree.call(this, handler, ns, this.listenerTree, 0);\n } else {\n handler = this._events[type];\n if (typeof handler === 'function') {\n this.event = type;\n switch (al) {\n case 1:\n handler.call(this);\n break;\n case 2:\n handler.call(this, arguments[1]);\n break;\n case 3:\n handler.call(this, arguments[1], arguments[2]);\n break;\n default:\n args = new Array(al - 1);\n for (j = 1; j < al; j++) args[j - 1] = arguments[j];\n handler.apply(this, args);\n }\n return true;\n } else if (handler) {\n // need to make copy of handlers because list can change in the middle\n // of emit call\n handler = handler.slice();\n }\n }\n\n if (handler && handler.length) {\n if (al > 3) {\n args = new Array(al - 1);\n for (j = 1; j < al; j++) args[j - 1] = arguments[j];\n }\n for (i = 0, l = handler.length; i < l; i++) {\n this.event = type;\n switch (al) {\n case 1:\n handler[i].call(this);\n break;\n case 2:\n handler[i].call(this, arguments[1]);\n break;\n case 3:\n handler[i].call(this, arguments[1], arguments[2]);\n break;\n default:\n handler[i].apply(this, args);\n }\n }\n return true;\n } else if (!this._all && type === 'error') {\n if (arguments[1] instanceof Error) {\n throw arguments[1]; // Unhandled 'error' event\n } else {\n throw new Error(\"Uncaught, unspecified 'error' event.\");\n }\n return false;\n }\n\n return !!this._all;\n };\n\n EventEmitter.prototype.emitAsync = function() {\n if (!this._events && !this._all) {\n return false;\n }\n\n this._events || init.call(this);\n\n var type = arguments[0];\n\n if (type === 'newListener' && !this._newListener) {\n if (!this._events.newListener) { return Promise.resolve([false]); }\n }\n\n var promises= [];\n\n var al = arguments.length;\n var args,l,i,j;\n var handler;\n\n if (this._all) {\n if (al > 3) {\n args = new Array(al);\n for (j = 1; j < al; j++) args[j] = arguments[j];\n }\n for (i = 0, l = this._all.length; i < l; i++) {\n this.event = type;\n switch (al) {\n case 1:\n promises.push(this._all[i].call(this, type));\n break;\n case 2:\n promises.push(this._all[i].call(this, type, arguments[1]));\n break;\n case 3:\n promises.push(this._all[i].call(this, type, arguments[1], arguments[2]));\n break;\n default:\n promises.push(this._all[i].apply(this, args));\n }\n }\n }\n\n if (this.wildcard) {\n handler = [];\n var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n searchListenerTree.call(this, handler, ns, this.listenerTree, 0);\n } else {\n handler = this._events[type];\n }\n\n if (typeof handler === 'function') {\n this.event = type;\n switch (al) {\n case 1:\n promises.push(handler.call(this));\n break;\n case 2:\n promises.push(handler.call(this, arguments[1]));\n break;\n case 3:\n promises.push(handler.call(this, arguments[1], arguments[2]));\n break;\n default:\n args = new Array(al - 1);\n for (j = 1; j < al; j++) args[j - 1] = arguments[j];\n promises.push(handler.apply(this, args));\n }\n } else if (handler && handler.length) {\n handler = handler.slice();\n if (al > 3) {\n args = new Array(al - 1);\n for (j = 1; j < al; j++) args[j - 1] = arguments[j];\n }\n for (i = 0, l = handler.length; i < l; i++) {\n this.event = type;\n switch (al) {\n case 1:\n promises.push(handler[i].call(this));\n break;\n case 2:\n promises.push(handler[i].call(this, arguments[1]));\n break;\n case 3:\n promises.push(handler[i].call(this, arguments[1], arguments[2]));\n break;\n default:\n promises.push(handler[i].apply(this, args));\n }\n }\n } else if (!this._all && type === 'error') {\n if (arguments[1] instanceof Error) {\n return Promise.reject(arguments[1]); // Unhandled 'error' event\n } else {\n return Promise.reject(\"Uncaught, unspecified 'error' event.\");\n }\n }\n\n return Promise.all(promises);\n };\n\n EventEmitter.prototype.on = function(type, listener) {\n return this._on(type, listener, false);\n };\n\n EventEmitter.prototype.prependListener = function(type, listener) {\n return this._on(type, listener, true);\n };\n\n EventEmitter.prototype.onAny = function(fn) {\n return this._onAny(fn, false);\n };\n\n EventEmitter.prototype.prependAny = function(fn) {\n return this._onAny(fn, true);\n };\n\n EventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n EventEmitter.prototype._onAny = function(fn, prepend){\n if (typeof fn !== 'function') {\n throw new Error('onAny only accepts instances of Function');\n }\n\n if (!this._all) {\n this._all = [];\n }\n\n // Add the function to the event listener collection.\n if(prepend){\n this._all.unshift(fn);\n }else{\n this._all.push(fn);\n }\n\n return this;\n }\n\n EventEmitter.prototype._on = function(type, listener, prepend) {\n if (typeof type === 'function') {\n this._onAny(type, listener);\n return this;\n }\n\n if (typeof listener !== 'function') {\n throw new Error('on only accepts instances of Function');\n }\n this._events || init.call(this);\n\n // To avoid recursion in the case that type == \"newListeners\"! Before\n // adding it to the listeners, first emit \"newListeners\".\n if (this._newListener)\n this.emit('newListener', type, listener);\n\n if (this.wildcard) {\n growListenerTree.call(this, type, listener);\n return this;\n }\n\n if (!this._events[type]) {\n // Optimize the case of one listener. Don't need the extra array object.\n this._events[type] = listener;\n }\n else {\n if (typeof this._events[type] === 'function') {\n // Change to array.\n this._events[type] = [this._events[type]];\n }\n\n // If we've already got an array, just add\n if(prepend){\n this._events[type].unshift(listener);\n }else{\n this._events[type].push(listener);\n }\n\n // Check for listener leak\n if (\n !this._events[type].warned &&\n this._maxListeners > 0 &&\n this._events[type].length > this._maxListeners\n ) {\n this._events[type].warned = true;\n logPossibleMemoryLeak.call(this, this._events[type].length, type);\n }\n }\n\n return this;\n }\n\n EventEmitter.prototype.off = function(type, listener) {\n if (typeof listener !== 'function') {\n throw new Error('removeListener only takes instances of Function');\n }\n\n var handlers,leafs=[];\n\n if(this.wildcard) {\n var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);\n }\n else {\n // does not use listeners(), so no side effect of creating _events[type]\n if (!this._events[type]) return this;\n handlers = this._events[type];\n leafs.push({_listeners:handlers});\n }\n\n for (var iLeaf=0; iLeaf 0) {\n recursivelyGarbageCollect(root[key]);\n }\n if (Object.keys(obj).length === 0) {\n delete root[key];\n }\n }\n }\n recursivelyGarbageCollect(this.listenerTree);\n\n return this;\n };\n\n EventEmitter.prototype.offAny = function(fn) {\n var i = 0, l = 0, fns;\n if (fn && this._all && this._all.length > 0) {\n fns = this._all;\n for(i = 0, l = fns.length; i < l; i++) {\n if(fn === fns[i]) {\n fns.splice(i, 1);\n if (this._removeListener)\n this.emit(\"removeListenerAny\", fn);\n return this;\n }\n }\n } else {\n fns = this._all;\n if (this._removeListener) {\n for(i = 0, l = fns.length; i < l; i++)\n this.emit(\"removeListenerAny\", fns[i]);\n }\n this._all = [];\n }\n return this;\n };\n\n EventEmitter.prototype.removeListener = EventEmitter.prototype.off;\n\n EventEmitter.prototype.removeAllListeners = function(type) {\n if (type === undefined) {\n !this._events || init.call(this);\n return this;\n }\n\n if (this.wildcard) {\n var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);\n\n for (var iLeaf=0; iLeaf { + if (res.type == 'connect') { + if (res.data == "未打开适配器") { + wx.showModal({ + title: "提示", + content: "请检查手机蓝牙和定位功能是否打开?", + showCancel: false, + confirmText: "确定", + }); + } else { + this.setData({ + info: res.data + }) + app.globalData.bleStatus = res.data + } + } + }) + } + }, + + closeblue() { + wx.showLoading({ + title: "正在停止...", + }); + app.globalData.ble.close() + setTimeout(() => { + wx.hideLoading() + }, 1000); + app.globalData.bleStatus = false + this.setData({ + bleStatus: false, + respond: [] + }) + + }, + + + openLock(userTelephone, userPassword, pwd, openLockType) { + wx.showLoading({ + title: "正在发送...", + }); + setTimeout(() => { + wx.hideLoading() + }, 1000); + + let cmd = 0x41 + + let ut = util.stringToUint8Array(userTelephone) + + let up = util.stringToUint8Array(userPassword) + + let p = util.hexStringToBytesWithPadding(pwd, 10, 0xff) + + let length = 1+11+6+10+1 + + let b = new Uint8Array(length) + + b[0] = cmd + b.set(ut, 1) + b.set(up, 12) + b.set(p, 18) + b[28] = openLockType + console.log(b) + app.globalData.ble.send(cmd, b, length) + }, +}) + + +/** + * 版本比较 + */ +function versionCompare (ver1, ver2) { //版本比较 + // console.log("ver1" + ver1 + 'ver2' + ver2); + var version1pre = parseFloat(ver1) + var version2pre = parseFloat(ver2) + var version1next = parseInt(ver1.replace(version1pre + ".", "")) + var version2next = parseInt(ver2.replace(version2pre + ".", "")) + if (version1pre > version2pre) + return true + else if (version1pre < version2pre) + return false + else { + if (version1next > version2next) + return true + else + return false + } +} + +/** + * 微信版本检测 + * Android从微信 6.5.7 开始支持,iOS从微信 6.5.6 开始支持 + */ +function checkWechatVersion() { + wx.getSystemInfo({ + success: function (res) { + let si = res; + if (si.platform == 'android' && versionCompare('6.5.7', si.version)) { + + console.log("当前安卓微信版本过低,请更新至最新版本体验"); + + wx.showModal({ + title: '提示', + content: '当前微信版本过低,请更新至最新版本体验', + showCancel: false + }) + return false; + }else if (si.platform == 'ios' && versionCompare('6.5.6', si.version)) { + + console.log("当前苹果微信版本过低,请更新至最新版本体验"); + + wx.showModal({ + title: '提示', + content: '当前微信版本过低,请更新至最新版本体验', + showCancel: false + }) + return false; + } + return true; + } + }) +} + + + \ No newline at end of file diff --git a/pages/asyntest/asyntest.json b/pages/asyntest/asyntest.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/asyntest/asyntest.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/asyntest/asyntest.wxml b/pages/asyntest/asyntest.wxml new file mode 100644 index 0000000..26c9c68 --- /dev/null +++ b/pages/asyntest/asyntest.wxml @@ -0,0 +1,18 @@ + + + + + + {{info}} + + + + + + + + + + + + \ No newline at end of file diff --git a/pages/asyntest/asyntest.wxss b/pages/asyntest/asyntest.wxss new file mode 100644 index 0000000..b71144f --- /dev/null +++ b/pages/asyntest/asyntest.wxss @@ -0,0 +1,28 @@ +/* pages/asyntest/asyntest.wxss */ +.vertical{ + display: flex; + flex-direction: column; +} + +/**index.wxss**/ +.horizontal{ + display: flex; + flex-direction: row; +} + +.btinfo{ + height:100px; +} + +.contentview { +margin: 0 10px; +} + +.button { +margin: 5px; +} + +.myview{ + height:200px; + word-break:break-all;/* 自动换行 */ +} \ No newline at end of file diff --git a/pages/index/index.js b/pages/index/index.js new file mode 100644 index 0000000..bbdeac1 --- /dev/null +++ b/pages/index/index.js @@ -0,0 +1,212 @@ +const app = getApp() + +function inArray(arr, key, val) { + for (let i = 0; i < arr.length; i++) { + if (arr[i][key] === val) { + return i; + } + } + return -1; +} + +// ArrayBuffer转16进度字符串示例 +function ab2hex(buffer) { + var hexArr = Array.prototype.map.call( + new Uint8Array(buffer), + function (bit) { + return ('00' + bit.toString(16)).slice(-2) + } + ) + return hexArr.join(''); +} + +Page({ + data: { + devices: [], + connected: false, + chs: [], + }, + + openBluetoothAdapter() { + wx.openBluetoothAdapter({ + success: (res) => { + console.log('openBluetoothAdapter success', res) + this.startBluetoothDevicesDiscovery() + }, + fail: (res) => { + if (res.errCode === 10001) { + wx.onBluetoothAdapterStateChange(function (res) { + console.log('onBluetoothAdapterStateChange', res) + if (res.available) { + this.startBluetoothDevicesDiscovery() + } + }) + } + } + }) + }, + getBluetoothAdapterState() { + wx.getBluetoothAdapterState({ + success: (res) => { + console.log('getBluetoothAdapterState', res) + if (res.discovering) { + this.onBluetoothDeviceFound() + } else if (res.available) { + this.startBluetoothDevicesDiscovery() + } + } + }) + }, + startBluetoothDevicesDiscovery() { + if (this._discoveryStarted) { + return + } + this._discoveryStarted = true + wx.startBluetoothDevicesDiscovery({ + allowDuplicatesKey: true, + success: (res) => { + console.log('startBluetoothDevicesDiscovery success', res) + this.onBluetoothDeviceFound() + }, + }) + }, + stopBluetoothDevicesDiscovery() { + wx.stopBluetoothDevicesDiscovery() + }, + onBluetoothDeviceFound() { + wx.onBluetoothDeviceFound((res) => { + res.devices.forEach(device => { + if (!device.name && !device.localName) { + return + } + const foundDevices = this.data.devices + const idx = inArray(foundDevices, 'deviceId', device.deviceId) + const data = {} + if (idx === -1) { + data[`devices[${foundDevices.length}]`] = device + } else { + data[`devices[${idx}]`] = device + } + this.setData(data) + }) + }) + }, + createBLEConnection(e) { + const ds = e.currentTarget.dataset + const deviceId = ds.deviceId + const name = ds.name + wx.createBLEConnection({ + deviceId, + success: (res) => { + this.setData({ + connected: true, + name, + deviceId, + }) + this.getBLEDeviceServices(deviceId) + } + }) + this.stopBluetoothDevicesDiscovery() + }, + closeBLEConnection() { + wx.closeBLEConnection({ + deviceId: this.data.deviceId + }) + this.setData({ + connected: false, + chs: [], + canWrite: false, + }) + }, + getBLEDeviceServices(deviceId) { + wx.getBLEDeviceServices({ + deviceId, + success: (res) => { + for (let i = 0; i < res.services.length; i++) { + if (res.services[i].isPrimary) { + this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid) + return + } + } + } + }) + }, + getBLEDeviceCharacteristics(deviceId, serviceId) { + wx.getBLEDeviceCharacteristics({ + deviceId, + serviceId, + success: (res) => { + console.log('getBLEDeviceCharacteristics success', res.characteristics) + for (let i = 0; i < res.characteristics.length; i++) { + let item = res.characteristics[i] + if (item.properties.read) { + wx.readBLECharacteristicValue({ + deviceId, + serviceId, + characteristicId: item.uuid, + }) + } + if (item.properties.write) { + this.setData({ + canWrite: true + }) + this._deviceId = deviceId + this._serviceId = serviceId + this._characteristicId = item.uuid + this.writeBLECharacteristicValue() + } + if (item.properties.notify || item.properties.indicate) { + wx.notifyBLECharacteristicValueChange({ + deviceId, + serviceId, + characteristicId: item.uuid, + state: true, + }) + } + } + }, + fail(res) { + console.error('getBLEDeviceCharacteristics', res) + } + }) + // 操作之前先监听,保证第一时间获取数据 + wx.onBLECharacteristicValueChange((characteristic) => { + const idx = inArray(this.data.chs, 'uuid', characteristic.characteristicId) + const data = {} + if (idx === -1) { + data[`chs[${this.data.chs.length}]`] = { + uuid: characteristic.characteristicId, + value: ab2hex(characteristic.value) + } + } else { + data[`chs[${idx}]`] = { + uuid: characteristic.characteristicId, + value: ab2hex(characteristic.value) + } + } + // data[`chs[${this.data.chs.length}]`] = { + // uuid: characteristic.characteristicId, + // value: ab2hex(characteristic.value) + // } + this.setData(data) + }) + }, + + + writeBLECharacteristicValue() { + // 向蓝牙设备发送一个0x00的16进制数据 + let buffer = new ArrayBuffer(1) + let dataView = new DataView(buffer) + dataView.setUint8(0, Math.random() * 255 | 0) + wx.writeBLECharacteristicValue({ + deviceId: this._deviceId, + serviceId: this._deviceId, + characteristicId: this._characteristicId, + value: buffer, + }) + }, + closeBluetoothAdapter() { + wx.closeBluetoothAdapter() + this._discoveryStarted = false + }, +}) diff --git a/pages/index/index.json b/pages/index/index.json new file mode 100644 index 0000000..8835af0 --- /dev/null +++ b/pages/index/index.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/index/index.wxml b/pages/index/index.wxml new file mode 100644 index 0000000..1fb045b --- /dev/null +++ b/pages/index/index.wxml @@ -0,0 +1,41 @@ + +module.exports.max = function(n1, n2) { + return Math.max(n1, n2) +} +module.exports.len = function(arr) { + arr = arr || [] + return arr.length +} + + + + + +已发现 {{devices.length}} 个外围设备: + + + {{item.name}} + 信号强度: {{item.RSSI}}dBm ({{utils.max(0, item.RSSI + 100)}}%) + UUID: {{item.deviceId}} + Service数量: {{utils.len(item.advertisServiceUUIDs)}} + + + + + + 已连接到 {{name}} + + + + + + + 特性UUID: {{item.uuid}} + 特性值: {{item.value}} + + \ No newline at end of file diff --git a/pages/index/index.wxss b/pages/index/index.wxss new file mode 100644 index 0000000..561033e --- /dev/null +++ b/pages/index/index.wxss @@ -0,0 +1,41 @@ +page { + color: #333; +} +.devices_summary { + margin-top: 30px; + padding: 10px; + font-size: 16px; +} +.device_list { + height: 300px; + margin: 50px 5px; + margin-top: 0; + border: 1px solid #EEE; + border-radius: 5px; + width: auto; +} +.device_item { + border-bottom: 1px solid #EEE; + padding: 10px; + color: #666; +} +.device_item_hover { + background-color: rgba(0, 0, 0, .1); +} +.connected_info { + position: fixed; + bottom: 0; + width: 100%; + background-color: #F0F0F0; + padding: 10px; + padding-bottom: 20px; + margin-bottom: env(safe-area-inset-bottom); + font-size: 14px; + min-height: 100px; + box-shadow: 0px 0px 3px 0px; +} +.connected_info .operation { + position: absolute; + display: inline-block; + right: 30px; +} diff --git a/pages/lanyatest/lanyatest.js b/pages/lanyatest/lanyatest.js new file mode 100644 index 0000000..7e53386 --- /dev/null +++ b/pages/lanyatest/lanyatest.js @@ -0,0 +1,637 @@ +// pages/lanyatest/lanyatest.js + +var longUtil = require('./../../utils/long.js'); + +Page({ + + /** + * 页面的初始数据 + */ + data: { + info:"未初始化蓝牙适配器", + deviceName:"yxwl01680000004895", + connectedDeviceId:"", + deviceId:"", + services:"", + + mtuSize:512, + servicesUUID:"000018f0-0000-1000-8000-00805f9b34fb", + notifyUUID:"00002af0-0000-1000-8000-00805f9b34fb", + writeUUID:"00002af1-0000-1000-8000-00805f9b34fb", + + serviceId:"", + notifyCharacteristicsId:"", + writeCharacteristicsId: "", + + userTelephone:"13028878230", + userPassword:"130288", + pwd:"12344321", + openLockType:2, + sendmsg:"8989415B017BC796C6F8001DA0B0AAB7AFABB1B6B9B1BAB7B0BE8989A9AB8BABBE80EEEEE2E2E6E6EFE4", + systemInfo:{}, + }, + + lanyatest1(event){ + var that = this; + + wx.getSystemInfo({ + success: function (res) { + console.log(res.model) + console.log(res.pixelRatio) + console.log(res.windowWidth) + console.log(res.windowHeight) + console.log(res.language) + console.log(res.version) + console.log(res.platform) + console.log(res.environment) + that.setData({ + systemInfo:res + }); + } + }) + + checkWechatVersion(that.data.systemInfo) + + wx.openBluetoothAdapter({ + success: function (res) { + console.log('初始化蓝牙适配器成功') + //页面日志显示 + that.setData({ + info: '初始化蓝牙适配器成功' + }) + }, + fail: function (res) { + console.log('请打开蓝牙和定位功能') + that.setData({ + info: '请打开蓝牙和定位功能' + }) + } + }) + }, + + + + lanyatest2(event){ + var that = this; + wx.getBluetoothAdapterState({ + + success: function (res) { + + //打印相关信息 + console.log(JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available); + + that.setData({ + info: JSON.stringify(res.errMsg) +"\n蓝牙是否可用:" + res.available + }) + + }, + fail: function (res) { + + //打印相关信息 + console.log(JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available); + + that.setData({ + info: JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available + }) + + } + + }) + + }, + + + + lanyatest3(event){ + var that = this; + wx.startBluetoothDevicesDiscovery({ + services: [that.data.servicesUUID], //如果填写了此UUID,那么只会搜索出含有这个UUID的设备 + success: function (res) { + that.setData({ + info: "搜索设备" + JSON.stringify(res), + }) + console.log('搜索设备返回' + JSON.stringify(res)) + + } + }) + + }, + + + + lanyatest4(event){ + var that = this; + var pos; + wx.getBluetoothDevices({ + success: function (res) { + + for (var i = 0; i < res.devices.length; i++) { + pos = that.data.deviceName.indexOf(res.devices[i].name); + if(pos != -1) + { + that.setData({ + connectedDeviceId: res.devices[i].deviceId + }) + console.log('设备号:' + res.devices[i].name + " Mac地址: " + that.data.connectedDeviceId + " pos: " + pos + "\n") + break; + } + } + that.setData({ + info: "设备列表\n" + JSON.stringify(res.devices), + devices: res.devices + }) + + console.log('搜设备数目:' + res.devices.length) + console.log('设备信息:\n' + JSON.stringify(res.devices)+"\n") + } + }) + + }, + + + + lanyaconnect(event){ + var that = this; + wx.createBLEConnection({ + deviceId: that.data.connectedDeviceId, + success: function (res) { + console.log('调试信息:' + res.errMsg); + that.setData({ + info: "MAC地址:" + event.currentTarget.id + ' 调试信息:' + res.errMsg, + }) + if (that.data.systemInfo.platform == 'android') + { + wx.setBLEMTU({ + deviceId: that.data.connectedDeviceId, + mtu:that.data.mtuSize, + success:(res)=>{ + console.log("setBLEMTU success >> " + JSON.stringify(res)) + }, + fail:(res)=>{ + console.log("setBLEMTU fail >> " + JSON.stringify(res)) + } + }) + } + }, + fail: function () { + console.log("连接失败"); + }, + + }) + + }, + + + lanyatest6(event){ + var that = this; + wx.stopBluetoothDevicesDiscovery({ + success: function (res) { + console.log("停止搜索" + JSON.stringify(res.errMsg)); + that.setData({ + info: "停止搜索" + JSON.stringify(res.errMsg), + }) + } + }) + + }, + + + + lanyatest7(event){ + var that = this; + wx.getBLEDeviceServices({ + // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取 + deviceId: that.data.connectedDeviceId, + success: function (res) { + console.log('services UUID:\n', JSON.stringify(res.services)); + for (var i = 0; i < res.services.length; i++) { + console.log("第"+(i+1) + "个UUID:" + res.services[i].uuid+"\n") + } + that.setData({ + services: res.services, + info: JSON.stringify(res.services), + }) + } + }) + + }, + + + + lanyatest8(event){ + var that = this; + var myUUID = toPlatformString(that.data.systemInfo, that.data.servicesUUID);//具有写、通知属性的服务uuid + console.log(' UUID: ' + myUUID + " mac: " + that.data.connectedDeviceId) + wx.getBLEDeviceCharacteristics({ + // 这里的 deviceId 需要在上面的接口中获取 + deviceId: that.data.connectedDeviceId, + // 这里的 serviceId 需要在上面的 接口中获取 + serviceId: myUUID, + success: function (res) { + console.log("%c getBLEDeviceCharacteristics", "color:red;"); + for (var i = 0; i < res.characteristics.length; i++) { + console.log('特征值:' + res.characteristics[i].uuid) + + if (res.characteristics[i].properties.notify) { + console.log("notifyServicweId:", myUUID); + console.log("notifyCharacteristicsId:", res.characteristics[i].uuid); + that.setData({ + notifyServicweId: myUUID, + notifyCharacteristicsId: that.data.notifyUUID,//手动设置notifyCharacteristicsId为这个UUID,为了方便写死在这里 + + }) + } + if (res.characteristics[i].properties.write) { + console.log("writeServicweId:", myUUID); + console.log("writeCharacteristicsId:", res.characteristics[i].uuid); + that.setData({ + writeServicweId: myUUID, + //writeCharacteristicsId: res.characteristics[i].uuid, + writeCharacteristicsId: that.data.writeUUID,//手动设置writeCharacteristicsId为这个UUID,为了方便写死在这里 + }) + + } + + } + console.log('device getBLEDeviceCharacteristics:', res.characteristics); + + that.setData({ + msg: JSON.stringify(res.characteristics), + }) + }, + fail: function () { + console.log("fail"); + }, + + }) + + }, + + + + + lanyatest9(event){ + var that = this; + var notifyServicweId = toPlatformString(that.data.systemInfo, that.data.servicesUUID); //具有写、通知属性的服务uuid + var notifyCharacteristicsId = toPlatformString(that.data.systemInfo, that.data.notifyCharacteristicsId); + console.log("启用notify的serviceId", notifyServicweId); + console.log("启用notify的notifyCharacteristicsId", notifyCharacteristicsId); + + wx.notifyBLECharacteristicValueChange({ + state: true, // 启用 notify 功能 + deviceId: that.data.connectedDeviceId, + // 这里的 serviceId 就是that.data.servicesUUID + serviceId: notifyServicweId, + characteristicId: notifyCharacteristicsId, + success: function (res) { + console.log('notifyBLECharacteristicValueChange success', res.errMsg) + var msg = '启动notify:' + res.errMsg + that.setData({ + info: msg + }) + }, + fail: function () { + console.log('启动notify:' + res.errMsg); + + }, + }) + + + }, + + + + lanyatest10(event){ + var that = this; + console.log("开始接收数据"); + + wx.onBLECharacteristicValueChange(function (res) { + console.log("characteristicId:" + res.characteristicId) + console.log("serviceId: " + res.serviceId) + console.log("deviceId: " + res.deviceId) + console.log("Length: " + res.value.byteLength) + console.log("hex value: " + ab2hex(res.value)) + that.setData({ + info: that.data.info + ab2hex(res.value) + }) + + }) + + }, + + + + + lanyatest11(event){ + var that = this + //var hex = that.data.sendmsg //要发送的信息 + + var myUUID = toPlatformString(that.data.systemInfo, that.data.servicesUUID); //具有写、通知属性的服务uuid + var writeCharId = toPlatformString(that.data.systemInfo, that.data.writeCharacteristicsId); + + //console.log('要发送的信息是:'+hex) + + //var typedArray1 = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) { + // return parseInt(h, 16) + //})) + //console.log(typedArray1) + + var typedArray = packData(that.data.userTelephone, that.data.userPassword, that.data.pwd, that.data.openLockType) + + console.log(typedArray) + + wx.writeBLECharacteristicValue({ + deviceId: that.data.connectedDeviceId, + serviceId: myUUID, + characteristicId: writeCharId, + // 这里的value是ArrayBuffer类型 + value: typedArray.buffer, + success: function (res) { + console.log('写入成功', res.errMsg) + }, + fail(res){ + console.log('写入失败', res.errMsg) + } + }) + + }, + + + + //获取输入框的数据 + getmsg(event){ + this.setData({ + sendmsg:event.detail.value + }) + + }, + + + lanyatest12(event){ + var that = this; + wx.closeBLEConnection({ + deviceId: that.data.connectedDeviceId, + success: function (res) { + that.setData({ + connectedDeviceId: "", + }) + console.log('断开蓝牙设备成功:' + res.errMsg) + }, + fail:function(res){ + console.log('断开蓝牙设备失败:' + res.errMsg) + } + }) + }, + +}) + + +function toPlatformString(systemInfo, str) +{ + if (systemInfo.platform == 'android') + return str.toLowerCase(); + else if (systemInfo.platform == 'ios') + return str.toUpperCase(); + else + return str; +} + +/** + * 版本比较 + */ +function versionCompare (ver1, ver2) { //版本比较 + // console.log("ver1" + ver1 + 'ver2' + ver2); + var version1pre = parseFloat(ver1) + var version2pre = parseFloat(ver2) + var version1next = parseInt(ver1.replace(version1pre + ".", "")) + var version2next = parseInt(ver2.replace(version2pre + ".", "")) + if (version1pre > version2pre) + return true + else if (version1pre < version2pre) + return false + else { + if (version1next > version2next) + return true + else + return false + } +} + +/** + * 微信版本检测 + * Android从微信 6.5.7 开始支持,iOS从微信 6.5.6 开始支持 + */ +function checkWechatVersion(systemInfo) { + + if (systemInfo.platform == 'android' && versionCompare('6.5.7', systemInfo.version)) { + wx.showModal({ + title: '提示', + content: '当前微信版本过低,请更新至最新版本体验', + showCancel: false + }) + }else if (systemInfo.platform == 'ios' && versionCompare('6.5.6', systemInfo.version)) { + wx.showModal({ + title: '提示', + content: '当前微信版本过低,请更新至最新版本体验', + showCancel: false + }) + } +} + + +function Uint8ArrayToString(fileData){ + var dataString = ""; + for (var i = 0; i < fileData.length; i++) { + dataString += String.fromCharCode(fileData[i]); + } + return dataString +} + + +// 微信官方给的ArrayBuffer转十六进制示例 +function ab2hex(buffer) { + var hexArr = Array.prototype.map.call( + new Uint8Array(buffer), + function (bit) { + return ('00' + bit.toString(16)).slice(-2) + } + ) + return hexArr.join(','); +} + + + //转成可展会的文字 +function hexCharCodeToStr(hexCharCodeStr) { + var trimedStr = hexCharCodeStr.trim(); + var rawStr = trimedStr.substr(0, 2).toLowerCase() === '0x' ? trimedStr.substr(2) : trimedStr; + var len = rawStr.length; + var curCharCode; + var resultStr = []; + for (var i = 0; i < len; i = i + 2) { + curCharCode = parseInt(rawStr.substr(i, 2), 16); + resultStr.push(String.fromCharCode(curCharCode)); + } + return resultStr.join(''); +} + + //转换成需要的格式 +function buf2string(buffer) { + var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x) + + return arr.map((char, i) => { + return String.fromCharCode(char); + }).join(''); +} + + + + + + + function stringToUint8Array(str){ + let arr = []; + for (let i = 0, j = str.length; i < j; ++i) { + arr.push(str.charCodeAt(i)); + } + let tmpUint8Array = new Uint8Array(arr); + return tmpUint8Array + } + + function decodeHexNibble(c) { + if (c >= 48 && c <= 57) { + return c - 48; + } else if (c >= 65 && c <= 70) { + return c - 65 + 10; + } else { + return c >= 97 && c <= 102 ? c - 97 + 10 : -1; + } + } + + function decodeHexByte(s, pos) { + let hi = decodeHexNibble(s.charCodeAt(pos)); + let lo = decodeHexNibble(s.charCodeAt(pos + 1)); + return ((hi << 4) + lo); + } + + function hexStringToBytesWithPadding(str, byteLen, padding) { + let len = str.length + + let length = 2 * byteLen + + if (length >= len && (length & 1) == 0) { + if (length == 0) { + return [0]; + } else { + //let buffer = new ArrayBuffer(length >>> 1); + //let bytes = new Uint8Array(buffer); + let bytes = new Uint8Array(length >>> 1); + + for(let i = 0; i < len; i += 2) { + bytes[i >>> 1] = decodeHexByte(str, i); + } + + for(let i = 0; i < byteLen-len/2; i++) + bytes[len/2+i] = padding; + + return bytes; + } + } + else + return [0]; + } + + + function hexStringToBytes(str) { + let s = str; + if(s.length < 12) + { + let tmp = 12-s.length + for(let i = 0; i< tmp; i++) + s = "0" + s; + } + else + s = str.substr(s.length-12, s.length); + + let start = 0 + let length = s.length + + if (length >= 0 && (length & 1) == 0) { + if (length == 0) { + return new byte[0]; + } else { + let bytes = new Uint8Array(length >>> 1); + + for(let i = 0; i < length; i += 2) { + bytes[i >>> 1] = decodeHexByte(s, start + i); + } + + return bytes; + } + } + else + return [0]; + + } + + + function packData(userTelephone, userPassword, pwd, openLockType) + { + let cmd = 0x41 + + let ut = stringToUint8Array(userTelephone) + let up = stringToUint8Array(userPassword) + let p = hexStringToBytesWithPadding(pwd, 10, 0xff) + let length = 1+11+6+10+1 + + let b = new Uint8Array(length) + + b[0] = cmd + b.set(ut, 1) + b.set(up, 12) + b.set(p, 18) + b[28] = openLockType + + console.log(b) + + return packMsg(0x41, b, length) + } + + function packMsg(cmd, data, payloadLength) + { + let length = 13 + payloadLength + //let buffer = new ArrayBuffer(length); + let b = new Uint8Array(length); + + b[0] = 0x89; + b[1] = 0x89; + b[2] = cmd; + + let timestamp = new Date().getTime(); + let ts = timestamp.toString(16) + let t = hexStringToBytes(ts) + + b.set(t, 4) + + b[3] = b[9]; + + b[10] = (payloadLength>>8)&0xff; + b[11] = payloadLength & 0xff; + + let key = b[3]; + for (let i=0; i + + + + + {{info}} + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pages/lanyatest/lanyatest.wxss b/pages/lanyatest/lanyatest.wxss new file mode 100644 index 0000000..066f4e3 --- /dev/null +++ b/pages/lanyatest/lanyatest.wxss @@ -0,0 +1,28 @@ +/* pages/lanyatest/lanyatest.wxss */ +.vertical{ + display: flex; + flex-direction: column; +} + +/**index.wxss**/ +.horizontal{ + display: flex; + flex-direction: row; +} + +.btinfo{ + height:100px; +} + +.contentview { +margin: 0 10px; +} + +.button { +margin: 5px; +} + +.myview{ + height:200px; + word-break:break-all;/* 自动换行 */ +} \ No newline at end of file diff --git a/pages/logs/logs.js b/pages/logs/logs.js new file mode 100644 index 0000000..85f6aac --- /dev/null +++ b/pages/logs/logs.js @@ -0,0 +1,18 @@ +// logs.js +const util = require('../../utils/util.js') + +Page({ + data: { + logs: [] + }, + onLoad() { + this.setData({ + logs: (wx.getStorageSync('logs') || []).map(log => { + return { + date: util.formatTime(new Date(log)), + timeStamp: log + } + }) + }) + } +}) diff --git a/pages/logs/logs.json b/pages/logs/logs.json new file mode 100644 index 0000000..3ee76c1 --- /dev/null +++ b/pages/logs/logs.json @@ -0,0 +1,4 @@ +{ + "navigationBarTitleText": "查看启动日志", + "usingComponents": {} +} \ No newline at end of file diff --git a/pages/logs/logs.wxml b/pages/logs/logs.wxml new file mode 100644 index 0000000..0b6b645 --- /dev/null +++ b/pages/logs/logs.wxml @@ -0,0 +1,6 @@ + + + + {{index + 1}}. {{log.date}} + + diff --git a/pages/logs/logs.wxss b/pages/logs/logs.wxss new file mode 100644 index 0000000..94d4b88 --- /dev/null +++ b/pages/logs/logs.wxss @@ -0,0 +1,8 @@ +.log-list { + display: flex; + flex-direction: column; + padding: 40rpx; +} +.log-item { + margin: 10rpx; +} diff --git a/project.config.json b/project.config.json new file mode 100644 index 0000000..ec5a2b0 --- /dev/null +++ b/project.config.json @@ -0,0 +1,74 @@ +{ + "description": "项目配置文件", + "packOptions": { + "ignore": [] + }, + "setting": { + "urlCheck": true, + "es6": true, + "enhance": true, + "postcss": true, + "preloadBackgroundData": false, + "minified": true, + "newFeature": false, + "coverView": true, + "nodeModules": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "scopeDataCheck": false, + "uglifyFileName": false, + "checkInvalidKey": true, + "checkSiteMap": true, + "uploadWithSourceMap": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "enableEngineNative": false, + "useIsolateContext": true, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "showES6CompileOption": false + }, + "compileType": "miniprogram", + "libVersion": "2.19.4", + "appid": "wx7775ba175d855273", + "projectname": "%E8%93%9D%E7%89%99%E6%B5%8B%E8%AF%95", + "debugOptions": { + "hidedInDevtools": [] + }, + "scripts": {}, + "staticServerOptions": { + "baseURL": "", + "servePath": "" + }, + "isGameTourist": false, + "condition": { + "search": { + "list": [] + }, + "conversation": { + "list": [] + }, + "game": { + "list": [] + }, + "plugin": { + "list": [] + }, + "gamePlugin": { + "list": [] + }, + "miniprogram": { + "list": [] + } + } +} \ No newline at end of file diff --git a/sitemap.json b/sitemap.json new file mode 100644 index 0000000..ca02add --- /dev/null +++ b/sitemap.json @@ -0,0 +1,7 @@ +{ + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", + "rules": [{ + "action": "allow", + "page": "*" + }] +} \ No newline at end of file diff --git a/utils/btls/ble.js b/utils/btls/ble.js new file mode 100644 index 0000000..99866ef --- /dev/null +++ b/utils/btls/ble.js @@ -0,0 +1,59 @@ +import BLEHandler from "./bleHandler" + +class BLE extends BLEHandler { + constructor(blename, emitter) { + super(blename, emitter) + } + listen(callback) { + // 蓝牙事件注册,打开channel + this.emitter.removeAllListeners("channel") + this.emitter.on("channel", callback) + } + removeListen() { + // 移除所有蓝牙事件 + this.emitter.removeAllListeners("channel") + } + async init() { + let flow = false + // 打开蓝牙适配器状态监听 + this.onBLEConnectionStateChange() + // 蓝牙适配器初始化 + await this.openAdapter() + // 搜索蓝牙设备 + await this.startSearch() + // 获取设备ID + + flow = await this.onBluetoothFound() + if (!flow) return + + // 停止搜索设备 + await this.stopSearchBluetooth() + + // 连接蓝牙 + await this.connectBlue(); + + //安卓手机需要设置MTU Size + await this.setBLEMTU(); + + // 获取serviceId + await this.getBLEServices() + // 设置特征值 + await this.getCharacteristics(); + // 订阅特征值 + await this.notifyBLECharacteristicValueChange() + // 打开传输监听,等待设备反馈数据 + this.onBLECharacteristicValueChange() + } + // 发送指令 + async send(cmd, payload) { + let flow = await this.sentOrder(cmd, payload) + return flow + } + async close() { + await this.closeBLEConnection() + await this.closeBLEAdapter() + } + +} + +export { BLE }; diff --git a/utils/btls/bleHandler.js b/utils/btls/bleHandler.js new file mode 100644 index 0000000..9676999 --- /dev/null +++ b/utils/btls/bleHandler.js @@ -0,0 +1,296 @@ +import * as t from "./tools" + +/* +import { HTTP } from "../server"; +*/ + +/** + * 蓝牙工具类 + * 封装小程序蓝牙流程方法 + * 处理事件通信 + */ +class BLEHandler { + constructor(blename, emitter) { + this.blename = blename //厂家自定义的蓝牙设备名称 + this.emitter = emitter + this.readCharacteristicId = ""; //能从硬件返回的信息中自动提取 + this.writeCharacteristicId = "00002af1-0000-1000-8000-00805f9b34fb"; //能从硬件返回的信息中自动提取 + this.notifyCharacteristicId = "00002af0-0000-1000-8000-00805f9b34fb"; //能从硬件返回的信息中自动提取 + this.deviceId = ""; //蓝牙Mac地址 + this.serviceId = "000018f0-0000-1000-8000-00805f9b34fb";//具体的serviceId要自己根据硬件提供设置。 + + this.receivePacket = []; + this.recPktLength = 0; + this.recPktOffset = 0; + } + async openAdapter() { + let [err, res] = await t._openAdapter.call(this); + if (err != null) { + this.emitter.emit("channel", { + type: "connect", + data: "未打开适配器" + }) + return false; + } + return true + } + async startSearch() { + let [err, res] = await t._startSearch.call(this); + if (err != null) { + return; + } + this.emitter.emit("channel", { + type: "connect", + data: "正在连接中..." + }) + + } + async onBluetoothFound() { + let [err, res] = await t._onBluetoothFound.call(this); + if (err != null) { + this.emitter.emit("channel", { + type: "connect", + data: "未找到设备" + }) + return false; + } + return true + } + + async getBluetoothDevices() { + let [err, res] = await t._getBluetoothDevices.call(this); + if (err != null) { + this.emitter.emit("channel", { + type: "connect", + data: "未找到设备" + }) + return false; + } + return true + } + + + async stopSearchBluetooth() { + let [err, res] = await t._stopSearchBluetooth.call(this); + if (err != null) { + return; + } + } + async connectBlue() { + let [err, res] = await t._connectBlue.call(this); + if (err != null) { + return; + } + } + + async setBLEMTU() { + let [err, res] = await t._setBLEMTU.call(this); + if (err != null) { + return; + } + } + + async getBLEServices() { + let [err, res] = await t._getBLEServices.call(this); + if (err != null) { + return; + } + } + async getCharacteristics() { + let [err, res] = await t._getCharacteristics.call(this); + if (err != null) { + this.emitter.emit("channel", { + type: "connect", + data: "无法订阅特征值" + }) + // 取消连接 + this.closeBLEConnection() + this.closeBLEAdapter() + wx.setStorageSync("bluestatus", ""); + return false; + } + this.emitter.emit("channel", { + type: "connect", + data: "蓝牙已连接" + }) + wx.setStorageSync("bluestatus", "on"); + return true + } + async notifyBLECharacteristicValueChange() { + let [err, res] = await t._notifyBLECharacteristicValueChange.call(this); + if (err != null) { + return; + } + } + async closeBLEConnection() { + let [err, res] = await t._closeBLEConnection.call(this); + if (err != null) { + return; + } + } + async closeBLEAdapter() { + let [err, res] = await t._closeBLEAdapter.call(this); + if (err != null) { + return; + } + } + async sentOrder(cmd, payload) { + let data = t._sentOrder(cmd, payload) + console.log("-- 发送数据:", data) + let arrayBuffer = new Uint8Array(data).buffer; + let [err, res] = await t._writeBLECharacteristicValue.call(this, arrayBuffer) + if (err != null) { + return false + } + console.log("数据发送成功!") + return true + + } + + // 打开蓝牙适配器状态监听 + onBLEConnectionStateChange() { + wx.onBLEConnectionStateChange(res => { + // 该方法回调中可以用于处理连接意外断开等异常情况 + if (!res.connected) { + this.closeBLEAdapter() + wx.setStorageSync("bluestatus", ""); + this.emitter.emit("channel", { + type: "connect", + data: "蓝牙已断开" + }) + } + }, err => { + console.log('err', err) + }) + } + + // 收到设备推送的notification + onBLECharacteristicValueChange() { + wx.onBLECharacteristicValueChange(res => { + //let arrbf = new Uint8Array(res.value) + //console.log(`收到硬件数据反馈!命令码为:${arrbf[2]}`) + //if (this._checkData(arrbf)) { + //} + let arrbf = new Uint8Array(res.value) + if (arrbf[0] == 0x89 && arrbf[1] == 0x89) + { + let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff) + this.recPktLength = 13 + dataLength + this.receivePacket = new Uint8Array(this.recPktLength) + this.recPktOffset = 0 + console.log("开始接收数据:length= " + arrbf.length + " data= " + arrbf) + this.receivePacket.set(arrbf, this.recPktOffset) + this.recPktOffset += arrbf.length; + if( this.recPktOffset == this.recPktLength){ + this.getReceivePacket(this.receivePacket) + } + } + else + { + console.log("继续接收数据:length= " + arrbf.length + " data= " + arrbf) + this.receivePacket.set(arrbf, this.recPktOffset) + this.recPktOffset += arrbf.length; + if( this.recPktOffset == this.recPktLength){ + this.getReceivePacket(this.receivePacket) + } + } + }) + } + + /* + _uploadInfo(message) { + console.log("-- 准备数据同步!", this._mapToArray(message)) + let bleorder = wx.getStorageSync("bleorder"); + let blecabinet = wx.getStorageSync("blecabinet") + HTTP({ + url: "cabinet/uploadBlueData", + methods: "post", + data: { + cabinetQrCode: blecabinet, + order: bleorder, + message: this._mapToArray(message) + } + }).then(res => { + console.log("✔ 数据同步成功!") + + }, err => { + console.log('✘ 数据同步失败', err) + }) + } + */ + + _mapToArray(arrbf) { + let arr = [] + arrbf.map(item => { + arr.push(item) + }) + return arr + } + + // 校验数据正确性 + _checkData(arrbf) { + let packetLen = arrbf.length; + console.log("接收数据:" + arrbf) + + // 校验帧头帧尾 + if (arrbf[0] != 0x89 || arrbf[1] != 0x89) { + console.log('不是该设备返回的包') + return false + } + if (packetLen < 14) { + console.log("包长太短,不是该设备返回的包"); + return false; + } + + let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff); + if (dataLength != (packetLen - 13)) { + let calLen = packetLen - 13; + console.log("✘ 数据长度错误: " + dataLength + " is not " + calLen); + return false; + } + //校验包 + let check = arrbf[0]; + for (let i = 1; i < packetLen - 1; i++) + check ^= arrbf[i]; + if (check != arrbf[packetLen - 1]) { + console.log("crc校验错误,请重发." + check); + return false; + } + console.log('✔ 数据校验成功,接收完整!') + return true + } + + getReceivePacket(arrbf) + { + let packetLen = arrbf.length; + console.log("接收数据:" + arrbf) + // 校验帧头帧尾 + if (arrbf[0] != 0x89 || arrbf[1] != 0x89) { + console.log('不是该设备返回的包') + return false + } + if (packetLen < 14) { + console.log("包长太短,不是该设备返回的包"); + return false; + } + + let dataLength = ((arrbf[10] << 8) & 0xff00) + (arrbf[11] & 0x00ff); + if (dataLength != (packetLen - 13)) { + let calLen = packetLen - 13; + console.log("✘ 数据长度错误: " + dataLength + " is not " + calLen); + return false; + } + //校验包 + let check = arrbf[0]; + for (let i = 1; i < packetLen - 1; i++) + check ^= arrbf[i]; + if (check != arrbf[packetLen - 1]) { + console.log("crc校验错误,请重发." + check); + return false; + } + console.log('✔ 数据校验成功,接收完整! packet= ' + arrbf) + return true + } + +} +export default BLEHandler \ No newline at end of file diff --git a/utils/btls/error.js b/utils/btls/error.js new file mode 100644 index 0000000..e1bd08e --- /dev/null +++ b/utils/btls/error.js @@ -0,0 +1,44 @@ +export default function (err) { + if (err && err.errCode) { + // 微信BLE蓝牙错误码 + switch (err.errCode) { + case 10001: + return err.errCode + ":蓝牙适配失败,请检查手机蓝牙和定位功能是否打开" + case 10002: + return err.errCode + ":没有找到指定设备" + case 10003: + return err.errCode + ":连接失败" + case 10004: + return err.errCode + ":没有找到指定服务" + case 10005: + return err.errCode + ":没有找到指定特征值" + case 10006: + return err.errCode + ":当前连接已断开" + case 10007: + return err.errCode + ":当前特征值不支持此操作" + case 10008: + return err.errCode + ":其余所有系统上报的异常" + case 10009: + return err.errCode + ":Android 系统特有,系统版本低于 4.3 不支持 BLE" + case 10012: + return err.errCode + ":连接超时" + case 10013: + return err.errCode + ":连接 deviceId 为空或者是格式不正确" + default: + return "蓝牙功能暂不支持" + } + } else { + // 自定义错误码 + if (typeof err === 'string') { + switch (err) { + case 'device not found': + return "找不到该设备" + default: + break; + } + } else { + return "蓝牙功能暂不支持" + } + } + +} \ No newline at end of file diff --git a/utils/btls/tools.js b/utils/btls/tools.js new file mode 100644 index 0000000..9ee2d16 --- /dev/null +++ b/utils/btls/tools.js @@ -0,0 +1,481 @@ +import errToString from "./error"; +var util = require('../util'); + +let PRINT_SHOW = true //是否开启蓝牙调试 +let SYSTEM_INFO = {} +let MTU_SIZE = 512 + +function toPlatformString(systemInfo, str) +{ + if (systemInfo.platform == 'android') + return str.toLowerCase(); + else if (systemInfo.platform == 'ios') + return str.toUpperCase(); + else + return str; +} + +function _openAdapter() { + + print(`准备初始化蓝牙适配器...`); + + wx.getSystemInfo({ + success: function (res) { + print(`model: ${res.model}`); + print(`pixelRatio: ${res.pixelRatio}`); + print(`windowWidth: ${res.windowWidth}`); + print(`windowHeight: ${res.windowHeight}`); + print(`language: ${res.language}`); + print(`version: ${res.version}`); + print(`platform: ${res.platform}`); + print(`environment: ${res.environment}`); + SYSTEM_INFO = res; + } + }) + + return wx.openBluetoothAdapter().then( + (res) => { + print(`✔ 适配器初始化成功!`); + return [null, res] + }, + (err) => { + print(`✘ 初始化失败!${errToString(err)}`); + return [errToString(err), null] + } + ); +} + +/** + * @param {Array} services + * @param { Int } interval + */ +function _startSearch() { + print(`准备搜寻附近的蓝牙外围设备...`); + return promisify(wx.startBluetoothDevicesDiscovery, { + services: [this.serviceId], //如果填写了此UUID,那么只会搜索出含有这个UUID的设备 + allowDuplicatesKey: false, + interval: 1000 + }).then( + (res) => { + print(`✔ 搜索成功!`); + return [null, res] + + }, + (err) => { + print(`✘ 搜索蓝牙设备失败!${errToString(err)}`); + return [errToString(err), null] + } + ); +} + +/** + *@param {Array} devices + *@deviceId 设备ID + */ +function _onBluetoothFound() { + print(`监听搜寻新设备事件...`); + return _onBluetoothFound_promise.call(this).then(res => { + print(`✔ 设备 ${this.blename} 查找成功!`); + return [null, res] + }, err => { + print(`✘ 设备 ${this.blename} 查找失败!`); + return [errToString(err), null] + + }) +} + +/** + * @param {Array} devices 查找到设备数组 + * @param {int} count 计数器-嗅探2次 + */ +function _onBluetoothFound_promise() { + let devices = [] + let count = 0 + return new Promise((resolve, reject) => { + wx.onBluetoothDeviceFound(res => { + devices.push(...res.devices) + print(`已嗅探设备数:${devices.length}...`) + print(`已嗅探设备信息:${JSON.stringify(devices)}`) + count++ + print(`已嗅探次数:${count}`) + //if (count > 1) + if(devices.length>0) + { + devices.forEach(element => { + if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) { + this.deviceId = element.deviceId + + print(`我的设备Mac:${this.deviceId} `) + print(`我的设备名:${element.name}, ${element.localName}`) + + resolve(res) + } + }); + + } + + reject('device not found') + + }, err => { + reject(err) + }) + }) +} + +/** + *@param {Array} devices + *@deviceId 设备ID + */ +function _getBluetoothDevices() { + print(`监听搜寻新设备事件...`); + let devices = [] + return wx.getBluetoothDevices().then( + (res) => { + devices.push(res.devices) + print(`已嗅探设备数:${res.devices.length}...`) + print(`已嗅探设备信息:${JSON.stringify(res.devices)}`) + if(devices.length>0) + { + devices.forEach(element => { + if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) { + this.deviceId = element.deviceId + + print(`我的设备Mac:${this.deviceId} `) + print(`我的设备名:${element.name}, ${element.localName}`) + + print(`✔ 设备 ${this.blename} 查找成功!`); + return [null, res] + } + }); + } + + return [ "暂时没有嗅探到设备 ${this.blename}, 继续嗅探...", null] + + }, + (err) => { + print(`✘ 设备 ${this.blename} 查找失败!`); + return [errToString(err), null] + } + ); +} + + +function _getBluetoothDevices_1() { + print(`监听搜寻新设备事件...`); + return _getBluetoothDevices_promise.call(this).then(res => { + print(`✔ 设备 ${this.blename} 查找成功!`); + return [null, res] + }, err => { + print(`✘ 设备 ${this.blename} 查找失败!`); + return [errToString(err), null] + }) +} + +/** + * @param {Array} devices 查找到设备数组 + * @param {int} count 计数器-嗅探2次 + */ +function _getBluetoothDevices_promise() { + let devices = [] + print(`1111`) + return new Promise((resolve, reject) => { + + print(`2222`) + + wx.getBluetoothDevices(res => { + + print(`3333`) + devices.push(...res.devices) + print(`已嗅探设备数:${devices.length}...`) + print(`已嗅探设备信息:${JSON.stringify(devices)}`) + if(devices.length>0) + { + devices.forEach(element => { + if ((element.name && element.name == this.blename) || (element.localName && element.localName == this.blename)) { + this.deviceId = element.deviceId + + print(`我的设备Mac:${this.deviceId} `) + print(`我的设备名:${element.name}, ${element.localName}`) + + resolve(res) + } + }); + + } + reject('device not found') + + }, err => { + + print(`4444`) + + reject(err) + }) + }) +} + + + +function _stopSearchBluetooth() { + print(`停止查找新设备...`); + return wx.stopBluetoothDevicesDiscovery().then( + (res) => { + print(`✔ 停止查找设备成功!`); + return [null, res] + }, + (err) => { + print(`✘ 停止查询设备失败!${errToString(err)}`); + return [errToString(err), null] + } + ); +} + +function _connectBlue() { + print(`准备连接设备...`); + return promisify(wx.createBLEConnection, { + deviceId: this.deviceId, + }).then( + (res) => { + print(`✔ 连接蓝牙成功!`); + return [null, res] + }, + (err) => { + print(`✘ 连接蓝牙失败!${errToString(err)}`); + return [errToString(err), null] + } + ); +} + +function _setBLEMTU() { + + if (SYSTEM_INFO.platform != 'android') + { + print(`仅安卓手机需要设置MTU Size`); + return ["仅安卓手机需要设置MTU Size", null]; + } + + print(`准备设置 MTU Size...`); + + return promisify(wx.setBLEMTU, { + deviceId: this.deviceId, + mtu:MTU_SIZE + }).then( + (res) => { + + //console.log("setBLEMTU success >> " + JSON.stringify(res)) + print(`✔ 设置MTU Size = ${MTU_SIZE} 成功!`); + return [null, res] + }, + (err) => { + + //console.log("setBLEMTU fail >> " + JSON.stringify(res)) + print(`✘ 设置MTU Size 失败!`); + return [errToString(err), null] + } + ); +} + +function _closeBLEConnection() { + print(`断开蓝牙连接...`) + return promisify(wx.closeBLEConnection, { + deviceId: this.deviceId, + }).then( + (res) => { + print(`✔ 断开蓝牙成功!`); + return [null, res] + }, + (err) => { + print(`✘ 断开蓝牙连接失败!${errToString(err)}`); + return [errToString(err), null] + } + ); +} + +function _closeBLEAdapter() { + print(`释放蓝牙适配器...`) + return wx.closeBluetoothAdapter().then(res => { + print(`✔ 释放适配器成功!`) + return [null, res] + }, err => { + print(`✘ 释放适配器失败!${errToString(err)}`) + return [errToString(err), null] + }) +} + +function _getBLEServices() { + print(`获取蓝牙设备所有服务...`) + return promisify(wx.getBLEDeviceServices, { + deviceId: this.deviceId + }).then(res => { + print(`✔ 获取service成功!`) + console.log('services UUID:\n', JSON.stringify(res.services)); + for (var i = 0; i < res.services.length; i++) { + console.log("第"+(i+1) + "个UUID:" + res.services[i].uuid+"\n") + } + return [null, res] + }, err => { + print(`✘ 获取service失败!${errToString(err)}`) + return [errToString(err), null] + }) +} + +function _getCharacteristics() { + print(`开始获取特征值...`); + return promisify(wx.getBLEDeviceCharacteristics, { + deviceId: this.deviceId, + serviceId: toPlatformString(SYSTEM_INFO, this.serviceId),//具有写、通知属性的服务uuid + }).then( + (res) => { + print(`✔ 获取特征值成功!`); + for (let i = 0; i < res.characteristics.length; i++) { + let item = res.characteristics[i]; + if (item.properties.read) { + this.readCharacteristicId = item.uuid; + print(`readCharacteristicId:${item.uuid}`) + } + if (item.properties.write && !item.properties.read) { + this.writeCharacteristicId = item.uuid; + print(`writeCharacteristicId:${item.uuid}`) + } + if (item.properties.notify || item.properties.indicate) { + this.notifyCharacteristicId = item.uuid; + print(`notifyCharacteristicId:${item.uuid}`) + } + } + return [null, res] + }, + (err) => { + print(`✘ 获取特征值失败!${errToString(err)}`); + return [errToString(err), null] + } + ); +} + +// 订阅特征值 +function _notifyBLECharacteristicValueChange() { + return promisify(wx.notifyBLECharacteristicValueChange, { + deviceId: this.deviceId, + serviceId: toPlatformString(SYSTEM_INFO, this.serviceId), + characteristicId: toPlatformString(SYSTEM_INFO, this.notifyCharacteristicId), + state: true + }).then(res => { + print(`✔ 订阅notify成功!`) + + return [null, res] + }, err => { + print(`✘ 订阅notify失败!${errToString(err)}`) + return [errToString(err), null] + }) +} + +/** + * 指令封装 + * @param {Array} data + */ +function _sentOrder(cmd, payload){ + print(`开始封装指令...`) + let data = payload + let payloadLength = data.length; + let length = 13 + payload.length + let b = new Uint8Array(length); + + b[0] = 0x89; + b[1] = 0x89; + b[2] = cmd; + + let timestamp = new Date().getTime(); + let ts = timestamp.toString(16) + let t = util.hexStringToBytes(ts) + b.set(t, 4) + b[3] = b[9]; + b[10] = (payloadLength>>8)&0xff; + b[11] = payloadLength & 0xff; + let key = b[3]; + for (let i=0; i { + print(`✔ 写入数据成功!`) + return [null, res] + }, err => { + print(`✘ 写入数据失败!${errToString(err)}`) + return [errToString(err), null] + }) +} + +/** + * 对微信接口的promise封装 + * @param {function} fn + * @param {object} args + */ +function promisify(fn, args) { + return new Promise((resolve, reject) => { + fn({ + ...(args || {}), + success: (res) => resolve(res), + fail: (err) => reject(err), + }); + }); +} + +/** + * 对微信接口回调函数的封装 + * @param {function} fn + */ +function promisify_callback(fn) { + return new Promise((resolve, reject) => { + fn( + (res) => { + resolve(res); + }, + (rej) => { + reject(rej); + } + ); + }); +} + +function print(str) { + PRINT_SHOW ? console.log(str) : null; +} + +export { + print, + _getCharacteristics, + _connectBlue, + _setBLEMTU, + _getBLEServices, + _closeBLEConnection, + _closeBLEAdapter, + _stopSearchBluetooth, + _notifyBLECharacteristicValueChange, + _onBluetoothFound, + _getBluetoothDevices, + _startSearch, + _openAdapter, + _sentOrder, + _writeBLECharacteristicValue, + promisify, + promisify_callback, +}; diff --git a/utils/global.js b/utils/global.js new file mode 100644 index 0000000..8669353 --- /dev/null +++ b/utils/global.js @@ -0,0 +1,6 @@ +//公共配置项 +const globalData = { + appId: "", + baseUrlImg: "", +}; +export { globalData }; diff --git a/utils/long.js b/utils/long.js new file mode 100644 index 0000000..4d08f64 --- /dev/null +++ b/utils/long.js @@ -0,0 +1,8 @@ +!function(t,i){"object"==typeof exports&&"object"==typeof module?module.exports=i():"function"==typeof define&&define.amd?define([],i):"object"==typeof exports?exports.Long=i():t.Long=i()}("undefined"!=typeof self?self:this,function(){return function(t){function i(h){if(n[h])return n[h].exports;var e=n[h]={i:h,l:!1,exports:{}};return t[h].call(e.exports,e,e.exports,i),e.l=!0,e.exports}var n={};return i.m=t,i.c=n,i.d=function(t,n,h){i.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:h})},i.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(n,"a",n),n},i.o=function(t,i){return Object.prototype.hasOwnProperty.call(t,i)},i.p="",i(i.s=0)}([function(t,i){function n(t,i,n){this.low=0|t,this.high=0|i,this.unsigned=!!n}function h(t){return!0===(t&&t.__isLong__)}function e(t,i){var n,h,e;return i?(t>>>=0,(e=0<=t&&t<256)&&(h=l[t])?h:(n=r(t,(0|t)<0?-1:0,!0),e&&(l[t]=n),n)):(t|=0,(e=-128<=t&&t<128)&&(h=f[t])?h:(n=r(t,t<0?-1:0,!1),e&&(f[t]=n),n))}function s(t,i){if(isNaN(t))return i?p:m;if(i){if(t<0)return p;if(t>=c)return q}else{if(t<=-w)return _;if(t+1>=w)return E}return t<0?s(-t,i).neg():r(t%d|0,t/d|0,i)}function r(t,i,h){return new n(t,i,h)}function o(t,i,n){if(0===t.length)throw Error("empty string");if("NaN"===t||"Infinity"===t||"+Infinity"===t||"-Infinity"===t)return m;if("number"==typeof i?(n=i,i=!1):i=!!i,(n=n||10)<2||360)throw Error("interior hyphen");if(0===h)return o(t.substring(1),i,n).neg();for(var e=s(a(n,8)),r=m,u=0;u>>0:this.low},B.toNumber=function(){return this.unsigned?(this.high>>>0)*d+(this.low>>>0):this.high*d+(this.low>>>0)},B.toString=function(t){if((t=t||10)<2||36>>0,f=g.toString(t);if(r=u,r.isZero())return f+o;for(;f.length<6;)f="0"+f;o=""+f+o}},B.getHighBits=function(){return this.high},B.getHighBitsUnsigned=function(){return this.high>>>0},B.getLowBits=function(){return this.low},B.getLowBitsUnsigned=function(){return this.low>>>0},B.getNumBitsAbs=function(){if(this.isNegative())return this.eq(_)?64:this.neg().getNumBitsAbs();for(var t=0!=this.high?this.high:this.low,i=31;i>0&&0==(t&1<=0},B.isOdd=function(){return 1==(1&this.low)},B.isEven=function(){return 0==(1&this.low)},B.equals=function(t){return h(t)||(t=u(t)),(this.unsigned===t.unsigned||this.high>>>31!=1||t.high>>>31!=1)&&(this.high===t.high&&this.low===t.low)},B.eq=B.equals,B.notEquals=function(t){return!this.eq(t)},B.neq=B.notEquals,B.ne=B.notEquals,B.lessThan=function(t){return this.comp(t)<0},B.lt=B.lessThan,B.lessThanOrEqual=function(t){return this.comp(t)<=0},B.lte=B.lessThanOrEqual,B.le=B.lessThanOrEqual,B.greaterThan=function(t){return this.comp(t)>0},B.gt=B.greaterThan,B.greaterThanOrEqual=function(t){return this.comp(t)>=0},B.gte=B.greaterThanOrEqual,B.ge=B.greaterThanOrEqual,B.compare=function(t){if(h(t)||(t=u(t)),this.eq(t))return 0;var i=this.isNegative(),n=t.isNegative();return i&&!n?-1:!i&&n?1:this.unsigned?t.high>>>0>this.high>>>0||t.high===this.high&&t.low>>>0>this.low>>>0?-1:1:this.sub(t).isNegative()?-1:1},B.comp=B.compare,B.negate=function(){return!this.unsigned&&this.eq(_)?_:this.not().add(y)},B.neg=B.negate,B.add=function(t){h(t)||(t=u(t));var i=this.high>>>16,n=65535&this.high,e=this.low>>>16,s=65535&this.low,o=t.high>>>16,g=65535&t.high,f=t.low>>>16,l=65535&t.low,a=0,d=0,c=0,w=0;return w+=s+l,c+=w>>>16,w&=65535,c+=e+f,d+=c>>>16,c&=65535,d+=n+g,a+=d>>>16,d&=65535,a+=i+o,a&=65535,r(c<<16|w,a<<16|d,this.unsigned)},B.subtract=function(t){return h(t)||(t=u(t)),this.add(t.neg())},B.sub=B.subtract,B.multiply=function(t){if(this.isZero())return m;if(h(t)||(t=u(t)),g){return r(g.mul(this.low,this.high,t.low,t.high),g.get_high(),this.unsigned)}if(t.isZero())return m;if(this.eq(_))return t.isOdd()?_:m;if(t.eq(_))return this.isOdd()?_:m;if(this.isNegative())return t.isNegative()?this.neg().mul(t.neg()):this.neg().mul(t).neg();if(t.isNegative())return this.mul(t.neg()).neg();if(this.lt(v)&&t.lt(v))return s(this.toNumber()*t.toNumber(),this.unsigned);var i=this.high>>>16,n=65535&this.high,e=this.low>>>16,o=65535&this.low,f=t.high>>>16,l=65535&t.high,a=t.low>>>16,d=65535&t.low,c=0,w=0,p=0,y=0;return y+=o*d,p+=y>>>16,y&=65535,p+=e*d,w+=p>>>16,p&=65535,p+=o*a,w+=p>>>16,p&=65535,w+=n*d,c+=w>>>16,w&=65535,w+=e*a,c+=w>>>16,w&=65535,w+=o*l,c+=w>>>16,w&=65535,c+=i*d+n*a+e*l+o*f,c&=65535,r(p<<16|y,c<<16|w,this.unsigned)},B.mul=B.multiply,B.divide=function(t){if(h(t)||(t=u(t)),t.isZero())throw Error("division by zero");if(g){if(!this.unsigned&&-2147483648===this.high&&-1===t.low&&-1===t.high)return this;return r((this.unsigned?g.div_u:g.div_s)(this.low,this.high,t.low,t.high),g.get_high(),this.unsigned)}if(this.isZero())return this.unsigned?p:m;var i,n,e;if(this.unsigned){if(t.unsigned||(t=t.toUnsigned()),t.gt(this))return p;if(t.gt(this.shru(1)))return b;e=p}else{if(this.eq(_)){if(t.eq(y)||t.eq(N))return _;if(t.eq(_))return y;return i=this.shr(1).div(t).shl(1),i.eq(m)?t.isNegative()?y:N:(n=this.sub(t.mul(i)),e=i.add(n.div(t)))}if(t.eq(_))return this.unsigned?p:m;if(this.isNegative())return t.isNegative()?this.neg().div(t.neg()):this.neg().div(t).neg();if(t.isNegative())return this.div(t.neg()).neg();e=m}for(n=this;n.gte(t);){i=Math.max(1,Math.floor(n.toNumber()/t.toNumber()));for(var o=Math.ceil(Math.log(i)/Math.LN2),f=o<=48?1:a(2,o-48),l=s(i),d=l.mul(t);d.isNegative()||d.gt(n);)i-=f,l=s(i,this.unsigned),d=l.mul(t);l.isZero()&&(l=y),e=e.add(l),n=n.sub(d)}return e},B.div=B.divide,B.modulo=function(t){if(h(t)||(t=u(t)),g){return r((this.unsigned?g.rem_u:g.rem_s)(this.low,this.high,t.low,t.high),g.get_high(),this.unsigned)}return this.sub(this.div(t).mul(t))},B.mod=B.modulo,B.rem=B.modulo,B.not=function(){return r(~this.low,~this.high,this.unsigned)},B.and=function(t){return h(t)||(t=u(t)),r(this.low&t.low,this.high&t.high,this.unsigned)},B.or=function(t){return h(t)||(t=u(t)),r(this.low|t.low,this.high|t.high,this.unsigned)},B.xor=function(t){return h(t)||(t=u(t)),r(this.low^t.low,this.high^t.high,this.unsigned)},B.shiftLeft=function(t){return h(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?r(this.low<>>32-t,this.unsigned):r(0,this.low<>>t|this.high<<32-t,this.high>>t,this.unsigned):r(this.high>>t-32,this.high>=0?0:-1,this.unsigned)},B.shr=B.shiftRight,B.shiftRightUnsigned=function(t){return h(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?r(this.low>>>t|this.high<<32-t,this.high>>>t,this.unsigned):32===t?r(this.high,0,this.unsigned):r(this.high>>>t-32,0,this.unsigned)},B.shru=B.shiftRightUnsigned,B.shr_u=B.shiftRightUnsigned,B.rotateLeft=function(t){var i;return h(t)&&(t=t.toInt()),0==(t&=63)?this:32===t?r(this.high,this.low,this.unsigned):t<32?(i=32-t,r(this.low<>>i,this.high<>>i,this.unsigned)):(t-=32,i=32-t,r(this.high<>>i,this.low<>>i,this.unsigned))},B.rotl=B.rotateLeft,B.rotateRight=function(t){var i;return h(t)&&(t=t.toInt()),0==(t&=63)?this:32===t?r(this.high,this.low,this.unsigned):t<32?(i=32-t,r(this.high<>>t,this.low<>>t,this.unsigned)):(t-=32,i=32-t,r(this.low<>>t,this.high<>>t,this.unsigned))},B.rotr=B.rotateRight,B.toSigned=function(){return this.unsigned?r(this.low,this.high,!1):this},B.toUnsigned=function(){return this.unsigned?this:r(this.low,this.high,!0)},B.toBytes=function(t){return t?this.toBytesLE():this.toBytesBE()},B.toBytesLE=function(){var t=this.high,i=this.low;return[255&i,i>>>8&255,i>>>16&255,i>>>24,255&t,t>>>8&255,t>>>16&255,t>>>24]},B.toBytesBE=function(){var t=this.high,i=this.low;return[t>>>24,t>>>16&255,t>>>8&255,255&t,i>>>24,i>>>16&255,i>>>8&255,255&i]},n.fromBytes=function(t,i,h){return h?n.fromBytesLE(t,i):n.fromBytesBE(t,i)},n.fromBytesLE=function(t,i){return new n(t[0]|t[1]<<8|t[2]<<16|t[3]<<24,t[4]|t[5]<<8|t[6]<<16|t[7]<<24,i)},n.fromBytesBE=function(t,i){return new n(t[4]<<24|t[5]<<16|t[6]<<8|t[7],t[0]<<24|t[1]<<16|t[2]<<8|t[3],i)}}])}); +//# sourceMappingURL=long.js.map \ No newline at end of file diff --git a/utils/util.js b/utils/util.js new file mode 100644 index 0000000..5e703a9 --- /dev/null +++ b/utils/util.js @@ -0,0 +1,153 @@ +function formatTime(date) { + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + + return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':') +} + +function formatNumber(n) { + n = n.toString() + return n[1] ? n : '0' + n +} + + +function uint8ArrayToString(fileData){ + let dataString = ""; + for (let i = 0; i < fileData.length; i++) { + dataString += String.fromCharCode(fileData[i]); + } + return dataString +} + +function stringToUint8Array(str){ + let arr = []; + for (let i = 0, j = str.length; i < j; ++i) { + arr.push(str.charCodeAt(i)); + } + let tmpUint8Array = new Uint8Array(arr); + return tmpUint8Array +} + + +// 微信官方给的ArrayBuffer转十六进制示例 +function ab2hex(buffer) { + let hexArr = Array.prototype.map.call( + new Uint8Array(buffer), + function (bit) { + return ('00' + bit.toString(16)).slice(-2) + } + ) + return hexArr.join(','); +} + +//转成可展会的文字 +function hexCharCodeToStr(hexCharCodeStr) { + let trimedStr = hexCharCodeStr.trim(); + let rawStr = trimedStr.substr(0, 2).toLowerCase() === '0x' ? trimedStr.substr(2) : trimedStr; + let len = rawStr.length; + let curCharCode; + let resultStr = []; + for (let i = 0; i < len; i = i + 2) { + curCharCode = parseInt(rawStr.substr(i, 2), 16); + resultStr.push(String.fromCharCode(curCharCode)); + } + return resultStr.join(''); +} + +//转换成需要的格式 +function buf2string(buffer) { + let arr = Array.prototype.map.call(new Uint8Array(buffer), x => x) + + return arr.map((char, i) => { + return String.fromCharCode(char); + }).join(''); +} + +function decodeHexNibble(c) { + if (c >= 48 && c <= 57) { + return c - 48; + } else if (c >= 65 && c <= 70) { + return c - 65 + 10; + } else { + return c >= 97 && c <= 102 ? c - 97 + 10 : -1; + } +} + +function decodeHexByte(s, pos) { + let hi = decodeHexNibble(s.charCodeAt(pos)); + let lo = decodeHexNibble(s.charCodeAt(pos + 1)); + return ((hi << 4) + lo); +} + +function hexStringToBytesWithPadding(str, byteLen, padding) { + let len = str.length + let length = 2 * byteLen + + if (length >= len && (length & 1) == 0) { + if (length == 0) { + return [0]; + } else { + let bytes = new Uint8Array(length >>> 1); + + for(let i = 0; i < len; i += 2) { + bytes[i >>> 1] = decodeHexByte(str, i); + } + + for(let i = 0; i < byteLen-len/2; i++) + bytes[len/2+i] = padding; + + return bytes; + } + } + else + return [0]; +} + + +function hexStringToBytes(str) { + let s = str; + if(s.length < 12) + { + let tmp = 12-s.length + for(let i = 0; i< tmp; i++) + s = "0" + s; + } + else + s = str.substr(s.length-12, s.length); + + let start = 0 + let length = s.length + + if (length >= 0 && (length & 1) == 0) { + if (length == 0) { + return new byte[0]; + } else { + let bytes = new Uint8Array(length >>> 1); + + for(let i = 0; i < length; i += 2) { + bytes[i >>> 1] = decodeHexByte(s, start + i); + } + + return bytes; + } + } + else + return [0]; +} + +module.exports = { + formatTime: formatTime, + uint8ArrayToString: uint8ArrayToString, + stringToUint8Array: stringToUint8Array, + ab2hex: ab2hex, + hexCharCodeToStr, + hexCharCodeToStr: buf2string, + decodeHexNibble, + decodeHexNibble: decodeHexByte, + hexStringToBytesWithPadding: hexStringToBytesWithPadding, + hexStringToBytes: hexStringToBytes +}