cleanup
This commit is contained in:
parent
dc902565f3
commit
781ad51d9b
94
src/phone.ts
94
src/phone.ts
|
|
@ -5,10 +5,12 @@ import { sleep } from "bun"
|
||||||
import { processStderr, processStdout } from "./utils/stdio"
|
import { processStderr, processStdout } from "./utils/stdio"
|
||||||
import Buzz from "./buzz"
|
import Buzz from "./buzz"
|
||||||
import { join } from "path"
|
import { join } from "path"
|
||||||
import { GPIO } from "./pins"
|
import GPIO from "./pins"
|
||||||
import { Agent } from "./agent"
|
import { Agent } from "./agent"
|
||||||
import { searchWeb } from "./agent/tools"
|
import { searchWeb } from "./agent/tools"
|
||||||
|
|
||||||
|
// TODO: Kill baresip process on exit
|
||||||
|
|
||||||
type CancelableTask = () => void
|
type CancelableTask = () => void
|
||||||
|
|
||||||
type PhoneContext = {
|
type PhoneContext = {
|
||||||
|
|
@ -80,58 +82,58 @@ if (!agentId) {
|
||||||
|
|
||||||
await startPhone(agentId, apiKey)
|
await startPhone(agentId, apiKey)
|
||||||
|
|
||||||
// log.info("📞 GPIO inputs initialized")
|
const startBaresip = async (hook: GPIO.InputPin) => {
|
||||||
|
// const baresipConfig = join(import.meta.dir, "..", "baresip")
|
||||||
|
// const baresip = new Baresip(["/usr/bin/baresip", "-v", "-f", baresipConfig])
|
||||||
|
|
||||||
// // const baresipConfig = join(import.meta.dir, "..", "baresip")
|
// baresip.registrationSuccess.connect(async () => {
|
||||||
// // const baresip = new Baresip(["/usr/bin/baresip", "-v", "-f", baresipConfig])
|
// log.info("🐻 server connected")
|
||||||
|
// const result = await gpio.get(pins.hook)
|
||||||
|
// if (result.state === "low") {
|
||||||
|
// phoneService.send({ type: "initialized" })
|
||||||
|
// } else {
|
||||||
|
// phoneService.send({ type: "pick_up" })
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
// // baresip.registrationSuccess.connect(async () => {
|
// baresip.callReceived.connect(({ contact }) => {
|
||||||
// // log.info("🐻 server connected")
|
// log.info(`🐻 incoming call from ${contact}`)
|
||||||
// // const result = await gpio.get(pins.hook)
|
// phoneService.send({ type: "incoming_call", from: contact })
|
||||||
// // if (result.state === "low") {
|
// })
|
||||||
// // phoneService.send({ type: "initialized" })
|
|
||||||
// // } else {
|
|
||||||
// // phoneService.send({ type: "pick_up" })
|
|
||||||
// // }
|
|
||||||
// // })
|
|
||||||
|
|
||||||
// // baresip.callReceived.connect(({ contact }) => {
|
// baresip.callEstablished.connect(({ contact }) => {
|
||||||
// // log.info(`🐻 incoming call from ${contact}`)
|
// log.info(`🐻 call established with ${contact}`)
|
||||||
// // phoneService.send({ type: "incoming_call", from: contact })
|
// phoneService.send({ type: "answered" })
|
||||||
// // })
|
// })
|
||||||
|
|
||||||
// // baresip.callEstablished.connect(({ contact }) => {
|
// baresip.hungUp.connect(() => {
|
||||||
// // log.info(`🐻 call established with ${contact}`)
|
// log.info("🐻 call hung up")
|
||||||
// // phoneService.send({ type: "answered" })
|
// phoneService.send({ type: "remote_hang_up" })
|
||||||
// // })
|
// })
|
||||||
|
|
||||||
// // baresip.hungUp.connect(() => {
|
// baresip.connect().catch((error) => {
|
||||||
// // log.info("🐻 call hung up")
|
// log.error("🐻 connection error:", error)
|
||||||
// // phoneService.send({ type: "remote_hang_up" })
|
// phoneService.send({ type: "error", message: error.message })
|
||||||
// // })
|
// })
|
||||||
|
|
||||||
// // baresip.connect().catch((error) => {
|
// baresip.error.connect(async ({ message }) => {
|
||||||
// // log.error("🐻 connection error:", error)
|
// log.error("🐻 error:", message)
|
||||||
// // phoneService.send({ type: "error", message: error.message })
|
// phoneService.send({ type: "error", message })
|
||||||
// // })
|
// for (let i = 0; i < 4; i++) {
|
||||||
|
// await ring(500)
|
||||||
|
// await sleep(250)
|
||||||
|
// }
|
||||||
|
// process.exit(1)
|
||||||
|
// })
|
||||||
|
|
||||||
// // baresip.error.connect(async ({ message }) => {
|
// const agent = new Agent({
|
||||||
// // log.error("🐻 error:", message)
|
// agentId,
|
||||||
// // phoneService.send({ type: "error", message })
|
// apiKey,
|
||||||
// // for (let i = 0; i < 4; i++) {
|
// tools: {
|
||||||
// // await ring(500)
|
// search_web: (args: { query: string }) => searchWeb(args.query),
|
||||||
// // await sleep(250)
|
// },
|
||||||
// // }
|
// })
|
||||||
// // process.exit(1)
|
}
|
||||||
// // })
|
|
||||||
|
|
||||||
// const agent = new Agent({
|
|
||||||
// agentId,
|
|
||||||
// apiKey,
|
|
||||||
// tools: {
|
|
||||||
// search_web: (args: { query: string }) => searchWeb(args.query),
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
|
|
||||||
// handleAgentEvents(agent)
|
// handleAgentEvents(agent)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
import { readdir } from "node:fs/promises"
|
|
||||||
import { gpiod, cstr } from "./ffi"
|
|
||||||
import { Output } from "./output"
|
|
||||||
import { Input } from "./input"
|
|
||||||
import { ChipNotFoundError } from "./errors"
|
|
||||||
import type { OutputOptions, InputOptions, ChipInfo } from "./types"
|
|
||||||
|
|
||||||
export class GPIO {
|
|
||||||
#chipPath: string
|
|
||||||
|
|
||||||
constructor(options?: { chip?: string }) {
|
|
||||||
this.#chipPath = options?.chip ?? "/dev/gpiochip0"
|
|
||||||
}
|
|
||||||
|
|
||||||
output(pin: number, options?: OutputOptions): Output {
|
|
||||||
return new Output(this.#chipPath, pin, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
input(pin: number, options?: InputOptions): Input {
|
|
||||||
return new Input(this.#chipPath, pin, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
async listChips(): Promise<ChipInfo[]> {
|
|
||||||
const chips: ChipInfo[] = []
|
|
||||||
|
|
||||||
try {
|
|
||||||
const files = await readdir("/dev")
|
|
||||||
const chipFiles = files.filter((f) => f.startsWith("gpiochip"))
|
|
||||||
|
|
||||||
for (const file of chipFiles) {
|
|
||||||
const path = `/dev/${file}`
|
|
||||||
|
|
||||||
try {
|
|
||||||
const chip = gpiod.gpiod_chip_open(cstr(path))
|
|
||||||
if (!chip) continue
|
|
||||||
|
|
||||||
const info = gpiod.gpiod_chip_get_info(chip)
|
|
||||||
if (!info) {
|
|
||||||
gpiod.gpiod_chip_close(chip)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const name = gpiod.gpiod_chip_info_get_name(info)
|
|
||||||
const label = gpiod.gpiod_chip_info_get_label(info)
|
|
||||||
const numLines = gpiod.gpiod_chip_info_get_num_lines(info)
|
|
||||||
|
|
||||||
chips.push({
|
|
||||||
path,
|
|
||||||
name: String(name || ""),
|
|
||||||
label: String(label || ""),
|
|
||||||
numLines: Number(numLines),
|
|
||||||
})
|
|
||||||
|
|
||||||
gpiod.gpiod_chip_close(chip)
|
|
||||||
} catch {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// /dev might not be accessible, return empty array
|
|
||||||
}
|
|
||||||
|
|
||||||
return chips
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +1,87 @@
|
||||||
export { GPIO } from "./gpio"
|
import { readdir } from "node:fs/promises"
|
||||||
export {
|
import { gpiod, cstr } from "./ffi"
|
||||||
|
import { Output } from "./output"
|
||||||
|
import { Input } from "./input"
|
||||||
|
import type * as Type from "./types"
|
||||||
|
import {
|
||||||
GPIOError,
|
GPIOError,
|
||||||
PermissionError,
|
PermissionError,
|
||||||
PinInUseError,
|
PinInUseError,
|
||||||
ChipNotFoundError,
|
ChipNotFoundError,
|
||||||
InvalidConfigError,
|
InvalidConfigError,
|
||||||
} from "./errors"
|
} from "./errors"
|
||||||
export type {
|
|
||||||
InputOptions,
|
class GPIO {
|
||||||
OutputOptions,
|
#chipPath: string
|
||||||
InputEvent,
|
|
||||||
InputGroupEvent,
|
constructor(options?: { chip?: string }) {
|
||||||
ChipInfo,
|
this.#chipPath = options?.chip ?? "/dev/gpiochip0"
|
||||||
PullMode,
|
}
|
||||||
EdgeMode,
|
|
||||||
} from "./types"
|
output(pin: number, options?: Type.OutputOptions): Output {
|
||||||
|
return new Output(this.#chipPath, pin, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
input(pin: number, options?: Type.InputOptions): Input {
|
||||||
|
return new Input(this.#chipPath, pin, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
async listChips(): Promise<Type.ChipInfo[]> {
|
||||||
|
const chips: Type.ChipInfo[] = []
|
||||||
|
|
||||||
|
try {
|
||||||
|
const files = await readdir("/dev")
|
||||||
|
const chipFiles = files.filter((f) => f.startsWith("gpiochip"))
|
||||||
|
|
||||||
|
for (const file of chipFiles) {
|
||||||
|
const path = `/dev/${file}`
|
||||||
|
|
||||||
|
try {
|
||||||
|
const chip = gpiod.gpiod_chip_open(cstr(path))
|
||||||
|
if (!chip) continue
|
||||||
|
|
||||||
|
const info = gpiod.gpiod_chip_get_info(chip)
|
||||||
|
if (!info) {
|
||||||
|
gpiod.gpiod_chip_close(chip)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = gpiod.gpiod_chip_info_get_name(info)
|
||||||
|
const label = gpiod.gpiod_chip_info_get_label(info)
|
||||||
|
const numLines = gpiod.gpiod_chip_info_get_num_lines(info)
|
||||||
|
|
||||||
|
chips.push({
|
||||||
|
path,
|
||||||
|
name: String(name || ""),
|
||||||
|
label: String(label || ""),
|
||||||
|
numLines: Number(numLines),
|
||||||
|
})
|
||||||
|
|
||||||
|
gpiod.gpiod_chip_close(chip)
|
||||||
|
} catch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// /dev might not be accessible, return empty array
|
||||||
|
}
|
||||||
|
|
||||||
|
return chips
|
||||||
|
}
|
||||||
|
|
||||||
|
static Error = GPIOError
|
||||||
|
static PermissionError = PermissionError
|
||||||
|
static PinInUseError = PinInUseError
|
||||||
|
static ChipNotFoundError = ChipNotFoundError
|
||||||
|
static InvalidConfigError = InvalidConfigError
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GPIO {
|
||||||
|
export type PullMode = Type.PullMode
|
||||||
|
export type EdgeMode = Type.EdgeMode
|
||||||
|
export type InputOptions = Type.InputOptions
|
||||||
|
export type OutputOptions = Type.OutputOptions
|
||||||
|
export type InputEvent = Type.InputEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GPIO
|
||||||
|
|
|
||||||
|
|
@ -17,15 +17,9 @@ export type InputEvent = {
|
||||||
timestamp: bigint // nanoseconds
|
timestamp: bigint // nanoseconds
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InputGroupEvent<T extends string = string> = InputEvent & {
|
|
||||||
pin: T // name of the pin that fired
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ChipInfo = {
|
export type ChipInfo = {
|
||||||
path: string
|
path: string
|
||||||
name: string
|
name: string
|
||||||
label: string
|
label: string
|
||||||
numLines: number
|
numLines: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PinConfig = Record<string, { offset: number; pull: PullMode }>
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user