HiveMind GSM Bridge
This bridges SMS sent to a physical GSM/USB modem to a HiveMind node. A HiveMind bridge is a satellite whose input and output are a chat platform instead of a microphone: SMS received by the modem become HiveMind utterances, and the hub's spoken replies are sent back as SMS to the original sender.
This bridge needs real hardware: a GSM/USB modem and a SIM card that can send and receive SMS. It has not been exercised against a live modem or a real HiveMind hub — only unit-tested with both sides mocked.
Hardware you need
- A USB GSM/GPRS modem with AT-command support. Cheap, widely available
modules that are known to work with the underlying
python-gsmmodemlibrary family: Huawei E169/E220/E3131 USB sticks, and standalone AT-command modems built around SIM800/SIM900 chipsets (e.g. many "SIM800L USB to serial" boards). Avoid modems locked to a single carrier's dongle software (some Huawei/ZTE sticks ship in "mass-storage first" mode and needusb_modeswitchto expose the modem interface at all — check the modem's exact model before buying). - A SIM card, activated with an SMS-capable plan, inserted into the modem. A prepaid SIM is enough for testing.
Finding the serial device
Plug the modem in, then check what device node Linux assigned it:
dmesg | tail -20
ls /dev/ttyUSB* /dev/ttyACM* 2>/dev/null
Most USB GSM modems expose more than one serial interface (e.g. modem
control, diagnostics, and the AT-command port); the AT-command port is
usually the one that responds to AT when you talk to it directly:
sudo apt install minicom # or screen
minicom -D /dev/ttyUSB2 -b 115200
# type AT and press enter; a modem that responds sends back "OK"
If nothing responds, try the other /dev/ttyUSB* nodes the modem
created. Once you have the right device, pass it as --port.
Registering the bridge on the hub
Every HiveMind client needs credentials and, separately, permission to
send the message types it uses. On the machine running hivemind-core:
hivemind-core add-client
This prints an access key and password; pass them to the bridge as
--access-key / --password (or store them once with
hivemind-client set-identity and omit the flags).
A freshly added client is denied every message type by default. The bridge needs at least:
hivemind-core allow-msg recognizer_loop:utterance <client_id>
hivemind-core allow-msg speak <client_id>
<client_id> is printed by add-client (and by hivemind-core list-clients afterwards). Skipping this step is the single most common
reason a bridge "connects fine" but nothing ever seems to happen: the
hub silently drops every message the client sends until it is
whitelisted.
Running the bridge
pip install .
hivemind-gsm-bridge \
--port /dev/ttyUSB2 --baud 115200 \
--access-key <key> --password <password> \
--host ws://127.0.0.1 --hivemind-port 5678
If the SIM requires a PIN, pass --sim-pin <pin>.
Useful flags:
--site-id: this bridge's HiveMind site id. If you run more than one bridge on the same host, give each a distinct site id — otherwise they collide over the same identity file and pinned peer keys.--self-signed: accept a self-signed TLS certificate onwss://hubs.--lang: the language tag attached to forwarded utterances (defaulten-us).
Note: --port is the serial device (e.g. /dev/ttyUSB0), and the
HiveMind hub's network port is --hivemind-port — the two are
deliberately named differently so they can never be confused on the
command line.
Run hivemind-gsm-bridge --help for the full list.
Docker
The modem is a physical device and must be passed through to the container:
docker build -t hivemind-gsm-bridge .
docker run --rm --device=/dev/ttyUSB2 \
-e GSM_PORT=/dev/ttyUSB2 \
-e HIVEMIND_ACCESS_KEY=... \
-e HIVEMIND_PASSWORD=... \
-e HIVEMIND_HOST=ws://hivemind-core \
hivemind-gsm-bridge
or via docker-compose.yml — copy it, fill in the environment section
and device path, and docker compose up.
What this bridge does, precisely
- Connects to a GSM modem over a serial port with
python-gsmmodem-new'sGsmModem, registering a callback for incoming SMS. - Connects to the HiveMind hub with
hivemind_bus_client.HiveMessageBusClient. - Drops empty or malformed SMS and anything received before the HiveMind handshake has completed — forwarding earlier would get the connection killed by the hub instead of just failing the one message.
- Forwards each remaining SMS as a
recognizer_loop:utterancebus message, carrying the sender's phone number in the message context so the hub'sspeakreply can be routed back to the right number. - Sends
speakreplies (and a fixed fallback line onhive.complete_intent_failure) back to the originating number through the modem'ssendSms.
Testing
pip install -e .[test]
pytest tests/
The test suite mocks both the modem object and the HiveMind
HiveMessageBusClient, so it runs without physical hardware or a live
hub. It has not been exercised against a real GSM modem or a real
HiveMind hub — that needs the actual hardware, which this repository
does not have.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hivemind_gsm_bridge-0.1.0.tar.gz.
File metadata
- Download URL: hivemind_gsm_bridge-0.1.0.tar.gz
- Upload date:
- Size: 12.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
565408d95ba633cc06fd33ecea08269946558b3764c6fe37ea36e426547136de
|
|
| MD5 |
f0d224eeb9242771198d56cebc976ce7
|
|
| BLAKE2b-256 |
d797aabb3b75406140c75ed119b47a02119812022bae1d36aca07a155e784106
|
File details
Details for the file hivemind_gsm_bridge-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hivemind_gsm_bridge-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3818cfc5df0a2d270c68a4f23ef5360621f069880fbf7416541a88a799b65dd9
|
|
| MD5 |
0ffd32bb095b4225fccaffd311b829da
|
|
| BLAKE2b-256 |
b04ced8c25c15d5f8714f6784c0e615b3df4b9b401465ae1b3df09cb2ab69870
|