mirror of
https://github.com/CharaChorder/DeviceManager.git
synced 2025-12-11 13:26:16 +00:00
fix: add timeout for device responses
This commit is contained in:
@@ -40,6 +40,16 @@ export async function canAutoConnect() {
|
||||
return getViablePorts().then(it => it.length === 1)
|
||||
}
|
||||
|
||||
function timeout<T>(promise: Promise<T>, ms: number): Promise<T> {
|
||||
let timer: number
|
||||
return Promise.race([
|
||||
promise,
|
||||
new Promise<T>((_, reject) => {
|
||||
timer = setTimeout(() => reject(new Error("Timeout")), ms) as unknown as number
|
||||
}),
|
||||
]).finally(() => clearTimeout(timer))
|
||||
}
|
||||
|
||||
export class CharaDevice {
|
||||
private port!: SerialPort
|
||||
private reader!: ReadableStreamDefaultReader<string>
|
||||
@@ -124,15 +134,25 @@ export class CharaDevice {
|
||||
}
|
||||
|
||||
private async internalRead() {
|
||||
const {value} = await this.reader.read()
|
||||
serialLog.update(it => {
|
||||
it.push({
|
||||
type: "output",
|
||||
value: value!,
|
||||
try {
|
||||
const {value} = await timeout(this.reader.read(), 5000)
|
||||
serialLog.update(it => {
|
||||
it.push({
|
||||
type: "output",
|
||||
value: value!,
|
||||
})
|
||||
return it
|
||||
})
|
||||
return it
|
||||
})
|
||||
return value!
|
||||
return value!
|
||||
} catch (e) {
|
||||
serialLog.update(it => {
|
||||
it.push({
|
||||
type: "output",
|
||||
value: `${e}`,
|
||||
})
|
||||
return it
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,31 +189,32 @@ export class CharaDevice {
|
||||
}
|
||||
const send = this.internalSend.bind(this)
|
||||
const read = this.internalRead.bind(this)
|
||||
const exec = new Promise<T>(async resolve => {
|
||||
let result!: T
|
||||
try {
|
||||
if (this.suspendDebounceId) {
|
||||
clearTimeout(this.suspendDebounceId)
|
||||
} else {
|
||||
await this.wake()
|
||||
}
|
||||
result = await callback(send, read)
|
||||
} finally {
|
||||
delete this.lock
|
||||
this.suspendDebounceId = setTimeout(() => {
|
||||
// cannot be locked here as all the code until clearTimeout is sync
|
||||
console.assert(this.lock === undefined)
|
||||
this.lock = this.suspend().then(() => {
|
||||
delete this.lock
|
||||
delete this.suspendDebounceId
|
||||
return true
|
||||
})
|
||||
}, this.suspendDebounce) as any
|
||||
resolve(result)
|
||||
}
|
||||
let resolveLock: (result: true) => void
|
||||
this.lock = new Promise<true>(resolve => {
|
||||
resolveLock = resolve
|
||||
})
|
||||
this.lock = exec.then(() => true)
|
||||
return exec
|
||||
let result!: T
|
||||
try {
|
||||
if (this.suspendDebounceId) {
|
||||
clearTimeout(this.suspendDebounceId)
|
||||
} else {
|
||||
await this.wake()
|
||||
}
|
||||
result = await callback(send, read)
|
||||
} finally {
|
||||
delete this.lock
|
||||
this.suspendDebounceId = setTimeout(() => {
|
||||
// cannot be locked here as all the code until clearTimeout is sync
|
||||
console.assert(this.lock === undefined)
|
||||
this.lock = this.suspend().then(() => {
|
||||
delete this.lock
|
||||
delete this.suspendDebounceId
|
||||
return true
|
||||
})
|
||||
}, this.suspendDebounce) as any
|
||||
resolveLock!(true)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,20 +1,25 @@
|
||||
export class SemVer {
|
||||
major: number
|
||||
minor: number
|
||||
patch: number
|
||||
major = 0
|
||||
minor = 0
|
||||
patch = 0
|
||||
preRelease?: string
|
||||
meta?: string
|
||||
|
||||
constructor(versionString: string) {
|
||||
const [, major, minor, patch, preRelease, meta] =
|
||||
const result =
|
||||
/^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+))?$/.exec(
|
||||
versionString,
|
||||
)!
|
||||
this.major = Number.parseInt(major)
|
||||
this.minor = Number.parseInt(minor)
|
||||
this.patch = Number.parseInt(patch)
|
||||
if (preRelease) this.preRelease = preRelease
|
||||
if (meta) this.meta = meta
|
||||
)
|
||||
if (!result) {
|
||||
console.error("Invalid version string:", versionString)
|
||||
} else {
|
||||
const [, major, minor, patch, preRelease, meta] = result
|
||||
this.major = Number.parseInt(major)
|
||||
this.minor = Number.parseInt(minor)
|
||||
this.patch = Number.parseInt(patch)
|
||||
if (preRelease) this.preRelease = preRelease
|
||||
if (meta) this.meta = meta
|
||||
}
|
||||
}
|
||||
|
||||
toString() {
|
||||
|
||||
@@ -69,10 +69,6 @@
|
||||
|
||||
$: chordActions = chord?.actions.slice(chord.actions.lastIndexOf(0) + 1).toSorted(compare)
|
||||
$: compoundIndices = chord?.actions.slice(0, chord.actions.indexOf(0))
|
||||
|
||||
$: {
|
||||
console.log(chord?.actions, chordActions, compoundIndices)
|
||||
}
|
||||
</script>
|
||||
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user