index.vue 10 KB

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