You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
505 lines
14 KiB
505 lines
14 KiB
<template>
|
|
<view class="kk-printer">
|
|
<view class="kk-printer-btn" @tap="clickBtn" style="color:#FFF;">
|
|
{{isPrinting?printingText:defaultText}}
|
|
</view>
|
|
<view class="kk-shadow" :class="isShowSearch?'show':''" @tap="handleSearchClose">
|
|
<view class="kk-modal" @tap.stop="doNothing">
|
|
<view class="kk-search-device">
|
|
<!-- <view class="kk-filter-wrap">
|
|
<view class="filter-title">根据SRRI过滤设备</view>
|
|
<slider @change="handleSRRIChange" max='-20' min='-100' value="-95" show-value/>
|
|
</view>
|
|
<view class="kk-filter-wrap">
|
|
<view class="filter-title">根据蓝牙名过滤</view>
|
|
<input type="text" placeholder-class="kk-placeholder-class" placeholder="请输入蓝牙名字或设备ID搜索" v-model="filterName" />
|
|
</view> -->
|
|
<view class="kk-btn-wrap">
|
|
<view class="kk-btn-item confirm-btn" @tap="searchBtnTap" v-if="!isSearching">
|
|
搜索设备
|
|
</view>
|
|
<view class="kk-btn-item confirm-btn" v-else>
|
|
搜索中...
|
|
</view>
|
|
<view class="kk-btn-item" @tap="stopSearchBtnTap">
|
|
停止搜索
|
|
</view>
|
|
</view>
|
|
<view class="kk-devices-wrap">
|
|
<view class="empty-wrap" v-if="filterDeviceList.length <= 0">
|
|
<view class="empty-icon"></view>
|
|
<view class="empty-text">无可搜索到的设备</view>
|
|
</view>
|
|
<view class="" v-else>
|
|
<view class="kk-devices-item" v-for="(item,index) in filterDeviceList" :key="index"
|
|
@tap="handleConnectDevice(item)">
|
|
<view class="name" style="color:#000;">
|
|
<text>设备名称:</text>
|
|
<text>{{item.name?item.name:'未命名'}}</text>
|
|
</view>
|
|
<view class="rssi">
|
|
<text>信号强度:</text>
|
|
<text>({{Math.max(0, item.RSSI + 100)}}%)</text>
|
|
</view>
|
|
<!-- <view class="deviceid">
|
|
<text>设备ID:</text>
|
|
<text>{{item.deviceId}}</text>
|
|
</view>
|
|
<view class="advmac" v-if="item.advMac">
|
|
<text>advMac:</text>
|
|
<text>{{item.advMac}}</text>
|
|
</view> -->
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import gbk from '@/components/kk-printer/utils/printUtil-GBK.js';
|
|
import * as blesdk from './utils/bluetoolth';
|
|
import util from './utils/util.js';
|
|
export default {
|
|
data() {
|
|
return {
|
|
//是否正在打印
|
|
isPrinting: false,
|
|
//是否正在搜索设备
|
|
isSearching: false,
|
|
//是否显示蓝牙列表
|
|
isShowSearch: false,
|
|
//按蓝牙名过滤
|
|
filterName: '',
|
|
//按信号过滤
|
|
filterRSSI: -95,
|
|
//设备列表
|
|
devicesList: [],
|
|
//连接的设备ID
|
|
deviceId: '',
|
|
//根据设备ID获取的服务
|
|
services: '',
|
|
//获取特征值时返回的三要素
|
|
serviceId: '',
|
|
writeId: '',
|
|
readId: '',
|
|
iosNo: false
|
|
}
|
|
},
|
|
props: {
|
|
//按钮默认文字
|
|
defaultText: {
|
|
type: String,
|
|
default: '打印'
|
|
},
|
|
//按钮打印中的文字
|
|
printingText: {
|
|
type: String,
|
|
default: '打印中...'
|
|
},
|
|
bufferData: {
|
|
type: String,
|
|
require: true
|
|
},
|
|
roomcode: {
|
|
type: String,
|
|
require: true
|
|
},
|
|
CustName: {
|
|
type: String,
|
|
require: true
|
|
},
|
|
roomid: {
|
|
type: String,
|
|
require: true
|
|
}
|
|
},
|
|
computed: {
|
|
mapFilterRSSI() {
|
|
return (0 - this.filterRSSI)
|
|
},
|
|
filterDeviceList() {
|
|
let devices = this.devicesList;
|
|
let name = this.filterName;
|
|
let rssi = this.filterRSSI;
|
|
//按RSSI过滤
|
|
let filterDevices1 = devices.filter((item) => {
|
|
return item.RSSI > rssi
|
|
})
|
|
// 按名字过滤
|
|
let filterDevices2
|
|
if (name != '') {
|
|
filterDevices2 = filterDevices1.filter((item) => {
|
|
return (item.name.indexOf(name) >= 0 || item.deviceId.indexOf(name) >= 0)
|
|
})
|
|
} else {
|
|
filterDevices2 = filterDevices1
|
|
}
|
|
// 根据广播数据提取MAC地址
|
|
for (let i = 0; i < filterDevices2.length; i++) {
|
|
if (filterDevices2[i].hasOwnProperty('advertisData')) {
|
|
if (filterDevices2[i].advertisData.byteLength == 8) {
|
|
filterDevices2[i].advMac = util.buf2hex(filterDevices2[i].advertisData.slice(2, 7));
|
|
}
|
|
}
|
|
}
|
|
return filterDevices2
|
|
}
|
|
},
|
|
mounted() {
|
|
|
|
},
|
|
beforeDestroy() {
|
|
|
|
this.stopSearchBtnTap();
|
|
},
|
|
methods: {
|
|
doNothing() {
|
|
return;
|
|
},
|
|
clickBtn() {
|
|
uni.setStorageSync('ok', true)
|
|
this.handlePrintTap()
|
|
},
|
|
//点击打印按钮
|
|
handlePrintTap() {
|
|
let that = this
|
|
// 初始化蓝牙模块
|
|
wx.openBluetoothAdapter({
|
|
mode: 'central',
|
|
success: (res2) => {
|
|
console.log('初始化蓝牙模块', res2)
|
|
// 开始搜索附近的蓝牙外围设备
|
|
wx.startBluetoothDevicesDiscovery({
|
|
success(res3) {
|
|
console.log('获取设备成功', res3)
|
|
// 监听扫描到新设备事件
|
|
wx.onBluetoothDeviceFound((res4) => {
|
|
console.log('监听新设备列表,拿到想要的就自动停止', res4)
|
|
res4.devices.forEach((device) => {
|
|
if(device.name == 'QR380A-6824_Ble'){ //搜索到需要的设备
|
|
// 找到要搜索的设备后,及时停止扫描
|
|
wx.stopBluetoothDevicesDiscovery()
|
|
wx.createBLEConnection({
|
|
deviceId: device.deviceId, // 搜索到设备的 deviceId
|
|
success: () => {
|
|
console.log('连接设备成功')
|
|
wx.getBLEDeviceServices({
|
|
deviceId: device.deviceId, // 搜索到设备的 deviceId
|
|
success: (res5) => {
|
|
console.log('获取服务成功',res5)
|
|
for (let i = 0; i < res5.services.length; i++) {
|
|
if (res5.services[i].isPrimary) {
|
|
// 可根据具体业务需要,选择一个主服务进行通信
|
|
}
|
|
}
|
|
wx.getBLEDeviceCharacteristics({
|
|
deviceId:device.deviceId, // 搜索到设备的 deviceId
|
|
serviceId:res5.services[0].uuid, // 上一步中找到的某个服务
|
|
success: (res6) => {
|
|
console.log('读写特征值成功',res6)
|
|
for (let i =0; i <res6.characteristics.length; i++) {
|
|
let item =res6.characteristics[i]
|
|
if (item.properties.write) { // 该特征值可写
|
|
console.log('该特征值可写')
|
|
let buffer = gbk.strToGBKByte(that.aaaSS())
|
|
|
|
let opt = {
|
|
deviceId: device.deviceId,
|
|
serviceId: res5.services[0].uuid,
|
|
value:buffer,
|
|
characteristicId:item.uuid,
|
|
lasterSuccess: that.onPrintSuccess,
|
|
onceLength: 180 //ios 180 安卓 20
|
|
}
|
|
blesdk.sendDataToDevice(opt);
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}else{
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
},
|
|
fail(err) {
|
|
console.log('获取设备失败', res)
|
|
}
|
|
})
|
|
},
|
|
fail: (res) => {
|
|
console.log('初始化失败', res)
|
|
}
|
|
})
|
|
|
|
},
|
|
aaaSS() {
|
|
let strCmd = blesdk.CreatCPCLPage(440, 320, 1, 0);
|
|
strCmd += blesdk.addCPCLText('0', '30', '24', '0', 0, '商品名:张三')
|
|
strCmd += blesdk.addCPCLText('0', '80', '24', '0', 0, '货 号:ZS001')
|
|
strCmd += blesdk.addCPCLText('0', '130', '24', '0', 0, '供应商:李四')
|
|
strCmd += blesdk.addCPCLText('0', '180', '24', '0', 0, '批发价:100')
|
|
strCmd += blesdk.addCPCLText('0', '230', '24', '0', 0, '零售价:100')
|
|
strCmd += blesdk.addCPCLQRCode(200, 140, 'H', '1', 6, ['45646132464651648','1654867048641651654']) //二维码
|
|
strCmd += blesdk.addCPCLLocation(0); //对齐指令 0-左对齐 1-右对齐 2-居中
|
|
strCmd += blesdk.addCPCLPrint();
|
|
|
|
return strCmd;
|
|
},
|
|
onGetDevice(res) {
|
|
this.devicesList = res;
|
|
},
|
|
handleSearchClose() {
|
|
this.isShowSearch = false
|
|
},
|
|
handleSRRIChange(e) {
|
|
this.filterRSSI = e.detail.value
|
|
},
|
|
//开始搜索设备
|
|
searchBtnTap() {
|
|
blesdk.startBluetoothDevicesDiscovery();
|
|
this.isSearching = true;
|
|
blesdk.onfindBlueDevices(this.onGetDevice)
|
|
},
|
|
//停止搜索设备
|
|
stopSearchBtnTap() {
|
|
blesdk.stopBlueDevicesDiscovery();
|
|
this.isSearching = false;
|
|
},
|
|
//点击连接设备
|
|
handleConnectDevice(device) {
|
|
|
|
let deviceId = device.deviceId;
|
|
let name = device.name;
|
|
this.deviceId = deviceId;
|
|
uni.setStorageSync('deviceId', deviceId);
|
|
uni.onBLEConnectionStateChange(function(res) {
|
|
if (res.connected) {
|
|
|
|
// plus.nativeUI.toast('设备'+ res.deviceId + '已连接',{
|
|
// verticalAlign:'center'
|
|
// })
|
|
} else {
|
|
// plus.nativeUI.toast('设备'+ res.deviceId + '已断开连接',{
|
|
// verticalAlign:'center'
|
|
// })
|
|
}
|
|
})
|
|
blesdk.createBLEConnection(deviceId, this.onConnectSuccess, this.onConnectFail);
|
|
this.devicesList == []
|
|
},
|
|
onConnectSuccess(res) {
|
|
this.stopSearchBtnTap()
|
|
uni.setStorageSync('ok', true)
|
|
blesdk.getBLEDeviceServices(this.deviceId, this.onGetServicesSuccess, this.onGetServicesFail);
|
|
},
|
|
onConnectFail(err) {
|
|
blesdk.closeBLEConnection(uni.getStorageSync('deviceId'));
|
|
this.isShowSearch = true
|
|
uni.removeStorageSync('deviceId')
|
|
uni.removeStorageSync('serviceId')
|
|
uni.removeStorageSync('writeId')
|
|
uni.removeStorageSync('readId')
|
|
// uni.
|
|
},
|
|
onGetServicesSuccess(res) {
|
|
this.services = res.serviceId;
|
|
|
|
blesdk.getDeviceCharacteristics(uni.getStorageSync('deviceId') ? uni.getStorageSync('deviceId') : this
|
|
.deviceId, uni.getStorageSync('services') ? uni.getStorageSync('services') : this.services, this
|
|
.onGetCharacterSuccess, this.onGetCharacterFail);
|
|
},
|
|
onGetServicesFail(err) {},
|
|
onGetCharacterSuccess(res) {
|
|
this.serviceId = res.serviceId;
|
|
this.writeId = res.writeId;
|
|
this.readId = res.readId;
|
|
uni.setStorageSync('serviceId', res.serviceId)
|
|
uni.setStorageSync('writeId', res.writeId)
|
|
uni.setStorageSync('readId', res.readId)
|
|
this.isShowSearch = false;
|
|
this.handlePrintTap()
|
|
},
|
|
onGetCharacterFail(err) {
|
|
|
|
},
|
|
onPrintSuccess() {
|
|
this.isPrinting = false;
|
|
this.$u.route('/pages/toll/toll', {
|
|
roomcode: this.roomcode,
|
|
CustName: this.CustName,
|
|
id: this.roomid
|
|
})
|
|
this.$emit('onPrintSuccess')
|
|
},
|
|
onPrintFail() {
|
|
this.isPrinting = false;
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.kk-printer {
|
|
&-btn {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.kk-shadow {
|
|
display: none;
|
|
|
|
&.show {
|
|
display: block;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
background: rgba(0, 0, 0, 0.4);
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
.kk-modal {
|
|
width: 680upx;
|
|
height: 80%;
|
|
padding: 24upx;
|
|
box-sizing: border-box;
|
|
overflow-y: auto;
|
|
border-radius: 20upx;
|
|
background: #ffffff;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
.kk-search-device {
|
|
width: 100%;
|
|
height: 100%;
|
|
|
|
.kk-filter-wrap {
|
|
width: 100%;
|
|
height: 160upx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: flex-start;
|
|
align-items: flex-start;
|
|
|
|
.filter-title {
|
|
line-height: 70upx;
|
|
font-size: 30upx;
|
|
color: #999999;
|
|
}
|
|
|
|
&>slider {
|
|
width: 90%;
|
|
height: 90upx;
|
|
}
|
|
|
|
&>input {
|
|
padding: 0 20upx;
|
|
box-sizing: border-box;
|
|
border-radius: 10upx;
|
|
height: 90upx;
|
|
width: 100%;
|
|
border: 1upx solid #ebebeb;
|
|
}
|
|
}
|
|
|
|
.kk-btn-wrap {
|
|
width: 100%;
|
|
height: 140upx;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
&>view {
|
|
flex: 1 1 auto;
|
|
height: 100upx;
|
|
line-height: 100upx;
|
|
border-radius: 16upx;
|
|
text-align: center;
|
|
color: #ffffff;
|
|
|
|
&.confirm-btn {
|
|
background: #007AFF;
|
|
margin-right: 30upx;
|
|
}
|
|
|
|
&:nth-last-child(1) {
|
|
background: #DD524D;
|
|
}
|
|
}
|
|
}
|
|
|
|
.kk-devices-wrap {
|
|
height: calc(100% - 460upx);
|
|
overflow-y: auto;
|
|
padding: 10upx 20upx;
|
|
box-sizing: border-box;
|
|
border: 1upx solid #ebebeb;
|
|
box-sizing: border-box;
|
|
border-radius: 20upx;
|
|
|
|
.empty-wrap {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
|
|
.empty-icon {
|
|
width: 268upx;
|
|
height: 240upx;
|
|
background-size: 100% 100%;
|
|
margin-bottom: 26upx;
|
|
}
|
|
|
|
.empty-text {
|
|
width: 100%;
|
|
line-height: 50upx;
|
|
font-size: 30upx;
|
|
text-align: center;
|
|
color: #999999;
|
|
}
|
|
}
|
|
|
|
.kk-devices-item {
|
|
width: 100%;
|
|
border-bottom: 1upx solid #ebebeb;
|
|
padding: 10upx 0;
|
|
box-sizing: border-box;
|
|
z-index: 500;
|
|
|
|
&:nth-last-child(1) {
|
|
border-bottom: none;
|
|
}
|
|
|
|
&>view {
|
|
width: 100%;
|
|
font-size: 30upx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
.kk-placeholder-class {
|
|
font-size: 30upx;
|
|
color: #999999;
|
|
}
|
|
</style>
|