1,首先判断手机是否开启蓝牙和定位,如未开启,提示用户开启。
2,搜索时间设为8秒,如未搜索到,提示用户无可用设备。(一旦开启搜索,则会一直进行搜索,要调用停止搜索事件才会停止)
3,如果搜索到设备,则进行连接,连接成功后停止搜索设备,并将设备连接状态置为true。
4,打印时,如果连接状态为true,直接打印,否则重新搜索及连接。
5,打印时,需要判断设备为安卓还是ios,安卓的最大长度为30,ios的最大长度是200。如果超出,则需要分段打印,打印时需要将字符串转化为16进制。
import { getInfoSync } from '@uni/system-info';
let ZPRINTER_SERVICE_UUID = ''; // Zebra Bluetooth LE Parser Service
let WRITE_TO_ZPRINTER_CHARACTERISTIC_UUID = ''; // Write to printer characteristic
let deviceList = [];
let barcodeValue = '';
let connectedDevice = false;
let timeout = null;
function FunTimeout() {
timeout = setTimeout(() => {
if (!connectedDevice) {
dd.hideLoading();
dd.showToast({
type: 'fail',
content: '暂无可用打印机',
});
stopDiscovery();
}
}, 8000);
}
function getBarCode() {
return (
'! 0 200 200 250 1\r\n' +
'JOURNAL\r\n' +
'CENTER\r\n' +
'; Annotate bar codes using font 5 size 2\r\n ' +
'; and offset 7 dots from the bar code.\r\n' +
'BARCODE-TEXT 5 2 7\r\n' +
'BARCODE 128 2 1 100 0 20 ' +
barcodeValue +
'\r\n' +
'BARCODE-TEXT OFF\r\n' +
'PRINT\r\n'
);
}
// 将字符串转换为十六进制字符串
function strToHex(str) {
let hex = '';
for (let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i).toString(16);
hex += charCode.length < 2 ? '0' + charCode : charCode;
}
return hex;
}
// 初始化蓝牙接口
function initBluetoothAdapter() {
return new Promise((resolve, reject) => {
dd.openBluetoothAdapter({
success: (res) => {
const { isSupportBLE } = res;
if (isSupportBLE) {
resolve(res);
} else {
dd.hideLoading();
dd.showToast({
type: 'fail',
content: '暂不支持打印',
});
reject(res);
}
},
fail: (res) => {
dd.hideLoading();
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
reject(res);
},
complete: (res) => {
console.log('initBluetoothAdapter', res);
},
});
});
}
function initChangeListener() {
dd.onBluetoothAdapterStateChange({
success: (res) => {
console.log('onBluetoothAdapterStateChange-success', res);
// const { available = false } = res || {};
// if (available) {
// getDevices();
// } else {
// dd.showToast({
// type: 'fail',
// content: '手机蓝牙模块不可用!',
// });
// }
},
fail: (res) => {
dd.hideLoading();
console.log('onBluetoothAdapterStateChange-fail', res);
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
},
});
dd.onBluetoothDeviceFound({
allowDuplicatesKey: true,
success: (res) => {
const { devices = [] } = res || {};
const My_devices = devices.filter((i) => i?.deviceName && i?.deviceName.includes('JJKY')) || [];
console.log(
'onBluetoothDeviceFound-success',
connectedDevice,
devices,
My_devices,
My_devices.length && My_devices?.[0].deviceId,
);
if (My_devices.length && My_devices?.[0].deviceId && !connectedDevice) {
connectDevice(My_devices?.[0].deviceId);
deviceList = My_devices;
}
},
fail: (res) => {
dd.hideLoading();
console.log('onBluetoothDeviceFound-fail', res);
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
},
});
dd.onBLEConnectionStateChanged({
success: (res) => {
console.log('onBLEConnectionStateChanged-success', connectedDevice, res);
const { connected, deviceId } = res || {};
if (connected && !connectedDevice) {
connectedDevice = true;
stopDiscovery(deviceId);
}
},
fail: (res) => {
dd.hideLoading();
console.log('onBLEConnectionStateChanged-fail', res);
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
},
});
}
// 开始搜索设备
function startDiscovery() {
dd.startBluetoothDevicesDiscovery({
success: (res) => {
console.log('startBluetoothDevicesDiscovery-success', res);
},
fail: (res) => {
dd.hideLoading();
console.log('startBluetoothDevicesDiscovery-fail', res);
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
},
});
}
// 停止搜索设备
function stopDiscovery(val) {
dd.stopBluetoothDevicesDiscovery({
success: (res) => {
console.log('stopBluetoothDevicesDiscovery-success', res);
val && getBLEDeviceServices(val);
},
fail: (res) => {
dd.hideLoading();
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
console.log('stopBluetoothDevicesDiscovery-fail', res);
},
});
}
// 连接设备
function connectDevice(val) {
dd.connectBLEDevice({
deviceId: val,
success: (res) => {
console.log('connectBLEDevice-success', res);
},
fail: (res) => {
dd.hideLoading();
console.log('connectBLEDevice-fail', res);
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
},
});
}
// 获取服务
function getBLEDeviceServices(val) {
dd.getBLEDeviceServices({
deviceId: val,
success: (res) => {
console.log('getBLEDeviceServices-success', res);
const { services = [] } = res || {};
ZPRINTER_SERVICE_UUID = services[services.length - 1]?.serviceId || '';
getBLEDeviceCharacteristics(val);
},
fail: (res) => {
dd.hideLoading();
console.log('getBLEDeviceServices-fail', res);
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
},
});
}
// 获取特征值
function getBLEDeviceCharacteristics(val) {
dd.getBLEDeviceCharacteristics({
deviceId: val,
serviceId: ZPRINTER_SERVICE_UUID,
success: (res) => {
console.log('getBLEDeviceCharacteristics-success', res);
const { characteristics = [] } = res || {};
WRITE_TO_ZPRINTER_CHARACTERISTIC_UUID =
characteristics?.find((i) => i?.properties?.write)?.characteristicId || '';
writeStringToPrinter(getBarCode());
},
fail: (res) => {
dd.hideLoading();
console.log('getBLEDeviceCharacteristics-fail', res);
const { errorMessage } = res;
dd.showToast({
type: 'fail',
content: errorMessage,
});
},
});
}
// 写入值
async function writeStringToPrinter(str) {
const sysInfo = getInfoSync();
let maxChunk = 20; // Default is 20 bytes per write to characteristic
if (sysInfo?.platform?.toLowerCase() === 'ios') {
maxChunk = 300; // 300 bytes per write to characteristic works for iOS
} else if (sysInfo?.platform?.toLowerCase() === 'android') {
maxChunk = 20; // Adjusting for Android
}
if (str.length <= maxChunk) {
writeStrToCharacteristic(str);
} else {
// Need to partion the string and write one chunk at a time.
let j = 0;
for (let i = 0; i < str.length; i += maxChunk) {
let subStr = '';
const middleStep = i + maxChunk <= str.length || false;
if (middleStep) {
subStr = str.substring(i, i + maxChunk);
} else {
subStr = str.substring(i, str.length);
}
setTimeout(() => writeStrToCharacteristic(subStr, middleStep), 250 * j); // Adjust the delay if needed
j++;
}
}
}
function writeStrToCharacteristic(strData, middleStep) {
console.log(
middleStep,
strData,
strToHex(strData),
deviceList,
deviceList[0].deviceId,
barcodeValue,
'writeStrToCharacteristic',
);
dd.writeBLECharacteristicValue({
deviceId: deviceList[0].deviceId,
serviceId: ZPRINTER_SERVICE_UUID,
characteristicId: WRITE_TO_ZPRINTER_CHARACTERISTIC_UUID,
// value: buf2hex(buffer),
value: strToHex(strData),
success(res) {
console.log('ssi - success to send ZPL to printer:', res);
!middleStep &&
dd.showToast({
type: 'success',
content: '打印成功',
});
},
fail(res) {
console.log('ssi - Failed to send ZPL to printer:', res);
const { errorMessage } = res;
!middleStep &&
dd.showToast({
type: 'fail',
content: errorMessage,
});
},
complete: (res) => {
console.log('[write res==>]', res);
dd.hideLoading();
},
});
}
async function getBluetoothCode(val) {
if (val) {
dd.getLocation({
success() {
dd.showLoading({
content: '打印中...',
});
barcodeValue = val;
async function init() {
await initBluetoothAdapter();
await initChangeListener();
startDiscovery();
FunTimeout();
}
if (connectedDevice) {
// 已连接
writeStringToPrinter(getBarCode());
} else {
// 未连接
init();
}
},
fail() {
dd.showToast({
type: 'fail',
content: '位置权限未开启!请给钉钉开启定位权限',
});
},
});
} else {
dd.showToast({
type: 'fail',
content: '无数据打印',
});
}
}
function closeBluetooth() {
// dd.disconnectBLEDevice({
// deviceId: deviceList[0].deviceId,
// });
// dd.closeBluetoothAdapter();
ZPRINTER_SERVICE_UUID = '';
WRITE_TO_ZPRINTER_CHARACTERISTIC_UUID = '';
deviceList = [];
connectedDevice = false;
barcodeValue = '';
clearTimeout(timeout);
}
export { connectedDevice, getBluetoothCode, closeBluetooth };