[uniapp]手机连接蓝牙打印机

2024-09-12 01:32:00 by wst

小程序

uniapp为我们提供了一套统一的接口让我们连接蓝牙打印机。

目前的开发场景:手机连接蓝牙打印机,然后把结账小票打出来。

环境

系统:deepin(Linux)

工具:uniapp

IDE:VSCode

语言:Vue3

代码

目录结构

src
├── App.vue
├── components
│   └── zwy-popup
│       └── zwy-popup.vue
├── config.js
├── main.js
├── manifest.json
├── pages
│   ├── data
│   │   ├── data.vue
│   │   └── order.vue
│   ├── login
│   │   └── login.vue
│   ├── mall
│   │   ├── mall.vue
│   │   ├── order_food.vue
│   │   └── pay_bill.vue
│   ├── manage
│   │   ├── dish-class.vue
│   │   ├── dish-clear.vue
│   │   ├── dish-combo.vue
│   │   ├── dish-list.vue
│   │   ├── manage.vue
│   │   └── table-list.vue
│   ├── protocol
│   │   └── protocol.vue
│   ├── receipt
│   │   ├── printpage.vue
│   │   └── receipt.vue
│   └── register
│       ├── changepwd.vue
│       └── register.vue
├── pages.json
├── shime-uni.d.ts
├── static
│   ├── libs
│   │   ├── BluetoothTool.js
│   │   ├── encoding-indexes.js
│   │   ├── encoding.js
│   │   ├── esc.js
│   │   ├── myprinter.js
│   │   └── tsc.js
│   ├── logo.png
│   └── tabbar
│       ├── data-color.png
│       ├── data.png
│       ├── mall-color.png
│       ├── mall.png
│       ├── mg-color.png
│       └── mg.png
├── styles
│   └── manage.scss
├── uni.scss
└── utils
    ├── date.js
    ├── login.js
    └── print.js

大家主要关注调用文件printpage.vue和库static/libs下的文件。

调用代码

printpage.vue

<template>
  <view>
      <scroll-view
          scroll-y
          class="box"
      >
          <view class="item" v-for="item in blueDeviceList" @click="connect(item)">
              <view>
                  <text>id: {{ item.deviceId }}</text>    
              </view>
              <view>
                  <text style="color: darkslateblue;font-weight: 700;">name: {{ item.name }}</text>  
              </view>
          </view>
      </scroll-view>

      <button @click="initBlue">1 初始化蓝牙</button>

      <button @click="discovery">2 搜索附近蓝牙设备</button>

      <button @click="getServices">3 获取蓝牙服务</button>

      <button @click="sendData">4 打印测试数据</button>

      <button @click="destroyed" type="warn" plain> 断开蓝牙</button>

      <button @click="return_my" type="primary">返回</button>

  </view>
</template>
<script setup>
import { ref } from 'vue';
import { print_content } from '@/static/libs/myprinter.js'
import { BASE_URL } from '../../config';
import { senBlData,check_print } from '../../utils/print';

// 搜索到的蓝牙设备列表
const blueDeviceList = ref([])
// 蓝牙设备的id
const deviceId = ref('')
// 蓝牙设备的服务列表
const myServices = ref([])
// 打印内容
var ticket = ref("");

// 【4】获取数据
function getData(){
    uni.request({
        url:BASE_URL+'/admin/data/print/test',
        data:{},
        success:(success)=>{
            console.log("res:", success.data)
            ticket.value = success.data.data.content
        },
    })
}

// 【1】初始化蓝牙
function initBlue() {
  uni.openBluetoothAdapter({
      success(res) {
          console.log('初始化蓝牙成功')
          console.log(res)
          uni.showToast({
            title: '初始化蓝牙成功',
            icon: 'none'
          })
      },
      fail(err) {
          console.log('初始化蓝牙失败')
          console.error(err)
      }
  })
}

function destroyed() {
    console.log("destroyed----------")
    console.log("deviceId:", deviceId.value)
    if(deviceId.value == ''){
        deviceId.value = uni.getStorageSync('deviceId')
    }
    if (deviceId.value != '') {
        uni.closeBLEConnection({
            deviceId: deviceId.value,
            success(res) {
                console.log(res)
                uni.showToast({
                    title: '蓝牙已断开',
                    icon: 'none'
                })
            }
        })
    }
}

/**返回我的页面 */
function return_my(){
    var url = '/pages/my/my';
    var current = uni.getStorageSync('current') || ''
    console.log("current:", current)
    if(current){
        uni.navigateTo({
            url: current,
        })
    } else {
        uni.switchTab({
            url:url,
        })
    }
}

// 【2】开始搜寻附近设备
function discovery() {
  uni.startBluetoothDevicesDiscovery({
      success(res) {
          console.log('开始搜索')
          uni.showToast({
            title: '搜索中。。。\n请在列表中选择您的设备',
            icon: 'none',
            duration: 3000
          })
          // 开启监听回调
          uni.onBluetoothDeviceFound(found)
      },
      fail(err) {
          console.log('搜索失败')
          console.error(err)
      }
  })
}

// 【3】找到新设备就触发该方法
function found(res) {
  console.log(res)
  blueDeviceList.value.push(res.devices[0])
}



// 【4】连接设备
function connect(data) {
  console.log(data)

  deviceId.value = data.deviceId // 将获取到的设备ID存起来
  uni.setStorageSync('deviceId', data.deviceId)

  uni.createBLEConnection({
      deviceId: deviceId.value,
      success(res) {
          console.log('连接成功')
          console.log(res)
          // 停止搜索
          stopDiscovery()
          uni.showToast({
              title: '连接成功'
          })
      },
      fail(err) {
          console.log('连接失败')
          console.error(err)
          uni.showToast({
              title: '连接成功',
              icon: 'error'
          })
      }
  })
}

// 【5】停止搜索
function stopDiscovery() {
  uni.stopBluetoothDevicesDiscovery({
      success(res) {
          console.log('停止成功')
          console.log(res)
      },
      fail(err) {
          console.log('停止失败')
          console.error(err)
      }
  })
}

// 【3】获取服务
function getServices() {
    // 如果是自动链接的话,uni.getBLEDeviceServices方法建议使用setTimeout延迟1秒后再执行
    uni.getBLEDeviceServices({
        deviceId: deviceId.value,
        success(res) {
            console.log(res) // 可以在res里判断有没有硬件佬给你的服务
            uni.showToast({
                title: '获取服务成功'
            })
        },
        fail(err) {
            console.error(err)
            uni.showToast({
                title: '获取服务失败',
                icon: 'error'
            })
        },
        complete(res) {
            console.log("当前蓝牙设备的服务:", res)

            for (var s = 0; s < res.services.length; s++) {
                console.log("服务" + s + ":", res.services[s].uuid)
                let serviceId = res.services[s].uuid
                uni.getBLEDeviceCharacteristics({
                    // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
                    deviceId: deviceId.value,
                    // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
                    serviceId: serviceId,
                    success(res) {
                        var re = JSON.parse(JSON.stringify(res))
                        console.log('遍历:deviceId = [' + deviceId.value + ']  serviceId = [' + serviceId + ']')
                        for (var c = 0; c < re.characteristics.length; c++) {
                            if (re.characteristics[c].properties.write == true) {
                                let uuid = re.characteristics[c].uuid
                                console.log('可用: deviceId = [' + deviceId.value + ']  serviceId = [' + serviceId + '] characteristics=[' +
                                    uuid + "]")
                                myServices.value.push({
                                    serviceId: serviceId,
                                    characteristicId: uuid
                                })
                                console.log("处理后的服务列表:", JSON.stringify(myServices.value))
                                uni.setStorageSync("myServices", myServices.value)
                            }
                        }
                    }
                })
            }

        }
    })
}

// 【5】发送数据
function sendData(){
    check_print()
    var command = ""
    command += "------内容开始------" + "\r\n";  
    command += 'hello' + "\r\n"; // 打印内容
    command += "------内容结束------\r\n"  
    command += "\r\n\r\n"   // 打印页低
    // var new_content = ticket.value+"\r\n\r\n"
    senBlData(deviceId.value, myServices.value[0].serviceId, myServices.value[0].characteristicId,print_content(command))
    uni.showToast({
        title: '发送成功',
        icon: 'none'
    })
}

// 硬件提供的服务id,开发中需要问硬件佬获取该id
const serviceId = ref('0000FFE0-0000-1000-8000-00805F9B34FB')

const characteristicId = ref('0000FFE1-0000-1000-8000-00805F9B34FB')

// 【8】开启消息监听
function notify() {
  uni.notifyBLECharacteristicValueChange({
      deviceId: deviceId.value, // 设备id
      serviceId: myServices.value[0].serviceId, // 监听指定的服务
      characteristicId: myServices.value[0].characteristicId, // 监听对应的特征值
      state:true,
      success(res) {
          console.log(res)
          listenValueChange()
          uni.showToast({
              title: '已开启监听'
          })
      },
      fail(err) {
          console.error(err)
          uni.showToast({
              title: '监听失败',
              icon: 'error'
          })
      }
  })
}

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
  const hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
)
  return hexArr.join('')
}

// 将16进制的内容转成我们看得懂的字符串内容
function hexCharCodeToStr(hexCharCodeStr) {
  var trimedStr = hexCharCodeStr.trim();
  var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
  var len = rawStr.length;
  if (len % 2 !== 0) {
          alert("存在非法字符!");
          return "";
  }
  var curCharCode;
  var resultStr = [];
  for (var i = 0; i < len; i = i + 2) {
          curCharCode = parseInt(rawStr.substr(i, 2), 16);
          resultStr.push(String.fromCharCode(curCharCode));
  }
  return resultStr.join("");
}

// 监听到的内容
const message = ref('')
const messageHex = ref('') // 十六进制

// 【9】监听消息变化
function listenValueChange() {
  uni.onBLECharacteristicValueChange(res => {
      console.log(res)
      let resHex = ab2hex(res.value)
      console.log(resHex)
      messageHex.value = resHex
      let result = hexCharCodeToStr(resHex)
      console.log(String(result))
      message.value = String(result)
  })
}


// 【11】读取数据
function read() {
  uni.readBLECharacteristicValue({
      deviceId: deviceId.value,
      serviceId: serviceId.value,
      characteristicId: characteristicId.value,
      success(res) {
          console.log(res)
          uni.showToast({
              title: 'read指令发送成功'
          })
      },
      fail(err) {
          console.error(err)
          uni.showToast({
              title: 'read指令发送失败',
              icon: 'error'
          })
      }
  })
}
</script>

<style>
.box {
  width: 98%;
  height: 400rpx;
  box-sizing: border-box;
  margin: 0 auto 20rpx;
  border: 2px solid dodgerblue;
}
.item {
  box-sizing: border-box;
  padding: 10rpx;
  border-bottom: 1px solid #ccc;
}
button {
  margin: 10rpx;
}

</style>

库文件static/libs太多了,大家可以关注这个公众号,回复uniapp-print获取。

总结

以上就是怎么在手机端连接蓝牙打印机、打印小票的过程。对了,截图如下:

如有问题,欢迎留言!


Comments(1) Add Your Comment

http://boyarka-inform.com/
I really love your site.. Grea colors & theme. Did yoou make this web site yourself? Please reply back as I'm hoping to create myy own personal website and wqnt to know where you got this from or what the theme is named. Appreciate it! http://boyarka-inform.com/