Creating an API for a legacy device over telnet using tmux and nodered
I love API’s. It allows automating processes and linking devices together a breeze. When a device doesn’t have an API usually its game over. Recently I was able to build an API for a legacy device with NodeRED and it worked quite well.
The legacy device I had only communicated via Telnet and SSH. The SSH connection didn’t provide you with a UNIX shell rather another Telnet connection. Sending commands remotely to the Telnet session was an option however there was a 5 second delay on startup. This wouldn’t work as the API would be called multiple times a second via a HTTP listener.
This is where NodeRED shines, it describes itself as:
Node-RED is a programming tool for wiring together hardware devices, APIs and online services in new and interesting ways.
You can find out more at NodeREDs homepage.
I was able to create a flow that achieves the following:
- On flow start - start a new session
- Wait for a POST request
- Configure the parameters and set the correct command
- Send the command
- Return an appropriate HTTP response
- Restart the session at X interval (poor mans error recovery)
This works well, I used tmux for session management because:
- I can view any errors thrown back from the device should something go wrong
- It’s an easier way to send commands to an already established SSH tunnel
tmux is an incredible tool:
tmux is a terminal multiplexer. It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal.
To start the tmux session:
tmux kill-session -t mysession 2>/dev/null || true && tmux new -d -s mysession '/bin/bash' && tmux send-keys -t mysession.0 "sshpass -f <(printf '%s\n' PASSWORD) ssh -o 'ControlPersist=yes' -o 'ControlMaster=auto' [email protected]" ENTER
- Kills any previous sessions
- Starts a new session with a specific session name so we can refer to it later
- Passes the SSH password and connection information and establishes an SSH shell
You may be thinking its bad security practice to include the password in this command, you’d be right - why not SSH keys? Well the legacy device doesn’t support them.
When sending commands to the session:
tmux send-keys -t mysession "YOUR COMMANDS HERE" ENTER
This utilises tmux’s send-keys command which you can read more about in the man page.
I haven’t designed an error correction system, therefore if tmux or SSH fails for any reason the HTTP response returns a 500 error. This could be solved by delaying the response and restarting the tmux session. For now I restart the session at regular intervals.
So next time you have a device that hasn’t got an API reach for NodeRED and tmux. I’d love to hear if you used this technique - send me an email.