蓝牙身份证阅读器使用Uniapp调用二次开发demo

<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>

相关推荐
浪裡遊11 分钟前
Typescript中的对象类型
开发语言·前端·javascript·vue.js·typescript·ecmascript
杨-羊羊羊18 分钟前
什么是深拷贝什么是浅拷贝,两者区别
开发语言·前端·javascript
发呆的薇薇°23 分钟前
在vue里,使用dayjs格式化时间并实现日期时间的实时更新
前端·javascript·vue.js
m0_6278275227 分钟前
vue3中 input 中放大镜在后面
javascript·vue.js·elementui
从味书1 小时前
安装typescript时,npm install -g typescript报错
javascript·typescript·npm
前端小崔1 小时前
从零开始学习three.js(15):一文详解three.js中的纹理映射UV
前端·javascript·学习·3d·webgl·数据可视化·uv
belldeep1 小时前
vite:npm 安装 pdfjs-dist , PDF.js View 预览功能示例
javascript·pdf·pdfjs-dist·pdf.worker
一只程序熊2 小时前
【uniapp】errMsg: “navigateTo:fail timeout“
服务器·前端·uni-app
Lysun0012 小时前
electron 结合 react(cra创建的) 创建桌面应用和打包桌面应用
javascript·react.js·electron
Hopebearer_3 小时前
什么是CacheStorage?
前端·javascript·web