├── README.md ├── app.js ├── app.json ├── app.wxss ├── bluetooth.zip ├── pages └── index │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── project.config.json ├── utils ├── md5.js └── util.js └── 蓝牙模块.jpeg /README.md: -------------------------------------------------------------------------------- 1 | # miniapp-bluetooth 2 | 小程序蓝牙项目 3 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | onLaunch: function () { 4 | // 展示本地存储能力 5 | var logs = wx.getStorageSync('logs') || [] 6 | logs.unshift(Date.now()) 7 | wx.setStorageSync('logs', logs) 8 | 9 | // 登录 10 | wx.login({ 11 | success: res => { 12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId 13 | } 14 | }) 15 | // 获取用户信息 16 | wx.getSetting({ 17 | success: res => { 18 | if (res.authSetting['scope.userInfo']) { 19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 20 | wx.getUserInfo({ 21 | success: res => { 22 | // 可以将 res 发送给后台解码出 unionId 23 | this.globalData.userInfo = res.userInfo 24 | 25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回 26 | // 所以此处加入 callback 以防止这种情况 27 | if (this.userInfoReadyCallback) { 28 | this.userInfoReadyCallback(res) 29 | } 30 | } 31 | }) 32 | } 33 | } 34 | }) 35 | }, 36 | globalData: { 37 | userInfo: null 38 | } 39 | }) -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages":[ 3 | "pages/index/index" 4 | ], 5 | "window":{ 6 | "backgroundTextStyle":"light", 7 | "navigationBarBackgroundColor": "#fff", 8 | "navigationBarTitleText": "WeChat", 9 | "navigationBarTextStyle":"black" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app.wxss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuxingzhijian1320/miniapp-bluetooth/9cfe37ecac212c6305a2e1fada34965d3083916a/app.wxss -------------------------------------------------------------------------------- /bluetooth.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuxingzhijian1320/miniapp-bluetooth/9cfe37ecac212c6305a2e1fada34965d3083916a/bluetooth.zip -------------------------------------------------------------------------------- /pages/index/index.js: -------------------------------------------------------------------------------- 1 | const app = getApp() 2 | const Util = require('../../utils/util.js') 3 | 4 | Page({ 5 | data: { 6 | available: false, // 设备可用 7 | discovering: false, // 搜索状态 8 | serviceId: '', // 服务Id 9 | characteristicId: '', // 特征值 10 | deviceId: '', // mac 地址 (ios的mac地址是UUID,由于隐私保护的原因引起的) 11 | name: '', // 设备编号 完整: ET01-XXXXX 12 | }, 13 | 14 | onLoad() { 15 | // console.log(Util.md5('123')) 16 | }, 17 | opendoor(e) { 18 | let id = e.target.dataset.id; 19 | console.info('设备的名称', id) 20 | this.setData({ 21 | name: id 22 | }) 23 | 24 | // 仅仅是单个设备 (wx.closeBLEConnection 只需要断开这个连接即可) 25 | // if (this.data.serviceId){ 26 | // this.this.connectBluetooth() 27 | // }else { 28 | // this.initBluetooth() 29 | // } 30 | 31 | // 多个设备连接(切换设备的时候的需要 wx.closeBLEConnection 和 wx.closeBluetoothAdapter 释放资源) 32 | this.initBluetooth() 33 | }, 34 | initBluetooth() { 35 | let that = this; 36 | 37 | // 版本过低兼容 38 | if (!wx.openBluetoothAdapter) { 39 | wx.showModal({ 40 | title: '提示', 41 | showCancel: false, 42 | content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。', 43 | }) 44 | return; 45 | } 46 | 47 | wx.openBluetoothAdapter({ 48 | success(res) { 49 | console.log("初始化蓝牙模块 --- 已开启") 50 | that.watchBluetoothStateChange() 51 | that.searchBluetooth() 52 | }, 53 | fail(err) { 54 | console.log("初始化蓝牙模块 --- 未开启") 55 | that.watchBluetoothStateChange() 56 | if (err.errCode == 10001) { 57 | wx.showToast({ 58 | title: '蓝牙未开启', 59 | icon: 'none' 60 | }) 61 | } 62 | } 63 | }) 64 | }, 65 | /** 66 | * 监听蓝牙适配器状态变化事件 67 | */ 68 | watchBluetoothStateChange() { 69 | let that = this; 70 | 71 | wx.onBluetoothAdapterStateChange((res) => { 72 | console.log("监听蓝牙状态改变", res) 73 | /** 74 | * 搜索状态 75 | */ 76 | if (that.data.discovering != res.discovering) { 77 | that.setData({ 78 | discovering: res.discovering 79 | }) 80 | } 81 | /** 82 | * 蓝牙状态 83 | */ 84 | if (that.data.available != res.available) { 85 | that.setData({ 86 | available: res.available 87 | }) 88 | if (!res.available) { 89 | wx.showToast({ 90 | title: '蓝牙未开启', 91 | icon: 'none' 92 | }) 93 | console.log('蓝牙适配器不可用') 94 | } else { 95 | if (!res.discovering && !that.data.devices.length) { 96 | console.info(789) 97 | that.searchBluetooth() 98 | } 99 | } 100 | } 101 | }) 102 | }, 103 | /** 104 | * 查找设备 105 | */ 106 | searchBluetooth() { 107 | let that = this; 108 | wx.startBluetoothDevicesDiscovery({ 109 | allowDuplicatesKey: false, 110 | success(res) { 111 | console.log("查找设备") 112 | that.watchBluetoothFound() 113 | // 20s 停止搜索 114 | setTimeout(that.stopSearchBluetooth, 20000) 115 | } 116 | }) 117 | }, 118 | /** 119 | * 监听寻找到新设备 120 | */ 121 | watchBluetoothFound() { 122 | let that = this; 123 | wx.onBluetoothDeviceFound(function(res) { 124 | 125 | let device = res.devices[0] 126 | console.info('shebei', device, device.localName) 127 | if (device.localName && device.localName.indexOf(`ET01-${that.data.name}`) > -1) { 128 | console.log(`查找到 ET01-${that.data.name}`, '设备id', device.deviceId) 129 | 130 | that.setData({ 131 | deviceId: device.deviceId 132 | }) 133 | console.info('连接成功---', that.data.deviceId) 134 | that.connectBluetooth() 135 | 136 | // 连接成功 需要断开蓝牙搜索 137 | that.stopSearchBluetooth() 138 | } 139 | }) 140 | }, 141 | /** 142 | * 停止查找 143 | */ 144 | stopSearchBluetooth() { 145 | let that = this; 146 | wx.stopBluetoothDevicesDiscovery({ 147 | success: function(res) { 148 | console.log("停止查找") 149 | } 150 | }) 151 | }, 152 | /** 153 | * 获取设备列表 154 | */ 155 | // getBluetoothDevices() { 156 | // let that = this; 157 | // wx.getBluetoothDevices({ 158 | // success: function(res) { 159 | // console.log('获取已发现的蓝牙设备', res.devices) 160 | // let devices = res.devices.filter((item) => item.localName == "JDY-16") 161 | // if (devices.length) { 162 | // that.setData({ 163 | // devices: devices 164 | // }) 165 | // console.log(that.data.devices) 166 | // } 167 | // } 168 | // }) 169 | // }, 170 | /** 171 | * 连接设备 172 | */ 173 | connectBluetooth() { 174 | console.info('connectBluetooth', this.data.deviceId) 175 | let that = this; 176 | wx.createBLEConnection({ 177 | deviceId: that.data.deviceId, 178 | success(res) { 179 | console.log("连接成功设备---" + JSON.stringify(res)) 180 | that.getBluetoothServers() 181 | }, 182 | fail(err) { 183 | that.closeConnectBluetooth() 184 | console.log("连接失败,结束---") 185 | } 186 | }) 187 | }, 188 | /** 189 | * 断开连接 190 | */ 191 | closeConnectBluetooth() { 192 | let that = this; 193 | // 断开BLE的连接 194 | wx.closeBLEConnection({ 195 | deviceId: that.data.deviceId, 196 | success(res) { 197 | console.log("手动断开连接") 198 | } 199 | }) 200 | // 断开蓝牙的连接 (初始化所有的状态) 201 | wx.closeBluetoothAdapter({ 202 | success(res) { 203 | console.log('断开蓝牙', res) 204 | that.setData({ 205 | deviceId: '', 206 | serviceId: '', 207 | characteristicId: '', 208 | name: '', 209 | }) 210 | } 211 | }) 212 | }, 213 | /** 214 | * 获取设备服务 215 | */ 216 | getBluetoothServers() { 217 | let that = this; 218 | wx.getBLEDeviceServices({ 219 | deviceId: that.data.deviceId, 220 | success(res) { 221 | console.log('获取设备服务', res.services) 222 | that.setData({ 223 | serviceId: res.services[0].uuid 224 | }) 225 | that.getBluetoothCharacteristics() 226 | }, 227 | }) 228 | }, 229 | /** 230 | * 获取设备某个服务特征值列表 231 | */ 232 | getBluetoothCharacteristics() { 233 | let that = this; 234 | wx.getBLEDeviceCharacteristics({ 235 | deviceId: that.data.deviceId, 236 | serviceId: that.data.serviceId, 237 | success(res) { 238 | console.info('获取设备某个服务特征值列表', res) 239 | that.setData({ 240 | characteristicId: res.characteristics[0].uuid 241 | }) 242 | that.notifyBluetoothCharacteristicValueChange() 243 | }, 244 | }) 245 | }, 246 | /** 247 | * 启用设备特征值变化时的 notify 功能 248 | */ 249 | notifyBluetoothCharacteristicValueChange() { 250 | let that = this; 251 | wx.notifyBLECharacteristicValueChange({ 252 | deviceId: that.data.deviceId, 253 | serviceId: that.data.serviceId, 254 | characteristicId: that.data.characteristicId, 255 | state: true, 256 | type: 'notification', 257 | success(res) { 258 | console.log("启用设备特征值变化时的 notify 功能", res) 259 | that.watchBluetoothCharacteristicValueChange() 260 | }, 261 | }) 262 | }, 263 | /** 264 | * 监听设备的特征值变化 265 | */ 266 | watchBluetoothCharacteristicValueChange() { 267 | let that = this; 268 | console.log("监听设备的特征值变化") 269 | 270 | wx.onBLECharacteristicValueChange(function(res) { 271 | 272 | console.log('onBLECharacteristicValueChange', res) 273 | console.log('返回数据', that.ab2hex(res.value)) 274 | // 和硬件约定 7b010403a000dd 这个返回值是开门成功 275 | if (that.ab2hex(res.value) == '7b010403a000dd') { 276 | wx.showModal({ 277 | title: '提示', 278 | content: '开门成功', 279 | showCancel: false 280 | }) 281 | } else { 282 | wx.showModal({ 283 | title: '提示', 284 | content: '开门失败', 285 | showCancel: false 286 | }) 287 | } 288 | that.closeConnectBluetooth() 289 | }) 290 | 291 | setTimeout(() => { 292 | that.writeBluetoothCharacteristicValue() 293 | }, 20) 294 | 295 | 296 | }, 297 | /** 298 | * 向设备特征值中写入二进制数据 299 | */ 300 | writeBluetoothCharacteristicValue(type) { 301 | let that = this; 302 | 303 | // 开门指令 304 | var arr = ['7A', '01', '04', '03', 'A0', '00', 'DE'] 305 | console.info('开门指令 转化 Buffer', that.strToBuf(arr)) 306 | 307 | wx.writeBLECharacteristicValue({ 308 | deviceId: that.data.deviceId, 309 | serviceId: that.data.serviceId, 310 | characteristicId: that.data.characteristicId, 311 | value: that.strToBuf(arr), 312 | success(res) { 313 | console.log("写入成功") 314 | }, 315 | fail(res) { 316 | console.log("写入失败 结束") 317 | } 318 | }) 319 | }, 320 | 321 | /** 322 | * hex转ArrayBuffer 323 | */ 324 | strToBuf(arr) { 325 | var length = arr.length 326 | var buffer = new ArrayBuffer(length + 2) 327 | var dataview = new DataView(buffer) 328 | for (let i = 0; i < length; i++) { 329 | dataview.setUint8(i, '0x' + arr[i]) 330 | } 331 | return buffer 332 | }, 333 | 334 | // ArrayBuffer转16进度字符串示例 335 | ab2hex(buffer) { 336 | const hexArr = Array.prototype.map.call( 337 | new Uint8Array(buffer), 338 | function(bit) { 339 | return ('00' + bit.toString(16)).slice(-2) 340 | } 341 | ) 342 | return hexArr.join('') 343 | }, 344 | // 16进度 转化 string 345 | hexToString(hex) { 346 | var string = ''; 347 | for (var i = 0; i < hex.length; i += 2) { 348 | string += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); 349 | } 350 | return string; 351 | } 352 | }) -------------------------------------------------------------------------------- /pages/index/index.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | .userinfo { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | padding: 50rpx; 6 | } 7 | button { 8 | margin-bottom: 30rpx; 9 | } -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件。", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": true, 9 | "postcss": true, 10 | "minified": true, 11 | "newFeature": true 12 | }, 13 | "compileType": "miniprogram", 14 | "libVersion": "1.9.98", 15 | "appid": "wx445c1727641eb032", 16 | "projectname": "%E8%93%9D%E7%89%99%E6%B5%8B%E8%AF%95", 17 | "condition": { 18 | "search": { 19 | "current": -1, 20 | "list": [] 21 | }, 22 | "conversation": { 23 | "current": -1, 24 | "list": [] 25 | }, 26 | "game": { 27 | "currentL": -1, 28 | "list": [] 29 | }, 30 | "miniprogram": { 31 | "current": -1, 32 | "list": [] 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /utils/md5.js: -------------------------------------------------------------------------------- 1 | /** 2 | * [js-md5]{@link https://github.com/emn178/js-md5} 3 | * 4 | * @namespace md5 5 | * @version 0.7.3 6 | * @author Chen, Yi-Cyuan [emn178@gmail.com] 7 | * @copyright Chen, Yi-Cyuan 2014-2017 8 | * @license MIT 9 | */ 10 | (function () { 11 | 'use strict'; 12 | 13 | var ERROR = 'input is invalid type'; 14 | var WINDOW = typeof window === 'object'; 15 | var root = WINDOW ? window : {}; 16 | if (root.JS_MD5_NO_WINDOW) { 17 | WINDOW = false; 18 | } 19 | var WEB_WORKER = !WINDOW && typeof self === 'object'; 20 | var NODE_JS = !root.JS_MD5_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node; 21 | if (NODE_JS) { 22 | root = global; 23 | } else if (WEB_WORKER) { 24 | root = self; 25 | } 26 | var COMMON_JS = !root.JS_MD5_NO_COMMON_JS && typeof module === 'object' && module.exports; 27 | var AMD = typeof define === 'function' && define.amd; 28 | var ARRAY_BUFFER = !root.JS_MD5_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined'; 29 | var HEX_CHARS = '0123456789abcdef'.split(''); 30 | var EXTRA = [128, 32768, 8388608, -2147483648]; 31 | var SHIFT = [0, 8, 16, 24]; 32 | var OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer', 'base64']; 33 | var BASE64_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); 34 | 35 | var blocks = [], buffer8; 36 | if (ARRAY_BUFFER) { 37 | var buffer = new ArrayBuffer(68); 38 | buffer8 = new Uint8Array(buffer); 39 | blocks = new Uint32Array(buffer); 40 | } 41 | 42 | if (root.JS_MD5_NO_NODE_JS || !Array.isArray) { 43 | Array.isArray = function (obj) { 44 | return Object.prototype.toString.call(obj) === '[object Array]'; 45 | }; 46 | } 47 | 48 | if (ARRAY_BUFFER && (root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) { 49 | ArrayBuffer.isView = function (obj) { 50 | return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer; 51 | }; 52 | } 53 | 54 | /** 55 | * @method hex 56 | * @memberof md5 57 | * @description Output hash as hex string 58 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 59 | * @returns {String} Hex string 60 | * @example 61 | * md5.hex('The quick brown fox jumps over the lazy dog'); 62 | * // equal to 63 | * md5('The quick brown fox jumps over the lazy dog'); 64 | */ 65 | /** 66 | * @method digest 67 | * @memberof md5 68 | * @description Output hash as bytes array 69 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 70 | * @returns {Array} Bytes array 71 | * @example 72 | * md5.digest('The quick brown fox jumps over the lazy dog'); 73 | */ 74 | /** 75 | * @method array 76 | * @memberof md5 77 | * @description Output hash as bytes array 78 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 79 | * @returns {Array} Bytes array 80 | * @example 81 | * md5.array('The quick brown fox jumps over the lazy dog'); 82 | */ 83 | /** 84 | * @method arrayBuffer 85 | * @memberof md5 86 | * @description Output hash as ArrayBuffer 87 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 88 | * @returns {ArrayBuffer} ArrayBuffer 89 | * @example 90 | * md5.arrayBuffer('The quick brown fox jumps over the lazy dog'); 91 | */ 92 | /** 93 | * @method buffer 94 | * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead. 95 | * @memberof md5 96 | * @description Output hash as ArrayBuffer 97 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 98 | * @returns {ArrayBuffer} ArrayBuffer 99 | * @example 100 | * md5.buffer('The quick brown fox jumps over the lazy dog'); 101 | */ 102 | /** 103 | * @method base64 104 | * @memberof md5 105 | * @description Output hash as base64 string 106 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 107 | * @returns {String} base64 string 108 | * @example 109 | * md5.base64('The quick brown fox jumps over the lazy dog'); 110 | */ 111 | var createOutputMethod = function (outputType) { 112 | return function (message) { 113 | return new Md5(true).update(message)[outputType](); 114 | }; 115 | }; 116 | 117 | /** 118 | * @method create 119 | * @memberof md5 120 | * @description Create Md5 object 121 | * @returns {Md5} Md5 object. 122 | * @example 123 | * var hash = md5.create(); 124 | */ 125 | /** 126 | * @method update 127 | * @memberof md5 128 | * @description Create and update Md5 object 129 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 130 | * @returns {Md5} Md5 object. 131 | * @example 132 | * var hash = md5.update('The quick brown fox jumps over the lazy dog'); 133 | * // equal to 134 | * var hash = md5.create(); 135 | * hash.update('The quick brown fox jumps over the lazy dog'); 136 | */ 137 | var createMethod = function () { 138 | var method = createOutputMethod('hex'); 139 | if (NODE_JS) { 140 | method = nodeWrap(method); 141 | } 142 | method.create = function () { 143 | return new Md5(); 144 | }; 145 | method.update = function (message) { 146 | return method.create().update(message); 147 | }; 148 | for (var i = 0; i < OUTPUT_TYPES.length; ++i) { 149 | var type = OUTPUT_TYPES[i]; 150 | method[type] = createOutputMethod(type); 151 | } 152 | return method; 153 | }; 154 | 155 | var nodeWrap = function (method) { 156 | var crypto = eval("require('crypto')"); 157 | var Buffer = eval("require('buffer').Buffer"); 158 | var nodeMethod = function (message) { 159 | if (typeof message === 'string') { 160 | return crypto.createHash('md5').update(message, 'utf8').digest('hex'); 161 | } else { 162 | if (message === null || message === undefined) { 163 | throw ERROR; 164 | } else if (message.constructor === ArrayBuffer) { 165 | message = new Uint8Array(message); 166 | } 167 | } 168 | if (Array.isArray(message) || ArrayBuffer.isView(message) || 169 | message.constructor === Buffer) { 170 | return crypto.createHash('md5').update(new Buffer(message)).digest('hex'); 171 | } else { 172 | return method(message); 173 | } 174 | }; 175 | return nodeMethod; 176 | }; 177 | 178 | /** 179 | * Md5 class 180 | * @class Md5 181 | * @description This is internal class. 182 | * @see {@link md5.create} 183 | */ 184 | function Md5(sharedMemory) { 185 | if (sharedMemory) { 186 | blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] = 187 | blocks[4] = blocks[5] = blocks[6] = blocks[7] = 188 | blocks[8] = blocks[9] = blocks[10] = blocks[11] = 189 | blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; 190 | this.blocks = blocks; 191 | this.buffer8 = buffer8; 192 | } else { 193 | if (ARRAY_BUFFER) { 194 | var buffer = new ArrayBuffer(68); 195 | this.buffer8 = new Uint8Array(buffer); 196 | this.blocks = new Uint32Array(buffer); 197 | } else { 198 | this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 199 | } 200 | } 201 | this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0; 202 | this.finalized = this.hashed = false; 203 | this.first = true; 204 | } 205 | 206 | /** 207 | * @method update 208 | * @memberof Md5 209 | * @instance 210 | * @description Update hash 211 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 212 | * @returns {Md5} Md5 object. 213 | * @see {@link md5.update} 214 | */ 215 | Md5.prototype.update = function (message) { 216 | if (this.finalized) { 217 | return; 218 | } 219 | 220 | var notString, type = typeof message; 221 | if (type !== 'string') { 222 | if (type === 'object') { 223 | if (message === null) { 224 | throw ERROR; 225 | } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) { 226 | message = new Uint8Array(message); 227 | } else if (!Array.isArray(message)) { 228 | if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) { 229 | throw ERROR; 230 | } 231 | } 232 | } else { 233 | throw ERROR; 234 | } 235 | notString = true; 236 | } 237 | var code, index = 0, i, length = message.length, blocks = this.blocks; 238 | var buffer8 = this.buffer8; 239 | 240 | while (index < length) { 241 | if (this.hashed) { 242 | this.hashed = false; 243 | blocks[0] = blocks[16]; 244 | blocks[16] = blocks[1] = blocks[2] = blocks[3] = 245 | blocks[4] = blocks[5] = blocks[6] = blocks[7] = 246 | blocks[8] = blocks[9] = blocks[10] = blocks[11] = 247 | blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; 248 | } 249 | 250 | if (notString) { 251 | if (ARRAY_BUFFER) { 252 | for (i = this.start; index < length && i < 64; ++index) { 253 | buffer8[i++] = message[index]; 254 | } 255 | } else { 256 | for (i = this.start; index < length && i < 64; ++index) { 257 | blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; 258 | } 259 | } 260 | } else { 261 | if (ARRAY_BUFFER) { 262 | for (i = this.start; index < length && i < 64; ++index) { 263 | code = message.charCodeAt(index); 264 | if (code < 0x80) { 265 | buffer8[i++] = code; 266 | } else if (code < 0x800) { 267 | buffer8[i++] = 0xc0 | (code >> 6); 268 | buffer8[i++] = 0x80 | (code & 0x3f); 269 | } else if (code < 0xd800 || code >= 0xe000) { 270 | buffer8[i++] = 0xe0 | (code >> 12); 271 | buffer8[i++] = 0x80 | ((code >> 6) & 0x3f); 272 | buffer8[i++] = 0x80 | (code & 0x3f); 273 | } else { 274 | code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); 275 | buffer8[i++] = 0xf0 | (code >> 18); 276 | buffer8[i++] = 0x80 | ((code >> 12) & 0x3f); 277 | buffer8[i++] = 0x80 | ((code >> 6) & 0x3f); 278 | buffer8[i++] = 0x80 | (code & 0x3f); 279 | } 280 | } 281 | } else { 282 | for (i = this.start; index < length && i < 64; ++index) { 283 | code = message.charCodeAt(index); 284 | if (code < 0x80) { 285 | blocks[i >> 2] |= code << SHIFT[i++ & 3]; 286 | } else if (code < 0x800) { 287 | blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; 288 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; 289 | } else if (code < 0xd800 || code >= 0xe000) { 290 | blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; 291 | blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; 292 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; 293 | } else { 294 | code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); 295 | blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; 296 | blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; 297 | blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; 298 | blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; 299 | } 300 | } 301 | } 302 | } 303 | this.lastByteIndex = i; 304 | this.bytes += i - this.start; 305 | if (i >= 64) { 306 | this.start = i - 64; 307 | this.hash(); 308 | this.hashed = true; 309 | } else { 310 | this.start = i; 311 | } 312 | } 313 | if (this.bytes > 4294967295) { 314 | this.hBytes += this.bytes / 4294967296 << 0; 315 | this.bytes = this.bytes % 4294967296; 316 | } 317 | return this; 318 | }; 319 | 320 | Md5.prototype.finalize = function () { 321 | if (this.finalized) { 322 | return; 323 | } 324 | this.finalized = true; 325 | var blocks = this.blocks, i = this.lastByteIndex; 326 | blocks[i >> 2] |= EXTRA[i & 3]; 327 | if (i >= 56) { 328 | if (!this.hashed) { 329 | this.hash(); 330 | } 331 | blocks[0] = blocks[16]; 332 | blocks[16] = blocks[1] = blocks[2] = blocks[3] = 333 | blocks[4] = blocks[5] = blocks[6] = blocks[7] = 334 | blocks[8] = blocks[9] = blocks[10] = blocks[11] = 335 | blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; 336 | } 337 | blocks[14] = this.bytes << 3; 338 | blocks[15] = this.hBytes << 3 | this.bytes >>> 29; 339 | this.hash(); 340 | }; 341 | 342 | Md5.prototype.hash = function () { 343 | var a, b, c, d, bc, da, blocks = this.blocks; 344 | 345 | if (this.first) { 346 | a = blocks[0] - 680876937; 347 | a = (a << 7 | a >>> 25) - 271733879 << 0; 348 | d = (-1732584194 ^ a & 2004318071) + blocks[1] - 117830708; 349 | d = (d << 12 | d >>> 20) + a << 0; 350 | c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375; 351 | c = (c << 17 | c >>> 15) + d << 0; 352 | b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209; 353 | b = (b << 22 | b >>> 10) + c << 0; 354 | } else { 355 | a = this.h0; 356 | b = this.h1; 357 | c = this.h2; 358 | d = this.h3; 359 | a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936; 360 | a = (a << 7 | a >>> 25) + b << 0; 361 | d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586; 362 | d = (d << 12 | d >>> 20) + a << 0; 363 | c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819; 364 | c = (c << 17 | c >>> 15) + d << 0; 365 | b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330; 366 | b = (b << 22 | b >>> 10) + c << 0; 367 | } 368 | 369 | a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897; 370 | a = (a << 7 | a >>> 25) + b << 0; 371 | d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426; 372 | d = (d << 12 | d >>> 20) + a << 0; 373 | c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341; 374 | c = (c << 17 | c >>> 15) + d << 0; 375 | b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983; 376 | b = (b << 22 | b >>> 10) + c << 0; 377 | a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416; 378 | a = (a << 7 | a >>> 25) + b << 0; 379 | d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417; 380 | d = (d << 12 | d >>> 20) + a << 0; 381 | c += (b ^ (d & (a ^ b))) + blocks[10] - 42063; 382 | c = (c << 17 | c >>> 15) + d << 0; 383 | b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162; 384 | b = (b << 22 | b >>> 10) + c << 0; 385 | a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682; 386 | a = (a << 7 | a >>> 25) + b << 0; 387 | d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101; 388 | d = (d << 12 | d >>> 20) + a << 0; 389 | c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290; 390 | c = (c << 17 | c >>> 15) + d << 0; 391 | b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329; 392 | b = (b << 22 | b >>> 10) + c << 0; 393 | a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510; 394 | a = (a << 5 | a >>> 27) + b << 0; 395 | d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632; 396 | d = (d << 9 | d >>> 23) + a << 0; 397 | c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713; 398 | c = (c << 14 | c >>> 18) + d << 0; 399 | b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302; 400 | b = (b << 20 | b >>> 12) + c << 0; 401 | a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691; 402 | a = (a << 5 | a >>> 27) + b << 0; 403 | d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083; 404 | d = (d << 9 | d >>> 23) + a << 0; 405 | c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335; 406 | c = (c << 14 | c >>> 18) + d << 0; 407 | b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848; 408 | b = (b << 20 | b >>> 12) + c << 0; 409 | a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438; 410 | a = (a << 5 | a >>> 27) + b << 0; 411 | d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690; 412 | d = (d << 9 | d >>> 23) + a << 0; 413 | c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961; 414 | c = (c << 14 | c >>> 18) + d << 0; 415 | b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501; 416 | b = (b << 20 | b >>> 12) + c << 0; 417 | a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467; 418 | a = (a << 5 | a >>> 27) + b << 0; 419 | d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784; 420 | d = (d << 9 | d >>> 23) + a << 0; 421 | c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473; 422 | c = (c << 14 | c >>> 18) + d << 0; 423 | b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734; 424 | b = (b << 20 | b >>> 12) + c << 0; 425 | bc = b ^ c; 426 | a += (bc ^ d) + blocks[5] - 378558; 427 | a = (a << 4 | a >>> 28) + b << 0; 428 | d += (bc ^ a) + blocks[8] - 2022574463; 429 | d = (d << 11 | d >>> 21) + a << 0; 430 | da = d ^ a; 431 | c += (da ^ b) + blocks[11] + 1839030562; 432 | c = (c << 16 | c >>> 16) + d << 0; 433 | b += (da ^ c) + blocks[14] - 35309556; 434 | b = (b << 23 | b >>> 9) + c << 0; 435 | bc = b ^ c; 436 | a += (bc ^ d) + blocks[1] - 1530992060; 437 | a = (a << 4 | a >>> 28) + b << 0; 438 | d += (bc ^ a) + blocks[4] + 1272893353; 439 | d = (d << 11 | d >>> 21) + a << 0; 440 | da = d ^ a; 441 | c += (da ^ b) + blocks[7] - 155497632; 442 | c = (c << 16 | c >>> 16) + d << 0; 443 | b += (da ^ c) + blocks[10] - 1094730640; 444 | b = (b << 23 | b >>> 9) + c << 0; 445 | bc = b ^ c; 446 | a += (bc ^ d) + blocks[13] + 681279174; 447 | a = (a << 4 | a >>> 28) + b << 0; 448 | d += (bc ^ a) + blocks[0] - 358537222; 449 | d = (d << 11 | d >>> 21) + a << 0; 450 | da = d ^ a; 451 | c += (da ^ b) + blocks[3] - 722521979; 452 | c = (c << 16 | c >>> 16) + d << 0; 453 | b += (da ^ c) + blocks[6] + 76029189; 454 | b = (b << 23 | b >>> 9) + c << 0; 455 | bc = b ^ c; 456 | a += (bc ^ d) + blocks[9] - 640364487; 457 | a = (a << 4 | a >>> 28) + b << 0; 458 | d += (bc ^ a) + blocks[12] - 421815835; 459 | d = (d << 11 | d >>> 21) + a << 0; 460 | da = d ^ a; 461 | c += (da ^ b) + blocks[15] + 530742520; 462 | c = (c << 16 | c >>> 16) + d << 0; 463 | b += (da ^ c) + blocks[2] - 995338651; 464 | b = (b << 23 | b >>> 9) + c << 0; 465 | a += (c ^ (b | ~d)) + blocks[0] - 198630844; 466 | a = (a << 6 | a >>> 26) + b << 0; 467 | d += (b ^ (a | ~c)) + blocks[7] + 1126891415; 468 | d = (d << 10 | d >>> 22) + a << 0; 469 | c += (a ^ (d | ~b)) + blocks[14] - 1416354905; 470 | c = (c << 15 | c >>> 17) + d << 0; 471 | b += (d ^ (c | ~a)) + blocks[5] - 57434055; 472 | b = (b << 21 | b >>> 11) + c << 0; 473 | a += (c ^ (b | ~d)) + blocks[12] + 1700485571; 474 | a = (a << 6 | a >>> 26) + b << 0; 475 | d += (b ^ (a | ~c)) + blocks[3] - 1894986606; 476 | d = (d << 10 | d >>> 22) + a << 0; 477 | c += (a ^ (d | ~b)) + blocks[10] - 1051523; 478 | c = (c << 15 | c >>> 17) + d << 0; 479 | b += (d ^ (c | ~a)) + blocks[1] - 2054922799; 480 | b = (b << 21 | b >>> 11) + c << 0; 481 | a += (c ^ (b | ~d)) + blocks[8] + 1873313359; 482 | a = (a << 6 | a >>> 26) + b << 0; 483 | d += (b ^ (a | ~c)) + blocks[15] - 30611744; 484 | d = (d << 10 | d >>> 22) + a << 0; 485 | c += (a ^ (d | ~b)) + blocks[6] - 1560198380; 486 | c = (c << 15 | c >>> 17) + d << 0; 487 | b += (d ^ (c | ~a)) + blocks[13] + 1309151649; 488 | b = (b << 21 | b >>> 11) + c << 0; 489 | a += (c ^ (b | ~d)) + blocks[4] - 145523070; 490 | a = (a << 6 | a >>> 26) + b << 0; 491 | d += (b ^ (a | ~c)) + blocks[11] - 1120210379; 492 | d = (d << 10 | d >>> 22) + a << 0; 493 | c += (a ^ (d | ~b)) + blocks[2] + 718787259; 494 | c = (c << 15 | c >>> 17) + d << 0; 495 | b += (d ^ (c | ~a)) + blocks[9] - 343485551; 496 | b = (b << 21 | b >>> 11) + c << 0; 497 | 498 | if (this.first) { 499 | this.h0 = a + 1732584193 << 0; 500 | this.h1 = b - 271733879 << 0; 501 | this.h2 = c - 1732584194 << 0; 502 | this.h3 = d + 271733878 << 0; 503 | this.first = false; 504 | } else { 505 | this.h0 = this.h0 + a << 0; 506 | this.h1 = this.h1 + b << 0; 507 | this.h2 = this.h2 + c << 0; 508 | this.h3 = this.h3 + d << 0; 509 | } 510 | }; 511 | 512 | /** 513 | * @method hex 514 | * @memberof Md5 515 | * @instance 516 | * @description Output hash as hex string 517 | * @returns {String} Hex string 518 | * @see {@link md5.hex} 519 | * @example 520 | * hash.hex(); 521 | */ 522 | Md5.prototype.hex = function () { 523 | this.finalize(); 524 | 525 | var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3; 526 | 527 | return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] + 528 | HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] + 529 | HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] + 530 | HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] + 531 | HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] + 532 | HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] + 533 | HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] + 534 | HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] + 535 | HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] + 536 | HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] + 537 | HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] + 538 | HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] + 539 | HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] + 540 | HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] + 541 | HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] + 542 | HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F]; 543 | }; 544 | 545 | /** 546 | * @method toString 547 | * @memberof Md5 548 | * @instance 549 | * @description Output hash as hex string 550 | * @returns {String} Hex string 551 | * @see {@link md5.hex} 552 | * @example 553 | * hash.toString(); 554 | */ 555 | Md5.prototype.toString = Md5.prototype.hex; 556 | 557 | /** 558 | * @method digest 559 | * @memberof Md5 560 | * @instance 561 | * @description Output hash as bytes array 562 | * @returns {Array} Bytes array 563 | * @see {@link md5.digest} 564 | * @example 565 | * hash.digest(); 566 | */ 567 | Md5.prototype.digest = function () { 568 | this.finalize(); 569 | 570 | var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3; 571 | return [ 572 | h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF, 573 | h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF, 574 | h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF, 575 | h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF 576 | ]; 577 | }; 578 | 579 | /** 580 | * @method array 581 | * @memberof Md5 582 | * @instance 583 | * @description Output hash as bytes array 584 | * @returns {Array} Bytes array 585 | * @see {@link md5.array} 586 | * @example 587 | * hash.array(); 588 | */ 589 | Md5.prototype.array = Md5.prototype.digest; 590 | 591 | /** 592 | * @method arrayBuffer 593 | * @memberof Md5 594 | * @instance 595 | * @description Output hash as ArrayBuffer 596 | * @returns {ArrayBuffer} ArrayBuffer 597 | * @see {@link md5.arrayBuffer} 598 | * @example 599 | * hash.arrayBuffer(); 600 | */ 601 | Md5.prototype.arrayBuffer = function () { 602 | this.finalize(); 603 | 604 | var buffer = new ArrayBuffer(16); 605 | var blocks = new Uint32Array(buffer); 606 | blocks[0] = this.h0; 607 | blocks[1] = this.h1; 608 | blocks[2] = this.h2; 609 | blocks[3] = this.h3; 610 | return buffer; 611 | }; 612 | 613 | /** 614 | * @method buffer 615 | * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead. 616 | * @memberof Md5 617 | * @instance 618 | * @description Output hash as ArrayBuffer 619 | * @returns {ArrayBuffer} ArrayBuffer 620 | * @see {@link md5.buffer} 621 | * @example 622 | * hash.buffer(); 623 | */ 624 | Md5.prototype.buffer = Md5.prototype.arrayBuffer; 625 | 626 | /** 627 | * @method base64 628 | * @memberof Md5 629 | * @instance 630 | * @description Output hash as base64 string 631 | * @returns {String} base64 string 632 | * @see {@link md5.base64} 633 | * @example 634 | * hash.base64(); 635 | */ 636 | Md5.prototype.base64 = function () { 637 | var v1, v2, v3, base64Str = '', bytes = this.array(); 638 | for (var i = 0; i < 15;) { 639 | v1 = bytes[i++]; 640 | v2 = bytes[i++]; 641 | v3 = bytes[i++]; 642 | base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] + 643 | BASE64_ENCODE_CHAR[(v1 << 4 | v2 >>> 4) & 63] + 644 | BASE64_ENCODE_CHAR[(v2 << 2 | v3 >>> 6) & 63] + 645 | BASE64_ENCODE_CHAR[v3 & 63]; 646 | } 647 | v1 = bytes[i]; 648 | base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] + 649 | BASE64_ENCODE_CHAR[(v1 << 4) & 63] + 650 | '=='; 651 | return base64Str; 652 | }; 653 | 654 | var exports = createMethod(); 655 | 656 | if (COMMON_JS) { 657 | module.exports = exports; 658 | } else { 659 | /** 660 | * @method md5 661 | * @description Md5 hash function, export to global in browsers. 662 | * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash 663 | * @returns {String} md5 hashes 664 | * @example 665 | * md5(''); // d41d8cd98f00b204e9800998ecf8427e 666 | * md5('The quick brown fox jumps over the lazy dog'); // 9e107d9d372bb6826bd81d3542a419d6 667 | * md5('The quick brown fox jumps over the lazy dog.'); // e4d909c290d0fb1ca068ffaddf22cbd0 668 | * 669 | * // It also supports UTF-8 encoding 670 | * md5('中文'); // a7bac2239fcdcb3a067903d8077c4a07 671 | * 672 | * // It also supports byte `Array`, `Uint8Array`, `ArrayBuffer` 673 | * md5([]); // d41d8cd98f00b204e9800998ecf8427e 674 | * md5(new Uint8Array([])); // d41d8cd98f00b204e9800998ecf8427e 675 | */ 676 | root.md5 = exports; 677 | if (AMD) { 678 | define(function () { 679 | return exports; 680 | }); 681 | } 682 | } 683 | })(); 684 | -------------------------------------------------------------------------------- /utils/util.js: -------------------------------------------------------------------------------- 1 | const md5 =require('./md5.js'); 2 | 3 | module.exports = { 4 | md5: md5 5 | } 6 | -------------------------------------------------------------------------------- /蓝牙模块.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liuxingzhijian1320/miniapp-bluetooth/9cfe37ecac212c6305a2e1fada34965d3083916a/蓝牙模块.jpeg --------------------------------------------------------------------------------