当前位置:网站首页>微信小程序蓝牙连接硬件设备并进行通讯,小程序蓝牙因距离异常断开自动重连,js实现crc校验位

微信小程序蓝牙连接硬件设备并进行通讯,小程序蓝牙因距离异常断开自动重连,js实现crc校验位

2022-07-06 23:55:00 苦海123

一、小程序实现搜索蓝牙:
注意:comtl是我封装的工具函数,无关紧要,实际项目中可能用不到:

const comtl = require('../../utils/commontool')
const app = getApp() // 拿到全局定义的变量,需要在app.js中:App({globalData: { params: ''}}),params为全局变量名
let timerid = 0 // 定时器id
Page({
    
  data: {
    
    datas:[], // 所有蓝牙数据
    deviceId:'', // 蓝牙设备 id
    bluename:'', // 蓝牙设备 name
    serviceuuid:'', // 选中蓝牙设备的服务uuid截取字符串
    serviceId:'', // 服务id ,uuid
    characteristicNotifyId:'', // 读数据的特征值id
    characteristicWriteId:'', // 写数据的特征值id
    timerStat:true
  },
  searchDevice: function() {
     // 蓝牙初始化
    clearInterval(timerid)
    wx.vibrateShort()
    let _this = this
    let arr = []
    this.setData({
    
      datas:arr
    })
    wx.openBluetoothAdapter({
    
      success: function(res) {
    
        _this.getBluetoothState()
      },
      fail: function(res) {
    
       comtl.toast('蓝牙初始化失败','error',2000)
      }
    })
  },
  getBluetoothState: function() {
     // 获取本地蓝牙适配器状态
    let _this = this
    wx.getBluetoothAdapterState({
    
      success: function(res) {
    
        _this.findBleDevices()
      },
      fail: function(e) {
    
        comtl.toast('获取本机蓝牙适配器状态失败','error',2000)
      }
    })
  },
  findBleDevices: function() {
     // 搜索蓝牙
    comtl.openloading('搜索蓝牙...',false)
    let _this = this
    wx.startBluetoothDevicesDiscovery({
    
      success: function(res) {
    
        _this.onBluetoothDeviceFound()
      },
      fail: function(res) {
    
        comtl.toast('搜索蓝牙失败','error',2000)
      }
    })
  },
  onBluetoothDeviceFound: function() {
     // 监听搜索到新设备的事件
    let _this = this
    wx.onBluetoothDeviceFound(function(res) {
    
      _this.getBluetoothDevices()
    })
  },
  getBluetoothDevices: function() {
    
    let _this = this
    wx.getBluetoothDevices({
     //获取在蓝牙模块生效期间所有搜索到的蓝牙设备,包括已经和本机处于连接状态的设备
      success: function(res) {
    
        _this.setData({
    
          datas:res.devices
        })
      },
      fail: function(res) {
    
        comtl.toast('获取蓝牙设备失败','error',2000)
      }
    })
  },
  clickBlueToolHandle: function(e) {
    
    wx.vibrateShort()
    let _this = this
    wx.closeBLEConnection({
     // 断开与蓝牙低功耗设备的连接
      deviceId:_this.data.deviceId
    })
    wx.stopBluetoothDevicesDiscovery() //停止搜寻附近的蓝牙外围设备
    if(e){
    
      let deviceId = e.currentTarget.dataset.deid;
      let bluename = e.currentTarget.dataset.bluename;
      let serviceuuid = e.currentTarget.dataset.serviceuuid;
      this.setData({
    
        deviceId:deviceId,
        bluename:bluename,
        serviceuuid:serviceuuid
      })
    }
    //蓝牙连接
    wx.createBLEConnection({
     // 连接与蓝牙低功耗设备的连接
      deviceId: _this.data.deviceId,
      timeout:5000,
      success: function(res) {
    
        clearInterval(timerid)
        _this.stopBluetooth() //停止搜索
        _this.monitorIsBreak();
        _this.getBLEDeviceServices();    //获取服务
      },
      fail: function(res) {
    
        wx.hideLoading()
        comtl.toast('连接低功耗蓝牙失败','error',2000)
      },
      complete: function (){
    
        comtl.toast('不支持','error',2000)
      }
    })
  },
  monitorIsBreak(){
     // 监听异常断开
    let _this = this
    wx.onBLEConnectionStateChange(function(res) {
    
      if(!res.connected) {
     // 判断是否为断开连接
        _this.timerConnect()// 开启定时器
        wx.vibrateLong()
        comtl.toast('蓝牙已断开','error',5000)
        _this.setData({
    
          timerStat:false
        })
      }else{
    
        _this.setData({
    
          timerStat:true
        })
      }
   })
  },
  stopBluetooth() {
     //停止蓝牙搜索
    wx.stopBluetoothDevicesDiscovery({
    
      success: function(res) {
    
        comtl.closeloading() // 关闭停止搜索遮挡层
        comtl.toast('停止蓝牙搜索','success',2000)
      },
      fail: function(res) {
    
        comtl.toast('停止蓝牙搜索失败','error',2000)
      }
    })
  },
  getBLEDeviceServices: function() {
     //获取蓝牙低功耗设备所有服务uuid
    let services = [];
    let _this = this;
    wx.getBLEDeviceServices({
    
      deviceId: _this.data.deviceId,
      success: function(res) {
    
        services = res.services
        if (services.length <= 0) {
    
          comtl.toast('没有服务','error',2000)
          return
        }
        //循环获取serviceId
        for (let x in services) {
     //x = index
          if (services[x].uuid.indexOf(_this.data.serviceuuid) >= 0) {
    
            //找到有效的UUID
            _this.setData({
    
              serviceId:services[x].uuid
            })
            _this.getBLEDeviceCharacteristics()
            break
          }
        }
      },
      fail: function(res) {
    
        comtl.toast('获取设备服务失败','error',2000)
      }
    })
  },
  getBLEDeviceCharacteristics: function() {
     //获取蓝牙低功耗设备某个服务中所有特征
    let charactArray = [];
    let _this = this;
    wx.getBLEDeviceCharacteristics({
    
      deviceId: this.data.deviceId,
      serviceId: this.data.serviceId, // 这个是上面那个UUID
      success: function(res) {
    
        charactArray = res.characteristics;
        if (charactArray.length <= 0) {
    
          comtl.toast('获取特征值失败','error',2000)
          return
        }
        //charactArray 也就是 res.characteristics 这个里面有能读数据的 能写数据的 要分着用
        for (var x in charactArray) {
    
          //写数据 
          if (charactArray[x].properties.write) {
    
            _this.setData({
    
              characteristicWriteId:charactArray[x].uuid
            })
          }
          //读数据
          if (charactArray[x].properties.notify) {
    
            _this.setData({
    
              characteristicNotifyId:charactArray[x].uuid
            })
          }
        }
        app.params = _this.data
        wx.switchTab({
    
          url: '../home/home'
        })
      },
      fail: function(res) {
    
        comtl.toast('蓝牙不支持','error',2000)
      }
    })
  },
  onShareAppMessage: function(res) {
    
    return {
    
      title: 'F3000X',
      path: 'pages/searchbuletool/searchbuletool',
      success: function(res) {
    }
    }
  },
  onShow(){
    
    clearInterval(timerid)
  },
  timerConnect(){
     //定时器自动重新连接(因距离导致断开重新连接)
    let _this = this
    if (_this.data.timerStat) {
    
     timerid = setInterval(()=>{
    
       _this.clickBlueToolHandle() 
      },5000)
    }
  }
})

二、连接某蓝牙设备
将datas:[]中的蓝牙数据遍历渲染到某个wxml页面上,点击某个设备的数据即可连接,需要注意的是,你自己的小程序需要支持某蓝牙设备,不然即使连接上蓝牙也无法操作设备,如:

const comtl = require('../../utils/commontool')
const app = getApp()
let dataString = ''
Page({
    
  data: {
    
    datas:[], // 所有蓝牙数据
    deviceId:'', // 蓝牙设备 id
    bluename:'', // 蓝牙设备 name
    serviceuuid:'', // 选中蓝牙设备的服务uuid截取字符串
    serviceId:'', // 服务id ,uuid
    characteristicNotifyId:'', // 读数据的特征值id
    characteristicWriteId:'', // 写数据的特征值id
    domdatas:{
    }, // 页面数值数据
    domunit:{
    }, // 页面单位数据
    transdat:'', //转换后的值
    transdat1:'', //转换后的值
    transdat2:'', //转换后的值
    timerId:0, // 定时器id
    isGoRest:false
  },
  onLoad() {
    
    let isExist = wx.getStorageSync('history')
    if(isExist === '' || isExist === undefined){
    
      wx.setStorageSync('history',[])
    }
  },
  redatat: function(dt) {
     // 读数据开始
    if(dt.BtchFlowCount){
    
      this.setData({
    
        domdatas:dt,
        transdat: this.filter(this.data.domdatas.ReadyConst,this.data.domunit.dotted),
        transdat1: this.filter(this.data.domdatas.MinutFlowCount,this.data.domunit.dotted),
        transdat2: this.filter(this.data.domdatas.BtchFlowCount,this.data.domunit.dotted)
      })
    }else if(dt.dotted){
    
      this.setData({
    
        domunit:dt
      })
    }
    let _this = this
    wx.notifyBLECharacteristicValueChange({
    
      deviceId: this.data.deviceId,
      serviceId: this.data.serviceId,
      characteristicId: this.data.characteristicNotifyId, 
      state: true,
      success: function(res) {
    
        _this.onBLECharacteristicValueChange();
      }
    })
    dataString = ''
  },
  onBLECharacteristicValueChange: function() {
     // 监听蓝牙特征值变化
    wx.onBLECharacteristicValueChange(function(res) {
    
      dataString += comtl.ab2hex(res.value)
    })
  },
  writedata: function(hex) {
     // 写数据
    wx.writeBLECharacteristicValue({
    
      deviceId: this.data.deviceId,
      serviceId: this.data.serviceId,
      characteristicId: this.data.characteristicWriteId,
      value: comtl.str2ab(hex),
      success: function(res) {
    },
      fail: function(res) {
    }
    })
  },
  startTimer(){
     // 定时获取数据:
    let ids = setInterval(()=>{
    
      this.readUnit()
    },100)
    setTimeout(()=>{
    
      clearInterval(ids)
    },800)
    let timerid = setInterval(()=>{
    
      this.readData()
    },1000)
    this.setData({
    
      timerId:timerid
    })
  },
  readData(){
     // 读数值数据:
    let domdat = comtl.transformData(dataString)
    this.redatat(domdat)
    this.writedata('01030001001E9402')
  },
  readUnit(){
     // 读单位:
    let domdat = comtl.transformUnit(dataString)
    this.redatat(domdat)
    this.writedata('01035003000624C8')
  },
  starttap(){
    
    wx.vibrateShort()
    this.writedata('011020070001020014862A')
    setTimeout(()=>{
    
      if(this.data.domdatas.OperatStat == '运行中'){
    
        comtl.toast('运行成功','success',200)
      }
    },1000)
    this.setData({
    
      isGoRest:false
    })
  },
  stoptap(){
    
    wx.vibrateShort()
    this.writedata('01102007000102001547EA')
    setTimeout(()=>{
    
      if(this.data.domdatas.OperatStat == '暂停'){
    
        comtl.toast('暂停成功','success',2000)
      }
    },1000)
    this.setData({
    
      isGoRest:false
    })
  },
  resettap(){
    
    wx.vibrateShort()
    this.writedata('01102007000102001E062D')
    setTimeout(()=>{
    
      if(this.data.domdatas.OperatStat == '结束'){
    
        comtl.toast('结束成功','success',2000)
      }
    },1000)
    this.setData({
    
      isGoRest:true
    })
  },
  gosetvaluepage() {
     // 跳转到修改定量值页面
    wx.vibrateShort()
    if (this.data.isGoRest) {
    
      wx.navigateTo({
    
        url: '../setvalue/setvalue?showvalue='+this.data.transdat+'&dotte='+this.data.domunit.dotted
      })
    }else{
    
      comtl.toast('请先结束','error',2000)
    }
  },
  filter(num,d){
     // 处理小数点
    let nums = num + ''
    let ds = Number(d)
    let indexdot =  nums.indexOf('.')
    if(indexdot == -1){
    
      nums += '.000000000'
      indexdot =  nums.indexOf('.')
    }else{
    
      nums += '000000000'
    }
    let lastnum = parseInt(nums.slice((indexdot + ds +1),(indexdot + ds + 2)))
    let secondlast = parseInt(nums.slice((indexdot + ds),(indexdot + ds + 1)))
    if (!secondlast && secondlast != 0){
    
      return nums.slice(0,indexdot)
    }else {
    
      if (lastnum >= 5){
    
        return nums.slice(0,(indexdot + ds)) + (secondlast + 1)
      } else {
    
        return  nums.slice(0,indexdot + ds +1)
      }
    }
  },
  onShow(){
    
    if (app.params) {
    
      this.setData({
    
        deviceId:app.params.deviceId,
        bluename:app.params.bluename,
        serviceuuid:app.params.serviceuuid,
        serviceId:app.params.serviceId,
        characteristicNotifyId:app.params.characteristicNotifyId,
        characteristicWriteId:app.params.characteristicWriteId
      })
    }
    this.startTimer()
  },
  onHide(){
    
    clearInterval(this.data.timerId)
  }
})

三、数据读写
蓝牙读写数据和tcp等都类似,都需要先发送东西给设备(服务),而小程序中则称为订阅,每次读写数据都需要发送指令,可能指令中还会包含计算校验位等等,不明白的可以百度一下,这里我不做过多解释,如下:

const app = getApp()
const crc = require('../../utils/crc.js')
const comtl = require('../../utils/commontool')
Page({
    
  data: {
    
    keybordshow:true,
    showvalue:'',
    inputvale:'',
    deviceId:'',
    bluename:'',
    serviceuuid:'',
    serviceId:'',
    characteristicNotifyId:'',
    characteristicWriteId:'',
    dotte:'',
    historys:[]
  },
  onLoad(options) {
    
    let history = wx.getStorageSync('history')
    this.setData({
    
      historys:history,
      showvalue:options.showvalue,
      dotte:options.dotte
    })
    if (app.params) {
    
      this.setData({
    
        deviceId:app.params.deviceId,
        bluename:app.params.bluename,
        serviceuuid:app.params.serviceuuid,
        serviceId:app.params.serviceId,
        characteristicNotifyId:app.params.characteristicNotifyId,
        characteristicWriteId:app.params.characteristicWriteId
      })
    }
  },
  transforminputvalue(num,d){
    
    let e = Number(num)
    switch(d){
    
      case '0':
        e = e*1 + '';
        break;
      case '1':
        e = e*10 + '';
        break;
      case '2':
          e = e*100 + '';
        break;
      case '3':
          e = e*1000 + '';
        break;
      default:
          e = e + '';
        break;
      }
      let nd = e.indexOf('.')
      if (nd >=0){
    
        let str = e.slice(0,e.indexOf('.'))
        return parseInt(str)
      } else {
    
      return e
    }
  },
  inputChangeHalder(e){
    
    this.setData({
    
      inputvale:e.detail.value
    })
  },
  writein(){
    
    wx.vibrateShort()
    let _this = this
    this.setData({
    
      keybordshow:true,
    })
    wx.writeBLECharacteristicValue({
    
      deviceId: this.data.deviceId,
      serviceId: this.data.serviceId,
      characteristicId: this.data.characteristicWriteId,
      value: crc(_this.transforminputvalue(_this.data.inputvale,_this.data.dotte),'01102005000204'),
      success: function(res) {
    
        comtl.toast('成功','success',2000)
        let newhistarr = _this.data.historys.concat(_this.data.inputvale)
        newhistarr = [...new Set(newhistarr.map(it => it))]
        if(newhistarr.length >= 8){
    
          newhistarr = newhistarr.splice(1, 9)
        }
        wx.setStorageSync('history',newhistarr)
        _this.setData({
    
          historys:newhistarr
        })
        console.log(_this.data.historys)
        wx.switchTab({
    
          url: '../home/home'
        })
      },
      fail: function(res) {
    
        console.log("发送指令失败:")
      }
    })
  },
  gobackhome(){
    
    wx.vibrateShort()
    wx.switchTab({
    
      url: '../home/home'
    })
  },
  restInputvalue(el){
    
    wx.vibrateShort()
    var newvalue = el.currentTarget.dataset.newvalue;
    this.setData({
    
      inputvale:newvalue
    })
  }
})

计算校验位:

// crc校验输出:
module.exports = (inputNumber,joinTempStr)=>{
    
    // let inputNumber = 0103011215,要输入的值:(需要转换的值) 
	// let joinTempStr = 011001030002,需要拼接的值
	// 将用户输入字符转:单精度浮点数:
	let flownum = parseFloat(inputNumber)
	// 浮点转16进制:
	let hexstr = flownum.toString(16)
    
    let count = 8 - hexstr.length
    if (count > 0) {
    
        let zeronum = ''
        for(let i = 0;i < count;i++){
    
            zeronum += '0'
        }
        hexstr = zeronum + hexstr
    }
	// 进行拼接:
	let temphex = joinTempStr + hexstr
    // 算crc校验位的方法:
	function returnCRC(parapms){
    
        var CRC = {
    };
        CRC._auchCRCHi = [
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
        ];
        CRC._auchCRCLo = [
            0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
            0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
            0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
            0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
            0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
            0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
            0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
            0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
            0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
            0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
            0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
            0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
            0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
            0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
            0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
            0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
            0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
            0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
            0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
            0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
            0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
            0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
            0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
            0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
            0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
            0x43, 0x83, 0x41, 0x81, 0x80, 0x40
        ];
        CRC.CRC16 = function (buffer) {
    
            var hi = 0xff;
            var lo = 0xff;
            for (var i = 0; i < buffer.length; i++) {
    
                var idx = hi ^ buffer[i];
                hi = (lo ^ CRC._auchCRCHi[idx]);
                lo = CRC._auchCRCLo[idx];
            }
            return CRC.padLeft((hi << 8 | lo ).toString(16).toUpperCase(), 4, '0');
        };
        CRC.isArray = function (arr) {
    
            return Object.prototype.toString.call(arr) === '[object Array]';
        };
        CRC.ToCRC16 = function (str) {
    
            return CRC.CRC16(CRC.isArray(str) ? str : CRC.strToByte(str));
        };
        CRC.ToModbusCRC16 = function (str) {
    
            return CRC.CRC16(CRC.isArray(str) ? str : CRC.strToHex(str));
        };
        CRC.strToByte = function (str) {
    
            var tmp = str.split(''), arr = [];
            for (var i = 0, c = tmp.length; i < c; i++) {
    
                var j = encodeURI(tmp[i]);
                if (j.length == 1) {
    
                    arr.push(j.charCodeAt());
                } else {
    
                    var b = j.split('%');
                    for (var m = 1; m < b.length; m++) {
    
                        arr.push(parseInt('0x' + b[m]));
                    }
                }
            }
            return arr;
        };
        CRC.convertChinese = function (str) {
    
        var tmp = str.split(''), arr = [];
            for (var i = 0, c = tmp.length; i < c; i++) {
    
                var s = tmp[i].charCodeAt();
                if (s <= 0 || s >= 127) {
    
                    arr.push(s.toString(16));
                }
                else {
    
                    arr.push(tmp[i]);
                }
            }
            return arr;
        };
        CRC.filterChinese = function (str) {
    
            var tmp = str.split(''), arr = [];
            for (var i = 0, c = tmp.length; i < c; i++) {
    
                var s = tmp[i].charCodeAt();
                if (s > 0 && s < 127) {
    
                    arr.push(tmp[i]);
                }
            }
            return arr;
        };
        CRC.strToHex = function (hex, isFilterChinese) {
    
            hex = isFilterChinese ? CRC.filterChinese(hex).join('') : CRC.convertChinese(hex).join('');
            //清除所有空格
            hex = hex.replace(/\s/g, "");
            //若字符个数为奇数,补一个空格
            hex += hex.length % 2 != 0 ? " " : "";
            var c = hex.length / 2, arr = [];
            for (var i = 0; i < c; i++) {
    
                arr.push(parseInt(hex.substr(i * 2, 2), 16));
            }
            return arr;
        };
        CRC.padLeft = function (s, w, pc) {
    
            if (pc == undefined) {
    
                pc = '0';
            }
            for (var i = 0, c = w - s.length; i < c; i++) {
    
                s = pc + s;
            }
            return s;
        };
        return CRC.ToModbusCRC16(parapms)
    }
    // 调用crc校验方法进行校验计算:
    let crcResult = returnCRC(temphex)
	// 二次拼接:
	let twoJoinStr = temphex + crcResult
	// 转Buffer:
	function strToBuffer(str) {
    
		var buf = new ArrayBuffer(str.length / 2);
		var bufView = new Uint8Array(buf);
		for (var i = 0, strLen = str.length; i < strLen; i++) {
    
		  bufView[i] = parseInt(str.slice(i * 2, i * 2 + 2),16);
		}
		return buf;
	}
    return strToBuffer(twoJoinStr);
}

封装的comtl工具:

// 存放公共的方法:
module.exports = {
    
  // 消息提示框:
  "toast": (title,icon,duration) => {
    
    wx.showToast({
    
      title,
      icon,
      duration
    })
  },
  // 开启loading:
  "openloading": (title,mask) => {
    
    wx.showLoading({
    
      title,
      mask
    })
  },
  // 关闭loading:
  "closeloading": () => {
    
    wx.hideLoading()
  },
  transformData(totalstr){
     // 转换数值类型(解析数值类型)
    let datatobj = {
    }
    // console.log("温度值:"+this.hexToSingle(totalstr.slice(30,38)))
    // console.log("流量批累计:"+this.hexToSingle(totalstr.slice(86,94)))
    // console.log("流量分累计:"+this.hexToSingle(totalstr.slice(94,102)))
    // console.log("预发定量值:"+this.hexToSingle(totalstr.slice(102,110)))
    // console.log("运行状态:"+parseInt(totalstr.slice(118,122),16))
    // console.log("分量数:"+this.hex2dex(totalstr.slice(110,114)))
    // console.log("批量数:"+this.hex2dex(totalstr.slice(114,118)))
    
    datatobj.MinutFlowCount = this.hexToSingle(totalstr.slice(94,102))
    datatobj.BtchFlowCount = this.hexToSingle(totalstr.slice(86,94))
    datatobj.PiCount = this.hex2dex(totalstr.slice(114,118))
    datatobj.MinutCount = this.hex2dex(totalstr.slice(110,114))
    datatobj.ReadyConst = this.hexToSingle(totalstr.slice(102,110))
    switch(parseInt(totalstr.slice(118,122),16)){
    
      case 0:
          datatobj.OperatStat='结束';
        break;
      case 1:
          datatobj.OperatStat='暂停';
        break;
      case 2:
          datatobj.OperatStat='本次已完成';
        break;
      case 3:
          datatobj.OperatStat='运行中';
        break;
    }
    return datatobj
  },
  transformUnit(totalstr){
    // 转换单位(解析单位)
    let dtunit = {
    }
    dtunit.dotted = this.hex2dex(totalstr.slice(26,30))
    switch(this.hex2dex(totalstr.slice(6,10))){
    
      case '2':
          dtunit.unit='m³';
        break;
      case '5':
          dtunit.unit='kg';
        break;
      case '8':
          dtunit.unit='L';
        break;
      case '11':
          dtunit.unit='t';
        break;
      case '41':
          dtunit.unit='mL';
        break;
    }
    return dtunit
  },
  ab2hex(buffer){
     // ArrayBuffer转16进度字符串
    const hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function(bit) {
    
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('')
  },
  str2ab(str){
     // 字符串转为ArrayBuffer对象
    let buf = new ArrayBuffer(str.length / 2);
    let bufView = new Uint8Array(buf);
    for (var i = 0, strLen = str.length; i < strLen; i++) {
    
      bufView[i] = parseInt(str.slice(i * 2, i * 2 + 2),16);
    }
    return buf;
  },
  hexToSingle(t) {
     // 十六进制转浮点
    let start = t.slice(0,4)
    let end = t.slice(4,8)
    t = end + start
    t = t.replace(/\s+/g, "");
    if (t == "") {
    
      return "";
    }
    if (t == "00000000") {
    
      return "0";
    }
    if ((t.length > 8) || (isNaN(parseInt(t, 16)))) {
    
      return "Error";
    }
    if (t.length < 8) {
    
      t = this.FillString(t, "0", 8, true);
    }
    t = parseInt(t, 16).toString(2);
    t = this.FillString(t, "0", 32, true);
    var s = t.substring(0, 1);
    var e = t.substring(1, 9);
    var m = t.substring(9);
    e = parseInt(e, 2) - 127;
    m = "1" + m;
    if (e >= 0) {
    
      m = m.substr(0, e + 1) + "." + m.substring(e + 1)
    } else {
    
      m = "0." + this.FillString(m, "0", m.length - e - 1, true)
    }
    if (m.indexOf(".") == -1) {
    
      m = m + ".0";
    }
    var a = m.split(".");
    var mi = parseInt(a[0], 2);
    var mf = 0;
    for (var i = 0; i < a[1].length; i++) {
    
      mf += parseFloat(a[1].charAt(i)) * Math.pow(2, -(i + 1));
    }
    m = parseInt(mi) + parseFloat(mf);
    if (s == 1) {
    
      m = 0 - m;
    }
    return m;
  },
  FillString(t, c, n, b) {
    
    if ((t == "") || (c.length != 1) || (n <= t.length)) {
    
      return t;
    }
    var l = t.length;
    for (var i = 0; i < n - l; i++) {
    
      if (b == true) {
    
        t = c + t;
      }
      else {
    
        t += c;
      }
    }
    return t;
  },
  hex2dex (str) {
     // 调用:16进制转10进制
    return parseInt(str, 16).toString(10)
  }
}

提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:[email protected]联系笔者删除。
笔者:苦海

原网站

版权声明
本文为[苦海123]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_46758988/article/details/125570613