There’s a hidden gem in the goTenna Python SDK I haven’t seen anyone talk about yet.
The SDK has functionality to support creating a low cost, low power Raspberry Pi gateway between the goTenna mesh network and, for example, the mobile SMS network. In particular, the SDK developers have included functionality that enables gateway nodes to advertise an external address (eg. an SMS phone number) over the mesh network.
A set of gateway nodes located in different locations can share a common mesh GID and advertise the same set of external SMS numbers that they will forward to. You may originally get the advertisement from one gateway, but a message forwarded to that gateway’s GID will be relayed through whichever gateway with the same GID happens to be closest.
A RPi based gateway can use a GSM dongle and a Twilio Programmable SIM (as described here) to create an SMS gateway that does not require internet connectivity. The goTenna gateway functionality is demonstrated by the sampleGateway.py file included with the goTenna Python SDK.
Some examples of how a low cost, and potentially even battery powered mesh-to-SMS gateway might be used:
- Operated at the edge of a wildfire area to allow people to connect with family and friends when centralized infrastructure is down or overloaded.
- Allow people to subscribe to news and weather updates during a hurricane.
- Provide a simple private email remailing service.
I don’t have time to build this project myself, but I’d love to assist someone interested in taking it on. I’ve written up some notes from my testing of the sampleGateway.py code below. Hopefully this can help everyone get started playing with gateway functionality. In my example below I have created a hypothetical “Crisis Response Network” or “CRN” service with the phone number (123) 456-7890.
Computer
- Connect a powered off goTenna Mesh device to your computer via USB
- Remove .goTenna storage file if present from a previous run
- Verify that the latest version of the Python SDK whl file is installed:
> python -m pip list
- Run gateway sample app (prefix with ‘sudo’ if on RPi).
> python sampleGateway.py [Your Token]
- Turn on goTenna Mesh, you will see “device_present” message and show connected COM port (eg. COM7 on Windows 10 or /dev/ttyACM0 on RPi).
- Register an external service that this gateway will advertise:
>>> g.register_external(1234567890, “CRN Service”)
- Verify list of contacts supported by the gateway:
>>> d._storage.get([“external_contacts”])
- Connect to goTenna Mesh, you will see “Connected to device” message
>>> d.connect(“COM7”)
or on RPi:
>>> d.connect(“/dev/ttyACM0”)
- Advertise the gateway’s external address to nearby goTenna Mesh devices. You should see lights blink on both gateway goTenna and then on the nearby goTenna devices.
>>> g.advertise()
- Check contacts on phone running the beta goTenna app or an instance of sample.py to confirm contact service has been added. Eg. ‘CRN Service’
- Broadcast a message from the gateway, should see ‘Broadcast forwarded’ message and goTenna Mesh lights should blink.
>>> p=goTenna.payload.TextPayload("first broadcast")
>>> ext_gid=goTenna.settings.GID(1234567890, goTenna.settings.GID.PRIVATE)
>>> g.forward_broadcast(p, ext_gid)
INFO:main.Gateway:Broadcast forwarded
- The message should appear as a Shout chat on the phone and be from the gateway:
- Long press on the message and send a private reply back to the gateway.
- On the gateway device you should see the reply.
- Send a private message from the gateway device to the phone
>>> ext_gid=goTenna.settings.GID(1234567890, goTenna.settings.GID.PRIVATE)
>>> ext_gid_dst=goTenna.settings.GID( 90180116423811 , goTenna.settings.GID.PRIVATE)
>>> p=goTenna.payload.TextPayload("private reply from gateway")
>>> g.forward_private(p, ext_gid, ext_gid_dst)
- The message should appear as a private chat from the CRN service:
- Test also that you can edit and delete the contact information.
- Disconnect and wait for goTenna device to be unpaired and start blinking before quitting.
>>> d.disconnect()
- Wait until disconnected and then quit python
>>> quit()