記錄--uni-app實現藍牙列印小票

来源:https://www.cnblogs.com/smileZAZ/archive/2022/09/13/16689771.html
-Advertisement-
Play Games

這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 說明 基於uni-app開發,調用官方藍牙相關api實現連接藍牙與向藍牙熱敏印表機發送位元組流,可列印文字,二維碼,圖片,調整字體大小等,本文提供大概思路 結構 bluetooth.js 藍牙連接相關模塊封裝 commands.js 列印十 ...


這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

說明

基於uni-app開發,調用官方藍牙相關api實現連接藍牙與向藍牙熱敏印表機發送位元組流,可列印文字,二維碼,圖片,調整字體大小等,本文提供大概思路

結構

image.png

  • bluetooth.js 藍牙連接相關模塊封裝
  • commands.js 列印十六進位相關代碼庫
  • gbk.js 編碼轉換庫地址
  • printerjobs.js 列印實現庫

bluetooth.js

藍牙連接相關封裝代碼

class Bluetooth {

    constructor() {
        this.isOpenBle = false;
        this.deviceId = "";
        this.serviceId = "";
        this.writeId = "";
        this.notifyId = "";
        this.BluetoothConnectStatus = false this.printStatus = false this.init()
    }
    init() {
        this.closeBluetoothAdapter().then(() = >{
            console.log("init初始關閉藍牙模塊") this.openBluetoothAdapter().then(() = >{
                console.log("init初始化藍牙模塊") this.reconnect() //自動連接藍牙設備
            })

        })
    }

    showToast(title) {
        uni.showToast({
            title: title,
            icon: 'none',
            'duration': 2000
        });
    }

    openBluetoothAdapter() {
        return new Promise((resolve, reject) = >{
            uni.openBluetoothAdapter({
                success: res = >{
                    this.isOpenBle = true;
                    resolve(res);
                },
                fail: err = >{
                    this.showToast(`藍牙未打開`);
                    reject(err);
                },
            });
        });

    }

    startBluetoothDevicesDiscovery() {
        if (!this.isOpenBle) {
            this.showToast(`初始化藍牙模塊失敗`) return;
        }

        let self = this;
        uni.showLoading({
            title: '藍牙搜索中'
        }) return new Promise((resolve, reject) = >{
            setTimeout(() = >{
                uni.startBluetoothDevicesDiscovery({
                    success: res = >{
                        resolve(res)
                    },
                    fail: res = >{
                        self.showToast(`搜索設備失敗` + JSON.stringify(err));
                        reject(err);
                    }
                })
            },
            300);
        });
    }

    stopBluetoothDevicesDiscovery() {
        let self = this;
        return new Promise((resolve, reject) = >{
            uni.stopBluetoothDevicesDiscovery({
                success: e = >{
                    uni.hideLoading();
                },
                fail: e = >{
                    uni.hideLoading();
                    self.showToast(`停止搜索藍牙設備失敗` + JSON.stringify(err));
                }
            })
        });
    }

    createBLEConnection() {
        //設備deviceId
        let deviceId = this.deviceId;
        let self = this;

        // uni.showLoading({
        // 	mask: true,
        // 	title: '設別連接中,請稍候...'
        // })
        console.log(this.deviceId);
        return new Promise((resolve, reject) = >{
            uni.createBLEConnection({
                deviceId,
                success: (res) = >{
                    console.log("res:createBLEConnection " + JSON.stringify(res));
                    resolve(res)
                },
                fail: err = >{
                    uni.hideLoading();
                    self.showToast(`停止搜索藍牙設備失敗` + JSON.stringify(err));
                    reject(err);
                }
            })
        });
    }

    //獲取藍牙設備所有服務(service)
    getBLEDeviceServices() {
        let _serviceList = [];
        let deviceId = this.deviceId;
        let self = this;

        return new Promise((resolve, reject) = >{
            setTimeout(() = >{
                uni.getBLEDeviceServices({
                    deviceId,
                    success: res = >{
                        for (let service of res.services) {
                            if (service.isPrimary) {
                                _serviceList.push(service);
                            }
                        }
                        uni.hideLoading();
                        console.log("_serviceList: " + JSON.stringify(_serviceList));
                        resolve(_serviceList)
                    },
                    fail: err = >{
                        uni.hideLoading();
                        // self.showToast(`獲取設備Services` + JSON.stringify(err));
                        reject(err);
                    },
                })
            },
            500);
        });
    }

    //獲取藍牙設備某個服務中所有特征值(characteristic)
    getBLEDeviceCharacteristics() {
        // console.log("getBLEDeviceCharacteristics")
        let deviceId = this.deviceId;
        let serviceId = this.serviceId;

        let self = this;
        return new Promise((resolve, reject) = >{
            uni.getBLEDeviceCharacteristics({
                deviceId,
                serviceId,
                success: res = >{
                    for (let _obj of res.characteristics) {
                        //獲取notify
                        if (_obj.properties.notify) {
                            self.notifyId = _obj.uuid;
                            uni.setStorageSync('notifyId', self.notifyId);
                        }
                        //獲取writeId
                        if (_obj.properties.write) {
                            self.writeId = _obj.uuid;
                            uni.setStorageSync('writeId', self.writeId);
                        }
                    }

                    //console.log("res:getBLEDeviceCharacteristics " + JSON.stringify(res));
                    let result = {
                        'notifyId': self.notifyId,
                        'writeId': self.writeId
                    };
                    // self.showToast(`獲取服務中所有特征值OK,${JSON.stringify(result)}`);
                    this.BluetoothStatus = true resolve(result)
                },
                fail: err = >{
                    self.showToast(`getBLEDeviceCharacteristics` + JSON.stringify(err));
                    reject(err);
                }
            })
        });
    }

    //斷開聯鏈接
    closeBLEConnection() {
        let deviceId = this.deviceId;
        uni.closeBLEConnection({
            deviceId,
            success(res) {
                console.log("closeBLEConnection" + res)
            }
        })
    }

    notifyBLECharacteristicValue() {
        let deviceId = this.deviceId;
        let serviceId = this.serviceId;
        let characteristicId = this.notifyId;

        uni.notifyBLECharacteristicValueChange({
            state: true,
            // 啟用 notify 功能
            deviceId,
            serviceId,
            characteristicId,
            success(res) {
                uni.onBLECharacteristicValueChange(function(res) {
                    console.log('onBLECharacteristicValueChange', res);
                });
            },
            fail(res) {
                console.log('notifyBLECharacteristicValueChange failed:' + res.errMsg);

            }
        });
    }

    writeBLECharacteristicValue(buffer) {
        let deviceId = this.deviceId;
        let serviceId = this.serviceId;
        let characteristicId = this.writeId;

        // console.log(deviceId);
        // console.log(serviceId);
        // console.log(characteristicId);
        return new Promise((resolve, reject) = >{
            uni.writeBLECharacteristicValue({
                deviceId,
                serviceId,
                characteristicId,
                value: buffer,
                success(res) {
                    // console.log('message發送成功', JSON.stringify(res));
                    resolve(res);
                },
                fail(err) {
                    // console.log('message發送失敗', JSON.stringify(err));
                    reject(err);
                }
            });
        });
    }

    closeBluetoothAdapter() {
        return new Promise((resolve, reject) = >{
            uni.closeBluetoothAdapter({
                success: res = >{
                    resolve()
                }
            });
        })

    }

    //若APP在之前已有搜索過某個藍牙設備,併成功建立連接,可直接傳入之前搜索獲取的 deviceId 直接嘗試連接該設備,無需進行搜索操作。
    reconnect() { (async() = >{
            try {
                this.deviceId = this.deviceId || uni.getStorageSync("deviceId");
                this.serviceId = this.serviceId || uni.getStorageSync("serviceId");
                console.log("this.deviceId", this.deviceId) console.log("this.serviceId", this.serviceId) let result1 = await this.createBLEConnection();
                console.log("createBLEConnection: " + JSON.stringify(result1));

                let result2 = await this.getBLEDeviceServices();
                console.log("getBLEDeviceServices: " + JSON.stringify(result2));

                let result3 = await this.getBLEDeviceCharacteristics();
                console.log("getBLEDeviceCharacteristics: " + JSON.stringify(result3));
                this.BluetoothConnectStatus = true this.showToast("藍牙列印設備連接成功")
                // this.writeId = uni.getStorageSync("writeId");
                // this.notifyId = uni.getStorageSync("notifyId");
            } catch(err) {
                console.log("err: " + err);
                // this.showToast("藍牙列印設備連接失敗")
            }

        })();
    }
}

export
default Bluetooth;

commands.js

印表機ESC/POS十六進位編碼庫

/**
 * 修改自https://github.com/song940/node-escpos/blob/master/commands.js
 * ESC/POS _ (Constants)
 */
var _ = {
  LF: [0x0a],
  FS: [0x1c],
  FF: [0x0c],
  GS: [0x1d],
  DLE: [0x10],
  EOT: [0x04],
  NUL: [0x00],
  ESC: [0x1b],
  EOL: '\n',
};

/**
 * [FEED_CONTROL_SEQUENCES Feed control sequences]
 * @type {Object}
 */
_.FEED_CONTROL_SEQUENCES = {
  CTL_LF: [0x0a],   // Print and line feed
  CTL_GLF: [0x4a, 0x00],   // Print and feed paper (without spaces between lines)
  CTL_FF: [0x0c],   // Form feed
  CTL_CR: [0x0d],   // Carriage return
  CTL_HT: [0x09],   // Horizontal tab
  CTL_VT: [0x0b],   // Vertical tab
};

_.CHARACTER_SPACING = {
  CS_DEFAULT: [0x1b, 0x20, 0x00],
  CS_SET: [0x1b, 0x20]
};

_.LINE_SPACING = {
  LS_DEFAULT: [0x1b, 0x32],
  LS_SET: [0x1b, 0x33]
};

/**
 * [HARDWARE Printer hardware]
 * @type {Object}
 */
_.HARDWARE = {
  HW_INIT: [0x1b, 0x40], // Clear data in buffer and reset modes
  HW_SELECT: [0x1b, 0x3d, 0x01], // Printer select
  HW_RESET: [0x1b, 0x3f, 0x0a, 0x00], // Reset printer hardware
  Print:[0x1b, 0x64,0x01] //Print and feed paper
};

/**
 * [CASH_DRAWER Cash Drawer]
 * @type {Object}
 */
_.CASH_DRAWER = {
  CD_KICK_2: [0x1b, 0x70, 0x00], // Sends a pulse to pin 2 []
  CD_KICK_5: [0x1b, 0x70, 0x01], // Sends a pulse to pin 5 []
};

/**
 * [MARGINS Margins sizes]
 * @type {Object}
 */
_.MARGINS = {
  BOTTOM: [0x1b, 0x4f], // Fix bottom size
  LEFT: [0x1b, 0x6c], // Fix left size
  RIGHT: [0x1b, 0x51], // Fix right size
};

/**
 * [PAPER Paper]
 * @type {Object}
 */
_.PAPER = {
  PAPER_FULL_CUT: [0x1d, 0x56, 0x00], // Full cut paper
  PAPER_PART_CUT: [0x1d, 0x56, 0x01], // Partial cut paper
  PAPER_CUT_A: [0x1d, 0x56, 0x41], // Partial cut paper
  PAPER_CUT_B: [0x1d, 0x56, 0x42], // Partial cut paper
};

/**
 * [TEXT_FORMAT Text format]
 * @type {Object}
 */
_.TEXT_FORMAT = {
  TXT_NORMAL: [0x1b, 0x21, 0x00], // Normal text
  TXT_2HEIGHT: [0x1b, 0x21, 0x10], // Double height text
  TXT_2WIDTH: [0x1b, 0x21, 0x20], // Double width text
  TXT_4SQUARE: [0x1b, 0x21, 0x30], // Double width & height text

  TXT_UNDERL_OFF: [0x1b, 0x2d, 0x00], // Underline font OFF
  TXT_UNDERL_ON: [0x1b, 0x2d, 0x01], // Underline font 1-dot ON
  TXT_UNDERL2_ON: [0x1b, 0x2d, 0x02], // Underline font 2-dot ON
  TXT_BOLD_OFF: [0x1b, 0x45, 0x00], // Bold font OFF
  TXT_BOLD_ON: [0x1b, 0x45, 0x01], // Bold font ON
  TXT_ITALIC_OFF: [0x1b, 0x35], // Italic font ON
  TXT_ITALIC_ON: [0x1b, 0x34], // Italic font ON

  TXT_FONT_A: [0x1b, 0x4d, 0x00], // Font type A
  TXT_FONT_B: [0x1b, 0x4d, 0x01], // Font type B
  TXT_FONT_C: [0x1b, 0x4d, 0x02], // Font type C

  TXT_ALIGN_LT: [0x1b, 0x61, 0x00], // Left justification
  TXT_ALIGN_CT: [0x1b, 0x61, 0x01], // Centering
  TXT_ALIGN_RT: [0x1b, 0x61, 0x02], // Right justification
};

/**
 * [BARCODE_FORMAT Barcode format]
 * @type {Object}
 */
_.BARCODE_FORMAT = {
  BARCODE_TXT_OFF: [0x1d, 0x48, 0x00], // HRI barcode chars OFF
  BARCODE_TXT_ABV: [0x1d, 0x48, 0x01], // HRI barcode chars above
  BARCODE_TXT_BLW: [0x1d, 0x48, 0x02], // HRI barcode chars below
  BARCODE_TXT_BTH: [0x1d, 0x48, 0x03], // HRI barcode chars both above and below

  BARCODE_FONT_A: [0x1d, 0x66, 0x00], // Font type A for HRI barcode chars
  BARCODE_FONT_B: [0x1d, 0x66, 0x01], // Font type B for HRI barcode chars

  BARCODE_HEIGHT: function (height) { // Barcode Height [1-255]
    return [0x1d, 0x68, height];
  },
  BARCODE_WIDTH: function (width) {   // Barcode Width  [2-6]
    return [0x1d, 0x77, width];
  },
  BARCODE_HEIGHT_DEFAULT: [0x1d, 0x68, 0x64], // Barcode height default:100
  BARCODE_WIDTH_DEFAULT: [0x1d, 0x77, 0x01], // Barcode width default:1

  BARCODE_UPC_A: [0x1d, 0x6b, 0x00], // Barcode type UPC-A
  BARCODE_UPC_E: [0x1d, 0x6b, 0x01], // Barcode type UPC-E
  BARCODE_EAN13: [0x1d, 0x6b, 0x02], // Barcode type EAN13
  BARCODE_EAN8: [0x1d, 0x6b, 0x03], // Barcode type EAN8
  BARCODE_CODE39: [0x1d, 0x6b, 0x04], // Barcode type CODE39
  BARCODE_ITF: [0x1d, 0x6b, 0x05], // Barcode type ITF
  BARCODE_NW7: [0x1d, 0x6b, 0x06], // Barcode type NW7
  BARCODE_CODE93: [0x1d, 0x6b, 0x48], // Barcode type CODE93
  BARCODE_CODE128: [0x1d, 0x6b, 0x49], // Barcode type CODE128
};

/**
 * [IMAGE_FORMAT Image format]
 * @type {Object}
 */
_.IMAGE_FORMAT = {
  S_RASTER_N: [0x1d, 0x76, 0x30, 0x00], // Set raster image normal size
  S_RASTER_2W: [0x1d, 0x76, 0x30, 0x01], // Set raster image double width
  S_RASTER_2H: [0x1d, 0x76, 0x30, 0x02], // Set raster image double height
  S_RASTER_Q: [0x1d, 0x76, 0x30, 0x03], // Set raster image quadruple
};

/**
 * [BITMAP_FORMAT description]
 * @type {Object}
 */
_.BITMAP_FORMAT = {
  BITMAP_S8: [0x1b, 0x2a, 0x00],
  BITMAP_D8: [0x1b, 0x2a, 0x01],
  BITMAP_S24: [0x1b, 0x2a, 0x20],
  BITMAP_D24: [0x1b, 0x2a, 0x21]
};

/**
 * [GSV0_FORMAT description]
 * @type {Object}
 */
_.GSV0_FORMAT = {
  GSV0_NORMAL: [0x1d, 0x76, 0x30, 0x00],
  GSV0_DW: [0x1d, 0x76, 0x30, 0x01],
  GSV0_DH: [0x1d, 0x76, 0x30, 0x02],
  GSV0_DWDH: [0x1d, 0x76, 0x30, 0x03]
};

/**
 * [BEEP description]
 * @type {string}
 */
_.BEEP = [0x1b, 0x42]; // Printer Buzzer pre hex

/**
 * [COLOR description]
 * @type {Object}
 */

_.COLOR = {
  0: [0x1b, 0x72, 0x00], // black
  1: [0x1b, 0x72, 0x01] // red
};

/**
 * [exports description]
 * @type {[type]}
 */
module.exports = _;

printerjobs.js

const commands = require('./commands');
const gbk = require('./gbk');

const printerJobs = function() {
	this._queue = Array.from(commands.HARDWARE.HW_INIT);
	this._enqueue = function(cmd) {
		this._queue.push.apply(this._queue, cmd);
	}
};

/**
 * 增加列印內容
 * @param  {string} content  文字內容
 */
printerJobs.prototype.text = function(content) {
	if (content) {
		let uint8Array = gbk.encode(content);
		let encoded = Array.from(uint8Array);
		this._enqueue(encoded);
	}
	return this;
};

/**
 * 列印文字
 * @param  {string} content  文字內容
 */
printerJobs.prototype.print = function(content) {
	this.text(content);
	// this._enqueue(commands.LF);
	return this;
};
printerJobs.prototype.printL = function(content) {
	this.text(content);
	this._enqueue(commands.LF);
	return this;
};

printerJobs.prototype.printImage = function(content) {

	if (content) {
		const cmds = [].concat([29, 118, 48, 0], content);
		// console.log("cmds",cmds)
		this._enqueue(cmds);
		this._enqueue(commands.LF);
	}

	return this;
};


/**
 * 列印文字並換行
 * @param  {string}  content  文字內容
 */
printerJobs.prototype.println = function(content = '') {
	return this.print(content + commands.EOL);
};

/**
 * 設置對齊方式
 * @param {string} align 對齊方式 LT/CT/RT
 */
printerJobs.prototype.setAlign = function(align) {
	this._enqueue(commands.TEXT_FORMAT['TXT_ALIGN_' + align.toUpperCase()]);
	return this;
};

/**
 * 設置字體
 * @param  {string} family A/B/C
 */
printerJobs.prototype.setFont = function(family) {
	this._enqueue(commands.TEXT_FORMAT['TXT_FONT_' + family.toUpperCase()]);
	return this;
};

/**
 * 設定字體尺寸
 * @param  {number} width 字體寬度 1~2
 * @param  {number} height 字體高度 1~2
 */
printerJobs.prototype.setSize = function(width, height) {
	if (2 >= width && 2 >= height) {
		this._enqueue(commands.TEXT_FORMAT.TXT_NORMAL);
		if (2 === width && 2 === height) {
			this._enqueue(commands.TEXT_FORMAT.TXT_4SQUARE);
		} else if (1 === width && 2 === height) {
			this._enqueue(commands.TEXT_FORMAT.TXT_2HEIGHT);
		} else if (2 === width && 1 === height) {
			this._enqueue(commands.TEXT_FORMAT.TXT_2WIDTH);
		}
	}
	return this;
};

/**
 * 設定字體是否加粗
 * @param  {boolean} bold
 */
printerJobs.prototype.setBold = function(bold) {
	if (typeof bold !== 'boolean') {
		bold = true;
	}
	this._enqueue(bold ? commands.TEXT_FORMAT.TXT_BOLD_ON : commands.TEXT_FORMAT.TXT_BOLD_OFF);
	return this;
};

/**
 * 設定是否開啟下劃線
 * @param  {boolean} underline
 */
printerJobs.prototype.setUnderline = function(underline) {
	if (typeof underline !== 'boolean') {
		underline = true;
	}
	this._enqueue(underline ? commands.TEXT_FORMAT.TXT_UNDERL_ON : commands.TEXT_FORMAT.TXT_UNDERL_OFF);
	return this;
};

/**
 * 設置行間距為 n 點行,預設值行間距是 30 點
 * @param {number} n 0≤n≤255
 */
printerJobs.prototype.setLineSpacing = function(n) {
	if (n === undefined || n === null) {
		this._enqueue(commands.LINE_SPACING.LS_DEFAULT);
	} else {
		this._enqueue(commands.LINE_SPACING.LS_SET);
		this._enqueue([n]);
	}
	return this;
};

/**
 * 列印空行
 * @param {number} n
 */
printerJobs.prototype.lineFeed = function(n = 1) {
	return this.print(new Array(n).fill(commands.EOL).join(''));
};

/**
 *  設置字體顏色,需要印表機支持
 *  @param  {number} color - 0 預設顏色黑色 1 紅色
 */
printerJobs.prototype.setColor = function(color) {
	this._enqueue(commands.COLOR[color === 1 ? 1 : 0]);
	return this;
};

/**
 * https://support.loyverse.com/hardware/printers/use-the-beeper-in-a-escpos-printers
 * 蜂鳴警報,需要印表機支持
 * @param  {number} n    蜂鳴次數,1-9
 * @param  {number} t 蜂鳴長短,1-9
 */
printerJobs.prototype.beep = function(n, t) {
	this._enqueue(commands.BEEP);
	this._enqueue([n, t]);
	return this;
};

/**
 * 清空任務
 */
printerJobs.prototype.clear = function() {
	this._queue = Array.from(commands.HARDWARE.HW_RESET);
	// this._enqueue(commands.HARDWARE.Print);
	return this;
};

/**
 * 返回ArrayBuffer
 */
printerJobs.prototype.buffer = function() {
	return new Uint8Array(this._queue).buffer;
};

module.exports = printerJobs;

代碼實現

封裝藍牙連接,搜索,斷開相關操作模塊

藍牙搜索

startBluetoothDeviceDiscovery() {
    let self = this;
    self.tempDeviceList = [];

    uni.startBluetoothDevicesDiscovery({
        success: res = >{
            uni.onBluetoothDeviceFound(devices = >{
                // console.log("發現設備: " + JSON.stringify(devices));
                if (!self.tempDeviceList.some(item = >{
                    return item.deviceId === devices.devices[0].deviceId || item.name === devices.devices[0].name
                })) {
                    // console.log("new", devices.devices)
                    self.tempDeviceList.push(devices.devices[0])
                }
            });

            this.connect = false this.$refs.popup.open()
        },
        fail: err = >{
            uni.showToast({
                title: '搜索設備失敗' + JSON.stringify(err),
                icon: 'none'
            })
        }
    })
},

搜索完成選擇設備

async select_deviceId(item) {
    this.deviceId = item.deviceId;
    this.$bluetooth.deviceId = item.deviceId;
    uni.setStorageSync('deviceId', this.$bluetooth.deviceId);
    this.serviceList = [];

    try {
        //1.鏈接設備
        let result = await this.$bluetooth.createBLEConnection();
        //2.尋找服務
        let result2 = null setTimeout(async() = >{
            result2 = await this.$bluetooth.getBLEDeviceServices();
            console.log("獲取服務: " + JSON.stringify(result2));
            this.serviceList = result2;

            console.log("serviceList", this.serviceList.length)

            if (this.serviceList[2].uuid) {
                this.select_service(this.serviceList[2].uuid)
            } else {
                uni.showToast({
                    title: '不是列印設備',
                    icon: 'none'
                })
            }

        },
        1000)

    } catch(e) {
        //TODO handle the exception
        console.log("e: " + JSON.stringify(e));
    }
},

選中服務

async select_service(res) {
    console.log("select_service", res)

    this.$bluetooth.serviceId = res;
    console.log("this.$bluetooth.serviceId", this.$bluetooth.serviceId) uni.setStorageSync('serviceId', res);

    try {
        let result = await this.$bluetooth.getBLEDeviceCharacteristics();
        console.log("resultresult", result) this.$refs.popup.close()

        uni.showToast({
            title: "連接成功"
        })
        // this.pickUpOnce()
    } catch(e) {
        //TODO handle the exception
        console.log("e: " + JSON.stringify(e));
    }
},

列印內容組合

async writeBLECharacteristicValueTongzhishu() {
	let Qrcode_res = await this.get_Qrcode()
	let sign = await this.getSign()
	console.log("sign")
	let printerJobs = new PrinterJobs()
	let p = printerJobs.setAlign('ct')
		.setBold(true)
		.printL("列印測試")

	let buffer = printerJobs.buffer();
	this.printbuffs(buffer);
},

列印內容組合

主要是實現列印編碼推送迴圈,手機藍牙可能出現編碼發送失敗情況,這個時候就是要迴圈保證每個位元組準確推送

printbuffs(buffer, fun) {
    console.log("printbuffs", buffer.byteLength) const maxChunk = 8;
    let p = Promise.resolve();
    for (let i = 0, j = 0, length = buffer.byteLength; i < length; i += maxChunk, j++) {
        let subPackage = buffer.slice(i, i + maxChunk <= length ? (i + maxChunk) : length);
        p = p.then(() = >{
            if (i == 0) {
                this.$bluetooth.printStatus = true this.$refs.loading.open();

            }
            if ((i + maxChunk) >= length) {
                console.log("printEnd")

                setTimeout(() = >{
                    this.$bluetooth.printStatus = false this.$refs.loading.close();
                },
                1000)
            }
            return this.printbuff(subPackage)
        })
    }
    p = p.then(() = >{
        console.log("printEve") fun()
    })

},
async printbuff(buffer) {
    while (true) {
        try {
            await this.$bluetooth.writeBLECharacteristicValue(buffer);
            break;
        } catch(e) {}
    }
},

本文轉載於:

https://juejin.cn/post/7001752261722537991

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Oracle實現金額小寫轉大寫函數 今天工作的時候遇到了,然後上網百度了一下,發現了有個大佬寫了一個很牛的函數,在此記錄下來。 原文:http://www.itpub.net/thread-240281-1-1.html 函數: create or replace function F_upper_ ...
  • 開心一刻 晚上,女兒眼噙淚水躺在床上 女兒:你口口聲聲說愛我,說陪我,卻天天想著騙我零花錢,你是我親爹嗎? 我:你想知道真相 女兒:想! 我:那你先給爸爸兩百塊錢! 環境準備 MySQL 不同版本 利用 docker 搭建了 7 個不同版本的 MySQL 5.5.62 5.6.51 5.7.36 8 ...
  • 問題解決秘籍 遇到問題,第一個請登錄蘋果開發者官網 檢查一遍賬號是否有許可權,是否被停用,是否過期,是否有協議需要同意,並且在右上角切換賬號後檢查所有關聯的賬號是否工作正常,apple賬號的郵箱也是個重要的地方,當有ipa上傳,賬號有發生變化,被停用,apple經常發送一些郵件,去檢查郵件通知,根據郵 ...
  • 在項目中出現多重嵌套情況時,會出現無法滑動的場景,比如經常碰到的場景 ViewPager -> Fragment -> RecyclerView -> RecyclerView | ViewPager 最外層是一個可滑動的 tabLayout+ViewPager,ViewPager 中是多個 Fra ...
  • AR作為一項增強現實技術,帶來了虛擬數字世界與現實世界的深度融合,這種虛實融合,不僅能應用於虛擬汽車展示、虛擬室內設計等視覺交互場景,更可通過動作交互控制虛擬世界場景,實現無邊界的人機互動。 比如人們在拍攝短視頻時,可以不接觸屏幕,僅通過做出特定手勢來控制特效切換;也可以在拍照時通過手勢識別控制快門 ...
  • Web 水印技術在信息安全和版權保護等領域有著廣泛的應用,對防止信息泄露或知識產品被侵犯有重要意義。水印根據可見性可分為可見水印和不可見水印(盲水印),本文將分別予以介紹,帶你探秘 web 水印技術。 ...
  • 前言 自成都九月份以來疫情原因被封了一兩周,居家著實無聊,每天都是盯著微信公眾號發佈的疫情數據看,那種頁面,就我一個前端仔來說,看著是真的醜啊!(⊙_⊙)?既然醜,那就自己動手開整!項目是2022.9.5開始的,截止2022.9.12我完成了大概有八成。主要是想讓數據更加直觀,而且可離線下載(當然還 ...
  • 跨域是什麼 簡單的講就是你在一個地方使用另一個地方的資源,被瀏覽器給擋下來了,不讓不用!當然,它擋下來是有自己理由的:為了安全(╬▔皿▔)╯。 解決跨域 我是用vue開發的,就vue代理模式解決跨域說明一下。 1、在vue.config.js中這樣寫: let devProxy = { //獲取ip ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...