This was one of my favorite projects and one of the most challenging technical builds I have worked on. The goal was to build controller software for a JCM iPro bill recycler, a hardware device that could both accept and dispense bills.
The device needed to be used inside a BTM workflow, which meant the software had to communicate reliably with physical hardware, follow the JCM ID003 protocol, manage RS232 SerialPort communication, and integrate with existing external APIs.
I built the controller personally from scratch in Node. At the time, this was the first controller of its kind that I knew of built in Node for this use case, which meant there was not a clean example to follow. I worked from JCM documentation, the ID003 protocol, hardware behavior, and external API specifications to figure out how the system needed to behave.
The hardest part was not simply sending commands to the device. The hard part was timing.
Hardware communication depends on sequence. Heartbeats, status checks, responses, acceptance states, escrow states, dispensing states, error states, and completion states all have to happen in the right order. If the controller asks the wrong question at the wrong time, waits too long, moves too fast, or misses the device’s current state, the workflow can fail.
To manage that, I built a custom finite state machine governed by a handbuilt controller. The controller tracked where the device was in the acceptance or redemption flow, what the next valid action should be, how to respond to device messages, and how to coordinate the physical bill recycler with the external system APIs.
The result was production controller software that connected a JCM iPro bill recycler, ID003 protocol communication, RS232 SerialPort messaging, Node-based controller logic, and external APIs into a working BTM bill acceptance and dispensing workflow.
This project is a strong example of the kind of technical work that lives at the edge of software and the physical world. The code does not just update a screen. It talks to hardware, waits for real-world events, follows strict protocol timing, and manages failure states carefully enough for the workflow to function reliably.