| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- const transport = require('../../transport/ble-core.js')
- const {
- alignBootloaderBuffer,
- getBootloaderExpectedLength,
- parseBootloaderResponse
- } = require('../../protocols/bootloader/index.js')
- const RESPONSE_TIMEOUT_MS = 3000
- let activeResponseWaiter = null
- function abortActiveResponseWaiter(message) {
- if (!activeResponseWaiter) return false
- const waiter = activeResponseWaiter
- activeResponseWaiter = null
- waiter.abort(new Error(message || '蓝牙已断开'))
- return true
- }
- function waitForResponse(kind, timeout, options = {}) {
- const expectedLength = getBootloaderExpectedLength(kind)
- const buffer = []
- return new Promise((resolve, reject) => {
- let settled = false
- let timer = null
- let unsubscribe = () => {}
- const waiter = {
- abort: (error) => {
- cleanup()
- reject(error)
- }
- }
- abortActiveResponseWaiter('新的 BootLoader 响应等待已开始')
- activeResponseWaiter = waiter
- unsubscribe = transport.subscribeRawResponse((bytes) => {
- buffer.push.apply(buffer, bytes)
- alignBootloaderBuffer(buffer)
- if (buffer.length < expectedLength) return
- const frame = buffer.slice(0, expectedLength)
- try {
- const response = parseBootloaderResponse(frame, kind)
- cleanup()
- resolve(response)
- } catch (error) {
- if (options.ignoreInvalid) {
- buffer.shift()
- return
- }
- cleanup()
- reject(error)
- }
- })
- timer = setTimeout(() => {
- cleanup()
- reject(new Error(`${kind} 响应超时`))
- }, timeout || RESPONSE_TIMEOUT_MS)
- function cleanup() {
- if (settled) return
- settled = true
- clearTimeout(timer)
- if (activeResponseWaiter === waiter) {
- activeResponseWaiter = null
- }
- unsubscribe()
- }
- })
- }
- async function sendRawFrame(frame, label) {
- return transport.sendRawFrameExact(frame, label)
- }
- async function sendFrame(frame, label, kind, timeout) {
- const responsePromise = kind ? waitForResponse(kind, timeout) : null
- const sent = await sendRawFrame(frame, label)
- if (!sent) {
- if (responsePromise) {
- responsePromise.catch(() => {})
- abortActiveResponseWaiter(`${label}发送失败`)
- }
- throw new Error(`${label}发送失败`)
- }
- return responsePromise ? responsePromise : true
- }
- module.exports = {
- RESPONSE_TIMEOUT_MS,
- abortActiveResponseWaiter,
- sendFrame,
- sendRawFrame,
- waitForResponse
- }
|