index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. <template>
  2. <view class="content">
  3. <view class="cz-box" :class="loading?'turn':''" @click="toWork">
  4. <u-image width="100rpx" height="100rpx" src="/static/chengzhong.png"></u-image>
  5. <view class="tits">投放称重</view>
  6. </view>
  7. <view class="bindDev" @click="toInit">
  8. {{statusStr}}
  9. </view>
  10. <view class="devList">
  11. <view v-for="item in deviceList" :key="item.deviceId">
  12. <view class="names">
  13. <view>{{item.name}}</view>
  14. <view class="texts">MAC:{{item.deviceId}}</view>
  15. </view>
  16. <view class="btns" @click="connectBlue(item)" v-if="!connectStatus">点击连接</view>
  17. <view class="btns" @click="closeBlue" v-else>断开连接</view>
  18. </view>
  19. </view>
  20. </view>
  21. </template>
  22. <script>
  23. export default {
  24. data() {
  25. return {
  26. deviceList:[], // 设备列表
  27. deviceId: '',
  28. connectedDeviceId: '',
  29. services: [],
  30. readsId:'',
  31. writeId:'',
  32. notifyServicweId: '',
  33. writeDatas: '',
  34. balanceData: '',
  35. hexstr: '',
  36. statusStr: '绑定电子秤',
  37. connectStatus: false ,// 设备连接状态
  38. loading: false ,// 正在连接
  39. }
  40. },
  41. onShow() {
  42. console.log('onShow')
  43. },
  44. methods: {
  45. // 去认证用户并开始称重
  46. toWork(){
  47. // 连接成功
  48. if(this.connectStatus){
  49. uni.navigateTo({
  50. url: '/pages/userAuth/userAuth'
  51. })
  52. }else{
  53. uni.showModal({
  54. title:'提示',
  55. content:'请先绑定并连接电子秤',
  56. showCancel: false,
  57. complete(e) {
  58. console.log(e)
  59. }
  60. })
  61. }
  62. },
  63. // 初始化蓝牙
  64. toInit(){
  65. let _this = this
  66. uni.openBluetoothAdapter({
  67. success(res) {
  68. console.log(res, 'openBluetoothAdapter success')
  69. _this.onBluetoothAdapterStateChange()
  70. setTimeout(()=>{
  71. _this.toFindDev()
  72. },500)
  73. },
  74. fail(err){
  75. console.log(err,'openBluetoothAdapter error')
  76. uni.showModal({
  77. title:'提示',
  78. content:'请开启手机蓝牙',
  79. showCancel: false,
  80. complete(e) {
  81. console.log(e)
  82. _this.statusStr = '请开启手机蓝牙'
  83. }
  84. })
  85. }
  86. })
  87. },
  88. toFindDev(){
  89. let _this = this
  90. console.log(this.connectStatus,this.deviceList.length,this.loading)
  91. if(this.connectStatus || this.deviceList.length > 0 || this.loading){
  92. return
  93. }
  94. _this.statusStr = '开始搜寻附近的电子秤'
  95. _this.loading = true
  96. uni.getBluetoothAdapterState({
  97. success(res) {
  98. console.log(res)
  99. if(res.available){
  100. // 开始搜寻附近的蓝牙外围设备
  101. _this.startBluetoothDevicesDiscovery()
  102. }else{
  103. _this.statusStr = '请开启手机蓝牙'
  104. }
  105. },
  106. fail(err) {
  107. console.log(err)
  108. }
  109. })
  110. },
  111. // 监听蓝牙状态
  112. onBluetoothAdapterStateChange(){
  113. let _this = this
  114. // 监听蓝牙适配器状态变化事件
  115. uni.onBluetoothAdapterStateChange(function (res) {
  116. console.log(res,'适配器变化')
  117. if(!res.available){
  118. // 关闭连接
  119. _this.statusStr = '蓝牙已关闭,请开启手机蓝牙'
  120. _this.connectedDeviceId = null
  121. _this.closeConnect()
  122. }else{
  123. if(!res.discovering && !_this.loading){
  124. _this.statusStr = '蓝牙已启用,请绑定设备'
  125. }
  126. }
  127. })
  128. },
  129. startBluetoothDevicesDiscovery(){
  130. let _this = this
  131. uni.startBluetoothDevicesDiscovery({
  132. services: [],
  133. success(res) {
  134. console.log(res)
  135. // 监听寻找到新设备的事件
  136. uni.onBluetoothDeviceFound(function (res) {
  137. let devices = res.devices.filter(item => item.name == 'FAYA')
  138. console.log(devices,'devices list')
  139. if(devices.length){
  140. _this.statusStr = '已发现设备'
  141. _this.deviceList = res.devices
  142. _this.loading = false
  143. }
  144. })
  145. }
  146. })
  147. },
  148. // 连接蓝牙设备
  149. connectBlue(item){
  150. this.deviceId = item.deviceId
  151. this.statusStr = '正在连接设备...'
  152. this.loading = true
  153. this.createBLEConnection()
  154. },
  155. // 断开蓝牙设备
  156. closeBlue(){
  157. this.statusStr = '连接已断开,请重新绑定设备'
  158. this.closeConnect()
  159. },
  160. // 开始连接指定设备
  161. createBLEConnection(){
  162. let _this = this
  163. uni.createBLEConnection({
  164. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  165. deviceId:this.deviceId,
  166. success(res) {
  167. console.log(res)
  168. _this.connectedDeviceId = _this.deviceId
  169. // 获取连接设备的service服务
  170. setTimeout(()=>{
  171. _this.getBLEDeviceServices()
  172. },1000)
  173. }
  174. })
  175. },
  176. // 获取连接设备的service服务
  177. getBLEDeviceServices(){
  178. let _this = this
  179. uni.getBLEDeviceServices({
  180. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  181. deviceId: _this.deviceId,
  182. success(res) {
  183. console.log('device services:', res.services)
  184. // _this.statusStr = '获取连接设备的service服务成功'
  185. _this.services = res.services
  186. /* 获取连接设备的所有特征值 */
  187. setTimeout(()=>{
  188. _this.getBLEDeviceCharacteristics()
  189. },500)
  190. // 停止搜索
  191. uni.stopBluetoothDevicesDiscovery({
  192. success: function(res) {
  193. console.log(res, '停止搜索')
  194. },
  195. fail(res) {
  196. }
  197. })
  198. }
  199. })
  200. },
  201. // 获取连接设备的所有特征值
  202. getBLEDeviceCharacteristics(){
  203. let _this = this
  204. this.notifyServicweId = this.services[1].uuid
  205. uni.getBLEDeviceCharacteristics({
  206. deviceId: this.connectedDeviceId,
  207. serviceId: this.notifyServicweId,
  208. success: function(res) {
  209. console.log(res)
  210. // _this.statusStr = '获取连接设备的所有特征值成功'
  211. for (let i = 0; i < res.characteristics.length; i++) {
  212. let properties = res.characteristics[i].properties
  213. // 读id
  214. if(properties.notify&&!properties.read&&!properties.write){
  215. _this.readsId = res.characteristics[i].uuid
  216. }
  217. // 写id
  218. if(!properties.notify&&!properties.read&&properties.write){
  219. _this.writeId = res.characteristics[i].uuid
  220. }
  221. console.log(_this.readsId,_this.writeId, '蓝牙特征值 ==========')
  222. // 启用低功耗蓝牙设备特征值变化时的 notify 功能
  223. setTimeout(()=>{
  224. _this.notifyBLECharacteristicValueChange()
  225. },500)
  226. }
  227. },
  228. fail: function(res) {
  229. console.log(res)
  230. }
  231. })
  232. },
  233. // 启用低功耗蓝牙设备特征值变化时的 notify 功能
  234. notifyBLECharacteristicValueChange() {
  235. let that = this;
  236. uni.notifyBLECharacteristicValueChange({
  237. state: true,
  238. deviceId: that.connectedDeviceId,
  239. serviceId: that.notifyServicweId,
  240. characteristicId: that.readsId,
  241. success(res) {
  242. console.log(res,'notifyBLECharacteristicValueChange')
  243. that.statusStr = '连接成功,请投放称重'
  244. that.connectStatus = true
  245. that.loading = false
  246. /*用来监听手机蓝牙设备的数据变化*/
  247. uni.onBLECharacteristicValueChange(function(res) {
  248. console.log(res,'read data')
  249. that.balanceData = that.buf2string(res.value)
  250. that.$u.vuex('vuex_balanceData',that.balanceData)
  251. })
  252. // that.sendData()
  253. },
  254. fail(res) {
  255. console.log(res, '启用低功耗蓝牙设备监听失败')
  256. that.statusStr = '设备连接失败,请点击重试'
  257. that.closeConnect()
  258. }
  259. })
  260. },
  261. /*转换成需要的格式*/
  262. buf2string(buffer) {
  263. let arr = Array.prototype.map.call(new Uint8Array(buffer), x => x)
  264. return arr.map((char, i) => {
  265. return String.fromCharCode(char);
  266. }).join('');
  267. },
  268. receiveData(buf) {
  269. return this.hexCharCodeToStr(this.ab2hex(buf))
  270. },
  271. /*转成二进制*/
  272. ab2hex (buffer) {
  273. let hexArr = Array.prototype.map.call(
  274. new Uint8Array(buffer), function (bit) {
  275. return ('00' + bit.toString(16)).slice(-2)
  276. }
  277. )
  278. return hexArr.join('')
  279. },
  280. /*转成可展会的文字*/
  281. hexCharCodeToStr(hexCharCodeStr) {
  282. let trimedStr = hexCharCodeStr.trim();
  283. let rawStr = trimedStr.substr(0, 2).toLowerCase() === '0x' ? trimedStr.substr(2) : trimedStr;
  284. let len = rawStr.length;
  285. let curCharCode;
  286. let resultStr = [];
  287. for (let i = 0; i < len; i = i + 2) {
  288. curCharCode = parseInt(rawStr.substr(i, 2), 16);
  289. resultStr.push(String.fromCharCode(curCharCode));
  290. }
  291. return resultStr.join('');
  292. },
  293. // 发送数据
  294. sendData(str) {
  295. let that = this;
  296. let dataBuffer = new ArrayBuffer(3)
  297. let dataView = new DataView(dataBuffer)
  298. dataView.setUint8(0, 0x02)
  299. dataView.setUint8(1, 0x41)
  300. dataView.setUint8(2, 0x03)
  301. let dataHex = that.ab2hex(dataBuffer);
  302. this.writeDatas = that.hexCharCodeToStr(dataHex);
  303. uni.writeBLECharacteristicValue({
  304. deviceId: that.connectedDeviceId,
  305. serviceId: that.notifyServicweId,
  306. characteristicId: that.writeId,
  307. value: dataBuffer,
  308. success: function (res) {
  309. console.log('发送数据成功:' + that.writeDatas)
  310. },
  311. fail: function (res) {
  312. console.log('发送失败:' + res)
  313. },
  314. complete: function (res) {
  315. }
  316. })
  317. },
  318. // 断开设备连接
  319. closeConnect() {
  320. let that = this;
  321. if (that.connectedDeviceId) {
  322. uni.closeBLEConnection({
  323. deviceId: that.connectedDeviceId,
  324. success: function(res) {
  325. console.log(res)
  326. that.closeBluetoothAdapter()
  327. },
  328. fail(res) {
  329. console.log(res)
  330. }
  331. })
  332. } else {
  333. that.closeBluetoothAdapter()
  334. }
  335. },
  336. // 关闭蓝牙模块
  337. closeBluetoothAdapter() {
  338. let that = this;
  339. uni.closeBluetoothAdapter({
  340. success: function(res) {
  341. console.log(res,'closeBluetoothAdapter')
  342. that.connectStatus = false
  343. that.loading = false
  344. that.balanceData = ''
  345. that.deviceList = []
  346. },
  347. fail: function(err) {
  348. }
  349. })
  350. },
  351. },
  352. onUnload() {
  353. this.closeConnect()
  354. }
  355. }
  356. </script>
  357. <style>
  358. .content{
  359. display: flex;
  360. align-items: center;
  361. justify-content: center;
  362. flex-direction: column;
  363. background-image: radial-gradient( #2ab4e5 0%, #0081c1 100%);
  364. height: 100vh;
  365. width: 100%;
  366. }
  367. .cz-box{
  368. text-align: center;
  369. background: #fff;
  370. padding: 50rpx 50rpx 30rpx;
  371. border-radius: 300rpx;
  372. box-shadow: 3rpx 3rpx 10rpx rgba(0,0,0,0.4);
  373. width: 250rpx;
  374. height: 250rpx;
  375. display: flex;
  376. align-items: center;
  377. justify-content: center;
  378. flex-direction: column;
  379. }
  380. .tits{
  381. padding: 20rpx 0;
  382. color: #ef9f2e;
  383. }
  384. .devList{
  385. width: 80%;
  386. padding:10rpx 30rpx;
  387. }
  388. .bindDev{
  389. margin: 30rpx 0;
  390. padding: 10rpx 40rpx;
  391. box-shadow: 2rpx 2rpx 8rpx rgba(0,0,0,0.3);
  392. border-radius: 100rpx;
  393. color: #fff;
  394. }
  395. .devList > view{
  396. display: flex;
  397. align-items: center;
  398. color: #00aaff;
  399. border-radius: 100rpx;
  400. background: rgba(255,255,255,0.8);
  401. padding: 15rpx 40rpx;
  402. box-shadow: 2rpx 2rpx 5rpx rgba(0,0,0,0.2);
  403. }
  404. .devList > view .names{
  405. flex-grow: 1;
  406. }
  407. .devList > view .texts{
  408. font-size: 24rpx;
  409. }
  410. .devList > view .btns{
  411. text-align: center;
  412. }
  413. .turn{
  414. animation:turn 1s linear infinite;
  415. }
  416. @keyframes turn{
  417. 0%{-webkit-transform:rotate(0deg);}
  418. 25%{-webkit-transform:rotate(90deg);}
  419. 50%{-webkit-transform:rotate(180deg);}
  420. 75%{-webkit-transform:rotate(270deg);}
  421. 100%{-webkit-transform:rotate(360deg);}
  422. }
  423. </style>