devices-update.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. <!-- 蓝牙平台限制 todo https://uniapp.dcloud.io/api/system/bluetooth?id=stopbluetoothdevicesdiscovery -->
  2. <template>
  3. <view>
  4. <uni-nav-bar id="nav-bar" status-bar="true" @clickLeft="onBack()" title="设备升级" color="#000000" fixed="true" :border="false">
  5. <view slot="left">
  6. <view class=" flex align-center margin-left">
  7. <image class="p-left-arrow" src="../../../static/p-left-arrow.png"></image>
  8. </view>
  9. </view>
  10. </uni-nav-bar>
  11. <view class="card-view padding-top padding-bottom" v-for="(item,index) in devicesList" :key="index" :class="item.bRatio?'hardware-border':''">
  12. <view class="flex justify-between align-center">
  13. <image style="margin-left: 30rpx; width: 200rpx;height: 120rpx;" :src="item.icon" mode="aspectFit"></image>
  14. <view style="width: 250rpx;">
  15. <view style="font-weight: bold; font-size: 18px; color: #565656; margin: 20rpx 0;">{{item.cname}}</view>
  16. <view v-if="send_index<=0&&item.currentVersion !== ''">
  17. <view style="margin: 20rpx 0; font-size: 12px; color: grey;">固件版本号:{{item.currentVersion}}</view>
  18. <!-- <view style="margin: 20rpx; font-size: 12px;" class="make-text-bPurple">更新版本号:{{item.latestVersion}}</view> -->
  19. </view>
  20. <!-- <view class="flex">
  21. <view style="margin: 20rpx; font-size: 12px; color: grey;">硬件rom:{{item.currentRomVersion}}</view>
  22. <view style="margin: 20rpx; font-size: 12px;" class="make-text-bPurple">更新版本rom:{{item.latestRomVersion}}</view>
  23. </view> -->
  24. <!-- <view class="flex">
  25. <view style="margin: 20rpx; font-size: 12px; color: grey;">Bytes:{{bin_offset}} 总 {{bin_byteLength}}</view>
  26. </view> -->
  27. <view v-if="send_index>0" class="flex justify-between align-center" style="width: 210rpx;">
  28. <view class="cu-progress round" style=" width: 140rpx; height: 15rpx;">
  29. <view class="bg-green" :style="[{ width:percentage+'%'}]"></view>
  30. </view>
  31. <view class="" style=" font-size: 12px; color: grey;">{{percentage}}%</view>
  32. <!-- <view>
  33. <progress :percent="percentage" stroke-width="3" />
  34. </view> -->
  35. <!-- ,total {{bin_total}} send:{{send_index}} -->
  36. <!-- <view style=" font-size: 12px; color: grey;"> {{percentage}}% </view> -->
  37. </view>
  38. </view>
  39. <view v-if = "!bStart" style="width: 180rpx;margin-right: 30rpx;">
  40. <view v-if="send_index<=0&&item.latestVersion !== ''">
  41. <view v-if="bCanUpdate&&downLoadOTA!==''" class="text-11px make-text-bPurple " style="text-decoration:underline"
  42. @click="onSendConnect"> 请更新版本{{item.latestVersion}}
  43. </view>
  44. <view v-else class="text-11px text-grey">最新版本{{item.latestVersion}}</view>
  45. <!-- <button v-else class="text-11px make-bg-bPurple text-white" @click="onCheckDeviceFiles">检查更新</button> -->
  46. <!-- <button v-if="item.currentVersion !== ''" class="text-11px margin" @click="onSendConnect">开始</button> -->
  47. <!-- <button v-if="item.currentVersion !== ''" class="text-11px margin" @click="onStop">停止</button> -->
  48. </view>
  49. <view v-if="send_index<=0&&item.latestVersion === ''" class="text-26px text-grey text-center"><text class="cuIcon-loading2 cuIconfont-spin"></text></view>
  50. </view>
  51. <view v-else style="width: 180rpx;margin-right: 30rpx;">
  52. <view v-if="send_index<=0&&!sending_file" class="text-11px text-grey">{{writeTip}}</view>
  53. <view v-else class="text-11px text-grey">{{writeTip}}</view>
  54. </view>
  55. </view>
  56. <!-- <view class="flex">
  57. <view style="margin: 20rpx; font-size: 12px; color: grey;">发送和接收的次数:send:{{send_index}}</view>
  58. <view style="margin: 20rpx; font-size: 12px;" class="make-text-bPurple">time:{{send_index/100}}</view>
  59. </view> -->
  60. <!-- <scroll-view class="text-box" scroll-y="true">
  61. <scroll-view scroll-x="true">
  62. <text selectable="true">{{text}}</text>
  63. </scroll-view>
  64. </scroll-view> -->
  65. </view>
  66. </view>
  67. </template>
  68. <script>
  69. import config from '@/common/config.js'
  70. import reqUtil from '@/util/util-js/requstUtil.js';
  71. import {
  72. mapState,
  73. mapMutations
  74. } from 'vuex';
  75. export default {
  76. computed: mapState(['bOpenBluetooth', 'bOpenSuccess', 'bListenAdapterStateChange', 'bListenDeviceFound',
  77. 'BLEConnectDevice', 'cIndex'
  78. ]),
  79. data() {
  80. return {
  81. /**
  82. * OTA config
  83. */
  84. UUID_OTA_SERVICE: "f000ffc0-0451-4000-b000-000000000000", //OTA 服务对应的服务的 UUID
  85. UUID_IDENTFY: "f000ffc1-0451-4000-b000-000000000000", //OTA 版本特征值的UUID,读取版本就是写向这个特征值写入:0x00
  86. UUID_BLOCK: "f000ffc2-0451-4000-b000-000000000000", //OTA 写bin文件特征值UUID,发送bin文件就是写这个特征值
  87. /*****/
  88. boxingList: [{
  89. cname: "蓝牙手柄",
  90. ename: "BLEHandle",
  91. icon: "/static/devicesIcon/handle.png",
  92. mIcon: "/static/devicesIcon/handle.png",
  93. bRatio: false,
  94. limitType: 'noRebound', //app处理蓝牙发送的数据
  95. deviceType: 'BLEHandle', //指的是外部蓝牙,目前定义为BLEHandle
  96. deviceName: 'PBox', //连接的设备名称
  97. limitDis: 100, //
  98. primaryUUID: 'f000ffc0', //OTA升级主服务id
  99. currentVersion: '', //当前固件版本
  100. latestVersion: '', //服务器最新固件版本
  101. currentRomVersion: '',
  102. latestRomVersion: '',
  103. UUID_OTA_SERVICE: "f000ffc0-0451-4000-b000-000000000000", //OTA 服务对应的服务的 UUID
  104. UUID_IDENTFY: "f000ffc1-0451-4000-b000-000000000000", //OTA 版本特征值的UUID,读取版本就是写向这个特征值写入:0x00
  105. UUID_BLOCK: "f000ffc2-0451-4000-b000-000000000000", //OTA 写bin文件特征值UUID,发送bin文件就是写这个特征值
  106. }],
  107. devicesList: [],
  108. downLoadOTA: '',
  109. //文件数据
  110. bin_buffer: [],
  111. bin_file_len: 0,
  112. bin_byteLength: 0,
  113. bin_total: 0,
  114. bin_offset: 0,
  115. //当前发送的下标
  116. send_index: 0,
  117. sending_file: false,
  118. // 当前进度
  119. percentage: 0,
  120. //是否可以发送
  121. bSend: true,
  122. //是否可以更新
  123. bCanUpdate: false,
  124. //是否开始
  125. bStart: false,
  126. bListenValueChange: false,
  127. //测试
  128. text: '',
  129. extraLine: [],
  130. //timeout 对象
  131. writeHeadTimeout: null,
  132. backTimeout: null,
  133. sendFileHeaderTimeout: null,
  134. writeTip:'准备写入数据..',
  135. bBacking:false,
  136. }
  137. },
  138. onLoad(option) {
  139. uni.$on('callbackCloseBLE', this.updateCallbackCloseBLE);
  140. this.devicesList = this.boxingList;
  141. //比如现在BLEHandle 对应的 1,
  142. //获得游戏列表
  143. reqUtil
  144. .requestData(config.URL.GETOTA, {
  145. bleType: 1, //目前只有一种设备,就是 BLEHandle,todo 后面如果设备多了需要设备多种ota
  146. })
  147. .then(
  148. res => {
  149. console.log('GETOTA =====', res);
  150. if (res.code == 0) {
  151. //设置对应的下载地址
  152. this.downLoadOTA = res.data.otaDownload;
  153. //读取需要更新的设备,存储在数据库
  154. this.onCheckServerFiles();
  155. this.onCheckDeviceFiles();
  156. uni.showToast({
  157. title: '获取信息...',
  158. icon: 'loading',
  159. duration: 20000
  160. })
  161. }
  162. },
  163. e => {
  164. console.log(e);
  165. }
  166. );
  167. },
  168. onUnload() {
  169. uni.$off('callbackCloseBLE', this.updateCallbackCloseBLE);
  170. //如果是获取版本指令timeout
  171. if (this.writeHeadTimeout) {
  172. clearTimeout(this.writeHeadTimeout);
  173. this.writeHeadTimeout = null;
  174. }
  175. //回退timeout
  176. if (this.backTimeout) {
  177. clearTimeout(this.backTimeout);
  178. this.backTimeout = null;
  179. }
  180. //发送头指令timeout
  181. if (this.sendFileHeaderTimeout) {
  182. clearTimeout(this.sendFileHeaderTimeout);
  183. this.sendFileHeaderTimeout = null;
  184. }
  185. this.onBack();
  186. },
  187. onShow() {
  188. },
  189. onHide() {},
  190. methods: {
  191. ...mapMutations(['initAdapter', 'onCloseBLEConnection',
  192. 'onGetRSSITransDistance'
  193. ]),
  194. updateCallbackCloseBLE() {
  195. this.onBack();
  196. },
  197. onBack() {
  198. // if(this.bStart){
  199. // }
  200. if(this.bBacking)return;
  201. this.bBacking = true;
  202. //停止发送数据
  203. this.onStop();
  204. console.log('onBack:',this.BLEConnectDevice);
  205. //关闭当前的蓝牙连接
  206. this.onCloseBLEConnection({
  207. getSuccess: () => {
  208. console.log("close ble");
  209. this.$store.state.bConnection = false;
  210. }
  211. });
  212. console.log('onBack');
  213. this.$store.state.cIndex = -1;
  214. this.$store.state.BLEConnectDevice = null;
  215. this.$store.state.BLEGetServices = null;
  216. this.$store.state.bOpenBluetooth = false;
  217. uni.navigateBack({
  218. delta: 1
  219. })
  220. },
  221. //获取版本
  222. onCheckDeviceFiles() {
  223. // console.log('onCheckDeviceFiles:', this.BLEConnectDevice);
  224. //直接连接对应服务
  225. this.notifyBLECharacteristicValueChange({
  226. deviceId: this.BLEConnectDevice.deviceId,
  227. serviceId: this.UUID_OTA_SERVICE,
  228. characteristicId: this.UUID_IDENTFY
  229. });
  230. },
  231. //开始写数据
  232. onSendConnect() {
  233. uni.showModal({
  234. title: '更新提示',
  235. content: '设备更新成功后会自动关闭,是否继续更新?',
  236. success: (resValue) => {
  237. if (resValue.confirm) {
  238. //直接连接对应服务
  239. this.notifyBLECharacteristicValueChange({
  240. deviceId: this.BLEConnectDevice.deviceId,
  241. serviceId: this.UUID_OTA_SERVICE,
  242. characteristicId: this.UUID_BLOCK
  243. });
  244. uni.showToast({
  245. title: '请求硬件更新数据...',
  246. icon: 'none',
  247. duration: 3000,
  248. mask:true
  249. })
  250. //发送头指令timeout
  251. if (this.sendFileHeaderTimeout) {
  252. clearTimeout(this.sendFileHeaderTimeout);
  253. this.sendFileHeaderTimeout = null;
  254. }
  255. this.sendFileHeaderTimeout = setTimeout(() => {
  256. let retryCount = 3;
  257. this.sendFileHeader(retryCount);
  258. // this.send_index = -1;
  259. }, 3000)
  260. this.bStart = true;
  261. }
  262. }
  263. })
  264. },
  265. //启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值。
  266. //注意:必须设备的特征值支持notify或者indicate才可以成功调用,具体参照 characteristic 的 properties 属性
  267. notifyBLECharacteristicValueChange(context) {
  268. var _self = this;
  269. let {
  270. deviceId,
  271. serviceId,
  272. characteristicId
  273. } = context;
  274. // 启用notify功能
  275. uni.notifyBLECharacteristicValueChange({
  276. state: true,
  277. deviceId: deviceId,
  278. serviceId: serviceId,
  279. characteristicId: characteristicId,
  280. success: function(res) {
  281. if (!_self.bListenValueChange) {
  282. _self.onBLECharacteristicValueChange(); //监听特征值变化
  283. _self.bListenValueChange = true;
  284. }
  285. if (characteristicId == _self.UUID_IDENTFY) {
  286. //重发3次
  287. _self.onGetDeviceVersion(context,3);
  288. }
  289. },
  290. fail: function(res) {
  291. uni.showToast({
  292. title: 'notify启动失败',
  293. icon: "none",
  294. mask: true
  295. });
  296. }
  297. })
  298. },
  299. onGetDeviceVersion(context,retryCount){
  300. let _self = this;
  301. let {
  302. deviceId,
  303. serviceId,
  304. characteristicId
  305. } = context;
  306. //如果是获取版本,延迟写一个指令
  307. if (_self.writeHeadTimeout) {
  308. clearTimeout(_self.writeHeadTimeout);
  309. _self.writeHeadTimeout = null;
  310. }
  311. _self.writeHeadTimeout = setTimeout(() => {
  312. // 向蓝牙设备发送一个0x00的16进制数据
  313. let bufferDevice = new ArrayBuffer(1)
  314. let dataViewDevice = new DataView(bufferDevice)
  315. dataViewDevice.setUint8(0, 0)
  316. uni.writeBLECharacteristicValue({
  317. deviceId: deviceId,
  318. serviceId: serviceId,
  319. characteristicId: characteristicId,
  320. value: bufferDevice,
  321. success:(res) => {
  322. console.log('获取版本:writeBLECharacteristicValue success', res.errMsg ," == " ,retryCount)
  323. },
  324. fail:(fail)=>{
  325. console.error('获取版本:writeBLECharacteristicValue fail', fail.errMsg ," == " ,retryCount)
  326. if(retryCount>0){
  327. retryCount--;
  328. setTimeout(()=>{
  329. _self.onGetDeviceVersion(context,retryCount);
  330. },300);
  331. return;
  332. }
  333. uni.showModal({
  334. title:'获取固件版本',
  335. content:'获取不成功,是否重新获取',
  336. success: (resValue) => {
  337. if(resValue.confirm){
  338. _self.onGetDeviceVersion(context,retryCount);
  339. }
  340. }
  341. })
  342. }
  343. })
  344. }, 3000)
  345. },
  346. //监听低功耗蓝牙设备的特征值变化。必须先启用notify接口才能接收到设备推送的notification。
  347. onBLECharacteristicValueChange() {
  348. var _self = this;
  349. // ArrayBuffer转16进制字符串示例
  350. // console.log("onBLECharacteristicValueChange");
  351. uni.onBLECharacteristicValueChange(function(res) {
  352. if (res.characteristicId.toLocaleLowerCase() === _self.UUID_IDENTFY) {
  353. //如果硬件的版本获取版本
  354. var resValue = ab2hext(res.value); //16进制字符串
  355. // console.log("Device 版本:", resValue.substr(0, 4), "Rom 版本号:", resValue.substr(16, 4));
  356. _self.devicesList[0].currentRomVersion = resValue.substr(16, 4);
  357. _self.devicesList[0].currentVersion = resValue.substr(0, 4);
  358. //读取到硬件版本,判断是否需要更新
  359. if (_self.devicesList[0].currentVersion === _self.devicesList[0].latestVersion && _self.devicesList[0].currentRomVersion ===
  360. _self.devicesList[0].latestRomVersion) {
  361. uni.showToast({
  362. title: '版本一致,无需升级',
  363. icon: 'none',
  364. mask: true,
  365. })
  366. _self.bCanUpdate = false;
  367. return;
  368. }
  369. uni.showToast({
  370. title: '获取信息成功',
  371. icon: 'success',
  372. mask: true,
  373. })
  374. //设置状态
  375. _self.bCanUpdate = true;
  376. } else {
  377. uni.hideToast();
  378. //成功发送头文件会走一个回调
  379. let uint8_buf = new DataView(res.value);
  380. _self.send_index = ((uint8_buf.getUint8(1) << 8) | uint8_buf.getUint8(0));
  381. console.log("val===>> data:" + ab2hext(res.value) + ",rv index:" + _self.send_index + _self.sending_file)
  382. if (_self.sending_file == false) {
  383. _self.sending_file = true;
  384. // console.log("SendBlePkg");
  385. _self.writeTip = "正在写入设备...";
  386. _self.SendBlePkg();
  387. }
  388. }
  389. });
  390. },
  391. //下载后读取
  392. onCheckServerFiles() {
  393. this.bin_buffer = [];
  394. this.bin_offset = 0;
  395. this.bin_total = 0;
  396. this.reset();
  397. uni.request({
  398. url: this.downLoadOTA,
  399. method: "GET",
  400. responseType: "arraybuffer",
  401. success: (res) => {
  402. //记录二进制数据
  403. this.bin_buffer = res.data;
  404. let binData = new Uint8Array(this.bin_buffer, 0, 16); //new Uint8Array(this.bin_buffer);
  405. this.bin_file_len = (binData[7] << 8) | binData[6]
  406. this.bin_total = (this.bin_file_len) / 4
  407. this.bin_byteLength = this.bin_buffer.byteLength;
  408. function uint8_to_hex_str(data) {
  409. var v = data.toString(16).slice(-2) + ''
  410. if (v == '0') {
  411. v = '00'
  412. }
  413. if (v.length == 1) {
  414. v = '0' + v
  415. }
  416. return v
  417. }
  418. // console.log("ver2:", uint8_to_hex_str(binData[4]) + uint8_to_hex_str(binData[5]), ",rom:", uint8_to_hex_str(
  419. // binData[14]) +
  420. // uint8_to_hex_str(binData[15]));
  421. //显示信息
  422. this.devicesList[0].latestRomVersion = uint8_to_hex_str(binData[14]) + uint8_to_hex_str(binData[15]); //str.substr(28, 2);
  423. this.devicesList[0].latestVersion = uint8_to_hex_str(binData[4]) + uint8_to_hex_str(binData[5]); //str.substr(8, 2);
  424. },
  425. fail: (fail) => {
  426. uni.showToast({
  427. title: '下载固件失败..',
  428. icon: 'none'
  429. });
  430. }
  431. });
  432. },
  433. //发送文件头信息(配置信息)
  434. sendFileHeader(retryCount) {
  435. console.log('---------- sendFileHeader --------------')
  436. let _self = this
  437. let buffer = new ArrayBuffer(16)
  438. let dataView = new DataView(buffer)
  439. var b = new Uint8Array(_self.bin_buffer, 0, 16);
  440. for (var i = 0; i < 16; i++) {
  441. dataView.setUint8(i, b[i])
  442. }
  443. console.log('send header:' + ab2hext(buffer))
  444. // return;
  445. uni.writeBLECharacteristicValue({
  446. deviceId: _self.BLEConnectDevice.deviceId,
  447. serviceId: _self.UUID_OTA_SERVICE.toLocaleUpperCase(),
  448. characteristicId: _self.UUID_IDENTFY.toLocaleUpperCase(),
  449. value: buffer,
  450. success: function(res) {
  451. // _self.send_index = -1
  452. // _self.sending_file = false
  453. uni.showToast({
  454. title: '准备更新数据...',
  455. icon: 'none',
  456. duration: 3000,
  457. mask:true
  458. })
  459. console.log('开始发送文件success', _self.sending_file)
  460. // _self.SendBlePkg()
  461. },
  462. fail: function(err) {
  463. console.log('read version fail! ' + JSON.stringify(err)+retryCount)
  464. if(retryCount>0){
  465. retryCount--;
  466. setTimeout(()=>{
  467. _self.sendFileHeader(retryCount);
  468. },300);
  469. return;
  470. }
  471. uni.showModal({
  472. title:'请求更新',
  473. content:'请求更新失败,是否重新尝试继续。',
  474. success: (resValue) => {
  475. if(resValue.confirm){
  476. _self.sendFileHeader(retryCount);
  477. }else if(resValue.cancel){
  478. _self.bStart = false;
  479. }
  480. }
  481. })
  482. }
  483. })
  484. },
  485. //发送一包数据
  486. SendBlePkg() {
  487. var _self = this;
  488. if (!_self.bSend) return;
  489. if (_self.send_index == -1) {
  490. return
  491. }
  492. if (_self.send_index >= _self.bin_total) {
  493. _self.percentage = 100;
  494. uni.showToast({
  495. title: "更新完成",
  496. duration: 2000,
  497. mask: true
  498. })
  499. //回退timeout
  500. if (this.backTimeout) {
  501. clearTimeout(this.backTimeout);
  502. this.backTimeout = null;
  503. }
  504. this.backTimeout = setTimeout(() => {
  505. //更新成功后设备会断开,此时回退出此页面
  506. uni.hideToast();
  507. _self.onBack();
  508. }, 1500)
  509. return;
  510. }
  511. _self.percentage = parseInt(_self.send_index / _self.bin_total * 100);
  512. //分包长度,16字节有效数据(总数据/16=次数)
  513. let length = 16;
  514. //发送每包数据的结构:2个字节的序号 + 16个字节的有效数据
  515. //设置数据包序号
  516. let lo = getLow8(_self.send_index);
  517. let hi = getHeight8(_self.send_index);
  518. //最要一个18字节的包
  519. let send_ab = new ArrayBuffer(18);
  520. let a = new Uint8Array(send_ab);
  521. //2个字节的序号
  522. a[0] = lo;
  523. a[1] = hi;
  524. if (_self.bin_offset + length > _self.bin_buffer.byteLength) {
  525. length = _self.bin_buffer.byteLength - _self.bin_offset;
  526. }
  527. var b = new Uint8Array(_self.bin_buffer, _self.bin_offset, length);
  528. a.set(b, 2);
  529. uni.writeBLECharacteristicValue({
  530. deviceId: _self.BLEConnectDevice.deviceId,
  531. serviceId: _self.UUID_OTA_SERVICE, // _deviceId,
  532. characteristicId: _self.UUID_BLOCK,
  533. value: send_ab,
  534. fail: function(res) {
  535. console.log('write BLEChar fail')
  536. _self.SendBlePkg();
  537. },
  538. success: function(res) {
  539. _self.send_index++;
  540. //发送的有效字节数
  541. _self.bin_offset += length;
  542. // _self.sending_file = false;
  543. _self.SendBlePkg();
  544. // console.log('success')
  545. },
  546. })
  547. },
  548. reset() {
  549. //发送字节的下标
  550. this.send_index = 0;
  551. //发送的有效字节数
  552. this.bin_offset = 0;
  553. this.percentage = 0;
  554. this.bSend = true;
  555. },
  556. onStop() {
  557. this.bSend = false;
  558. },
  559. onReadFile(url) {
  560. //游戏列表
  561. // firmwareList: [{
  562. // name: "24_LYY_3431Q_H2_S3_bk3435_ble_app_oad.bin",
  563. // downloadUrl: "https://www.yuyekeji.cn/Cocos/bin_version/24_LYY_3431Q_H2_S3_bk3435_ble_app_oad.bin",
  564. // fileName: "bin_version",
  565. // suffix: "bin",
  566. // type: "bin",
  567. // task: null,
  568. // progressVal: 0,
  569. // bFileExists: false,
  570. // bDownload: false,
  571. // }],
  572. // data URIs to buffer
  573. function dataURL2Buffer(dataURI) {
  574. var byteStr
  575. var intArray
  576. var ab
  577. var i
  578. var mimetype
  579. var parts
  580. parts = dataURI.split(',')
  581. parts[1] = parts[1].replace(/\s/g, '')
  582. // console.log(parts);
  583. if (~parts[0].indexOf('base64')) {
  584. byteStr = atob(parts[1])
  585. } else {
  586. byteStr = decodeURIComponent(parts[1])
  587. }
  588. // // ab = new ArrayBuffer(byteStr.length)
  589. // intArray = new Uint8Array(byteStr.length)
  590. // for (i = 0; i < byteStr.length; i++) {
  591. // intArray[i] = byteStr.charCodeAt(i)
  592. // }
  593. // console.log(intArray.length, intArray.byteLength);
  594. return byteStr;
  595. }
  596. let item = this.firmwareList[0];
  597. console.log("url:" + JSON.stringify(url));
  598. plus.io.resolveLocalFileSystemURL(url, function(entry) {
  599. entry.file(function(file) {
  600. var fileReader = new plus.io.FileReader();
  601. fileReader.readAsDataURL(file);
  602. fileReader.onloadend = function(evt) {
  603. // console.log("_buffer1:" + JSON.stringify(evt.target.result));
  604. // let _arrayBuffer = dataURL2Buffer(evt.target.result)
  605. let parts = evt.target.result.split(',')
  606. let _arrayBuffer = parts[1].replace(/\s/g, '')
  607. console.log("_buffer1:" + JSON.stringify(_arrayBuffer));
  608. let _buffer = uni.base64ToArrayBuffer(_arrayBuffer);
  609. console.log("_buffer2:", JSON.stringify(_buffer));
  610. console.log("_buffer:", _buffer.length, _buffer.byteLength, _buffer.byteOffset);
  611. }
  612. });
  613. }, function(e) {
  614. console.log("Resolve file URL failed: " + e.message);
  615. });
  616. },
  617. //下载固件
  618. downLoadBin() {
  619. let _self = this;
  620. let item = this.firmwareList[0];
  621. let downloadUrl = item.downloadUrl;
  622. let _filename = '_doc/' + item.name; //+'/'+item.name
  623. console.log(_filename, downloadUrl);
  624. item.task = plus.downloader.createDownload(downloadUrl, {
  625. filename: _filename
  626. });
  627. item.task.addEventListener("statechanged", (download, status) => {
  628. // console.log("status", status);
  629. //连接服务器后
  630. // no default
  631. switch (download.state) {
  632. case 1:
  633. console.log('开始下载');
  634. // item.bDownload = true;
  635. break;
  636. case 2:
  637. console.log('链接到服务器...');
  638. item.bDownload = true;
  639. break;
  640. case 3:
  641. if (status !== 200) {
  642. uni.showToast({
  643. title: 'status=' + status
  644. })
  645. return;
  646. }
  647. item.progressVal = Math.ceil(download.downloadedSize / download.totalSize * 100);
  648. // _this.precent = progressVal;
  649. console.log(item.progressVal);
  650. break;
  651. case 4:
  652. // 下载完成
  653. console.log("监听下载 success: " + download.getFileName());
  654. setTimeout(() => {
  655. item.bDownload = false;
  656. }, 500)
  657. break;
  658. }
  659. }, false);
  660. item.task.start();
  661. },
  662. add: function(data) {
  663. // console.log(data)
  664. if (this.extraLine.length > 500) {
  665. this.extraLine = [];
  666. this.text = this.extraLine.join('\n');
  667. }
  668. this.extraLine.push(data);
  669. this.text = this.extraLine.join('\n');
  670. },
  671. remove: function(e) {
  672. if (this.extraLine.length > 0) {
  673. // this.extraLine.pop();
  674. this.extraLine = [];
  675. this.text = this.extraLine.join('\n');
  676. }
  677. },
  678. }
  679. }
  680. function ab2hext(buffer) {
  681. var hexArr = Array.prototype.map.call(
  682. new Uint8Array(buffer),
  683. function(bit) {
  684. return ('00' + bit.toString(16)).slice(-2)
  685. }
  686. )
  687. return hexArr.join('');
  688. }
  689. function getHeight8(data) { //获取高8位
  690. let height;
  691. height = (data >> 8);
  692. return height;
  693. }
  694. function getLow8(data) { //获取低8位
  695. let low;
  696. low = (data & 0xFF);
  697. return low;
  698. }
  699. </script>
  700. <style>
  701. .hardware-border {
  702. border: 1rpx solid #9898FF;
  703. box-sizing: border-box;
  704. }
  705. .text-box {
  706. margin: 20rpx;
  707. display: flex;
  708. width: 95%;
  709. min-height: 300rpx;
  710. max-height: 600rpx;
  711. background-color: #EEEEEE;
  712. justify-content: center;
  713. align-items: center;
  714. text-align: center;
  715. font-size: 30upx;
  716. color: #353535;
  717. line-height: 1.8;
  718. border: 1rpx solid #555555;
  719. overflow-y: hidden;
  720. }
  721. </style>