<template>
<view class="content">
<view class="search" :loading="searchingstatus" @click="searchbluetooth"> {{searchingstatus?"搜索中":"搜索蓝牙阅读器"}} </view>
<view class="section">
<block v-for="(item, index) in devices" :key="item.deviceId">
<view :class="item.deviceconnected?'list-item deviceconnected':'list-item'">
<view class="list-item-left">
<view class="devices_name">设备名称:{{item.name}}</view>
<view class="devices_id">设备ID:{{item.deviceId}}</view>
</view>
<button class="devices_btn" size="mini" @click="connectDevices(index)"> {{item.deviceconnected?"已连接":"未连接"}} </button>
</view>
</block>
</view>
<view class="idCard_content" v-if="idCardName">
<view>姓名: {{idCardName}}</view>
<view>性别: {{idCardSex}}</view>
<view>身份证号码: {{idCardNo}}</view>
</view>
<view @click="readIdcard" class="submit">读取</view>
<view @click="reset" class="submit">清空</view>
</view>
</template>
<script>
var app = getApp()
var temp = []
var serviceId = "0000ffe0-0000-1000-8000-00805f9b34fb"
var characteristicId = "0000ffe1-0000-1000-8000-00805f9b34fb"
var searchCardResult = false
var selectCardResult = false
var index = 0
var cardInfoArray = new Array()
var util = require("../../utils/util.js");
var analyCardTimer
var strName = '';
var strSex = '';
var strNation = '';
var strBirth = null;
var strAddr = null;
var strIdCode = null;
var strIssue = null;
var strBeginDate = null;
var strEndDate = null;
let that;
export default {
data() {
return {
detectCode: '',
idCardNo: '',
idCardName: '',
idCardSex: '',
telephone: '',
remark: '',
userUid: '',
deviceId: '',
devices: [],
isbluetoothready: false,
deviceconnected_index: 0,
searchingstatus: false,
is_open_blue:false,//监听初始化页面时是否打开蓝牙
}
},
onLoad() {
that = this;
this.switchBlueTooth();
},
methods: {
switchBlueTooth: function () {
uni.openBluetoothAdapter({
success: function (res) {
that.is_open_blue = true;
//蓝牙打开成功,若当前没有链接设备,搜索设备
that.searchbluetooth();
uni.onBluetoothAdapterStateChange(function (res) {
console.log("监听蓝牙状态改变",res);
if(!res.available){
let devices = that.devices;
let connect_index = that.deviceconnected_index;
devices[connect_index].deviceconnected = false;
that.deviceconnected = false;
that.devices = devices;
}
that.isbluetoothready = res.available;
that.searchingstatus = res.discovering;
})
//监听蓝牙搜索到设备回调
uni.onBluetoothDeviceFound(function (devices) {
console.log("监听搜索回调",devices)
if (!devices.devices[0].name) {
return
} else {
temp.push(devices.devices[0])
that.devices =temp;
console.log('发现新蓝牙设备',devices);
//本地连过的历史记录
let local_devices = uni.getStorageSync("devices");
if(local_devices && local_devices[0].deviceId == devices.devices[0].deviceId){
that.connectTO(devices.devices[0]);
}
// uni.stopBluetoothDevicesDiscovery({
// success: function (res) {
// console.log("停止蓝牙搜索")
// }
// })
}
})
//接收数据
uni.onBLECharacteristicValueChange(function (characteristic) {
let buffer = characteristic.value
let dataView = new DataView(buffer)
var intArray = new Uint8Array(buffer) //将arraybuffer转换为array
if (!searchCardResult && searchCardIsOk(intArray)) { //寻卡成功
searchCardResult = true
uni.writeBLECharacteristicValue({ //选卡
deviceId: that.connectedDeviceId,
serviceId: serviceId,
characteristicId: characteristicId,
value: util.stringToArrayBuffer('aaaaaa96690003200221'),
success: function (res) {
console.log('writeBLECharacteristicValue success 2', res.errMsg)
},
})
} else if (searchCardResult && !selectCardResult) {
if (selectCardIsOk(intArray)) { //选卡成功
selectCardResult = true
uni.writeBLECharacteristicValue({ //读卡
deviceId: that.connectedDeviceId,
serviceId: serviceId,
characteristicId: characteristicId,
//value: util.stringToArrayBuffer('aaaaaa96690003301023'), //读文字+照片+指纹信息,小程序无法解析照片,故显示都无照片信息
value: util.stringToArrayBuffer('aaaaaa96690003300132'), //读文字+照片信息,小程序无法解析照片,故显示都无照片信息
success: function (res) {
console.log('writeBLECharacteristicValue success 3', res)
}
})
} else {
startSearchCard(that); //寻卡
}
} else if (searchCardResult && selectCardResult) {
for (var i = 0; i < intArray.byteLength; i++) {
cardInfoArray[index] = intArray[i]
index++ //二代证 1297 三代证2321
}
clearTimeout(analyCardTimer)
//if ((cardInfoArray.length == 2321) || (cardInfoArray.length == 1297)){
if ((cardInfoArray.length == 2321) || (cardInfoArray.length == 1295)) {
analyCardTimer = setTimeout(function () {
uni.hideLoading();
readCardIsOk(cardInfoArray)
updateInfo(that)
}, 500)
}
} else {
startSearchCard(that); //寻卡
}
var str = ""
for (var i = 0; i < dataView.byteLength; i++) {
// console.log((dataView.getUint8(i)))
// str += String.fromCharCode(dataView.getUint8(i))
var temp = (dataView.getUint8(i)).toString(16)
var len = temp.length
while (len < 2) {
temp = '0' + temp //补位
len++
}
// str = (dataView.getUint8(i)).toString(16)
str += temp
}
})
},
fail: function (res) {
uni.showModal({
title: '提示',
content: '请检查手机蓝牙是否打开',
success: function (res) {
that.is_open_blue = false;
that.isbluetoothready = false;
that.searchingstatus = false;
}
})
}
})
},
searchbluetooth: function () {
if(!this.is_open_blue){
//打开小程序前未打开蓝牙,点击搜索时需要重新初始化蓝牙
this.switchBlueTooth();
return;
}
temp = [];
this.devices.forEach(function(item){
if(item.deviceconnected){
temp.push(item);
}
})
var that = this
if (!that.searchingstatus) {
var that = this
uni.startBluetoothDevicesDiscovery({
//指定services搜索 0000ffe0-0000-1000-8000-00805f9b34fb 过滤掉其他类型蓝牙设备
services: ['0000ffe0-0000-1000-8000-00805f9b34fb'],
success: function (res) {
that.searchingstatus = !that.searchingstatus;
},
fail: function (res) {
uni.showToast({
icon: "none",
title: that.replaceMsg(res.errCode,res.errMsg),
})
}
})
} else {
that.searchingstatus = false;
uni.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log("停止蓝牙搜索",res)
}
})
}
},
connectDevices(index){
let devices = this.devices[index];
this.connectTO(devices)
},
connectTO: function (e) {
var that = this;
var devices = JSON.parse(JSON.stringify(this.devices));
var index = devices.findIndex(function(item) {
return item.deviceId === e.deviceId;
});
console.log(index)
if (devices[index].deviceconnected) {
uni.notifyBLECharacteristicValueChange({
state: false, // 停用notify 功能
deviceId: that.connectedDeviceId,
serviceId: serviceId,
characteristicId: characteristicId,
success: function (res) {
console.log("停用notify 功能")
}
})
uni.closeBLEConnection({
deviceId: e.deviceId,
complete: function (res) {
console.log("断开设备",res);
devices[index].deviceconnected = false;
that.devices = devices;
that.connectedDeviceId = "";
}
})
// getApp().globalData.devices = [];
} else {
uni.showLoading({
title: '连接蓝牙设备中...',
})
uni.createBLEConnection({
deviceId: e.deviceId,
success: function (res) {
console.log("createBLEConnection",res)
uni.getBLEDeviceServices({
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
deviceId: e.deviceId,
success: function (res) {
//下面两行,Android测试不行的时候注释测试下,Android比较复杂。
//苹果端可用 安卓端不可用,如果安卓读取失败,可以注释掉这行试试
uni.getSystemInfo({
success(resP) {
if( resP.platform == 'ios'){
serviceId = res.services[res.services.length - 1].uuid;
}else{
serviceId = res.services[res.services.length - 3].uuid;
}
}
})
console.log("serviceId",res,"e",e);
setTimeout(function () {
uni.getBLEDeviceCharacteristics({
deviceId: e.deviceId,
serviceId: serviceId,
success: function (res) {
characteristicId = res.characteristics[0].uuid;
// console.log("设备charater获取成功", res)
uni.notifyBLECharacteristicValueChange({
state: true, // 启用 notify 功能
deviceId: that.connectedDeviceId,
serviceId: serviceId,
characteristicId: characteristicId,
success: function (res) {
console.log("启用notify")
},
fail: function (res) {
console.log("启用notify失败", res)
},
})
},
fail: function (res) {
console.log("设备charater获取失败", res)
},
})
}, 2000)
}
})
uni.hideLoading()
uni.showToast({
title: '连接成功',
icon: 'success',
duration: 1000
})
console.log("连接设备成功",res)
devices.forEach((item) => {
item.deviceconnected = false
})
devices[index].deviceconnected = true;
that.connectedDeviceId = e.deviceId;
that.deviceconnected_index = index;
that.devices = devices;
// getApp().globalData.devices = [e];
// getApp().globalData.connectedDeviceId = e.deviceId;
uni.setStorageSync('devices', [e]);
},
fail: function (res) {
uni.hideLoading()
uni.showToast({
title: that.replaceMsg(res.errCode,res.errMsg),
icon: 'none',
duration: 1000
})
console.log("连接设备失败",res)
that.connected = false;
}
})
uni.stopBluetoothDevicesDiscovery({
success: function (res) {
console.log("停止蓝牙搜索")
}
})
}
},
readIdcard(){
let that = this;
uni.showLoading({
title: '读取中~',
})
startSearchCard(that)
},
replaceMsg(errCode,errMsg){
let codeMsg = errMsg;
if(errCode == -1){
codeMsg = '已连接';
}else if(errCode == 10001){
codeMsg = '请检查手机是否已打开蓝牙';
}else if(errCode == 10000){
codeMsg = '未初始化蓝牙适配器';
}else if(errCode == 10002){
codeMsg = '没有找到指定设备';
}else if(errCode == 10003){
codeMsg = '连接失败';
}else if(errCode == 10006){
codeMsg = '当前连接已断开';
}else if(errCode == 10012){
codeMsg = '连接超时';
}
return codeMsg
},
reset(){
this.idCardName = '';
this.idCardSex = '';
this.idCardNo = '';
}
}
}
//寻卡
function startSearchCard(that) {
searchCardResult = false
selectCardResult = false
index = 0;
console.log("1----")
uni.writeBLECharacteristicValue({
deviceId: that.connectedDeviceId,
serviceId: serviceId,
characteristicId: characteristicId,
value: util.stringToArrayBuffer('aaaaaa96690003200122'),
success: function (res) {
console.log(res)
console.log('writeBLECharacteristicValue success 1', res.errMsg)
},
fail: function (res) {
uni.hideLoading();
console.log("writeBLECharacteristicValue fail", res)
uni.showToast({
title: that.replaceMsg(res.errCode,res.errMsg),
icon:'none'
})
},
})
}
//寻卡结果分析
function searchCardIsOk(result) {
var SW1 = result[7];
var SW2 = result[8];
var SW3 = result[9];
if ((0x0 != SW1) || (0x0 != SW2) || (0x9F) != SW3) {
return false;
}
return true;
}
//选卡结果分析
function selectCardIsOk(result) {
console.log('选卡解析:', result)
var SW1 = result[7];
var SW2 = result[8];
var SW3 = result[9];
if ((0x0 != SW1) || (0x0 != SW2) || (0x90) != SW3) {
return false;
}
console.log('选卡成功')
return true;
}
//读卡结果分析
function readCardIsOk(_i_bys_resp) {
var SW1 = _i_bys_resp[7];
var SW2 = _i_bys_resp[8];
var SW3 = _i_bys_resp[9];
if ((0x0 != SW1) || (0x0 != SW2) || ((0x90) != SW3)) {
return false;
}
if (_i_bys_resp.length < 1024) {
return false;
}
///
//
var i = 0;
var j = 0;
var iOffset = 0;
var bysName = new Array(30);
var bysSexCode = new Array(2);
var bysNationCode = new Array(4);
var bysBirth = new Array(16);
var bysAddr = new Array(70);
var bysIdCode = new Array(36);
var bysIssue = new Array(30);
var bysBeginDate = new Array(16);
var bysEndDate = new Array(16);
var iTextSize = 0;
var iPhotoSize = 0;
var iFingerSize = 0;
iTextSize = _i_bys_resp[10] << 8 + _i_bys_resp[11];
iPhotoSize = _i_bys_resp[12] << 8 + _i_bys_resp[13];
iFingerSize = _i_bys_resp[14] << 8 + _i_bys_resp[15];
///
//截取数据
//iOffset = 16;
iOffset = 14;
//截取姓名
j = 0;
for (i = iOffset; i < (iOffset + 30); i++) {
bysName[j] = _i_bys_resp[i];
j++;
}
try {
strName = util.uint8ArrayToStr(bysName)
} catch (Exception) {}
iOffset += 30;
//截取性别
j = 0;
for (i = iOffset; i < (iOffset + 2); i++) {
bysSexCode[j] = _i_bys_resp[i];
j++;
}
var strSexCode = null;
try {
strSexCode = util.uint8ArrayToStr(bysSexCode);
strSex = util.getSexFromCode(strSexCode);
} catch (Exception) {}
iOffset += 2;
//截取民族
j = 0;
for (i = iOffset; i < (iOffset + 4); i++) {
bysNationCode[j] = _i_bys_resp[i];
j++;
}
var strNationCode = null;
try {
strNationCode = util.uint8ArrayToStr(bysNationCode, );
strNation = util.getNationFromCode(strNationCode);
} catch (Exception) {}
iOffset += 4;
//截取生日
j = 0;
for (i = iOffset; i < (iOffset + 16); i++) {
bysBirth[j] = _i_bys_resp[i];
j++;
}
try {
strBirth = new String(bysBirth, "UTF-16LE");
} catch (Exception) {}
iOffset += 16;
//截取地址
j = 0;
for (i = iOffset; i < (iOffset + 70); i++) {
bysAddr[j] = _i_bys_resp[i];
j++;
}
try {
strAddr = util.uint8ArrayToStr(bysAddr);
} catch (Exception) {}
iOffset += 70;
//截取身份证号
j = 0;
for (i = iOffset; i < (iOffset + 36); i++) {
bysIdCode[j] = _i_bys_resp[i];
j++;
}
try {
strIdCode = util.uint8ArrayToStr(bysIdCode);
} catch (Exception) {}
iOffset += 36;
//截取签发机关
j = 0;
for (i = iOffset; i < (iOffset + 30); i++) {
bysIssue[j] = _i_bys_resp[i];
j++;
}
try {
strIssue = util.uint8ArrayToStr(bysIssue);
} catch (Exception) {}
iOffset += 30;
//截取有效期开始日期
j = 0;
for (i = iOffset; i < (iOffset + 16); i++) {
bysBeginDate[j] = _i_bys_resp[i];
j++;
}
try {
strBeginDate = util.uint8ArrayToStr(bysBeginDate);
} catch (Exception) {}
iOffset += 16;
//截取有效期结束日期
j = 0;
for (i = iOffset; i < (iOffset + 16); i++) {
bysEndDate[j] = _i_bys_resp[i];
j++;
}
try {
if (bysEndDate[0] >= '0' && bysEndDate[0] <= '9') {
// strEndDate = new String(bysEndDate, "UTF-16LE");
} else {
// strEndDate = new String(bysEndDate, "UTF-16LE");
}
strEndDate = util.uint8ArrayToStr(bysEndDate)
} catch (Exception) {}
iOffset += 16;
// //照片
// var wlt = new byte[1024];
// byte[] bmp = new byte[14 + 40 + 308 * 126];
// for (i = 0; i < iPhotoSize; i++) {
// wlt[i] = _i_bys_resp[16 + iTextSize + i];
// }
// //int iResult = JniCall.hxgc_Wlt2Bmp(wlt, bmp, 0);
// int iResult = DecodeWlt.hxgc_Wlt2Bmp(wlt, bmp, 708);
// Bitmap bitmapIdPhoto = null;
// if (iResult != -1) {
// bitmapIdPhoto = BitmapFactory.decodeByteArray(bmp, 0, bmp.length);
// }
return true;
}
function updateInfo(that) {
console.log('姓名:', strName)
console.log('性别:', strSex)
console.log('身份证号:', strIdCode)
console.log('地址:', strAddr)
that.idCardName = strName;
that.idCardNo = strIdCode;
that.idCardSex = strSex;
}
function ab2hex(buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('')
}
</script>
<style>
.content {
/* display: flex;
flex-direction: column;
align-items: center;
justify-content: center; */
}
.search{
width: 100%;
height: 90rpx;
background: #0e47a1;
text-align: center;
line-height: 90rpx;
font-size: 32rpx;
font-weight: 600;
color: #fff;
letter-spacing: 2rpx;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
.idCard_content{
width: 700rpx;
margin-left: 50rpx;
font-size: 26rpx;
color: #000;
line-height: 40rpx;
margin-top: 50rpx;
}
.section{
margin: 20rpx 30rpx;
background: #fff;
border-radius: 10rpx;
color: #000;
font-size: 28rpx;
}
.section_devices{
background: none;
height: 130rpx;
overflow: scroll;
}
.list_item{
display: flex;
align-items: center;
justify-content: space-between;
padding: 7rpx 30rpx;
min-height: 80rpx;
position: relative;
}
.item_left{
width: 150rpx;
text-align: left;
}
.item_right{
text-align: right;
}
.list-item {
display: flex;
align-items: center;
background: #fff;
border-radius: 10rpx;
color: #000;
font-size: 28rpx;
padding: 20rpx;
margin-bottom: 15rpx;
}
.list-item:last-child{
margin-bottom: 0rpx;
}
.devices_name,.devices_id{
max-width: 480rpx;
padding: 5rpx 0;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
line-height: 31rpx;
max-height: 31rpx;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
word-wrap:break-word;
word-break:break-all;
}
.devices_btn {
margin-right: 10rpx;
}
.deviceconnected {
background-color: sandybrown
}
.submit{
width: 350rpx;
height: 80rpx;
line-height: 80rpx;
background: #0e47a1;
color: #fff;
font-size: 34rpx;
text-align: center;
border-radius: 40rpx;
margin: 20px auto;
}
</style>