专业编程基础技术教程

网站首页 > 基础教程 正文

微信小程序实现蓝牙打印小票功能

ccvgpt 2025-05-24 12:36:30 基础教程 8 ℃

一、效果展示

连接蓝牙打印机

微信小程序实现蓝牙打印小票功能

打印小票

二、微信小程序开发界面

三、核心代码

printcode.wxml

<!--打印二维码操作-->
<view class='qrcode_box'>
<view class='title'>打印违章车辆信息二维码</view>
<view class='content'>通过蓝牙连接打印,用做车辆出入库凭证</view>
<view class='open'>请确保蓝牙已打开</view>
</view>
<view class='canvasView'>
  <canvas canvas-id='qrCode' style='width:288px;height:288px;margin:0 auto'></canvas>
</view>
<button class='gray_btn_index active' style="bottom:30rpx" catchtap='printQrcode'>打印二维码</button> 

printcode.js

var orderId;
var matchDevice;
var deviceArray = [];//匹配过的设备数组
Page({
  /**
   * 页面的初始数据
   */
  data: {
    deviceInfo: {},
    codeText:"11111111111111111111112"
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.makeQrCode();
  },
  //生成二维码
  makeQrCode() {
    //打印二维码
    drawQrcode({
      width: 288,
      height: 288,
      canvasId: 'qrCode',
      text:this.data.codeText
    });
  },
  //打印二维码
  printQrcode() {
    //进入页面扫描蓝牙
    deviceArray = [];
    this.openBluetoothAdapter();
  },
  //初始化蓝牙模块,看是否打开手机蓝牙
  openBluetoothAdapter() {
    if (!wx.openBluetoothAdapter) {
      wx.showModal({
        title: '提示',
        content: '当前微信版本过低,请升级到最新微信版本后重试。'
      })
      return;
    }
    //初始化蓝牙模块,看是否打开手机蓝牙
    wx.openBluetoothAdapter({
      success: (res) => {
        console.log('openBluetoothAdapter success', res);
        //开始搜索附近蓝牙设备
        this.startBluetoothDevicesDiscovery()
      },
      fail: (res) => {
        console.log('openBluetoothAdapter fail', res)
        if (res.errCode === 10001) {
          wx.showModal({
            title: '提示',
            content: '未打开蓝牙, 请打开蓝牙后重试。',
            showCancel: false
          })
          //监听蓝牙适配器状态
          wx.onBluetoothAdapterStateChange((res) => {
            console.log('onBluetoothAdapterStateChange', res)
            if (res.available) {
              //能用,直接开始搜索附近蓝牙设备
              // 取消监听,否则stopBluetoothDevicesDiscovery后仍会继续触发onBluetoothAdapterStateChange,
              // 导致再次调用startBluetoothDevicesDiscovery
              wx.onBluetoothAdapterStateChange(() => {
              });
              //开始搜索蓝牙设备
              this.startBluetoothDevicesDiscovery()
            }
          })
        }
      }
    });
    //监听蓝牙连接状态
    wx.onBLEConnectionStateChange((res) => {
      // 该方法回调中可以用于处理连接意外断开等异常情况
      console.log('onBLEConnectionStateChange', `device ${res.deviceId} state has changed, connected: ${res.connected}`)
      this.setData({
        connected: res.connected
      })
      if (!res.connected) {
        wx.showModal({
          title: '错误',
          content: '蓝牙连接已断开',
          showCancel: false
        })
      }
    });
  },
  //开始扫描蓝牙附近设备
  startBluetoothDevicesDiscovery() {
    //_discoveryStarted是否已经开始搜索
    if (this._discoveryStarted) {
      return;
    }
    this._discoveryStarted = true
    //开始搜索附近蓝牙设备
    wx.startBluetoothDevicesDiscovery({
      success: (res) => {
        wx.showLoading({
          title: '正在搜索附近蓝牙',
          mask: true
        })
        console.log('startBluetoothDevicesDiscovery success', res)
        //蓝牙设备被找到事件回调
        this.onBluetoothDeviceFound()
      },
      fail: (res) => {
        console.log('startBluetoothDevicesDiscovery fail', res)
      }
    })
  },
  //关闭蓝牙搜索附近设备
  stopBluetoothDevicesDiscovery() {
    wx.stopBluetoothDevicesDiscovery({
      complete: () => {
        console.log('stopBluetoothDevicesDiscovery')
        this._discoveryStarted = false
      }
    })
  },
  //蓝牙设备被找到事件回调
  onBluetoothDeviceFound() {
    var $this = this;
    wx.onBluetoothDeviceFound((res) => {
      for (var i = 0; i < res.devices.length; i++) {
        var device = res.devices[i];
        if (device.name || device.localName) {
          var localName = device.name || device.localName;//获取设备名称
          if (deviceArray.indexOf(localName) == -1) {
            //先关闭蓝牙搜索
            deviceArray.push(localName)
            $this.stopBluetoothDevicesDiscovery();
            wx.hideLoading();
            wx.showModal({
              title: '设备匹配提示',
              content: localName,
              confirmText: '连接打印',
              showCancel: true,
              cancelText: '继续搜索',
              success: function (res) {
                if (res.confirm) {
                  var deviceInfo = $this.data.deviceInfo;
                  deviceInfo.name = localName;
                  deviceInfo.deviceId = device.deviceId;//获取设备ID
                  $this.setData({
                    deviceInfo: deviceInfo
                  })
                  //创建连接
                  $this._createBLEConnection(deviceInfo.deviceId, deviceInfo.name);
                }
                else {
                  //点击继续搜索
                  $this.startBluetoothDevicesDiscovery();
                }
              },
            })
            break;
          }
        }
      }
    })
  },
  //连接低功耗蓝牙设备。
  _createBLEConnection(deviceId, name) {
    var $this = this;
    wx.createBLEConnection({
      deviceId,
      success: () => {
        //链接成功,//获取服务
        $this.getBLEDeviceServices(deviceId);
      },
      fail: (res) => {
        //链接失败
        common.alert(name + "设备连接失败", false);
      }
    })
  },
  //获取设备服务
  getBLEDeviceServices(deviceId) {
    wx.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        console.log('getBLEDeviceServices', res)
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary) {
            this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
            return
          }
        }
      }
    })
  },
  //获取低功率设备服务
  getBLEDeviceCharacteristics(deviceId, serviceId) {
    var $this = this;
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {
        console.log('getBLEDeviceCharacteristics success', res.characteristics)
        // 这里会存在特征值是支持write,写入成功但是没有任何反应的情况
        // 只能一个个去试
        for (let i = 0; i < res.characteristics.length; i++) {
          const item = res.characteristics[i]
          if (item.properties.write) {
            var deviceInfo = $this.data.deviceInfo;
            deviceInfo.canWrite = true;//该设备支持写入
            deviceInfo.serviceId = serviceId;//蓝牙特征值对应服务的 uuid
            deviceInfo.characteristicId = item.uuid;//蓝牙特征值的 uuid
            $this.setData({
              deviceInfo: deviceInfo
            });
            $this.writeBLECharacteristicValue();
            break;
          }
        }
      },
      fail(res) {
        console.error('getBLEDeviceCharacteristics', res)
        common.alert("获取蓝牙设备某个服务中所有特征值失败", false);
      }
    })
  },
  //向设备写入数据
  writeBLECharacteristicValue() {
    var $this = this;
    // 1.并行调用多次会存在写失败的可能性
    // 2.建议每次写入不超过20字节
    // 分包处理,延时调用
    const maxChunk = 20;
    const delay = 20;
    //获取二维码像像素点
    wx.canvasGetImageData({
      canvasId: 'qrCode',
      x: 0,
      y: 0,
      width: 288,
      height: 288,
      success(res) {
        //4和一
        var arr = [];
        res = res.data;
        for (let i = 0; i < res.length; i++) {
          if (i % 4 == 0) {
            let rule = 0.29900 * res[i] + 0.58700 * res[i + 1] + 0.11400 * res[i + 2];
            if (rule > 128) {
              res[i] = 0;
            } else {
              res[i] = 1;
            }
            arr.push(res[i]);
          }
        }
        var data = [];
        for (let k = 0; k < arr.length; k += 8) {
          let temp = arr[k] * 128 + arr[k + 1] * 64 + arr[k + 2] * 32 + arr[k + 3] * 16 + arr[k + 4] * 8 + arr[k + 5] * 4 + arr[k + 6] * 2 + arr[k + 7] * 1
          data.push(temp);
        }
        //图片尺寸72*72,即24的3倍
        var arrayValue = [27, 74, 150].concat([27, 51, 0], [27, 97, 49]);
        var width = 288;
        for (let x = 0; x < width / 24; x++) {
          var printdata = [];
          for (let y = 0; y < width; y++) {
            for (let z = 0; z < 3; z++) {
              let index = 3 * x + (width / 24) * 3 * y + z;
              printdata.push(data[index]);
            }
          }
          var temp = [].concat([27, 42, 33, 32, 1], printdata, [10]);
          arrayValue = arrayValue.concat(temp);
        }
        arrayValue = arrayValue.concat([27, 74, 250]);//打印走纸
        var buffer = new Uint8Array(arrayValue).buffer;
        for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
          let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
          setTimeout(function () {
            $this._writeBLECharacteristicValue(subPackage);
          }, 20)
        }
      }
    })
  },
  _writeBLECharacteristicValue(buffer) {
    var $this = this;
    var deviceInfo = this.data.deviceInfo;
    wx.writeBLECharacteristicValue({
      deviceId: deviceInfo.deviceId,
      serviceId: deviceInfo.serviceId,
      characteristicId: deviceInfo.characteristicId,
      value: buffer,
      success(res) {
        common.alert("打印任务提交成功", false);
        console.log('writeBLECharacteristicValue success', res)
      },
      fail(res) {
        common.alert("打印任务失败", false);
        console.log('writeBLECharacteristicValue fail', res)
      }
    })
  },
  //关闭蓝牙模块
  closeBluetoothAdapter() {
    wx.closeBluetoothAdapter()
    this._discoveryStarted = false
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
    this.closeBluetoothAdapter();
  }
})

Tags:

最近发表
标签列表