The Story Behind OpenPayphone (Part 3: The Small Matter of Programming)

...continued from Part 2

This is part three of three, wherein our protagonist endeavors to implement a state machine to enable the exchange of money for time (on call).

So… what happened was… I got started on programming the thing and honestly just got busy with other projects. It’s now June of 2026, and I’ll be 40 in less than a week, so it’s been an entire year since this project kicked off. Time to finish it!

I started by firing up vi, then I realized how long winded this entire story has become and so I googled how to exit vi (j/k – I know you have to restart your computer). After the reboot, I fired up Claude Code (it’s 2026 now after all) and I pointed at what I had started last year. After giving me the usual praise for the things I had done well, I told it all the things I never had time to do, made a few architectural suggestions and a couple hours later, et viola … I mean, voila. Things truly are a “small matter” these days – I’m not sure how this prediction is going to fare, but software programming in 2026 is how I imagine textile work must have felt in 1810 – give it another year or two.

The OpenPayphone software in development

I would type up a paragraph about what was generated, but Claude puts it better:

“It’s an event-driven, multi-process state machine. Five cohesive tasks — phone (the state-machine "brain"), SIP/pjsua2, hardware I/O, recorder, and web UI — each run as isolated OS processes and talk only through a typed (Pydantic) event bus fanned out by a task manager. Concerns are cleanly separated behind abstractions (a board HAL with mock/real backends; a presentation-only UI reading a persisted recorder), making the domain logic hardware-independent and unit-testable off-device.

In three words: decoupled, message-passing, hardware-abstracted.”

The state machine looks like what you’d expect – everything returns to the hook state (there’s a few hidden states but this pretty much covers it):

The phone state machine diagram

It is a full-fledged PoE-powered SIP-compatible payphone, and has all the fun features you remember, like SIT tones (beep-beEP-BEEP We’re sorry…) and custom playback of operator audio (bring your own from the telco you remember!), custom call rate plans ($.50 for long distance), call logs, coinage tracking, and an optional backdoor to always get a refund on your calls (because it really won’t let you call without the deposit). It’s high enough fidelity that I think it could actually be deployed in a real COCOT situation if someone wanted to spend more time setting it up than a lifetime of returns could provide.

The finished payphone installed on the wallI don’t know what took me so long, but I’m happy I finally found time to get it polished off and installed. It’s a great addition to the network.

In case you are a hobbyist, or phone enthusiast and want to get something similar going, or even if you’re just curious as to the technical artifacts of a project like this, I’ve included all the design files including the hardware prints, PCB, BOM, placards, and the open source software in the OpenPayphone project here: https://github.com/eric-cgn/openpayphone

Thanks for reading, I hope you enjoyed this a bit as much as I did.

-Eric
@pwnpnw

The finished payphone