Handle dial failures with error tone and return to dial tone
When a dial command times out (e.g., due to SIP registration failure): - Play an error tone (fast busy signal) - Return to ready state (dial tone resumes) This provides feedback to the user when calls can't be placed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2428afd3db
commit
bed1fa0eb8
18
src/phone.ts
18
src/phone.ts
|
|
@ -119,6 +119,11 @@ const startBaresip = async (phoneService: PhoneService, hook: GPIO.Input, ringer
|
|||
phoneService.send({ type: "remote-hang-up" })
|
||||
})
|
||||
|
||||
baresip.dialFailed.on(({ reason }) => {
|
||||
log.error("🐻 dial failed:", reason)
|
||||
phoneService.send({ type: "dial-failed" } as any)
|
||||
})
|
||||
|
||||
baresip.connect().catch((error) => {
|
||||
log.error("🐻 connection error:", error)
|
||||
phoneService.send({ type: "error", message: error.message })
|
||||
|
|
@ -342,6 +347,16 @@ const answerCall = (ctx: PhoneContext) => {
|
|||
ctx.baresip.accept()
|
||||
}
|
||||
|
||||
const playDialFailedMessage = async () => {
|
||||
log.error("📞 Call failed - playing error tone")
|
||||
// Play fast busy signal (reorder tone)
|
||||
const errorTone = await player.playTone([480, 620], 500)
|
||||
await sleep(500)
|
||||
errorTone.stop()
|
||||
await player.playTone([480, 620], 500)
|
||||
await sleep(500)
|
||||
}
|
||||
|
||||
const makeCall = async (ctx: PhoneContext) => {
|
||||
log(`Dialing number: ${ctx.numberDialed}`)
|
||||
if (ctx.numberDialed === 1) {
|
||||
|
|
@ -455,8 +470,9 @@ const phoneMachine = createMachine(
|
|||
t("dial-stop", "outgoing"),
|
||||
t("digit_increment", "dialing", r(digitIncrement)),
|
||||
t("hang-up", "idle")),
|
||||
outgoing: invoke(makeCall,
|
||||
outgoing: invoke(makeCall,
|
||||
t("answered", "connected"),
|
||||
t("dial-failed", "ready", a(playDialFailedMessage)),
|
||||
t("hang-up", "idle", a(hangUp))),
|
||||
aborted: state(
|
||||
t("hang-up", "idle")),
|
||||
|
|
|
|||
19
src/sip.ts
19
src/sip.ts
|
|
@ -8,6 +8,7 @@ export class Baresip {
|
|||
callEstablished = new Emitter<{ contact: string }>()
|
||||
callReceived = new Emitter<{ contact: string }>()
|
||||
hungUp = new Emitter()
|
||||
dialFailed = new Emitter<{ reason: string }>()
|
||||
error = new Emitter<{ message: string; statusCode?: string; reason?: string }>()
|
||||
registrationSuccess = new Emitter()
|
||||
|
||||
|
|
@ -39,8 +40,11 @@ export class Baresip {
|
|||
executeCommand("a")
|
||||
}
|
||||
|
||||
dial(phoneNumber: string) {
|
||||
executeCommand(`d${phoneNumber}`)
|
||||
async dial(phoneNumber: string) {
|
||||
const success = await executeCommand(`d${phoneNumber}`)
|
||||
if (!success) {
|
||||
this.dialFailed.emit({ reason: "Command timed out - registration may have failed" })
|
||||
}
|
||||
}
|
||||
|
||||
hangUp() {
|
||||
|
|
@ -52,6 +56,7 @@ export class Baresip {
|
|||
this.callReceived.removeAllListeners()
|
||||
this.hungUp.removeAllListeners()
|
||||
this.registrationSuccess.removeAllListeners()
|
||||
this.dialFailed.removeAllListeners()
|
||||
this.error.removeAllListeners()
|
||||
}
|
||||
|
||||
|
|
@ -113,15 +118,21 @@ export class Baresip {
|
|||
}
|
||||
}
|
||||
|
||||
const executeCommand = async (command: string) => {
|
||||
const executeCommand = async (command: string): Promise<boolean> => {
|
||||
try {
|
||||
const url = new URL(`/?${command}`, "http://127.0.0.1:8000")
|
||||
const response = await Bun.fetch(url)
|
||||
const controller = new AbortController()
|
||||
const timeout = setTimeout(() => controller.abort(), 10000)
|
||||
|
||||
const response = await fetch(url, { signal: controller.signal })
|
||||
clearTimeout(timeout)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Error executing command: ${response.statusText}`)
|
||||
}
|
||||
return true
|
||||
} catch (error) {
|
||||
log.error("Failed to execute command:", error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user