meshtastic 0.0.178 → 0.0.179

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -175
  3. data/documentation/README.md +59 -0
  4. data/documentation/admin.md +54 -0
  5. data/documentation/apponly.md +22 -0
  6. data/documentation/atak.md +27 -0
  7. data/documentation/bluetooth-bluez.md +35 -0
  8. data/documentation/bluetooth.md +87 -0
  9. data/documentation/cannedmessages.md +25 -0
  10. data/documentation/channel.md +30 -0
  11. data/documentation/clientonly.md +21 -0
  12. data/documentation/config.md +29 -0
  13. data/documentation/connection-status.md +22 -0
  14. data/documentation/deviceonly.md +22 -0
  15. data/documentation/localonly.md +21 -0
  16. data/documentation/mesh-interface.md +52 -0
  17. data/documentation/meshtastic.md +45 -0
  18. data/documentation/module-config.md +26 -0
  19. data/documentation/mqtt.md +101 -0
  20. data/documentation/paxcount.md +25 -0
  21. data/documentation/portnums.md +67 -0
  22. data/documentation/position.md +34 -0
  23. data/documentation/protobufs.md +162 -0
  24. data/documentation/remote-hardware.md +33 -0
  25. data/documentation/rtttl.md +24 -0
  26. data/documentation/serial.md +78 -0
  27. data/documentation/storeforward.md +24 -0
  28. data/documentation/stream-interface.md +15 -0
  29. data/documentation/tcp.md +43 -0
  30. data/documentation/telemetry.md +32 -0
  31. data/documentation/traceroute.md +28 -0
  32. data/documentation/util.md +27 -0
  33. data/documentation/xmodem.md +22 -0
  34. data/lib/meshtastic/admin.rb +66 -8
  35. data/lib/meshtastic/apponly.rb +14 -8
  36. data/lib/meshtastic/atak.rb +21 -8
  37. data/lib/meshtastic/cannedmessages.rb +16 -8
  38. data/lib/meshtastic/channel.rb +13 -9
  39. data/lib/meshtastic/clientonly.rb +14 -8
  40. data/lib/meshtastic/config.rb +12 -9
  41. data/lib/meshtastic/connection_status.rb +7 -9
  42. data/lib/meshtastic/deviceonly.rb +11 -8
  43. data/lib/meshtastic/localonly.rb +11 -8
  44. data/lib/meshtastic/module_config.rb +12 -9
  45. data/lib/meshtastic/paxcount.rb +19 -9
  46. data/lib/meshtastic/portnums.rb +12 -9
  47. data/lib/meshtastic/position.rb +35 -0
  48. data/lib/meshtastic/remote_hardware.rb +34 -9
  49. data/lib/meshtastic/rtttl.rb +17 -8
  50. data/lib/meshtastic/storeforward.rb +16 -8
  51. data/lib/meshtastic/tcp.rb +102 -0
  52. data/lib/meshtastic/telemetry.rb +18 -9
  53. data/lib/meshtastic/traceroute.rb +33 -0
  54. data/lib/meshtastic/version.rb +1 -1
  55. data/lib/meshtastic/xmodem.rb +11 -9
  56. data/lib/meshtastic.rb +26 -5
  57. data/spec/lib/meshtastic/admin_pb_spec.rb +1 -1
  58. data/spec/lib/meshtastic/admin_spec.rb +39 -0
  59. data/spec/lib/meshtastic/apponly_pb_spec.rb +1 -1
  60. data/spec/lib/meshtastic/apponly_spec.rb +4 -0
  61. data/spec/lib/meshtastic/atak_pb_spec.rb +1 -1
  62. data/spec/lib/meshtastic/atak_spec.rb +22 -0
  63. data/spec/lib/meshtastic/cannedmessages_pb_spec.rb +1 -1
  64. data/spec/lib/meshtastic/cannedmessages_spec.rb +3 -0
  65. data/spec/lib/meshtastic/channel_pb_spec.rb +1 -1
  66. data/spec/lib/meshtastic/channel_spec.rb +21 -0
  67. data/spec/lib/meshtastic/clientonly_pb_spec.rb +1 -1
  68. data/spec/lib/meshtastic/clientonly_spec.rb +5 -0
  69. data/spec/lib/meshtastic/config_pb_spec.rb +1 -1
  70. data/spec/lib/meshtastic/config_spec.rb +22 -1
  71. data/spec/lib/meshtastic/connection_status_pb_spec.rb +1 -1
  72. data/spec/lib/meshtastic/connection_status_spec.rb +3 -0
  73. data/spec/lib/meshtastic/deviceonly_legacy_pb_spec.rb +1 -1
  74. data/spec/lib/meshtastic/deviceonly_pb_spec.rb +1 -1
  75. data/spec/lib/meshtastic/deviceonly_spec.rb +3 -0
  76. data/spec/lib/meshtastic/localonly_pb_spec.rb +1 -1
  77. data/spec/lib/meshtastic/localonly_spec.rb +3 -0
  78. data/spec/lib/meshtastic/mesh_beacon_pb_spec.rb +1 -1
  79. data/spec/lib/meshtastic/mesh_pb_spec.rb +1 -1
  80. data/spec/lib/meshtastic/module_config_pb_spec.rb +1 -1
  81. data/spec/lib/meshtastic/module_config_spec.rb +21 -0
  82. data/spec/lib/meshtastic/mqtt_pb_spec.rb +1 -1
  83. data/spec/lib/meshtastic/paxcount_pb_spec.rb +1 -1
  84. data/spec/lib/meshtastic/paxcount_spec.rb +23 -0
  85. data/spec/lib/meshtastic/portnums_pb_spec.rb +1 -1
  86. data/spec/lib/meshtastic/portnums_spec.rb +4 -0
  87. data/spec/lib/meshtastic/position_spec.rb +33 -0
  88. data/spec/lib/meshtastic/remote_hardware_pb_spec.rb +1 -1
  89. data/spec/lib/meshtastic/remote_hardware_spec.rb +24 -0
  90. data/spec/lib/meshtastic/rtttl_pb_spec.rb +1 -1
  91. data/spec/lib/meshtastic/rtttl_spec.rb +21 -0
  92. data/spec/lib/meshtastic/storeforward_pb_spec.rb +1 -1
  93. data/spec/lib/meshtastic/storeforward_spec.rb +21 -0
  94. data/spec/lib/meshtastic/tcp_spec.rb +48 -0
  95. data/spec/lib/meshtastic/telemetry_pb_spec.rb +1 -1
  96. data/spec/lib/meshtastic/telemetry_spec.rb +21 -0
  97. data/spec/lib/meshtastic/traceroute_spec.rb +27 -0
  98. data/spec/lib/meshtastic/xmodem_pb_spec.rb +1 -1
  99. data/spec/lib/meshtastic/xmodem_spec.rb +6 -1
  100. data/spec/lib/meshtastic_spec.rb +3 -0
  101. metadata +38 -1
@@ -0,0 +1,52 @@
1
+ # Meshtastic::MeshInterface
2
+
3
+ Packet builder used by Serial, Bluetooth, TCP, and MQTT. Instantiated internally; you can also call it directly to get protobuf bytes without writing a radio.
4
+
5
+ ## Instance methods
6
+
7
+ - `initialize(debug_out:, is_connected:, is_proto:, no_nodes:)`
8
+ - `generate_packet_id(last_packet_id:)`
9
+ - `get_cipher_keys(psks:)` — normalize Base64 PSK hash keys
10
+ - `gps_search(lat:, lon:)` — Geocoder reverse lookup
11
+ - `start_config` — `ToRadio.want_config_id` bytes
12
+ - `my_node_info`
13
+ - `send_packet` — encrypt when `psks` present; `via: :radio` → `ToRadio`, `via: :mqtt` → `ServiceEnvelope`
14
+ - `send_data` / `send_text`
15
+ - `send_to_radio` / `send_to_mqtt` — serialize only
16
+ - `decode_payload` — TEXT_MESSAGE_APP as UTF-8; other portnums as nested protobufs when known
17
+ - `help` / `authors`
18
+
19
+ On Serial/Bluetooth/TCP, transports pass `psks: nil` so the radio owns channel crypto. MQTT must pass `psks`.
20
+
21
+ `send_text` refuses payloads larger than `Meshtastic::Constants::DATA_PAYLOAD_LEN`.
22
+
23
+ ## Example
24
+
25
+ ```ruby
26
+ mesh = Meshtastic::MeshInterface.new
27
+ bytes = mesh.start_config
28
+
29
+ text_bytes = mesh.send_text(
30
+ from: '!11223344',
31
+ to: '!ffffffff',
32
+ channel: 0,
33
+ text: 'Hello',
34
+ via: :radio,
35
+ psks: nil
36
+ )
37
+
38
+ envelope = mesh.send_text(
39
+ from: '!c0ffee00',
40
+ to: '!ffffffff',
41
+ channel: 93,
42
+ text: 'Hello MQTT',
43
+ via: :mqtt,
44
+ psks: { LongFast: 'AQ==' }
45
+ )
46
+ ```
47
+
48
+ ## Related
49
+
50
+ - [Meshtastic::Serial](serial.md)
51
+ - [Meshtastic::MQTT](mqtt.md)
52
+ - [Meshtastic::Portnums](portnums.md)
@@ -0,0 +1,45 @@
1
+ # Meshtastic (top-level)
2
+
3
+ `require 'meshtastic'` loads protobufs, autoloads client modules, and reopens a few generated classes (`Channel`, `Config`, `ModuleConfig`, `Paxcount`, `Position`, `Telemetry`).
4
+
5
+ ## Constants
6
+
7
+ | Name | Value | Meaning |
8
+ | --- | --- | --- |
9
+ | `NODELESS_WANT_CONFIG_ID` | `69420` | Config handshake id when `no_nodes` is set |
10
+ | `START1` | `0x94` | UART/TCP frame magic |
11
+ | `START2` | `0xC3` | UART/TCP frame magic |
12
+ | `HEADER_LEN` | `4` | Frame header bytes |
13
+ | `MAX_TO_FROM_RADIO_SIZE` | `512` | Max ToRadio/FromRadio body |
14
+ | `VERSION` | gem version string | `Meshtastic::VERSION` |
15
+
16
+ ## Methods
17
+
18
+ ### `Meshtastic.help`
19
+
20
+ Returns sorted constants in the namespace (not printed usage).
21
+
22
+ ```ruby
23
+ require 'meshtastic'
24
+ Meshtastic.help
25
+ # => [:ADMIN_APP, :ATAK, :Admin, :AdminMessage, ...]
26
+ ```
27
+
28
+ ### `Meshtastic.deliver_data`
29
+
30
+ Routes a `Meshtastic::Data` payload to a connected radio.
31
+
32
+ ```ruby
33
+ Meshtastic.deliver_data(
34
+ serial_obj: serial_obj, # or bluetooth_obj: or tcp_obj:
35
+ data: Meshtastic::Data.new(portnum: :TEXT_MESSAGE_APP, payload: 'hi'),
36
+ port_num: Meshtastic::PortNum::TEXT_MESSAGE_APP
37
+ )
38
+ ```
39
+
40
+ Raises `ArgumentError` unless `data` is a `Meshtastic::Data` and one of `serial_obj`, `bluetooth_obj`, or `tcp_obj` is present.
41
+
42
+ ## Related
43
+
44
+ - [Transports](README.md#transports)
45
+ - [Generated protobuf types](protobufs.md)
@@ -0,0 +1,26 @@
1
+ # Meshtastic::ModuleConfig
2
+
3
+ Reopens the generated `Meshtastic::ModuleConfig` protobuf class. Get/set module configuration via [Admin](admin.md).
4
+
5
+ ## Methods
6
+
7
+ - `get(serial_obj:, module_config_type: :MQTT_CONFIG)`
8
+ - `set(serial_obj:, module_config:)`
9
+ - `help` / `authors`
10
+
11
+ `module_config_type` values include `:MQTT_CONFIG`, `:SERIAL_CONFIG`, `:STOREFORWARD_CONFIG`, `:TELEMETRY_CONFIG`, `:REMOTEHARDWARE_CONFIG`, `:CANNEDMSG_CONFIG`, `:AUDIO_CONFIG`, `:PAXCOUNTER_CONFIG`, `:NEIGHBORINFO_CONFIG`, `:DETECTIONSENSOR_CONFIG`, `:EXTNOTIF_CONFIG`, `:RANGETEST_CONFIG`, `:AMBIENTLIGHTING_CONFIG`, `:STATUSMESSAGE_CONFIG`, `:MESHBEACON_CONFIG`, `:TAK_CONFIG`, `:TRAFFICMANAGEMENT_CONFIG`.
12
+
13
+ ## Example
14
+
15
+ ```ruby
16
+ Meshtastic::ModuleConfig.get(serial_obj: serial_obj, module_config_type: :MQTT_CONFIG)
17
+
18
+ mod = Meshtastic::ModuleConfig.new
19
+ mod.mqtt = Meshtastic::ModuleConfig::MQTTConfig.new(enabled: true, address: 'mqtt.example.test')
20
+ Meshtastic::ModuleConfig.set(serial_obj: serial_obj, module_config: mod)
21
+ ```
22
+
23
+ ## Related
24
+
25
+ - [Meshtastic::Admin](admin.md)
26
+ - [Meshtastic::Config](config.md)
@@ -0,0 +1,101 @@
1
+ # Meshtastic::MQTT
2
+
3
+ Broker client. The host encrypts and decrypts with channel PSKs. Default public broker is `mqtt.meshtastic.org` (port 1883, user `meshdev`).
4
+
5
+ `channel:` on MQTT is the integer hash seen in envelopes, not the radio channel index (that is Serial/Bluetooth/TCP).
6
+
7
+ ## Methods
8
+
9
+ - `connect` — returns an `MQTT::Client`
10
+ - `subscribe` — blocking loop; yields a hash per envelope, or pretty-prints without a block. Disconnects on exit.
11
+ - `send_text` — publishes a `ServiceEnvelope` (raises if text exceeds `Meshtastic::Constants::DATA_PAYLOAD_LEN`)
12
+ - `disconnect`
13
+ - `help` / `authors`
14
+
15
+ ### `connect`
16
+
17
+ ```ruby
18
+ mqtt_obj = Meshtastic::MQTT.connect(
19
+ host: 'mqtt.meshtastic.org',
20
+ port: 1883,
21
+ tls: false,
22
+ username: 'meshdev',
23
+ password: 'large4cats',
24
+ client_id: nil, # default: random 4-byte hex
25
+ keep_alive: 15,
26
+ ack_timeout: 30
27
+ )
28
+ ```
29
+
30
+ ### `subscribe`
31
+
32
+ ```ruby
33
+ Meshtastic::MQTT.subscribe(
34
+ mqtt_obj: mqtt_obj,
35
+ root_topic: 'msh',
36
+ region: 'US',
37
+ topic: '2/e/LongFast/#',
38
+ psks: { LongFast: 'AQ==' },
39
+ qos: 0,
40
+ exclude: nil, # comma-delimited substrings to hide
41
+ include: nil, # all listed substrings must appear
42
+ gps_metadata: false,
43
+ include_raw: false
44
+ ) do |message|
45
+ puts message.inspect
46
+ end
47
+ ```
48
+
49
+ `include: '_APP, LongFast'` keeps only messages whose flattened inspect contains both strings.
50
+
51
+ ### `send_text`
52
+
53
+ ```ruby
54
+ require 'meshtastic'
55
+
56
+ mqtt_obj = Meshtastic::MQTT.connect
57
+ client_id = "!#{mqtt_obj.client_id}"
58
+ Meshtastic::MQTT.send_text(
59
+ mqtt_obj: mqtt_obj,
60
+ from: client_id,
61
+ to: '!ffffffff',
62
+ root_topic: 'msh',
63
+ region: 'US',
64
+ topic: '2/e/LongFast/#',
65
+ channel: 93,
66
+ text: 'Hello, World!',
67
+ psks: { LongFast: 'AQ==' }
68
+ )
69
+ ```
70
+
71
+ Default `channel` is `6`. The value that actually works is the integer in a received envelope for that mesh channel. Subscribe with `include: '!YOUR_CLIENT_ID'` while sending a test message from the official app:
72
+
73
+ ```ruby
74
+ mqtt_obj = Meshtastic::MQTT.connect
75
+ Meshtastic::MQTT.subscribe(
76
+ mqtt_obj: mqtt_obj,
77
+ root_topic: 'msh',
78
+ region: 'US',
79
+ topic: '2/e/LongFast/#',
80
+ psks: { LongFast: 'AQ==' },
81
+ include: '!c0ffee00'
82
+ ) do |message|
83
+ puts message.inspect
84
+ end
85
+ ```
86
+
87
+ Example envelope (placeholders):
88
+
89
+ ```
90
+ {packet: {from: 3237997296, to: 4294967295, channel: 93, id: 1, rx_time: 1735689600, rx_snr: 0.0, hop_limit: 3, want_ack: false, priority: :HIGH, rx_rssi: 0, delayed: :NO_DELAY, via_mqtt: false, hop_start: 3, public_key: "", pki_encrypted: false, next_hop: 0, relay_node: 0, tx_after: 0, decoded: {portnum: :TEXT_MESSAGE_APP, payload: "WHAT IS MY channel VALUE?", want_response: false, dest: 0, source: 0, request_id: 0, reply_id: 0, emoji: 0, bitfield: 0}, encrypted: :decrypted, topic: "msh/US/2/e/LongFast/!c0ffee00", node_id_from: "!c0ffee00", node_id_to: "!ffffffff", rx_time_utc: "2025-01-01 00:00:00 UTC"}, channel_id: "LongFast", gateway_id: "!c0ffee00"}
91
+ ```
92
+
93
+ Use `channel: 93` from that dump when publishing.
94
+
95
+ `AQ==` is expanded to the well-known LongFast PSK. Pass a Base64 channel key for private channels.
96
+
97
+ ## Related
98
+
99
+ - [Meshtastic::MeshInterface](mesh-interface.md) (`via: :mqtt`)
100
+ - [Meshtastic::Portnums](portnums.md)
101
+ - Protobuf: `ServiceEnvelope`, `MapReport` in [protobufs.md](protobufs.md)
@@ -0,0 +1,25 @@
1
+ # Meshtastic::Paxcount
2
+
3
+ Reopens the generated `Meshtastic::Paxcount` protobuf class. Transmits `PAXCOUNTER_APP` (port 34).
4
+
5
+ Use `build` / `transmit`, not `send` / `encode`.
6
+
7
+ ## Methods
8
+
9
+ - `build(wifi:, ble:, uptime:)`
10
+ - `transmit`
11
+ - `help` / `authors`
12
+
13
+ ## Example
14
+
15
+ ```ruby
16
+ Meshtastic::Paxcount.transmit(
17
+ serial_obj: serial_obj,
18
+ wifi: 3,
19
+ ble: 2
20
+ )
21
+ ```
22
+
23
+ ## Related
24
+
25
+ - [Meshtastic::Telemetry](telemetry.md)
@@ -0,0 +1,67 @@
1
+ # Meshtastic::Portnums
2
+
3
+ Looks up `Meshtastic::PortNum` names and numbers.
4
+
5
+ ## Methods
6
+
7
+ - `lookup(name_or_number)` — symbol → integer, integer → symbol
8
+ - `help` / `authors`
9
+
10
+ The enum itself is `Meshtastic::PortNum` (`lookup` / `resolve` / constants).
11
+
12
+ ## Example
13
+
14
+ ```ruby
15
+ Meshtastic::Portnums.lookup(:TEXT_MESSAGE_APP) # => 1
16
+ Meshtastic::Portnums.lookup(1) # => :TEXT_MESSAGE_APP
17
+ Meshtastic::PortNum::ADMIN_APP # => 6
18
+ ```
19
+
20
+ | Name | Value |
21
+ | --- | --- |
22
+ | UNKNOWN_APP | 0 |
23
+ | TEXT_MESSAGE_APP | 1 |
24
+ | REMOTE_HARDWARE_APP | 2 |
25
+ | POSITION_APP | 3 |
26
+ | NODEINFO_APP | 4 |
27
+ | ROUTING_APP | 5 |
28
+ | ADMIN_APP | 6 |
29
+ | TEXT_MESSAGE_COMPRESSED_APP | 7 |
30
+ | WAYPOINT_APP | 8 |
31
+ | AUDIO_APP | 9 |
32
+ | DETECTION_SENSOR_APP | 10 |
33
+ | ALERT_APP | 11 |
34
+ | KEY_VERIFICATION_APP | 12 |
35
+ | REMOTE_SHELL_APP | 13 |
36
+ | REPLY_APP | 32 |
37
+ | IP_TUNNEL_APP | 33 |
38
+ | PAXCOUNTER_APP | 34 |
39
+ | STORE_FORWARD_PLUSPLUS_APP | 35 |
40
+ | NODE_STATUS_APP | 36 |
41
+ | MESH_BEACON_APP | 37 |
42
+ | PAGING_APP | 38 |
43
+ | SERIAL_APP | 64 |
44
+ | STORE_FORWARD_APP | 65 |
45
+ | RANGE_TEST_APP | 66 |
46
+ | TELEMETRY_APP | 67 |
47
+ | ZPS_APP | 68 |
48
+ | SIMULATOR_APP | 69 |
49
+ | TRACEROUTE_APP | 70 |
50
+ | NEIGHBORINFO_APP | 71 |
51
+ | ATAK_PLUGIN | 72 |
52
+ | MAP_REPORT_APP | 73 |
53
+ | POWERSTRESS_APP | 74 |
54
+ | LORAWAN_BRIDGE | 75 |
55
+ | RETICULUM_TUNNEL_APP | 76 |
56
+ | CAYENNE_APP | 77 |
57
+ | ATAK_PLUGIN_V2 | 78 |
58
+ | LORA_OTA_APP | 79 |
59
+ | GROUPALARM_APP | 112 |
60
+ | PRIVATE_APP | 256 |
61
+ | ATAK_FORWARDER | 257 |
62
+ | MAX | 511 |
63
+
64
+ ## Related
65
+
66
+ - [Meshtastic::MeshInterface](mesh-interface.md)
67
+ - [Generated protobuf types](protobufs.md)
@@ -0,0 +1,34 @@
1
+ # Meshtastic::Position
2
+
3
+ Reopens the generated `Meshtastic::Position` protobuf class. Sends `POSITION_APP` (port 3). Latitude/longitude are scaled by 1e7.
4
+
5
+ Do not define class methods named `send` or `encode` on this class. Use `transmit` and `build`.
6
+
7
+ ## Methods
8
+
9
+ - `build(lat:, lon:, altitude:, time:)`
10
+ - `transmit` — deliver `POSITION_APP`
11
+ - `help` / `authors`
12
+
13
+ ## Example
14
+
15
+ ```ruby
16
+ Meshtastic::Position.transmit(
17
+ serial_obj: serial_obj,
18
+ lat: 37.7749,
19
+ lon: -122.4194,
20
+ altitude: 10
21
+ )
22
+
23
+ pos = Meshtastic::Position.build(lat: 37.7749, lon: -122.4194)
24
+ # pos.latitude_i == 377749000
25
+ ```
26
+
27
+ Same kwargs as other radio sends: `to:`, `channel:`, `want_ack:`, plus `bluetooth_obj:` / `tcp_obj:`.
28
+
29
+ Protobuf fields also include `location_source`, `ground_speed`, `sats_in_view`, `precision_bits`, and related GPS metadata. See [protobufs.md](protobufs.md).
30
+
31
+ ## Related
32
+
33
+ - [Meshtastic::Telemetry](telemetry.md)
34
+ - [Meshtastic::MeshInterface](mesh-interface.md)
@@ -0,0 +1,162 @@
1
+ # Generated protobuf types
2
+
3
+ These classes and enums come from `lib/meshtastic/*_pb.rb` (Meshtastic protobufs via `grpc_tools_ruby_protoc`). They live in the `Meshtastic` namespace. Typical API:
4
+
5
+ ```ruby
6
+ msg = Meshtastic::User.new(long_name: 'Node', short_name: 'N1')
7
+ bytes = msg.to_proto
8
+ again = Meshtastic::User.decode(bytes)
9
+ msg.to_h
10
+ ```
11
+
12
+ Enums: `Meshtastic::PortNum::TEXT_MESSAGE_APP`, `Meshtastic::PortNum.lookup(1)`, `Meshtastic::PortNum.resolve(:TEXT_MESSAGE_APP)`.
13
+
14
+ A few generated **classes** are reopened with extra class methods: `Channel`, `Config`, `ModuleConfig`, `Paxcount`, `Position`, `Telemetry`. Do not name those extras `send` or `encode`.
15
+
16
+ First-class wrappers for many of these types: [documentation index](README.md).
17
+
18
+ ## admin.proto
19
+
20
+ - Messages: `AdminMessage`, `AdminMessage::InputEvent`, `AdminMessage::OTAEvent`, `LockdownAuth`, `HamParameters`, `NodeRemoteHardwarePinsResponse`, `SharedContact`, `KeyVerificationAdmin`, `SensorConfig`, `SCD4X_config`, `SEN5X_config`, `SEN6X_config`, `SCD30_config`, `SHTXX_config`, `DS248X_config`, `AS3935_config`
21
+ - Enums: `AdminMessage::ConfigType`, `AdminMessage::ModuleConfigType`, `AdminMessage::BackupLocation`, `KeyVerificationAdmin::MessageType`, `OTAMode`
22
+
23
+ See [Admin](admin.md).
24
+
25
+ ## apponly.proto
26
+
27
+ - `ChannelSet` — [Apponly](apponly.md)
28
+
29
+ ## atak.proto
30
+
31
+ - Messages: `TAKPacket`, `GeoChat`, `Group`, `Status`, `Contact`, `PLI`, `AircraftTrack`, `CotGeoPoint`, `DrawnShape`, `Marker`, `RangeAndBearing`, `Route`, `Route::Link`, `CasevacReport`, `ZMistEntry`, `EmergencyAlert`, `TaskRequest`, `TAKEnvironment`, `SensorFov`, `TakTalkMessage`, `TakTalkRoomData`, `Marti`, `TAKPacketV2`
32
+ - Enums: `GeoChat::ReceiptType`, `DrawnShape::Kind`, `DrawnShape::StyleMode`, `Marker::Kind`, `Route::Method`, `Route::Direction`, `CasevacReport::Precedence`, `CasevacReport::HlzMarking`, `CasevacReport::Security`, `EmergencyAlert::Type`, `TaskRequest::Priority`, `TaskRequest::Status`, `SensorFov::SensorType`, `Team`, `MemberRole`, `CotHow`, `CotType`, `GeoPointSource`
33
+
34
+ See [ATAK](atak.md).
35
+
36
+ ## cannedmessages.proto
37
+
38
+ - `CannedMessageModuleConfig` — [Cannedmessages](cannedmessages.md)
39
+
40
+ ## channel.proto
41
+
42
+ - `ChannelSettings`, `ModuleSettings`, `Channel`, `Channel::Role` — [Channel](channel.md)
43
+
44
+ ## clientonly.proto
45
+
46
+ - `DeviceProfile` — [Clientonly](clientonly.md)
47
+
48
+ ## config.proto
49
+
50
+ - `Config` and nested `DeviceConfig`, `PositionConfig`, `PowerConfig`, `NetworkConfig`, `DisplayConfig`, `LoRaConfig`, `BluetoothConfig`, `SecurityConfig`, `SessionkeyConfig` plus their enums — [Config](config.md)
51
+
52
+ ## connection_status.proto
53
+
54
+ - `DeviceConnectionStatus`, `WifiConnectionStatus`, `EthernetConnectionStatus`, `NetworkConnectionStatus`, `BluetoothConnectionStatus`, `SerialConnectionStatus` — [ConnectionStatus](connection-status.md)
55
+
56
+ ## device_ui.proto
57
+
58
+ - `DeviceUIConfig`, `NodeFilter`, `NodeHighlight`, `GeoPoint`, `Map`
59
+ - Enums: `DeviceUIConfig::GpsCoordinateFormat`, `CompassMode`, `Theme`, `Language`
60
+
61
+ No dedicated wrapper; set via Admin `DEVICEUI_CONFIG` / `Config.device_ui`.
62
+
63
+ ## deviceonly.proto / deviceonly_legacy.proto
64
+
65
+ - `PositionLite`, `UserLite`, `NodeInfoLite`, `DeviceState`, `NodePositionEntry`, `NodeTelemetryEntry`, `NodeEnvironmentEntry`, `NodeStatusEntry`, `NodeDatabase`, `ChannelFile`, `BackupPreferences`
66
+ - Legacy: `NodeInfoLite_Legacy`, `NodeDatabase_Legacy`
67
+
68
+ See [Deviceonly](deviceonly.md).
69
+
70
+ ## interdevice.proto
71
+
72
+ - `FileTransfer`, `DirectoryListing`, `I2CTransaction`, `SdCardInfo`, `I2CResult`, `InterdeviceMessage`
73
+ - Enums: `SdCardInfo::CardType`, `SdCardInfo::FatType`, `I2CResult::Status`, `InterdeviceVersion`, `FileOperation`, `FileStatus`, `SdCommand`
74
+
75
+ No dedicated wrapper. Encode/decode the generated classes directly.
76
+
77
+ ## localonly.proto
78
+
79
+ - `LocalConfig`, `LocalModuleConfig` — [Localonly](localonly.md)
80
+
81
+ ## lorawan_bridge.proto
82
+
83
+ - `LoRaWANBridge` plus nested `Uplink`, `Downlink`, `PayloadChunk`, `TxResult`
84
+
85
+ No dedicated wrapper. Port `LORAWAN_BRIDGE` (75).
86
+
87
+ ## mesh_beacon.proto
88
+
89
+ - `MeshBeacon` — port `MESH_BEACON_APP` (37)
90
+
91
+ ## mesh.proto
92
+
93
+ Core radio types:
94
+
95
+ - `Position` ([Position](position.md)), `User`, `RouteDiscovery` ([Traceroute](traceroute.md)), `Routing`, `Data`, `KeyVerification`, `StoreForwardPlusPlus`, `RemoteShell`, `BoundingBox`, `Waypoint`, `StatusMessage`, `MqttClientProxyMessage`, `MeshPacket`, `NodeInfo`, `MyNodeInfo`, `LogRecord`, `QueueStatus`, `FromRadio`, `LockdownStatus`, `ClientNotification`, `KeyVerificationNumberInform`, `KeyVerificationNumberRequest`, `KeyVerificationFinal`, `DuplicatedPublicKey`, `LowEntropyKey`, `FileInfo`, `ToRadio`, `Compressed`, `NeighborInfo`, `Neighbor`, `DeviceMetadata`, `LoRaPresetGroup`, `LoRaRegionPresets`, `LoRaRegionPresetMap`, `Heartbeat`, `NodeRemoteHardwarePin`, `ChunkedPayload`, `resend_chunks`, `ChunkedPayloadResponse`
96
+ - Enums: `HardwareModel`, `Constants`, `CriticalErrorCode`, `FirmwareEdition`, `ExcludedModules`, plus nested enums on Position, Routing, MeshPacket, LogRecord, LockdownStatus, RemoteShell, StoreForwardPlusPlus
97
+
98
+ Serial/TCP frames carry `ToRadio` / `FromRadio`. MQTT publishes `ServiceEnvelope` wrapping `MeshPacket`.
99
+
100
+ ## module_config.proto
101
+
102
+ - `ModuleConfig` and nested MQTT/Serial/StoreForward/Telemetry/… configs — [ModuleConfig](module-config.md)
103
+ - `RemoteHardwarePin`, `RemoteHardwarePinType`
104
+
105
+ ## mqtt.proto
106
+
107
+ - `ServiceEnvelope`, `MapReport` — [MQTT](mqtt.md)
108
+
109
+ ## paxcount.proto
110
+
111
+ - `Paxcount` — [Paxcount](paxcount.md)
112
+
113
+ ## portnums.proto
114
+
115
+ - `PortNum` — [Portnums](portnums.md)
116
+
117
+ ## powermon.proto
118
+
119
+ - `PowerMon`, `PowerStressMessage` (and nested enums)
120
+
121
+ No dedicated wrapper. Port `POWERSTRESS_APP` (74).
122
+
123
+ ## remote_hardware.proto
124
+
125
+ - `HardwareMessage`, `HardwareMessage::Type` — [RemoteHardware](remote-hardware.md)
126
+
127
+ ## rtttl.proto
128
+
129
+ - `RTTTLConfig` — [RTTTL](rtttl.md)
130
+
131
+ ## serial_hal.proto
132
+
133
+ - `SerialHalCommand`, `SerialHalResponse`
134
+
135
+ GPIO serial HAL, not USB CDC. See [Serial](serial.md) for the USB Stream API.
136
+
137
+ ## storeforward.proto
138
+
139
+ - `StoreAndForward` plus `Statistics`, `History`, `Heartbeat`, `RequestResponse` — [Storeforward](storeforward.md)
140
+
141
+ ## telemetry.proto
142
+
143
+ - `Telemetry` ([Telemetry](telemetry.md)), `DeviceMetrics`, `EnvironmentMetrics`, `SoilWaterMetrics`, `PowerMetrics`, `AirQualityMetrics`, `LocalStats`, `TrafficManagementStats`, `HealthMetrics`, `HostMetrics`, `Nau7802Config`, `AS3935Config`, `SEN5XState`, `SEN6XState`, `TelemetrySensorType`
144
+
145
+ ## xmodem.proto
146
+
147
+ - `XModem`, `XModem::Control` — [Xmodem](xmodem.md)
148
+
149
+ ## nanopb
150
+
151
+ `require 'nanopb_pb'` is loaded with the gem. It is not a `Meshtastic::` module.
152
+
153
+ ## Example: inspect a type
154
+
155
+ ```ruby
156
+ require 'meshtastic'
157
+
158
+ Meshtastic::AdminMessage.descriptor.each { |f| puts f.name }
159
+ Meshtastic::PortNum.constants.sort
160
+ user = Meshtastic::User.new(long_name: 'Node', short_name: 'N1')
161
+ Meshtastic::User.decode(user.to_proto)
162
+ ```
@@ -0,0 +1,33 @@
1
+ # Meshtastic::RemoteHardware
2
+
3
+ GPIO control on `REMOTE_HARDWARE_APP` (port 2) using `Meshtastic::HardwareMessage`.
4
+
5
+ ## Methods
6
+
7
+ - `encode(type:, gpio_mask:, gpio_value:)`
8
+ - `send`
9
+ - `read_gpios(gpio_mask:)`
10
+ - `write_gpios(gpio_mask:, gpio_value:)`
11
+ - `watch_gpios(gpio_mask:)`
12
+ - `help` / `authors`
13
+
14
+ `type` values: `:UNSET`, `:WRITE_GPIOS`, `:WATCH_GPIOS`, `:GPIOS_CHANGED`, `:READ_GPIOS`, `:READ_GPIOS_REPLY`.
15
+
16
+ ## Example
17
+
18
+ ```ruby
19
+ Meshtastic::RemoteHardware.write_gpios(
20
+ serial_obj: serial_obj,
21
+ gpio_mask: 0x01,
22
+ gpio_value: 0x01
23
+ )
24
+
25
+ Meshtastic::RemoteHardware.read_gpios(serial_obj: serial_obj, gpio_mask: 0x01)
26
+ Meshtastic::RemoteHardware.watch_gpios(serial_obj: serial_obj, gpio_mask: 0x01)
27
+ ```
28
+
29
+ Enable the Remote Hardware module on the node and only drive pins the firmware exposes.
30
+
31
+ ## Related
32
+
33
+ - [Meshtastic::ModuleConfig](module-config.md)
@@ -0,0 +1,24 @@
1
+ # Meshtastic::RTTTL
2
+
3
+ Ringtone helpers. `encode` builds `RTTTLConfig`. `set` / `get` go through [Admin](admin.md) (`set_ringtone_message` / `get_ringtone_request`).
4
+
5
+ ## Methods
6
+
7
+ - `encode(ringtone:)`
8
+ - `set(serial_obj:, ringtone:)`
9
+ - `get(serial_obj:)`
10
+ - `help` / `authors`
11
+
12
+ ## Example
13
+
14
+ ```ruby
15
+ Meshtastic::RTTTL.set(
16
+ serial_obj: serial_obj,
17
+ ringtone: 'Mario:d=4,o=5,b=125:16e6'
18
+ )
19
+ Meshtastic::RTTTL.get(serial_obj: serial_obj)
20
+ ```
21
+
22
+ ## Related
23
+
24
+ - [Meshtastic::Admin](admin.md)
@@ -0,0 +1,78 @@
1
+ # Meshtastic::Serial
2
+
3
+ USB/UART Stream API. Framing is `[0x94][0xC3][len_hi][len_lo]` plus a `ToRadio` / `FromRadio` protobuf.
4
+
5
+ The radio applies channel crypto. Payloads go out decoded. `channel:` is the device channel index (usually `0`), not an MQTT hash.
6
+
7
+ ## Setup
8
+
9
+ Use the USB CDC port (`/dev/ttyACM*` or `/dev/ttyUSB*`). Enable Radio Configuration → Security → Serial Console (`security.serial_enabled`). That is not Module Configuration → Serial (`TEXTMSG` / `PROTO` on GPIO). Keep “Override Console Serial Port” off.
10
+
11
+ Do not open Serial and Bluetooth to the same radio at once.
12
+
13
+ ## Methods
14
+
15
+ - `connect(block_dev:, baud:, data_bits:, stop_bits:, parity:, debug_out:, want_config:)`
16
+ - `wait_for_config(serial_obj:, timeout:)` — raises `Timeout::Error` if handshake never completes
17
+ - `wake_up_device` — writes 32 × `START2`
18
+ - `request` — raw bytes
19
+ - `send_to_radio` — framed `ToRadio`
20
+ - `send_text` / `send_data`
21
+ - `recv_from_radio(timeout:)` — `0` polls, `nil` blocks, default `5`. Closed empty queue → `nil`. Unplug → `IOError`
22
+ - `drain_from_radio`
23
+ - `dump_stdout_data` / `flush_data` / `monitor_stdout` (`:proto` or `:console`)
24
+ - `subscribe` — blocking FromRadio loop
25
+ - `disconnect`
26
+ - `help` / `authors`
27
+
28
+ `send_text` / `send_data` return bytes written, not mesh delivery. `want_ack: true` asks for `ROUTING_APP` (`error_reason: NONE` means the local radio accepted the route). Incoming text is UTF-8 under `message[:packet][:decoded][:payload]`.
29
+
30
+ Call `wait_for_config` before using `my_node_num` or sending. Opening a port is not a completed handshake.
31
+
32
+ ## Send / receive
33
+
34
+ ```ruby
35
+ require 'meshtastic'
36
+
37
+ serial_obj = nil
38
+ begin
39
+ serial_obj = Meshtastic::Serial.connect(block_dev: '/dev/ttyACM0', baud: 115_200)
40
+ Meshtastic::Serial.wait_for_config(serial_obj: serial_obj, timeout: 10)
41
+ puts "local node: !#{serial_obj[:my_node_num].to_s(16)}"
42
+
43
+ Meshtastic::Serial.send_text(
44
+ serial_obj: serial_obj,
45
+ to: '!aabbccdd', # or '!ffffffff' for the shared channel
46
+ channel: 0,
47
+ text: 'Hello over serial!',
48
+ want_ack: true
49
+ )
50
+
51
+ Meshtastic::Serial.subscribe(
52
+ serial_obj: serial_obj,
53
+ include: 'TEXT_MESSAGE_APP'
54
+ ) do |message|
55
+ packet = message[:packet]
56
+ puts "#{packet[:node_id_from]}: #{packet.dig(:decoded, :payload)}"
57
+ end
58
+ ensure
59
+ Meshtastic::Serial.disconnect(serial_obj: serial_obj)
60
+ end
61
+ ```
62
+
63
+ Drive the loop yourself:
64
+
65
+ ```ruby
66
+ from_radio = Meshtastic::Serial.recv_from_radio(serial_obj: serial_obj, timeout: 0)
67
+ msgs = Meshtastic::Serial.drain_from_radio(serial_obj: serial_obj, max: 256)
68
+ ```
69
+
70
+ If `wait_for_config` times out, the USB path is up but the Stream API is not (wrong port, Serial Console disabled, or firmware not responding).
71
+
72
+ Default `block_dev` is `/dev/ttyUSB0`, baud `115200`, 8N1.
73
+
74
+ ## Related
75
+
76
+ - [Meshtastic::TCP](tcp.md) (same framing)
77
+ - [Meshtastic::Bluetooth](bluetooth.md)
78
+ - [Meshtastic::Admin](admin.md)
@@ -0,0 +1,24 @@
1
+ # Meshtastic::Storeforward
2
+
3
+ Sends `Meshtastic::StoreAndForward` on `STORE_FORWARD_APP` (port 65).
4
+
5
+ ## Methods
6
+
7
+ - `encode(rr:)` — request/response enum, default `:ROUTER_HEARTBEAT`
8
+ - `send`
9
+ - `help` / `authors`
10
+
11
+ `rr` includes values such as `:CLIENT_HISTORY`, `:ROUTER_HEARTBEAT`.
12
+
13
+ ## Example
14
+
15
+ ```ruby
16
+ Meshtastic::Storeforward.send(
17
+ serial_obj: serial_obj,
18
+ rr: :CLIENT_HISTORY
19
+ )
20
+ ```
21
+
22
+ ## Related
23
+
24
+ - [Meshtastic::ModuleConfig](module-config.md) (`:STOREFORWARD_CONFIG`)