Building a High-Availability SMS Gateway with Raspberry Pi
We did Edge Computing before "Edge Computing" was a thing.
Long before the term became a buzzword, we were already deploying decentralized nodes to process data at the source. In an era where 2G was the lifeline for millions, we engineered a bare-metal SMS gateway using Raspberry Pis to bridge the digital divide.
In the era of 5G and fiber optics, we often forget that a massive chunk of the population still relies on 2G networks and simple SMS. When a major NGO approached us to collect data from rural areas with spotty internet connectivity, we knew a web app wouldn't cut it.
The Challenge: Reaching the "Offline" Billion
The client needed a way for citizens to send simple structured data (Location, Needs, Status) to a central server. The constraints were severe:
- No Internet: The end users did not have smartphones.
- High Volume: We expected bursts of traffic during specific campaign hours.
- Low Cost: Traditional "Short Code" services (like 56767) were too expensive and took weeks to procure.
The Solution: A Bare-Metal Gateway
We decided to build our own telecom tower—in a box. Using a Raspberry Pi as the controller, we attached multiple USB GSM Modems (Huawei/ZTE dongles), effectively turning a $35 computer into a multi-channel SMS center.
The Stack: Gammu & SMSD
Directly communicating with modems via Serial Ports (AT Commands) is error-prone. We utilized Gammu, a command-line utility that abstracts the complexity of cellular protocols.
Specifically, we ran the Gammu SMS Daemon (gammu-smsd). This service monitors the modems and automatically dumps incoming SMS messages into a MySQL database or a flat file, triggering a Python script for processing.
The Engineering Hurdle: Device Enumeration
The biggest technical challenge was Linux device management. When you reboot a Raspberry Pi with multiple modems, /dev/ttyUSB0 might suddenly become /dev/ttyUSB2. This breaks the configuration.
We solved this by writing custom UDEV rules to identify modems by their physical USB port path, ensuring that "Modem A" always remained "Modem A" regardless of reboots.
# Example UDEV rule for persistent modem naming
SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{idVendor}=="12d1", ATTRS{idProduct}=="1001", SYMLINK+="gsm_modem_1"
The Workflow
- Ingest: User sends an SMS to the publicized number.
- Buffer: The modem receives the PDU (Protocol Data Unit) and stores it in SIM memory.
- Process: Gammu-SMSD polls the modem, retrieves the message, and decodes the PDU into text.
- Action: A Python script parses the text (e.g., "HELP 411001"), logs the request, and triggers an API call to the main server whenever the Pi finds an internet connection.
Why this matters
This project proved that resilient engineering isn't always about the cloud. Sometimes, it's about hacking hardware to bridge the digital divide. We processed over 50,000 messages with zero downtime, proving that a Raspberry Pi can be enterprise-grade if you configure it correctly.