@ -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 | |||
), | |||
}) |
@ -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" | |||
} |
@ -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; | |||
} |
@ -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<leafs.length; iLeaf++) { | |||
var leaf = leafs[iLeaf]; | |||
handlers = leaf._listeners; | |||
if (isArray(handlers)) { | |||
var position = -1; | |||
for (var i = 0, length = handlers.length; i < length; i++) { | |||
if (handlers[i] === listener || | |||
(handlers[i].listener && handlers[i].listener === listener) || | |||
(handlers[i]._origin && handlers[i]._origin === listener)) { | |||
position = i; | |||
break; | |||
} | |||
} | |||
if (position < 0) { | |||
continue; | |||
} | |||
if(this.wildcard) { | |||
leaf._listeners.splice(position, 1); | |||
} | |||
else { | |||
this._events[type].splice(position, 1); | |||
} | |||
if (handlers.length === 0) { | |||
if(this.wildcard) { | |||
delete leaf._listeners; | |||
} | |||
else { | |||
delete this._events[type]; | |||
} | |||
} | |||
if (this._removeListener) | |||
this.emit("removeListener", type, listener); | |||
return this; | |||
} | |||
else if (handlers === listener || | |||
(handlers.listener && handlers.listener === listener) || | |||
(handlers._origin && handlers._origin === listener)) { | |||
if(this.wildcard) { | |||
delete leaf._listeners; | |||
} | |||
else { | |||
delete this._events[type]; | |||
} | |||
if (this._removeListener) | |||
this.emit("removeListener", type, listener); | |||
} | |||
} | |||
function recursivelyGarbageCollect(root) { | |||
if (root === undefined) { | |||
return; | |||
} | |||
var keys = Object.keys(root); | |||
for (var i in keys) { | |||
var key = keys[i]; | |||
var obj = root[key]; | |||
if ((obj instanceof Function) || (typeof obj !== "object") || (obj === null)) | |||
continue; | |||
if (Object.keys(obj).length > 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<leafs.length; iLeaf++) { | |||
var leaf = leafs[iLeaf]; | |||
leaf._listeners = null; | |||
} | |||
} | |||
else if (this._events) { | |||
this._events[type] = null; | |||
} | |||
return this; | |||
}; | |||
EventEmitter.prototype.listeners = function(type) { | |||
if (this.wildcard) { | |||
var handlers = []; | |||
var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice(); | |||
searchListenerTree.call(this, handlers, ns, this.listenerTree, 0); | |||
return handlers; | |||
} | |||
this._events || init.call(this); | |||
if (!this._events[type]) this._events[type] = []; | |||
if (!isArray(this._events[type])) { | |||
this._events[type] = [this._events[type]]; | |||
} | |||
return this._events[type]; | |||
}; | |||
EventEmitter.prototype.eventNames = function(){ | |||
return Object.keys(this._events); | |||
} | |||
EventEmitter.prototype.listenerCount = function(type) { | |||
return this.listeners(type).length; | |||
}; | |||
EventEmitter.prototype.listenersAny = function() { | |||
if(this._all) { | |||
return this._all; | |||
} | |||
else { | |||
return []; | |||
} | |||
}; | |||
if (typeof define === 'function' && define.amd) { | |||
// AMD. Register as an anonymous module. | |||
define(function() { | |||
return EventEmitter; | |||
}); | |||
} else if (typeof exports === 'object') { | |||
// CommonJS | |||
module.exports = EventEmitter; | |||
} | |||
else { | |||
// Browser global. | |||
window.EventEmitter2 = EventEmitter; | |||
} | |||
}(); | |||
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); }) | |||
return __REQUIRE__(1585827830357); | |||
})() | |||
//# sourceMappingURL=index.js.map |
@ -0,0 +1,191 @@ | |||
const app = getApp(); | |||
var longUtil = require('./../../utils/long'); | |||
var util = require('../../utils/util'); | |||
import { BLE } from "./../../utils/btls/ble"; | |||
const emitter = app.globalData.emitter | |||
Page({ | |||
/** | |||
* 页面的初始数据 | |||
*/ | |||
data: { | |||
baseUrlImg: app.globalData.baseUrlImg, | |||
bleStatus: false, | |||
respond: [], | |||
blueyes: false, //是否重发同步指令 | |||
connectStatus: "", | |||
info:"未初始化蓝牙适配器", | |||
}, | |||
btntest1(event){ | |||
var that = this; | |||
this.startconnect() | |||
}, | |||
btntest2(event){ | |||
var that = this | |||
let userTelephone = "13028878230" | |||
let userPassword = "130288" | |||
let pwd = "12344321" | |||
let openLockType = 2 | |||
this.openLock(userTelephone, userPassword, pwd, openLockType) | |||
}, | |||
//获取输入框的数据 | |||
getmsg(event){ | |||
this.setData({ | |||
sendmsg:event.detail.value | |||
}) | |||
}, | |||
btntest3(event){ | |||
var that = this; | |||
this.closeblue() | |||
}, | |||
startconnect() { | |||
//if(checkWechatVersion()) | |||
{ | |||
const ble = new BLE("yxwl01680000004895", emitter) | |||
app.globalData.ble = ble | |||
this.watchBLE() | |||
app.globalData.ble.init() | |||
} | |||
}, | |||
watchBLE() { | |||
if (app.globalData.ble) { | |||
app.globalData.ble.listen(res => { | |||
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; | |||
} | |||
}) | |||
} | |||
@ -0,0 +1,3 @@ | |||
{ | |||
"usingComponents": {} | |||
} |
@ -0,0 +1,18 @@ | |||
<!--pages/asyntest/asyntest.wxml--> | |||
<view class="contentview"> | |||
<view class='myview' > | |||
{{info}} | |||
</view> | |||
<button type="primary" class="button" bindtap="btntest1">初始化蓝牙</button> | |||
<view class="section"> | |||
<input placeholder='请输入要发送的信息' bindinput='getmsg'/> | |||
</view> | |||
<button type="primary" class="button" bindtap="btntest2">微信发送消息</button> | |||
<button type="primary" class="button" bindtap="btntest3">断开蓝牙设备</button> | |||
</view> |
@ -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;/* 自动换行 */ | |||
} |
@ -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 | |||
}, | |||
}) |
@ -0,0 +1,3 @@ | |||
{ | |||
"usingComponents": {} | |||
} |
@ -0,0 +1,41 @@ | |||
<wxs module="utils"> | |||
module.exports.max = function(n1, n2) { | |||
return Math.max(n1, n2) | |||
} | |||
module.exports.len = function(arr) { | |||
arr = arr || [] | |||
return arr.length | |||
} | |||
</wxs> | |||
<button bindtap="openBluetoothAdapter">开始扫描</button> | |||
<button bindtap="stopBluetoothDevicesDiscovery">停止扫描</button> | |||
<button bindtap="closeBluetoothAdapter">结束流程</button> | |||
<view class="devices_summary">已发现 {{devices.length}} 个外围设备:</view> | |||
<scroll-view class="device_list" scroll-y scroll-with-animation> | |||
<view wx:for="{{devices}}" wx:key="index" | |||
data-device-id="{{item.deviceId}}" | |||
data-name="{{item.name || item.localName}}" | |||
bindtap="createBLEConnection" | |||
class="device_item" | |||
hover-class="device_item_hover"> | |||
<view style="font-size: 16px; color: #333;">{{item.name}}</view> | |||
<view style="font-size: 10px">信号强度: {{item.RSSI}}dBm ({{utils.max(0, item.RSSI + 100)}}%)</view> | |||
<view style="font-size: 10px">UUID: {{item.deviceId}}</view> | |||
<view style="font-size: 10px">Service数量: {{utils.len(item.advertisServiceUUIDs)}}</view> | |||
</view> | |||
</scroll-view> | |||
<view class="connected_info" wx:if="{{connected}}"> | |||
<view> | |||
<text>已连接到 {{name}}</text> | |||
<view class="operation"> | |||
<button wx:if="{{canWrite}}" size="mini" bindtap="writeBLECharacteristicValue">写数据</button> | |||
<button size="mini" bindtap="closeBLEConnection">断开连接</button> | |||
</view> | |||
</view> | |||
<view wx:for="{{chs}}" wx:key="index" style="font-size: 12px; margin-top: 10px;"> | |||
<view>特性UUID: {{item.uuid}}</view> | |||
<view>特性值: {{item.value}}</view> | |||
</view> | |||
</view> |
@ -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; | |||
} |
@ -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<payloadLength; i++) { | |||
data[i] -= (payloadLength - i) ^ key; | |||
data[i] = (data[i] ^ (key ^ i)); | |||
} | |||
b.set(data, 12) | |||
let xor = b[0]; | |||
for (let i=1; i<length-1; i++) | |||
xor ^= b[i]; | |||
b[length-1] = xor; | |||
return b; | |||
} | |||
@ -0,0 +1,3 @@ | |||
{ | |||
"usingComponents": {} | |||
} |
@ -0,0 +1,29 @@ | |||
<!--pages/lanyatest/lanyatest.wxml--> | |||
<view class="contentview"> | |||
<view class='myview' > | |||
{{info}} | |||
</view> | |||
<button type="primary" class="button" bindtap="lanyatest1">1初始化蓝牙</button> | |||
<button type="primary" class="button" bindtap="lanyatest2">2获取蓝牙状态</button> | |||
<button type="primary" class="button" bindtap="lanyatest3">3搜索周边设备</button> | |||
<button type="primary" class="button" bindtap="lanyatest4">4获取所有设备</button> | |||
<block wx:for="{{devices}}" wx:key="{{test}}"> | |||
<button type="primary" class="button" id="{{item.deviceId}}" style='background-color:red' bindtap="lanyaconnect">5连接{{item.name}} </button> | |||
</block> | |||
<button type="primary" class="button" bindtap="lanyatest6">6停止搜索周边蓝牙设备</button> | |||
<button type="primary" class="button" bindtap="lanyatest7">7获取所有service</button> | |||
<button type="primary" class="button" bindtap="lanyatest8">8获取所有特征值</button> | |||
<button type="primary" class="button" bindtap="lanyatest9">9启用特征值变化notify</button> | |||
<button type="primary" class="button" bindtap="lanyatest10">10接收蓝牙返回消息</button> | |||
<view class="section"> | |||
<input placeholder='请输入要发送的信息' bindinput='getmsg'/> | |||
</view> | |||
<button type="primary" class="button" bindtap="lanyatest11">11微信发送消息</button> | |||
<button type="primary" class="button" bindtap="lanyatest12">12断开蓝牙设备</button> | |||
</view> |
@ -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;/* 自动换行 */ | |||
} |
@ -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 | |||
} | |||
}) | |||
}) | |||
} | |||
}) |
@ -0,0 +1,4 @@ | |||
{ | |||
"navigationBarTitleText": "查看启动日志", | |||
"usingComponents": {} | |||
} |
@ -0,0 +1,6 @@ | |||
<!--logs.wxml--> | |||
<view class="container log-list"> | |||
<block wx:for="{{logs}}" wx:key="timeStamp" wx:for-item="log"> | |||
<text class="log-item">{{index + 1}}. {{log.date}}</text> | |||
</block> | |||
</view> |
@ -0,0 +1,8 @@ | |||
.log-list { | |||
display: flex; | |||
flex-direction: column; | |||
padding: 40rpx; | |||
} | |||
.log-item { | |||
margin: 10rpx; | |||
} |
@ -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": [] | |||
} | |||
} | |||
} |
@ -0,0 +1,7 @@ | |||
{ | |||
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", | |||
"rules": [{ | |||
"action": "allow", | |||
"page": "*" | |||
}] | |||
} |
@ -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 }; |
@ -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 |
@ -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 "蓝牙功能暂不支持" | |||
} | |||
} | |||
} |
@ -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<string>} 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<string>} 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<string>} 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<payloadLength; i++) { | |||
data[i] -= (payloadLength - i) ^ key; | |||
data[i] = (data[i] ^ (key ^ i)); | |||
} | |||
b.set(data, 12) | |||
let xor = b[0]; | |||
for (let i=1; i<length-1; i++) | |||
xor ^= b[i]; | |||
b[length-1] = xor; | |||
print(`✔ 封装成功! ${b}`) | |||
return b; | |||
} | |||
function _writeBLECharacteristicValue(data) { | |||
return promisify(wx.writeBLECharacteristicValue, { | |||
deviceId: this.deviceId, | |||
serviceId: toPlatformString(SYSTEM_INFO, this.serviceId), | |||
characteristicId: toPlatformString(SYSTEM_INFO, this.writeCharacteristicId), | |||
value: data, | |||
}).then(res => { | |||
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, | |||
}; |
@ -0,0 +1,6 @@ | |||
//公共配置项 | |||
const globalData = { | |||
appId: "", | |||
baseUrlImg: "", | |||
}; | |||
export { globalData }; |
@ -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 | |||
} |