A Meshtastic desktop client, allowing simple, offline deployment and administration of an ad-hoc mesh communication network. Built in Rust and TypeScript.
Position is Meshtastic’s protobuf. NodeData is almost exactly the same as NodeInfo protobuf of Meshtastic but instead of containing point-in-time data it will hold the history of data.
Set channels (using the new API). A special channel is the "primary channel". The other records are secondary channels. Note: only one channel can be marked as primary. If the client sets a particular channel to be primary, the previous channel will be set to SECONDARY automatically.
Send the specified channel in the response to this message NOTE: This field is sent with the channel index + 1 (to ensure we never try to send 'zero' - which protobufs treats as not present)
Setting channels/radio config remotely carries the risk that you might send an invalid config and the radio never talks to your mesh again. Therefore if setting either of these properties remotely, you must send a confirm_xxx message within 10 minutes. If you fail to do so, the radio will assume loss of comms and revert your changes. These messages are optional when changing the local node.
We should send our position this often (but only if it has changed significantly) Defaults to 15 minutes
position_broadcast_smart_disabled
bool
Disable adaptive position braoadcast, which is now the default.
fixed_position
bool
If set, this node is at a fixed position. We will generate GPS position updates at the regular interval, but use whatever the last lat/lon/alt we have for the node. The lat/lon/alt can be set by an internal GPS or with the help of the app.
gps_disabled
bool
Should the GPS be disabled for this node?
gps_update_interval
uint32
How often should we try to get GPS position (in seconds) or zero for the default of once every 30 seconds or a very large value (maxint) to update only once at boot.
gps_attempt_time
uint32
How long should we try to get our position during each gps_update_interval attempt? (in seconds) Or if zero, use the default of 30 seconds. If we don't get a new gps fix in that time, the gps will be put into sleep until the next gps_update_rate window.
position_flags
uint32
Bit field of boolean configuration options for POSITION messages (bitwise OR of PositionFlags)
A version integer used to invalidate old save files when we make incompatible changes This integer is set at build time and is private to NodeDB.cpp in the device code.
The part of the config that is specific to the Bluetooth settings
version
uint32
A version integer used to invalidate old save files when we make incompatible changes This integer is set at build time and is private to NodeDB.cpp in the device code.
Not normally used, but for testing a sender can request that recipient responds in kind (i.e. if it received a position, it should unicast back it's position). Note: that if you set this on a broadcast you will receive many replies.
dest
fixed32
The address of the destination node. This field is is filled in by the mesh radio device software, application layer software should never need it. RouteDiscovery messages must populate this. Other message types might need to if they are doing multihop routing.
source
fixed32
The address of the original sender for this message. This field should only be populated for reliable multihop packets (to keep packets small).
request_id
fixed32
Only used in routing or response messages. Indicates the original message ID that this message is reporting failure on. (formerly called original_id)
reply_id
fixed32
If set, this message is intened to be a reply to a previously sent message with the defined id.
emoji
fixed32
Defaults to false. If true, then what is in the payload should be treated as an emoji like giving a message a heart or poop emoji.
Mesh Packet
Field
Type
Description
from
fixed32
The sending node number. Note: Our crypto implementation uses this field as well. See crypto for details. FIXME - really should be fixed32 instead, this encoding only hurts the ble link though.
to
fixed32
The (immediatSee Priority description for more details.y should be fixed32 instead, this encoding only hurts the ble link though.
channel
uint32
(Usually) If set, this indicates the index in the secondary_channels table that this packet was sent/received on. If unset, packet was on the primary channel. A particular node might know only a subset of channels in use on the mesh. Therefore channel_index is inherently a local concept and meaningless to send between nodes. Very briefly, while sending and receiving deep inside the device Router code, this field instead contains the 'channel hash' instead of the index. This 'trick' is only used while the payloadVariant is an 'encrypted'.
A unique ID for this packet. Always 0 for no-ack packets or non broadcast packets (and therefore take zero bytes of space). Otherwise a unique ID for this packet, useful for flooding algorithms. ID only needs to be unique on a per sender basis, and it only needs to be unique for a few minutes (long enough to last for the length of any ACK or the completion of a mesh broadcast flood). Note: Our crypto implementation uses this id as well. See crypto for details. FIXME - really should be fixed32 instead, this encoding only hurts the ble link though.
rx_time
fixed32
The time this message was received by the esp32 (secs since 1970). Note: this field is never sent on the radio link itself (to save space) Times are typically not sent over the mesh, but they will be added to any Packet (chain of SubPacket) sent to the phone (so the phone can know exact time of reception)
rx_snr
float
Never* sent over the radio links. Set during reception to indicate the SNR of this packet. Used to collect statistics on current link quality.
hop_limit
uint32
If unset treated as zero (no forwarding, send to adjacent nodes only) if 1, allow hopping through one node, etc... For our usecase real world topologies probably have a max of about 3. This field is normally placed into a few of bits in the header.
want_ack
bool
This packet is being sent as a reliable message, we would prefer it to arrive at the destination. We would like to receive a ack packet in response. Broadcasts messages treat this flag specially: Since acks for broadcasts would rapidly flood the channel, the normal ack behavior is suppressed. Instead, the original sender listens to see if at least one node is rebroadcasting this packet (because naive flooding algorithm). If it hears that the odds (given typical LoRa topologies) the odds are very high that every node should eventually receive the message. So FloodingRouter.cpp generates an implicit ack which is delivered to the original sender. If after some time we don't hear anyone rebroadcast our packet, we will timeout and retransmit, using the regular resend logic. Note: This flag is normally sent in a flag bit in the header when sent over the wire
This position data. Note: before 1.2.14 we would also store the last time we've heard from this node in position.time, that is no longer true. Position.time now indicates the last time we received a POSITION from that node.
snr
float
Returns the Signal-to-noise ratio (SNR) of the last received message, as measured by the receiver. Return SNR of the last received message in dB
last_heard
fixed32
Set to indicate the last time we received a packet from this node
An error message we'd like to report back to the mothership through analytics. It indicates a serious bug occurred on the device, the device coped with it, but we still want to tell the devs about the bug. This field will be cleared after the phone reads MyNodeInfo (i.e. it will only be reported once) a numeric error code to go with error message, zero means no error
error_address
uint32
A numeric error address (nonzero if available)
error_count
uint32
The total number of errors this node has ever encountered (well - since the last time we discarded preferences)
reboot_count
uint32
The total number of reboots this node has ever encountered (well - since the last time we discarded preferences)
bitrate
float
Calculated bitrate of the current channel (in Bytes Per Second)
message_timeout_msec
uint32
How long before we consider a message abandoned and we can clear our caches of any messages in flight Normally quite large to handle the worst case message delivery time, 5 minutes. Formerly called FLOOD_EXPIRE_TIME in the device code
min_app_version
uint32
The minimum app version that can talk to this device. Phone/PC apps should compare this to their build number and if too low tell the user they must update their app
air_period_tx
uint32
24 time windows of 1hr each with the airtime transmitted out of the device per hour.
air_period_rx
uint32
24 time windows of 1hr each with the airtime of valid packets for your mesh.
has_wifi
bool
Is the device wifi capable?
channel_utilization
float
Utilization for the current channel, including well formed TX, RX and malformed RX (aka noise).
air_util_tx
float
Percent of airtime for transmission used within the last hour.
Position
Field
Type
Description
latitude_i
sfixed32
The new preferred location encoding, divide by 1e-7 to get degrees in floating point
longitude_i
sfixed32
altitude
int32
In meters above MSL (but see issue #359)
time
fixed32
This is usually not sent over the mesh (to save space), but it is sent from the phone so that the local device can set its RTC If it is sent over the mesh (because there are devices on the mesh without GPS), it will only be sent by devices which has a hardware GPS clock. seconds since 1970
location_source
Position.LocSource
altitude_source
Position.AltSource
pos_timestamp
fixed32
Positional timestamp (actual timestamp of GPS solution) in integer epoch seconds
pos_time_millis
int32
Pos. timestamp milliseconds adjustment (rarely available or required)
altitude_hae
sint32
HAE altitude in meters - can be used instead of MSL altitude
alt_geoid_sep
sint32
Geoidal separation in meters
PDOP
uint32
Horizontal, Vertical and Position Dilution of Precision, in 1/100 units - PDOP is sufficient for most cases - for higher precision scenarios, HDOP and VDOP can be used instead, in which case PDOP becomes redundant (PDOP=sqrt(HDOP^2 + VDOP^2)) TODO: REMOVE/INTEGRATE
HDOP
uint32
VDOP
uint32
gps_accuracy
uint32
GPS accuracy (a hardware specific constant) in mm multiplied with DOP to calculate positional accuracy Default: "'bout three meters-ish" :)
ground_speed
uint32
Ground speed in m/s and True North TRACK in 1/100 degrees Clarification of terms: - "track" is the direction of motion (measured in horizontal plane) - "heading" is where the fuselage points (measured in horizontal plane) - "yaw" indicates a relative rotation about the vertical axis TODO: REMOVE/INTEGRATE
ground_track
uint32
fix_quality
uint32
GPS fix quality (from NMEA GxGGA statement or similar)
fix_type
uint32
GPS fix type 2D/3D (from NMEA GxGSA statement)
sats_in_view
uint32
GPS "Satellites in View" number
sensor_id
uint32
Sensor ID - in case multiple positioning sensors are being used
pos_next_update
uint32
Estimated/expected time (in seconds) until next update: - if we update at fixed intervals of X seconds, use X - if we update at dynamic intervals (based on relative movement etc), but "AT LEAST every Y seconds", use Y
pos_seq_number
uint32
A sequence number, incremented with each Position message to help detect lost updates if needed
Mesh Packet Priority
Name
Number
Description
UNSET
0
Treated as Priority.DEFAULT
MIN
1
BACKGROUND
10
Background position updates are sent with very low priority - if the link is super congested they might not go out at all
DEFAULT
64
This priority is used for most messages that don't have a priority set
RELIABLE
70
If priority is unset but the message is marked as want_ack, assume it is important and use a slightly higher priority
ACK
120
Ack/naks are sent with very high priority to ensure that retransmission stops as soon as possible
MAX
127
PortNum
Name
Number
Description
UNKNOWN_APP
0
Deprecated: do not use in new code (formerly called OPAQUE) A message sent from a device outside of the mesh, in a form the mesh does not understand NOTE: This must be 0, because it is documented in IMeshService.aidl to be so
TEXT_MESSAGE_APP
1
A simple UTF-8 text message, which even the little micros in the mesh can understand and show on their screen eventually in some circumstances even signal might send messages in this form (see below)
REMOTE_HARDWARE_APP
2
Reserved for built-in GPIO/example app. See remote_hardware.proto/HardwareMessage for details on the message sent/received to this port number
POSITION_APP
3
The built-in position messaging app. Payload is a Position message
NODEINFO_APP
4
The built-in user info app. Payload is a User message
ROUTING_APP
5
Protocol control packets for mesh protocol use. Payload is a Routing message
ADMIN_APP
6
Admin control packets. Payload is a AdminMessage message
Provides a 'ping' service that replies to any packet it receives. Also serves as a small example module.
IP_TUNNEL_APP
33
Used for the python IP tunnel feature
SERIAL_APP
64
Provides a hardware serial interface to send and receive from the Meshtastic network. Connect to the RX/TX pins of a device with 38400 8N1. Packets received from the Meshtastic network is forwarded to the RX pin while sending a packet to TX will go out to the Mesh network. Maximum packet size of 240 bytes. Module is disabled by default can be turned on by setting SERIAL_MODULE_ENABLED = 1 in SerialPlugh.cpp.
STORE_FORWARD_APP
65
STORE_FORWARD_APP (Work in Progress) Maintained by Jm Casler (MC Hamster) : jm@casler.org
RANGE_TEST_APP
66
Optional port for messages for the range test module.
TELEMETRY_APP
67
Provides a format to send and receive telemetry data from the Meshtastic network. Maintained by Charles Crossan (crossan007) : crossan007@gmail.com
ZPS_APP
68
Experimental tools for estimating node position without a GPS Maintained by Github user a-f-G-U-C (a Meshtastic contributor) Project files at https://github.com/a-f-G-U-C/Meshtastic-ZPS
PRIVATE_APP
256
Private applications should use portnums >= 256. To simplify initial development and testing you can use "PRIVATE_APP" in your code without needing to rebuild protobuf files (via regen-protos.sh)
Data Types
On admin’s side, we want to to save data in json format represented below:
AdminDB
NodeData
Position is Meshtastic’s protobuf. NodeData is almost exactly the same as NodeInfo protobuf of Meshtastic but instead of containing point-in-time data it will hold the history of data.
Signal
We will use Meshtastic’s protobufs to represent other data. We will especially make use of the highlighted cells.
Admin Message
User
Channel
Channel
User
AdminMessage.ConfigType
Config
Config
AdminMessage.ModuleConfigType
ModuleConfig
ModuleConfig
DeviceMetadata
Position Config
Config.PositionConfig.PositionFlags
POS_UNDEFINED
0
POS_ALTITUDE
1
POS_ALT_MSL
2
POS_GEO_SEP
4
POS_DOP
8
POS_HVDOP
16
POS_SATINVIEW
32
POS_SEQ_NOS
64
POS_TIMESTAMP
128
POS_HEADING
256
POS_SPEED
512
Device State
MyNodeInfo
User
NodeInfo
MeshPacket
MeshPacket
Local Config
Config.DeviceConfig
Config.PositionConfig
Config.PowerConfig
Config.WiFiConfig
Config.DisplayConfig
Config.LoRaConfig
Config.BluetoothConfig
Data
PortNum
Mesh Packet
Data
MeshPacket.Priority
MeshPacket.Delayed
NodeInfo
The Bluetooth to device link.
User
Position
DeviceMetrics
MyNodeInfo
CriticalErrorCode
Position
Position.LocSource
Position.AltSource
Mesh Packet Priority
UNSET
0
MIN
1
BACKGROUND
10
DEFAULT
64
RELIABLE
70
ACK
120
MAX
127
PortNum
UNKNOWN_APP
0
TEXT_MESSAGE_APP
1
REMOTE_HARDWARE_APP
2
POSITION_APP
3
NODEINFO_APP
4
ROUTING_APP
5
ADMIN_APP
6
TEXT_MESSAGE_COMPRESSED_APP
7
WAYPOINT_APP
8
REPLY_APP
32
IP_TUNNEL_APP
33
SERIAL_APP
64
STORE_FORWARD_APP
65
RANGE_TEST_APP
66
TELEMETRY_APP
67
ZPS_APP
68
PRIVATE_APP
256
ATAK_FORWARDER
257
MAX
511
Source: https://meshtastic.org/docs/developers/protobufs/api