ConnectBleDevice.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. <template>
  2. <view class="box">
  3. <view class="content">
  4. <view>
  5. <label class="radio" @click="isWifi=true">
  6. <radio value="wifi" :checked="isWifi" />wifi
  7. </label>
  8. <label class="radio" @click="isWifi=false">
  9. <radio value="4G" :checked="!isWifi" />4G
  10. </label>
  11. </view>
  12. <view class="input-row">
  13. <text>wifi名称:</text>
  14. <input class="edittext" v-model="wifiName" />
  15. </view>
  16. <view class="input-row">
  17. <text>wifi密码:</text>
  18. <input class="edittext" v-model="wifiPwd" />
  19. </view>
  20. <view style="margin-top: 10rpx;">
  21. <button @click="connectBle()">下一步</button>
  22. </view>
  23. <text style="margin-top: 10rpx;">{{errorText}}</text>
  24. </view>
  25. <view class="loadView" v-if="showLoading">
  26. <image class="rotateAnim" src="../../static/loading.svg"></image>
  27. <text style="margin-left: 10rpx;">{{loadingText}}</text>
  28. </view>
  29. </view>
  30. </template>
  31. <script>
  32. const server_uuid = "0000FFE5-0000-1000-8000-00805F9B34FB";
  33. //const baidu_server_uuid = "00001111-0000-1000-8000-00805f9b34fb";
  34. export default {
  35. data() {
  36. return {
  37. deviceName: "",
  38. deviceId: "",
  39. isWifi: true,
  40. wifiName: "JackieHou_Mac",
  41. wifiPwd: "1234567890",
  42. connected: false,
  43. connecting: false,
  44. iccid: '',
  45. withoutWifiInterval: undefined,
  46. configTimeout: undefined,
  47. showLoading: false, //是否显示loading
  48. loadingText: '正在连接设备', //load框的文字提示
  49. errorText: "",
  50. }
  51. },
  52. onLoad(option) {
  53. this.deviceName = option.name;
  54. this.deviceId = option.mac
  55. console.log(`name = ${this.deviceName},mac = ${this.deviceId}`);
  56. //this.getWifiBuffer()
  57. },
  58. methods: {
  59. test2() {
  60. function doSomething(str) {
  61. return new Promise((resolve, reject) => {
  62. setTimeout(() => {
  63. resolve(str.toUpperCase());
  64. }, 2000)
  65. })
  66. }
  67. let strs = ['aaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeeeee'];
  68. let promiseList = strs.map(doSomething);
  69. let time = Date.now();
  70. (async () => {
  71. let res = await Promise.allSettled(promiseList)
  72. console.log(Date.now() - time);
  73. console.log(res);
  74. })();
  75. },
  76. test() {
  77. let buffer = Buffer.from(
  78. "1abcdefghijklmnopqrstuvwxyz2abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz")
  79. console.log(buffer.length);
  80. let count = Math.ceil(buffer.length / 20)
  81. let buffers = []
  82. for (var i = 0; i < count; i++) {
  83. let size = Math.min(20, buffer.length - i * 20)
  84. console.log(size);
  85. let buf = buffer.slice(i * 20, size + i * 20)
  86. buffers.push(buf)
  87. }
  88. for (let b of buffers) {
  89. console.log(b);
  90. }
  91. },
  92. connectBle() {
  93. let that = this
  94. if (!that.connecting && !that.connected) {
  95. console.log('创建连接')
  96. clearInterval(that.withoutWifiInterval)
  97. clearTimeout(that.configTimeout)
  98. that.connecting = true
  99. that.showLoading = true
  100. that.loadingText = '正在连接设备'
  101. that.errorText = ""
  102. uni.createBLEConnection({
  103. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  104. deviceId: that.deviceId,
  105. success(res) {
  106. that.connected = true
  107. console.log('连接成功')
  108. console.log(res)
  109. that.connecting = false
  110. that.loadingText = '正在获取服务'
  111. //获取服务
  112. that.getBleDeviceServices()
  113. },
  114. fail(err) {
  115. console.log('连接失败')
  116. console.log(err)
  117. that.connecting = false
  118. that.showLoading = false
  119. that.errorText = '连接失败!请将手机靠近设备'
  120. uni.showToast({
  121. title: '连接失败!请将手机靠近设备',
  122. icon: 'none',
  123. duration: 2000
  124. })
  125. }
  126. })
  127. }
  128. },
  129. listenBleConnectState() {
  130. uni.onBLEConnectionStateChange(function(res) {
  131. // 该方法回调中可以用于处理连接意外断开等异常情况
  132. console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`)
  133. that.connected = res.connected
  134. if (res.connected === false) {
  135. clearInterval(that.withoutWifiInterval)
  136. clearTimeout(that.configTimeout)
  137. that.showLoading = false
  138. that.errorText = '连接已断开,请重试!'
  139. uni.showToast({
  140. title: '连接已断开,请重试!',
  141. icon: 'none',
  142. duration: 2000
  143. })
  144. }
  145. })
  146. },
  147. getBleDeviceServices() {
  148. let that = this
  149. setTimeout(() => {
  150. uni.getBLEDeviceServices({
  151. deviceId: that.deviceId,
  152. success(res) {
  153. console.log('获取服务成功')
  154. console.log(res)
  155. for (let service of res.services) {
  156. console.log(service)
  157. if (server_uuid.toUpperCase() == service.uuid.toUpperCase()) {
  158. that.loadingText = '正在获取特征'
  159. //获取特征
  160. that.getBLEDeviceCharacteristics(server_uuid)
  161. return
  162. }
  163. }
  164. },
  165. fail(err) {
  166. console.log('获取服务失败')
  167. console.log(err);
  168. that.closeBLEConnection()
  169. that.errorText = '获取服务失败'
  170. }
  171. })
  172. }, 1000)
  173. },
  174. getBLEDeviceCharacteristics(uuid) {
  175. console.log("获取特征");
  176. let that = this
  177. //setTimeout(() => {
  178. uni.getBLEDeviceCharacteristics({
  179. deviceId: that.deviceId,
  180. serviceId: uuid,
  181. success(res) {
  182. console.log('获取特征成功');
  183. console.log(res);
  184. //todo直接写入数据
  185. //that.sendCongifComm(res.characteristics[0].uuid)
  186. that.notifyBLECharacteristicValueChange(res.characteristics[0].uuid)
  187. },
  188. fail(err) {
  189. console.log('获取特征失败');
  190. console.log(err);
  191. that.closeBLEConnection()
  192. that.errorText = '获取特征失败'
  193. }
  194. })
  195. //}, 1000)
  196. },
  197. notifyBLECharacteristicValueChange(characteristicId) {
  198. let that = this
  199. setTimeout(() => {
  200. that.loadingText = '正在配网'
  201. //设置一个超时配网的时间
  202. that.configTimeout = setTimeout(() => {
  203. that.closeBLEConnection()
  204. uni.showToast({
  205. title: "配网超时,请重试",
  206. icon: 'none',
  207. duration: 1000
  208. })
  209. that.errorText = '配网超时,请重试'
  210. }, 20 * 1000)
  211. uni.notifyBLECharacteristicValueChange({
  212. state: true,
  213. deviceId: that.deviceId,
  214. serviceId: server_uuid,
  215. characteristicId: characteristicId,
  216. }).then(res => {
  217. console.log("notify成功");
  218. console.log(res);
  219. }).catch(err => {
  220. console.log("notify失败");
  221. console.log(err);
  222. })
  223. //监听设备发送过来的数据
  224. uni.onBLECharacteristicValueChange(function(res) {
  225. //console.warn('收到设备发送过来的数据');
  226. //console.log(res);
  227. let buf = Buffer.from(res.value);
  228. let receiveStr = buf.toString()
  229. console.log(`收到数据:${receiveStr}`);
  230. if (receiveStr === 'connect_success') {
  231. let text = `${that.isWifi ? 'WIFI' : '4g'}配网成功`
  232. uni.showToast({
  233. title: text,
  234. icon: 'none',
  235. duration: 1000
  236. })
  237. that.closeBLEConnection()
  238. that.errorText = text
  239. } else if (receiveStr.indexOf('failure') >= 0) {
  240. uni.showToast({
  241. title: '配网失败',
  242. icon: 'none',
  243. duration: 1000
  244. })
  245. that.closeBLEConnection()
  246. that.errorText = '配网失败'
  247. } else if (receiveStr.indexOf('ic0:') >= 0) { //用来获取iccid的
  248. that.iccid = receiveStr.substring(4, receiveStr.length);
  249. } else if (receiveStr.indexOf('ic1:') >= 0) { //用来获取iccid的 把ic0 和ic1拼接起来
  250. let ic1 = receiveStr.substring(4, receiveStr.length);
  251. that.iccid = that.iccid + ic1;
  252. //发送4G配网指令
  253. //let buf = Buffer.from('without_WiFi')
  254. //setTimeout(() =>{that.sendCongifCmd(characteristicId,buf.buffer)},800)
  255. setTimeout(() => {
  256. that.sendWithoutWifiCommand(characteristicId);
  257. }, 800)
  258. } else if (receiveStr.indexOf('start_network') >= 0 || receiveStr.indexOf(
  259. 'recv_finish') >= 0) {
  260. //发送 AIrSMArT_CLOSE指令
  261. setTimeout(() => {
  262. let buf = Buffer.from('AIrSMArT_CLOSE')
  263. that.sendCongifCmd(characteristicId,buf.buffer)
  264. }, 2000)
  265. } else if (receiveStr.indexOf('without_WiFi_OK') >= 0) {
  266. let text = `4G配网成功`
  267. uni.showToast({
  268. title: text,
  269. icon: 'none',
  270. duration: 1000
  271. })
  272. that.errorText = text
  273. that.closeBLEConnection()
  274. }
  275. })
  276. //发送数据给设备
  277. setTimeout(() => {
  278. let buffer
  279. if (that.isWifi) {
  280. buffer = that.getWifiBuffer()
  281. //that.sendCongifCmd(characteristicId,buffer)
  282. } else {
  283. //4G设备先获取iccid
  284. let buf = Buffer.from('get_iccid')
  285. buffer = buf.buffer
  286. }
  287. that.sendCongifCmd(characteristicId, buffer)
  288. }, 800)
  289. }, 1000)
  290. },
  291. sendCongifCmd(characteristicId, buffer) { //发送配网指令
  292. let that = this
  293. let count = Math.ceil(buffer.byteLength / 20)
  294. //拆分成的ArrayBuffer数组,每个ArrayBuffer不超过20个字节
  295. let buffers = []
  296. for (var i = 0; i < count; i++) {
  297. let size = Math.min(20, buffer.byteLength - i * 20)
  298. let buf = buffer.slice(i * 20, size + i * 20)
  299. buffers.push(buf)
  300. }
  301. //返回的是一个promise对象
  302. function sendData(buffer) {
  303. return uni.writeBLECharacteristicValue({
  304. deviceId: that.deviceId,
  305. serviceId: server_uuid,
  306. characteristicId: characteristicId,
  307. value: buffer,
  308. })
  309. };
  310. (async () => {
  311. for (let b of buffers) {
  312. let res = await sendData(b)
  313. //console.log(res);
  314. console.log(`发送的数据为:${Buffer.from(b)} errorCode: ${res[res.length-1].errCode}`);
  315. }
  316. // let promises = buffers.map((b) => sendData(b))
  317. // let res = await Promise.all(promises)
  318. })();
  319. },
  320. sendCongifCmd1(characteristicId, buffer) { //发送配网指令
  321. let that = this
  322. uni.writeBLECharacteristicValue({
  323. deviceId: that.deviceId,
  324. serviceId: server_uuid,
  325. characteristicId: characteristicId,
  326. value: buffer,
  327. success(res) {
  328. console.log(`发送数据成功 ${Buffer.from(buffer)}`);
  329. console.log(res)
  330. },
  331. fail(err) {
  332. console.log(`发送数据失败 ${Buffer.from(buffer)}`);
  333. console.log(err)
  334. }
  335. })
  336. },
  337. sendWithoutWifiCommand(characteristicId) { //间隔2S发送WithoutWifi指令,直到设备有返回指令
  338. let that = this
  339. function sendWithoutWifi(uuid) {
  340. let buf = Buffer.from('without_WiFi')
  341. that.sendCongifCmd(characteristicId, buf.buffer)
  342. }
  343. if (that.withoutWifiInterval === undefined) {
  344. that.withoutWifiInterval = setInterval(sendWithoutWifi, 2000, characteristicId)
  345. }
  346. sendWithoutWifi()
  347. },
  348. getWifiBuffer() {
  349. let ssidBuf = Buffer.from(this.wifiName)
  350. console.log(ssidBuf.length);
  351. let pwdBuf = Buffer.from(this.wifiPwd)
  352. console.log(pwdBuf.length);
  353. let buffer = new ArrayBuffer(ssidBuf.length + pwdBuf.length + 6);
  354. let dataView = new DataView(buffer);
  355. dataView.setUint8(0, 0x22)
  356. dataView.setUint8(1, ssidBuf.length + pwdBuf.length + 6)
  357. dataView.setUint8(2, 0x33)
  358. dataView.setUint8(3, ssidBuf.length)
  359. let j = 0
  360. for (var i = 4; i < ssidBuf.length + 4; ++i) {
  361. dataView.setUint8(i, ssidBuf[j++])
  362. }
  363. dataView.setUint8(ssidBuf.length + 4, 0x44)
  364. dataView.setUint8(ssidBuf.length + 5, pwdBuf.length)
  365. j = 0
  366. for (var i = ssidBuf.length + 6; i < ssidBuf.length + pwdBuf.length + 6; ++i) {
  367. dataView.setUint8(i, pwdBuf[j++])
  368. }
  369. //打印arrayBuffer
  370. // let buf = Buffer.from(buffer);
  371. // console.log(buf);
  372. //console.log(buffer.byteLength)
  373. return buffer;
  374. },
  375. closeBLEConnection() {
  376. let that = this
  377. uni.closeBLEConnection({
  378. deviceId: that.deviceId,
  379. success(res) {
  380. console.log('关闭连接成功');
  381. console.log(res)
  382. },
  383. fail(err) {
  384. console.log(err)
  385. console.log('关闭连接失败');
  386. }
  387. })
  388. clearInterval(that.withoutWifiInterval)
  389. clearTimeout(that.configTimeout)
  390. that.connected = false
  391. that.showLoading = false
  392. }
  393. }
  394. }
  395. </script>
  396. <style>
  397. .box {
  398. display: flex;
  399. flex-direction: column;
  400. width: 100vw;
  401. height: 100vh;
  402. }
  403. .content {
  404. display: flex;
  405. flex-direction: column;
  406. /* align-items: center;
  407. justify-content: center; */
  408. }
  409. .input-row {
  410. display: flex;
  411. margin-top: 10rpx;
  412. flex-direction: row;
  413. align-items: center;
  414. }
  415. .loadView {
  416. display: flex;
  417. flex-direction: column;
  418. align-self: center;
  419. align-items: center;
  420. /* margin-top: 35vh; */
  421. }
  422. .edittext {
  423. display: flex;
  424. width: 60vw;
  425. height: 50rpx;
  426. border: 1rpx solid #333333;
  427. }
  428. .rotateAnim {
  429. width: 60rpx;
  430. height: 60rpx;
  431. animation: turn 1200ms linear infinite;
  432. }
  433. @keyframes turn {
  434. 0% {
  435. transform: rotate(0deg);
  436. }
  437. 50% {
  438. transform: rotate(180deg);
  439. }
  440. 100% {
  441. transform: rotate(360deg);
  442. }
  443. }
  444. </style>