wip
This commit is contained in:
parent
28186bc0ce
commit
c07cb297e3
|
|
@ -1 +1 @@
|
||||||
<sip:yellow@probablycorey.sip.twilio.com;transport=tls>;auth_pass=zgm-kwx2bug5hwf3YGF;unregister_on_exit=yes;regint=300
|
<sip:yellow@probablycorey.sip.twilio.com;transport=tls>;auth_pass=zgm-kwx2bug5hwf3YGF;unregister_on_exit=yes
|
||||||
|
|
@ -51,13 +51,17 @@ module stun.so
|
||||||
module turn.so
|
module turn.so
|
||||||
module ice.so
|
module ice.so
|
||||||
|
|
||||||
|
# STUN Server
|
||||||
|
stun_host stun.l.google.com
|
||||||
|
stun_port 19302
|
||||||
|
|
||||||
module httpd.so
|
module httpd.so
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Temporary Modules (loaded then unloaded)
|
# Temporary Modules (loaded then unloaded)
|
||||||
|
|
||||||
module_tmp uuid.so
|
module uuid.so
|
||||||
module_tmp account.so
|
module account.so
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,13 @@ const PHONE_SERVICE_FILE = "/etc/systemd/system/phone.service"
|
||||||
export const setupServices = async (installDir: string) => {
|
export const setupServices = async (installDir: string) => {
|
||||||
console.log("\nInstalling systemd services...")
|
console.log("\nInstalling systemd services...")
|
||||||
|
|
||||||
|
// Detect user from environment or use default
|
||||||
|
// SUDO_USER is set when running with sudo, which is what we want
|
||||||
|
const serviceUser = process.env.SERVICE_USER || process.env.SUDO_USER || process.env.USER || "corey"
|
||||||
|
const userUid = await $`id -u ${serviceUser}`.text().then((s) => s.trim())
|
||||||
|
|
||||||
|
console.log(`Setting up services for user: ${serviceUser} (UID: ${userUid})`)
|
||||||
|
|
||||||
// Find where bun is installed
|
// Find where bun is installed
|
||||||
const bunPath = await $`which bun`
|
const bunPath = await $`which bun`
|
||||||
.quiet()
|
.quiet()
|
||||||
|
|
@ -61,7 +68,7 @@ WantedBy=multi-user.target
|
||||||
writeFileSync(WEB_SERVICE_FILE, webServiceContent, "utf8")
|
writeFileSync(WEB_SERVICE_FILE, webServiceContent, "utf8")
|
||||||
console.log("✓ Created phone-web.service")
|
console.log("✓ Created phone-web.service")
|
||||||
|
|
||||||
// Create phone service
|
// Create phone service (system service with environment variables for audio access)
|
||||||
const phoneServiceContent = `[Unit]
|
const phoneServiceContent = `[Unit]
|
||||||
Description=Phone Application
|
Description=Phone Application
|
||||||
After=network.target sound.target
|
After=network.target sound.target
|
||||||
|
|
@ -69,7 +76,10 @@ Requires=sound.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User=corey
|
User=${serviceUser}
|
||||||
|
Group=audio
|
||||||
|
Environment=XDG_RUNTIME_DIR=/run/user/${userUid}
|
||||||
|
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${userUid}/bus
|
||||||
ExecStart=${bunPath} ${installDir}/src/main.ts
|
ExecStart=${bunPath} ${installDir}/src/main.ts
|
||||||
WorkingDirectory=${installDir}
|
WorkingDirectory=${installDir}
|
||||||
EnvironmentFile=${installDir}/.env
|
EnvironmentFile=${installDir}/.env
|
||||||
|
|
@ -90,9 +100,9 @@ WantedBy=multi-user.target
|
||||||
await $`systemctl enable phone.service`
|
await $`systemctl enable phone.service`
|
||||||
console.log("✓ Services enabled")
|
console.log("✓ Services enabled")
|
||||||
|
|
||||||
console.log("\nStarting the services...")
|
console.log("\nRestarting the services...")
|
||||||
await $`systemctl start phone-ap.service`
|
await $`systemctl restart phone-ap.service`
|
||||||
await $`systemctl start phone-web.service`
|
await $`systemctl restart phone-web.service`
|
||||||
await $`systemctl start phone.service`
|
await $`systemctl restart phone.service`
|
||||||
console.log("✓ Services started")
|
console.log("✓ Services restarted")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@ if (process.getuid && process.getuid() !== 0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get install directory from argument or use default
|
// Get install directory from argument or use default
|
||||||
const INSTALL_DIR = process.argv[2] || "/home/corey/phone"
|
const defaultUser = process.env.USER || "corey"
|
||||||
|
const INSTALL_DIR = process.argv[2] || `/home/${defaultUser}/phone`
|
||||||
|
|
||||||
console.log(`Install directory: ${INSTALL_DIR}`)
|
console.log(`Install directory: ${INSTALL_DIR}`)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
import { $ } from "bun"
|
import { $ } from "bun"
|
||||||
|
|
||||||
|
const defaultUser = process.env.USER ?? "corey"
|
||||||
const PI_HOST = process.env.PI_HOST ?? "phone.local"
|
const PI_HOST = process.env.PI_HOST ?? "phone.local"
|
||||||
const PI_DIR = process.env.PI_DIR ?? "/home/corey/phone"
|
const PI_DIR = process.env.PI_DIR ?? `/home/${defaultUser}/phone`
|
||||||
|
|
||||||
// Parse command line arguments
|
// Parse command line arguments
|
||||||
const shouldBootstrap = process.argv.includes("--bootstrap")
|
const shouldBootstrap = process.argv.includes("--bootstrap")
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
import { setupServices } from "./bootstrap-services"
|
import { setupServices } from "./bootstrap-services"
|
||||||
|
|
||||||
// Get install directory from argument or use default
|
// Get install directory from argument or use default
|
||||||
const INSTALL_DIR = process.argv[2] || "/home/corey/phone"
|
const defaultUser = process.env.USER || "corey"
|
||||||
|
const INSTALL_DIR = process.argv[2] || `/home/${defaultUser}/phone`
|
||||||
|
|
||||||
console.log(`Setting up services for: ${INSTALL_DIR}`)
|
console.log(`Setting up services for: ${INSTALL_DIR}`)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ export const runPhone = async (agentId: string, agentKey: string) => {
|
||||||
using rotaryInUse = gpio.input(22, { pull: "up", debounce: 3 })
|
using rotaryInUse = gpio.input(22, { pull: "up", debounce: 3 })
|
||||||
using rotaryNumber = gpio.input(23, { pull: "up", debounce: 3 })
|
using rotaryNumber = gpio.input(23, { pull: "up", debounce: 3 })
|
||||||
|
|
||||||
await Buzz.setVolume(0.4)
|
await Buzz.setVolume(0.2)
|
||||||
log(`📞 Phone is ${hook.value ? "off hook" : "on hook"}`)
|
log(`📞 Phone is ${hook.value ? "off hook" : "on hook"}`)
|
||||||
|
|
||||||
playStartRing(ringer)
|
playStartRing(ringer)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import Buzz from "../buzz/index.ts"
|
import Buzz from "../buzz/index.ts"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
import { random } from "./index.ts"
|
import { random } from "./index.ts"
|
||||||
|
import { log } from "console"
|
||||||
|
|
||||||
export class WaitingSounds {
|
export class WaitingSounds {
|
||||||
typingPlayback?: Buzz.Playback
|
typingPlayback?: Buzz.Playback
|
||||||
|
|
@ -38,39 +39,42 @@ export class WaitingSounds {
|
||||||
const playedSounds = new Set<string>()
|
const playedSounds = new Set<string>()
|
||||||
let dir: SoundDir | undefined
|
let dir: SoundDir | undefined
|
||||||
return new Promise<void>(async (resolve) => {
|
return new Promise<void>(async (resolve) => {
|
||||||
|
// Don't start playing speaking sounds until the operator stream has been silent for a bit
|
||||||
while (operatorStream.bufferEmptyFor < 1500) {
|
while (operatorStream.bufferEmptyFor < 1500) {
|
||||||
await Bun.sleep(100)
|
await Bun.sleep(100)
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const lastSoundDir = dir
|
const lastSoundDir = dir
|
||||||
const value = Math.random() * 100
|
|
||||||
if (lastSoundDir === "body-noises") {
|
if (lastSoundDir === "body-noises") {
|
||||||
dir = "apology"
|
dir = "apology"
|
||||||
} else if (value > 99 && !lastSoundDir) {
|
|
||||||
dir = "body-noises"
|
|
||||||
} else if (value > 75 && !lastSoundDir) {
|
|
||||||
dir = "stalling"
|
|
||||||
} else {
|
} else {
|
||||||
dir = undefined
|
// sleep for 4-6 seconds
|
||||||
await Bun.sleep(1000)
|
await Bun.sleep(4000 + Math.random() * 2000)
|
||||||
|
const value = Math.random() * 100
|
||||||
|
|
||||||
|
if (value > 95) {
|
||||||
|
dir = "body-noises"
|
||||||
|
} else {
|
||||||
|
dir = "stalling"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir) {
|
|
||||||
const speakingSound = getSound(dir, Array.from(playedSounds))
|
const speakingSound = getSound(dir, Array.from(playedSounds))
|
||||||
this.speakingPlayback = await this.player.play(speakingSound)
|
this.speakingPlayback = await this.player.play(speakingSound)
|
||||||
playedSounds.add(speakingSound)
|
playedSounds.add(speakingSound)
|
||||||
await this.speakingPlayback.finished()
|
await this.speakingPlayback.finished()
|
||||||
}
|
|
||||||
} while (this.typingPlayback)
|
} while (this.typingPlayback)
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async stop() {
|
async stop() {
|
||||||
|
log(`🛑 Stopping waiting sounds. Has typingPlayback: ${!!this.typingPlayback}`)
|
||||||
if (!this.typingPlayback) return
|
if (!this.typingPlayback) return
|
||||||
|
|
||||||
await Promise.all([this.typingPlayback.stop(), this.speakingPlayback?.finished()])
|
await Promise.all([this.typingPlayback.stop(), this.speakingPlayback?.finished()])
|
||||||
|
log("🛑 Waiting sounds stopped")
|
||||||
this.typingPlayback = undefined
|
this.typingPlayback = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user