From 781ad51d9b7b958bd8be314301e5d57a313fec89 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 19 Nov 2025 13:19:18 -0800 Subject: [PATCH] cleanup --- src/phone.ts | 94 ++++++++++++++++++++++++----------------------- src/pins/gpio.ts | 65 -------------------------------- src/pins/index.ts | 92 ++++++++++++++++++++++++++++++++++++++++------ src/pins/types.ts | 6 --- 4 files changed, 129 insertions(+), 128 deletions(-) delete mode 100644 src/pins/gpio.ts diff --git a/src/phone.ts b/src/phone.ts index 31cbd74..c2f677b 100644 --- a/src/phone.ts +++ b/src/phone.ts @@ -5,10 +5,12 @@ import { sleep } from "bun" import { processStderr, processStdout } from "./utils/stdio" import Buzz from "./buzz" import { join } from "path" -import { GPIO } from "./pins" +import GPIO from "./pins" import { Agent } from "./agent" import { searchWeb } from "./agent/tools" +// TODO: Kill baresip process on exit + type CancelableTask = () => void type PhoneContext = { @@ -80,58 +82,58 @@ if (!agentId) { 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") -// // const baresip = new Baresip(["/usr/bin/baresip", "-v", "-f", baresipConfig]) + // baresip.registrationSuccess.connect(async () => { + // 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 () => { -// // 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.callReceived.connect(({ contact }) => { + // log.info(`🐻 incoming call from ${contact}`) + // phoneService.send({ type: "incoming_call", from: contact }) + // }) -// // baresip.callReceived.connect(({ contact }) => { -// // log.info(`🐻 incoming call from ${contact}`) -// // phoneService.send({ type: "incoming_call", from: contact }) -// // }) + // baresip.callEstablished.connect(({ contact }) => { + // log.info(`🐻 call established with ${contact}`) + // phoneService.send({ type: "answered" }) + // }) -// // baresip.callEstablished.connect(({ contact }) => { -// // log.info(`🐻 call established with ${contact}`) -// // phoneService.send({ type: "answered" }) -// // }) + // baresip.hungUp.connect(() => { + // log.info("🐻 call hung up") + // phoneService.send({ type: "remote_hang_up" }) + // }) -// // baresip.hungUp.connect(() => { -// // log.info("🐻 call hung up") -// // phoneService.send({ type: "remote_hang_up" }) -// // }) + // baresip.connect().catch((error) => { + // log.error("🐻 connection error:", error) + // phoneService.send({ type: "error", message: error.message }) + // }) -// // baresip.connect().catch((error) => { -// // log.error("🐻 connection error:", error) -// // phoneService.send({ type: "error", message: error.message }) -// // }) + // baresip.error.connect(async ({ message }) => { + // log.error("🐻 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 }) => { -// // log.error("🐻 error:", message) -// // phoneService.send({ type: "error", message }) -// // for (let i = 0; i < 4; i++) { -// // await ring(500) -// // await sleep(250) -// // } -// // process.exit(1) -// // }) - -// const agent = new Agent({ -// agentId, -// apiKey, -// tools: { -// search_web: (args: { query: string }) => searchWeb(args.query), -// }, -// }) + // const agent = new Agent({ + // agentId, + // apiKey, + // tools: { + // search_web: (args: { query: string }) => searchWeb(args.query), + // }, + // }) +} // handleAgentEvents(agent) diff --git a/src/pins/gpio.ts b/src/pins/gpio.ts deleted file mode 100644 index fea7051..0000000 --- a/src/pins/gpio.ts +++ /dev/null @@ -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 { - 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 - } -} diff --git a/src/pins/index.ts b/src/pins/index.ts index c2d155b..34b0606 100644 --- a/src/pins/index.ts +++ b/src/pins/index.ts @@ -1,17 +1,87 @@ -export { GPIO } from "./gpio" -export { +import { readdir } from "node:fs/promises" +import { gpiod, cstr } from "./ffi" +import { Output } from "./output" +import { Input } from "./input" +import type * as Type from "./types" +import { GPIOError, PermissionError, PinInUseError, ChipNotFoundError, InvalidConfigError, } from "./errors" -export type { - InputOptions, - OutputOptions, - InputEvent, - InputGroupEvent, - ChipInfo, - PullMode, - EdgeMode, -} from "./types" + +class GPIO { + #chipPath: string + + constructor(options?: { chip?: string }) { + this.#chipPath = options?.chip ?? "/dev/gpiochip0" + } + + 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 { + 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 diff --git a/src/pins/types.ts b/src/pins/types.ts index 45bd01a..a5756af 100644 --- a/src/pins/types.ts +++ b/src/pins/types.ts @@ -17,15 +17,9 @@ export type InputEvent = { timestamp: bigint // nanoseconds } -export type InputGroupEvent = InputEvent & { - pin: T // name of the pin that fired -} - export type ChipInfo = { path: string name: string label: string numLines: number } - -export type PinConfig = Record