Meshtastic Client (WIP)
Elixir client for Meshtastic devices. Connects over TCP to send and receive mesh network messages using Protobuf.
Installation
Add to your mix.exs:
def deps do
[
{:meshtastic_client, "~> 0.1.0"}
]
end
Then run mix deps.get to install.
Quick Start
# Connect to your device
{:ok, conn} = MeshtasticClient.connect(type: :tcp, host: "192.168.1.100")
# Subscribe to incoming messages
MeshtasticClient.subscribe(conn)
# Send a message to the mesh
MeshtasticClient.send_text(conn, "Hello from Elixir!")
# Collect messages
messages = MeshtasticClient.collect_messages(timeout: 5000)
IO.inspect(messages)
See the examples/ directory for more usage patterns.
[!NOTE] Protobuf client is generated automatically but not all features are available on the Elixir client
Setup
This library uses Meshtastic's protobuf definitions. You'll need protoc installed to generate the Elixir modules:
# Fedora/RHEL
sudo dnf install protobuf-compiler protobuf-devel
# Ubuntu/Debian
sudo apt-get install protobuf-compiler protobuf-devel
# macOS
brew install protobufInstall the Elixir protobuf plugin:
mix escript.install hex protobuf 0.14.0
The protobuf files are in priv/protos/. Generate modules using the Mix task:
mix protobuf.genTo regenerate all modules from scratch:
mix protobuf.gen --cleanConnections
TCP
Most Meshtastic devices expose TCP on port 4403:
{:ok, conn} = MeshtasticClient.connect(
type: :tcp,
host: "192.168.1.100",
port: 4403 # default
)Serial & BLE
Not implemented yet.
Sending Messages
Text Messages
# Broadcast to all nodes
MeshtasticClient.send_text(conn, "Hello mesh!")
# Send to specific node
MeshtasticClient.send_text(conn, "Direct message", to: 0x12345678, want_ack: true)
# Send on channel 1
MeshtasticClient.send_text(conn, "Channel message", channel: 1)Position Updates
MeshtasticClient.send_position(conn,
latitude: 37.7749,
longitude: -122.4194,
altitude: 15
)Receiving Messages
Two approaches: collect or stream.
Collect Messages
Gather messages for a set time:
MeshtasticClient.subscribe(conn)
messages = MeshtasticClient.collect_messages(timeout: 5000, count: 10)
Enum.each(messages, &IO.inspect/1)Stream Messages
Handle messages as they arrive:
MeshtasticClient.subscribe(conn)
receive do
{:meshtastic_message, %{payload_variant: {:packet, packet}}} ->
IO.puts("Got packet: #{inspect(packet)}")
endDevice Info
Request configuration and node details:
# Triggers config response messages
MeshtasticClient.get_config(conn)
# Same as get_config
MeshtasticClient.get_node_info(conn)These functions send requests; responses arrive as messages you receive via subscription.
Client architecture
MeshtasticClient- Public APIMeshtasticClient.Connection- TCP connection manager (GenServer)MeshtasticClient.Message- Message encoding/framingMeshtastic.*- Generated protobuf structs (mesh.proto, config.proto, etc.)
Message Types
When you receive messages, check the payload_variant field:
case message.payload_variant do
{:my_info, info} -> # Device node info
{:node_info, node} -> # Other node discovered
{:packet, packet} -> # Mesh packet (text, telemetry, etc.)
{:config, config} -> # Device config
{:channel, channel} -> # Channel settings
_ -> # Other message types
end