meshtastic 0.0.178 → 0.0.180

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -175
  3. data/documentation/README.md +60 -0
  4. data/documentation/admin-channel.md +33 -0
  5. data/documentation/admin-config.md +28 -0
  6. data/documentation/admin-firmware.md +69 -0
  7. data/documentation/admin.md +55 -0
  8. data/documentation/apponly.md +22 -0
  9. data/documentation/atak.md +110 -0
  10. data/documentation/bluetooth-bluez.md +35 -0
  11. data/documentation/bluetooth.md +87 -0
  12. data/documentation/cannedmessages.md +25 -0
  13. data/documentation/channel.md +3 -0
  14. data/documentation/clientonly.md +21 -0
  15. data/documentation/config.md +3 -0
  16. data/documentation/connection-status.md +22 -0
  17. data/documentation/deviceonly.md +22 -0
  18. data/documentation/localonly.md +21 -0
  19. data/documentation/mesh-interface.md +52 -0
  20. data/documentation/meshtastic.md +45 -0
  21. data/documentation/module-config.md +26 -0
  22. data/documentation/mqtt.md +101 -0
  23. data/documentation/paxcount.md +25 -0
  24. data/documentation/portnums.md +67 -0
  25. data/documentation/position.md +34 -0
  26. data/documentation/protobufs.md +162 -0
  27. data/documentation/remote-hardware.md +33 -0
  28. data/documentation/rtttl.md +24 -0
  29. data/documentation/serial.md +78 -0
  30. data/documentation/storeforward.md +24 -0
  31. data/documentation/stream-interface.md +15 -0
  32. data/documentation/tcp.md +43 -0
  33. data/documentation/telemetry.md +32 -0
  34. data/documentation/traceroute.md +28 -0
  35. data/documentation/util.md +27 -0
  36. data/documentation/xmodem.md +22 -0
  37. data/lib/meshtastic/admin/channel.rb +90 -0
  38. data/lib/meshtastic/admin/config.rb +154 -0
  39. data/lib/meshtastic/admin/firmware.rb +173 -0
  40. data/lib/meshtastic/admin.rb +495 -7
  41. data/lib/meshtastic/apponly.rb +26 -8
  42. data/lib/meshtastic/atak.rb +298 -7
  43. data/lib/meshtastic/bluetooth/bluez.rb +20 -1
  44. data/lib/meshtastic/bluetooth.rb +70 -59
  45. data/lib/meshtastic/cannedmessages.rb +23 -8
  46. data/lib/meshtastic/channel.rb +3 -21
  47. data/lib/meshtastic/clientonly.rb +26 -8
  48. data/lib/meshtastic/config.rb +3 -21
  49. data/lib/meshtastic/connection_status.rb +13 -8
  50. data/lib/meshtastic/deviceonly.rb +23 -8
  51. data/lib/meshtastic/localonly.rb +23 -8
  52. data/lib/meshtastic/mesh_interface.rb +11 -0
  53. data/lib/meshtastic/module_config.rb +18 -9
  54. data/lib/meshtastic/mqtt.rb +72 -35
  55. data/lib/meshtastic/paxcount.rb +30 -9
  56. data/lib/meshtastic/portnums.rb +18 -8
  57. data/lib/meshtastic/position.rb +45 -0
  58. data/lib/meshtastic/remote_hardware.rb +50 -9
  59. data/lib/meshtastic/rtttl.rb +26 -8
  60. data/lib/meshtastic/serial.rb +81 -70
  61. data/lib/meshtastic/storeforward.rb +23 -8
  62. data/lib/meshtastic/stream_interface.rb +11 -0
  63. data/lib/meshtastic/tcp.rb +153 -0
  64. data/lib/meshtastic/telemetry.rb +27 -9
  65. data/lib/meshtastic/traceroute.rb +42 -0
  66. data/lib/meshtastic/util.rb +3 -1
  67. data/lib/meshtastic/version.rb +1 -1
  68. data/lib/meshtastic/xmodem.rb +17 -8
  69. data/lib/meshtastic.rb +46 -6
  70. data/spec/conventions_spec.rb +321 -0
  71. data/spec/lib/meshtastic/admin/channel_spec.rb +45 -0
  72. data/spec/lib/meshtastic/admin/config_spec.rb +48 -0
  73. data/spec/lib/meshtastic/admin/firmware_spec.rb +118 -0
  74. data/spec/lib/meshtastic/admin_pb_spec.rb +1 -1
  75. data/spec/lib/meshtastic/admin_spec.rb +79 -0
  76. data/spec/lib/meshtastic/apponly_pb_spec.rb +1 -1
  77. data/spec/lib/meshtastic/apponly_spec.rb +4 -0
  78. data/spec/lib/meshtastic/atak_pb_spec.rb +1 -1
  79. data/spec/lib/meshtastic/atak_spec.rb +147 -0
  80. data/spec/lib/meshtastic/bluetooth_spec.rb +1 -1
  81. data/spec/lib/meshtastic/cannedmessages_pb_spec.rb +1 -1
  82. data/spec/lib/meshtastic/cannedmessages_spec.rb +3 -0
  83. data/spec/lib/meshtastic/channel_pb_spec.rb +1 -1
  84. data/spec/lib/meshtastic/channel_spec.rb +3 -0
  85. data/spec/lib/meshtastic/clientonly_pb_spec.rb +1 -1
  86. data/spec/lib/meshtastic/clientonly_spec.rb +5 -0
  87. data/spec/lib/meshtastic/config_pb_spec.rb +1 -1
  88. data/spec/lib/meshtastic/config_spec.rb +4 -1
  89. data/spec/lib/meshtastic/connection_status_pb_spec.rb +1 -1
  90. data/spec/lib/meshtastic/connection_status_spec.rb +3 -0
  91. data/spec/lib/meshtastic/deviceonly_legacy_pb_spec.rb +1 -1
  92. data/spec/lib/meshtastic/deviceonly_pb_spec.rb +1 -1
  93. data/spec/lib/meshtastic/deviceonly_spec.rb +3 -0
  94. data/spec/lib/meshtastic/localonly_pb_spec.rb +1 -1
  95. data/spec/lib/meshtastic/localonly_spec.rb +3 -0
  96. data/spec/lib/meshtastic/mesh_beacon_pb_spec.rb +1 -1
  97. data/spec/lib/meshtastic/mesh_pb_spec.rb +1 -1
  98. data/spec/lib/meshtastic/module_config_pb_spec.rb +1 -1
  99. data/spec/lib/meshtastic/module_config_spec.rb +21 -0
  100. data/spec/lib/meshtastic/mqtt_pb_spec.rb +1 -1
  101. data/spec/lib/meshtastic/paxcount_pb_spec.rb +1 -1
  102. data/spec/lib/meshtastic/paxcount_spec.rb +23 -0
  103. data/spec/lib/meshtastic/portnums_pb_spec.rb +1 -1
  104. data/spec/lib/meshtastic/portnums_spec.rb +4 -0
  105. data/spec/lib/meshtastic/position_spec.rb +33 -0
  106. data/spec/lib/meshtastic/remote_hardware_pb_spec.rb +1 -1
  107. data/spec/lib/meshtastic/remote_hardware_spec.rb +24 -0
  108. data/spec/lib/meshtastic/rtttl_pb_spec.rb +1 -1
  109. data/spec/lib/meshtastic/rtttl_spec.rb +21 -0
  110. data/spec/lib/meshtastic/storeforward_pb_spec.rb +1 -1
  111. data/spec/lib/meshtastic/storeforward_spec.rb +21 -0
  112. data/spec/lib/meshtastic/tcp_spec.rb +48 -0
  113. data/spec/lib/meshtastic/telemetry_pb_spec.rb +1 -1
  114. data/spec/lib/meshtastic/telemetry_spec.rb +21 -0
  115. data/spec/lib/meshtastic/traceroute_spec.rb +27 -0
  116. data/spec/lib/meshtastic/xmodem_pb_spec.rb +1 -1
  117. data/spec/lib/meshtastic/xmodem_spec.rb +6 -1
  118. data/spec/lib/meshtastic_spec.rb +3 -0
  119. metadata +48 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89ae445ffe5b5a92527ac776eefac452593bdd34473a325c6048d8b19d3b7d9a
4
- data.tar.gz: b3173a5209a3b9efefad113218573f399bb2f62ae794c037a1f5ea9c4ba24ed7
3
+ metadata.gz: f12d73c0e68d9f1171a2b92d2cfe2277d22e4e78c7c33788cc52924ee6d40778
4
+ data.tar.gz: b0be149633c2a659dcea3ce83546f9a2ea5121f632a90bb3ee9b21a43ae79221
5
5
  SHA512:
6
- metadata.gz: 2e94b436cb0340c13a372e1e11c3cb85b9f26303ed2e7d667ba754eb205e30a84383894b494904d548b4d86bcce2c8a245fd85b03fd42b4a9e9c4d64de2cc696
7
- data.tar.gz: 4d784f09138ee9ecf2c9fde1503adf3974b651a82a35e5f96ed3cb64109ecd9ceae007e582ca3e3b208fb0a2e574d9e9f11a3c1c5fd584518d199cd9c14ec3b3
6
+ metadata.gz: a4d41dbc793a0eb380cbfb815ce9cd15ac98802e80a3903ea7ed765d09c42ff9a4009a2d68ff44338026e553f18fd7d96d4419233018185ff3f733735b033149
7
+ data.tar.gz: d035c8f9c42d536ad97bdefc0de870dff4694ef651c86dd1e7002ada63145f089e9e70a74d73144ebac991d0d9dd8365f5c53ae0b0b6154c466d99f849e4b34a
data/README.md CHANGED
@@ -24,185 +24,13 @@ If bundler is not being used to manage dependencies, install the gem by executin
24
24
 
25
25
  ## Usage
26
26
 
27
- The primary interaction modules today are `Meshtastic::MQTT` (broker), `Meshtastic::Serial` (USB/UART), and `Meshtastic::Bluetooth` (BLE via Linux BlueZ). Examples for each follow.
28
-
29
- ### MQTT
30
-
31
- To view MQTT messages, and include only messages containing `_APP` _and_ `LongFast` strings, use the following code:
32
-
33
- ```ruby
34
- require 'meshtastic'
35
- Meshtastic::MQTT.help
36
- mqtt_obj = Meshtastic::MQTT.connect
37
- puts mqtt_obj.inspect
38
- Meshtastic::MQTT.subscribe(
39
- mqtt_obj: mqtt_obj,
40
- include: '_APP, LongFast'
41
- )
42
- ```
43
-
44
- This code will dump the contents of every message:
45
-
46
- ```ruby
47
- require 'meshtastic'
48
- mqtt_obj = Meshtastic::MQTT.connect
49
- Meshtastic::MQTT.subscribe(
50
- mqtt_obj: mqtt_obj,
51
- root_topic: 'msh',
52
- region: 'US',
53
- topic: '2/e/LongFast/#',
54
- psks: { LongFast: 'AQ==' }
55
- ) do |message|
56
- puts message.inspect
57
- end
58
- ```
59
-
60
- Sending a message over MQTT:
61
-
62
- ```ruby
63
- require 'meshtastic'
64
- mqtt_obj = Meshtastic::MQTT.connect
65
- client_id = "!#{mqtt_obj.client_id}"
66
- Meshtastic::MQTT.send_text(
67
- mqtt_obj: mqtt_obj,
68
- from: client_id,
69
- to: '!ffffffff',
70
- root_topic: 'msh',
71
- region: 'US',
72
- topic: '2/e/LongFast/#',
73
- channel: 93,
74
- text: 'Hello, World!',
75
- psks: { LongFast: 'AQ==' }
76
- )
77
- ```
78
-
79
- One of the "gotchas" when sending messages is ensuring you're sending over the proper integer for the `channel` parameter. The best way to determine the proper `channel` value is by sending a test message from within the meshtastic app and then viewing the MQTT message similar to the following:
27
+ All usage examples live under [documentation/](documentation/README.md): transports (MQTT, Serial, Bluetooth, TCP), Admin and other feature modules, internals, and generated protobuf types.
80
28
 
81
29
  ```ruby
82
30
  require 'meshtastic'
83
- mqtt_obj = Meshtastic::MQTT.connect
84
- Meshtastic::MQTT.subscribe(
85
- mqtt_obj: mqtt_obj,
86
- root_topic: 'msh',
87
- region: 'US',
88
- topic: '2/e/LongFast/#',
89
- psks: { LongFast: 'AQ==' },
90
- include: '!YOUR_CLIENT_ID'
91
- ) do |message|
92
- puts message.inspect
93
- end
94
- ```
95
-
96
- You should see something like this:
97
-
31
+ Meshtastic.help # constants in the namespace
32
+ Meshtastic::Serial.help # methods for one module
98
33
  ```
99
- {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"}
100
- ```
101
-
102
- Note where is says `channel: 93`. This is the `channel` value required to send messages in this particular example.
103
-
104
- ### Serial and Bluetooth (send / receive)
105
-
106
- `Meshtastic::Serial` (USB/UART) and `Meshtastic::Bluetooth` (Linux BLE via BlueZ) talk to a local radio using the same client API. The radio encrypts with its configured channel keys. Payloads are sent decoded; `channel:` is the index on the device, not an MQTT channel hash.
107
-
108
- Do not open Serial and Bluetooth to the same radio at once. Disconnect when finished (`ensure` is the reliable pattern). `send_text` / `send_data` report bytes written, not mesh delivery. `want_ack: true` requests a `ROUTING_APP` acknowledgment (`error_reason: NONE` means the local radio accepted the route). Incoming text is a UTF-8 string under `message[:packet][:decoded][:payload]`.
109
-
110
- Call `wait_for_config` before using `my_node_num` or sending. It raises `Timeout::Error` if the firmware never completes the handshake. Opening a port or pairing is not the same as a completed handshake.
111
-
112
- #### Serial (`Meshtastic::Serial`)
113
-
114
- Use the device’s 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.
115
-
116
- ```ruby
117
- require 'meshtastic'
118
-
119
- serial_obj = nil
120
- begin
121
- serial_obj = Meshtastic::Serial.connect(block_dev: '/dev/ttyACM0', baud: 115_200)
122
- Meshtastic::Serial.wait_for_config(serial_obj: serial_obj, timeout: 10)
123
- puts "local node: !#{serial_obj[:my_node_num].to_s(16)}"
124
-
125
- # Direct message, or to: '!ffffffff' for the shared channel.
126
- Meshtastic::Serial.send_text(
127
- serial_obj: serial_obj,
128
- to: '!aabbccdd',
129
- channel: 0,
130
- text: 'Hello over serial!',
131
- want_ack: true
132
- )
133
-
134
- Meshtastic::Serial.subscribe(
135
- serial_obj: serial_obj,
136
- include: 'TEXT_MESSAGE_APP'
137
- ) do |message|
138
- packet = message[:packet]
139
- puts "#{packet[:node_id_from]}: #{packet.dig(:decoded, :payload)}"
140
- end
141
- ensure
142
- Meshtastic::Serial.disconnect(serial_obj: serial_obj)
143
- end
144
- ```
145
-
146
- Drive the loop yourself with `recv_from_radio(serial_obj:, timeout:)` (`0` polls, `nil` blocks) or `drain_from_radio`. A closed empty queue returns `nil`; an unplugged device raises `IOError`. 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).
147
-
148
- #### Bluetooth (`Meshtastic::Bluetooth`)
149
-
150
- Linux only (BlueZ + `ruby-dbus`). Connect with a BLE address (`AA:BB:CC:DD:EE:FF`), not a mesh id (`!11223344`). Pair first; this gem does not guess a PIN. BLE writes unframed ToRadio protobufs (no UART `0x94 0xC3` header).
151
-
152
- Scan:
153
-
154
- ```ruby
155
- require 'meshtastic'
156
- Meshtastic::Bluetooth.scan(adapter: 'hci0', timeout: 5)
157
- # => [{ address: 'AA:BB:CC:DD:EE:FF', name: 'Meshtastic_eeff', paired: true }, ...]
158
- ```
159
-
160
- Pair while discovery is running. Screen devices typically show a random 6-digit PIN:
161
-
162
- ```text
163
- bluetoothctl
164
- agent KeyboardDisplay
165
- default-agent
166
- scan on
167
- pair AA:BB:CC:DD:EE:FF
168
- trust AA:BB:CC:DD:EE:FF
169
- scan off
170
- quit
171
- ```
172
-
173
- `Failed to pair: AuthenticationFailed` means the agent never got the PIN. `Device … not available` means scan first; the advertisement dropped.
174
-
175
- Send and receive (same options as Serial, `bluetooth_obj:` instead of `serial_obj:`):
176
-
177
- ```ruby
178
- require 'meshtastic'
179
-
180
- bluetooth_obj = nil
181
- begin
182
- bluetooth_obj = Meshtastic::Bluetooth.connect(address: 'AA:BB:CC:DD:EE:FF')
183
- Meshtastic::Bluetooth.wait_for_config(bluetooth_obj: bluetooth_obj, timeout: 30)
184
-
185
- Meshtastic::Bluetooth.send_text(
186
- bluetooth_obj: bluetooth_obj,
187
- to: '!aabbccdd',
188
- channel: 0,
189
- text: 'Hello over BLE!',
190
- want_ack: true
191
- )
192
-
193
- Meshtastic::Bluetooth.subscribe(
194
- bluetooth_obj: bluetooth_obj,
195
- include: 'TEXT_MESSAGE_APP'
196
- ) do |message|
197
- packet = message[:packet]
198
- puts "#{packet[:node_id_from]}: #{packet.dig(:decoded, :payload)}"
199
- end
200
- ensure
201
- Meshtastic::Bluetooth.disconnect(bluetooth_obj: bluetooth_obj)
202
- end
203
- ```
204
-
205
- Disconnect the phone’s Meshtastic BLE session while Linux is connected. After an aborted reconnect (`le-connection-abort-by-local`), `bluetoothctl disconnect <addr>` and wait a couple of seconds before `connect` again. Config dumps over BLE can take longer than serial; 30 seconds is a reasonable `wait_for_config` timeout.
206
34
 
207
35
  ## Contributing
208
36
 
@@ -0,0 +1,60 @@
1
+ # Meshtastic Ruby documentation
2
+
3
+ Usage for every constant in the `Meshtastic` namespace lives here. The root [README](../README.md) is install, expectations, and contributing only.
4
+
5
+ `require 'meshtastic'` then `Meshtastic.help` lists loaded constants. Each first-class API module also has `.help` and `.authors`.
6
+
7
+ Examples use placeholder addresses only:
8
+
9
+ - Serial port: `/dev/ttyACM0`
10
+ - BLE: `AA:BB:CC:DD:EE:FF`
11
+ - Mesh node: `!aabbccdd` (destination), `!11223344` (local)
12
+ - MQTT sample node: `!c0ffee00`
13
+ - TCP radio: `192.0.2.10`
14
+ - Broadcast: `!ffffffff` (protocol all-nodes address)
15
+
16
+ ## Transports
17
+
18
+ - [Meshtastic::MQTT](mqtt.md)
19
+ - [Meshtastic::Serial](serial.md)
20
+ - [Meshtastic::Bluetooth](bluetooth.md)
21
+ - [Meshtastic::Bluetooth::BlueZ](bluetooth-bluez.md)
22
+ - [Meshtastic::TCP](tcp.md)
23
+
24
+ Feature modules send protobufs over Serial, Bluetooth, or TCP via `Meshtastic.deliver_data`. Pass `serial_obj:`, `bluetooth_obj:`, or `tcp_obj:`. MQTT encrypts on the host; the radio encrypts on the other three.
25
+
26
+ Do not open Serial and Bluetooth to the same radio at once. Always `disconnect` in `ensure`.
27
+
28
+ ## Feature modules
29
+
30
+ - [Meshtastic::Admin](admin.md)
31
+ - [Meshtastic::Admin::Channel](admin-channel.md)
32
+ - [Meshtastic::Admin::Config](admin-config.md)
33
+ - [Meshtastic::Admin::Firmware](admin-firmware.md)
34
+ - [Meshtastic::ModuleConfig](module-config.md)
35
+ - [Meshtastic::Position](position.md)
36
+ - [Meshtastic::Telemetry](telemetry.md)
37
+ - [Meshtastic::Traceroute](traceroute.md)
38
+ - [Meshtastic::RemoteHardware](remote-hardware.md)
39
+ - [Meshtastic::Storeforward](storeforward.md)
40
+ - [Meshtastic::ATAK](atak.md)
41
+ - [Meshtastic::Paxcount](paxcount.md)
42
+ - [Meshtastic::Cannedmessages](cannedmessages.md)
43
+ - [Meshtastic::RTTTL](rtttl.md)
44
+ - [Meshtastic::Portnums](portnums.md)
45
+ - [Meshtastic::Apponly](apponly.md)
46
+ - [Meshtastic::Clientonly](clientonly.md)
47
+ - [Meshtastic::Deviceonly](deviceonly.md)
48
+ - [Meshtastic::Localonly](localonly.md)
49
+ - [Meshtastic::ConnectionStatus](connection-status.md)
50
+ - [Meshtastic::Xmodem](xmodem.md)
51
+
52
+ ## Internals
53
+
54
+ - [Meshtastic (top-level)](meshtastic.md)
55
+ - [Meshtastic::MeshInterface](mesh-interface.md)
56
+ - [Meshtastic::StreamInterface](stream-interface.md)
57
+ - [Meshtastic::Util](util.md)
58
+ - [Generated protobuf types](protobufs.md)
59
+
60
+ Protobuf message classes that this gem reopens (`Channel`, `Config`, `Position`, `Telemetry`, `ModuleConfig`, `Paxcount`) must not define class methods named `send` or `encode` (those belong to protobuf). Use `get`/`set`, `transmit`, `build`, or `request` instead.
@@ -0,0 +1,33 @@
1
+ # Meshtastic::Admin::Channel
2
+
3
+ Admin get/set for mesh channels. The generated protobuf remains `Meshtastic::Channel`; this module talks to the node on `ADMIN_APP`.
4
+
5
+ Roles: `:PRIMARY`, `:SECONDARY`, `:DISABLED`.
6
+
7
+ ## Methods
8
+
9
+ - `build_settings` — `ChannelSettings` (name, psk, uplink/downlink, AEAD)
10
+ - `build` — `Channel` (index, role, settings)
11
+ - `get(index:)` — `get_channel_request`
12
+ - `set` — `set_channel` with a Channel protobuf
13
+ - `help` / `authors`
14
+
15
+ Do not pass a Channel protobuf as MeshInterface `channel:` (that field is the numeric channel index). This module strips that key before send.
16
+
17
+ ## Example
18
+
19
+ ```ruby
20
+ settings = Meshtastic::Admin::Channel.build_settings(name: 'LongFast', uplink_enabled: true)
21
+ Meshtastic::Admin::Channel.set(
22
+ serial_obj: serial_obj,
23
+ index: 0,
24
+ role: :PRIMARY,
25
+ settings: settings
26
+ )
27
+ Meshtastic::Admin::Channel.get(serial_obj: serial_obj, index: 0)
28
+ ```
29
+
30
+ ## Related
31
+
32
+ - [Meshtastic::Admin](admin.md)
33
+ - [Meshtastic::Admin::Config](admin-config.md)
@@ -0,0 +1,28 @@
1
+ # Meshtastic::Admin::Config
2
+
3
+ Admin get/set for radio `Meshtastic::Config` sections. The generated protobuf remains `Meshtastic::Config`.
4
+
5
+ ## Methods
6
+
7
+ - `get(config_type:)` — default `:DEVICE_CONFIG`
8
+ - `set(config:)`
9
+ - Named getters: `get_device`, `get_position`, `get_power`, `get_network`, `get_display`, `get_lora`, `get_bluetooth`, `get_security`, `get_sessionkey`, `get_device_ui`
10
+ - `set_device(device:)`, `set_lora(lora:)`
11
+ - `help` / `authors`
12
+
13
+ `config_type` values: `:DEVICE_CONFIG`, `:POSITION_CONFIG`, `:POWER_CONFIG`, `:NETWORK_CONFIG`, `:DISPLAY_CONFIG`, `:LORA_CONFIG`, `:BLUETOOTH_CONFIG`, `:SECURITY_CONFIG`, `:SESSIONKEY_CONFIG`, `:DEVICEUI_CONFIG`.
14
+
15
+ ## Example
16
+
17
+ ```ruby
18
+ Meshtastic::Admin::Config.get_lora(serial_obj: serial_obj)
19
+
20
+ config = Meshtastic::Config.new
21
+ config.device = Meshtastic::Config::DeviceConfig.new(role: :CLIENT)
22
+ Meshtastic::Admin::Config.set(serial_obj: serial_obj, config: config)
23
+ ```
24
+
25
+ ## Related
26
+
27
+ - [Meshtastic::Admin](admin.md)
28
+ - [Meshtastic::Admin::Channel](admin-channel.md)
@@ -0,0 +1,69 @@
1
+ # Meshtastic::Admin::Firmware
2
+
3
+ Install Meshtastic firmware using the PhoneAPI / admin path (not esptool). Nested under [Admin](admin.md) because OTA is an `AdminMessage`.
4
+
5
+ ## What it does
6
+
7
+ 1. SHA-256 the image (`-update.bin` for ESP32 BLE/WiFi OTA).
8
+ 2. Send `ota_request` (`OTAEvent`: 32-byte hash + `:OTA_BLE` or `:OTA_WIFI`) on `ADMIN_APP`.
9
+ 3. On serial / TCP / Bluetooth, stream the image as `ToRadio.xmodemPacket` (SOH 128-byte blocks, CRC16, EOT). MQTT has no PhoneAPI XModem; it only publishes the admin `ota_request` so the node can reboot into OTA.
10
+
11
+ `enter_dfu` sends `enter_dfu_mode_request` (nRF52 USB UF2 / serial DFU). `reboot_ota(seconds:)` is the older `reboot_ota_seconds` field.
12
+
13
+ Use a firmware file that matches the board. Interrupting a flash can brick the radio. Keep battery high.
14
+
15
+ This is not the web flasher / `esptool` USB bootloader path, and not nRF `.zip` via `adafruit-nrfutil`.
16
+
17
+ ## Methods
18
+
19
+ - `install(firmware:, mode:, serial_obj: | tcp_obj: | bluetooth_obj: | mqtt_obj:)`
20
+ - `request_ota` — admin hash + mode only
21
+ - `enter_dfu`
22
+ - `reboot_ota(seconds: 10)`
23
+ - `xmodem_blocks(bytes)` / `send_xmodem(xmodem:)`
24
+ - `sha256`
25
+ - `help` / `authors`
26
+
27
+ `mode:` is `:OTA_BLE` or `:OTA_WIFI`. `firmware:` is a path; `bytes:` is raw image bytes.
28
+
29
+ ## Serial / TCP / Bluetooth
30
+
31
+ ```ruby
32
+ Meshtastic::Admin::Firmware.install(
33
+ serial_obj: serial_obj,
34
+ firmware: 'firmware-heltec-v3-update.bin',
35
+ mode: :OTA_BLE
36
+ )
37
+
38
+ Meshtastic::Admin::Firmware.install(
39
+ tcp_obj: tcp_obj,
40
+ firmware: 'firmware-heltec-v3-update.bin',
41
+ mode: :OTA_WIFI
42
+ )
43
+
44
+ Meshtastic::Admin::Firmware.install(
45
+ bluetooth_obj: bluetooth_obj,
46
+ firmware: 'firmware-heltec-v3-update.bin',
47
+ mode: :OTA_BLE
48
+ )
49
+ ```
50
+
51
+ ## MQTT (remote admin)
52
+
53
+ Publishes one encrypted `ADMIN_APP` envelope. The node must accept remote admin. It does not push XModem over the broker.
54
+
55
+ ```ruby
56
+ Meshtastic::Admin::Firmware.install(
57
+ mqtt_obj: mqtt_obj,
58
+ firmware: 'firmware-heltec-v3-update.bin',
59
+ mode: :OTA_WIFI,
60
+ to: '!aabbccdd',
61
+ psks: { LongFast: 'AQ==' }
62
+ )
63
+ ```
64
+
65
+ ## Related
66
+
67
+ - [Meshtastic::Admin](admin.md)
68
+ - [Meshtastic::Xmodem](xmodem.md)
69
+ - [Meshtastic::MQTT](mqtt.md)
@@ -0,0 +1,55 @@
1
+ # Meshtastic::Admin
2
+
3
+ Builds `Meshtastic::AdminMessage` and sends it on `ADMIN_APP` (port 6) through [Meshtastic.deliver_data](meshtastic.md). Pass a connected `serial_obj`, `bluetooth_obj`, `tcp_obj`, or `mqtt_obj`.
4
+
5
+ Responses come back as `FromRadio` packets on the same transport (`subscribe` / `recv_from_radio`).
6
+
7
+ ## Methods
8
+
9
+ - `encode` — copies matching keys onto an `AdminMessage`
10
+ - `send` — wrap and deliver (`want_response` default true)
11
+ - `reboot(seconds: 5)`
12
+ - `shutdown(seconds: 5)`
13
+ - `get_owner` / `set_owner(long_name:, short_name:, owner:)`
14
+ - `get_channel(index:)` / `set_channel(channel_settings:)`
15
+ - `get_config(config_type:)` / `set_config(config:)`
16
+ - `nodedb_reset`
17
+ - `help` / `authors`
18
+
19
+ `config_type` values: `:DEVICE_CONFIG`, `:POSITION_CONFIG`, `:POWER_CONFIG`, `:NETWORK_CONFIG`, `:DISPLAY_CONFIG`, `:LORA_CONFIG`, `:BLUETOOTH_CONFIG`, `:SECURITY_CONFIG`, `:SESSIONKEY_CONFIG`, `:DEVICEUI_CONFIG`.
20
+
21
+ Any other `AdminMessage` field can be passed to `send` / `encode` (for example `set_ringtone_message`, `get_module_config_request`).
22
+
23
+ ## Examples
24
+
25
+ ```ruby
26
+ require 'meshtastic'
27
+
28
+ serial_obj = Meshtastic::Serial.connect(block_dev: '/dev/ttyACM0')
29
+ Meshtastic::Serial.wait_for_config(serial_obj: serial_obj)
30
+
31
+ Meshtastic::Admin.set_owner(serial_obj: serial_obj, long_name: 'Node', short_name: 'N1')
32
+ Meshtastic::Admin.get_owner(serial_obj: serial_obj)
33
+ Meshtastic::Admin.get_config(serial_obj: serial_obj, config_type: :LORA_CONFIG)
34
+ Meshtastic::Admin.get_channel(serial_obj: serial_obj, index: 0)
35
+ Meshtastic::Admin.reboot(serial_obj: serial_obj, seconds: 5)
36
+ # Meshtastic::Admin.shutdown(serial_obj: serial_obj, seconds: 5)
37
+ # Meshtastic::Admin.nodedb_reset(serial_obj: serial_obj)
38
+ ```
39
+
40
+ Raw field:
41
+
42
+ ```ruby
43
+ Meshtastic::Admin.send(
44
+ serial_obj: serial_obj,
45
+ factory_reset_config: true
46
+ )
47
+ ```
48
+
49
+ ## Related
50
+
51
+ - [Meshtastic::Admin::Firmware](admin-firmware.md)
52
+ - [Meshtastic::Channel](channel.md)
53
+ - [Meshtastic::Config](config.md)
54
+ - [Meshtastic::ModuleConfig](module-config.md)
55
+ - [Meshtastic::RTTTL](rtttl.md)
@@ -0,0 +1,22 @@
1
+ # Meshtastic::Apponly
2
+
3
+ App-side channel export: `Meshtastic::ChannelSet` (from `apponly.proto`).
4
+
5
+ ## Methods
6
+
7
+ - `encode(settings:, lora_config:)`
8
+ - `decode(bytes)`
9
+ - `help` / `authors`
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ set = Meshtastic::Apponly.encode(
15
+ settings: [Meshtastic::ChannelSettings.new(name: 'LongFast')]
16
+ )
17
+ round_trip = Meshtastic::Apponly.decode(set.to_proto)
18
+ ```
19
+
20
+ ## Related
21
+
22
+ - [Meshtastic::Channel](channel.md)
@@ -0,0 +1,110 @@
1
+ # Meshtastic::ATAK
2
+
3
+ TAK / ATAK over Meshtastic. Three wire formats, same as the official clients:
4
+
5
+ | Format | Port | Payload |
6
+ | --- | --- | --- |
7
+ | V1 `ATAK_PLUGIN` | 72 | Bare `TAKPacket` (PLI, GeoChat, optional `detail` bytes) |
8
+ | V2 `ATAK_PLUGIN_V2` | 78 | `[flags][TAKPacketV2]`. This gem emits uncompressed frames (`flags=0xFF`) |
9
+ | V1 `ATAK_FORWARDER` | 257 | zlib-compressed CoT XML (single packet, max `DATA_PAYLOAD_LEN`) |
10
+
11
+ V2 typed payloads: GeoChat, aircraft, shapes, markers, range-and-bearing, routes, CASEVAC, emergency, task, TAKTALK, raw detail. Contact / group / status on V1; callsign / team / role / lat-lon on V2.
12
+
13
+ Firmware ≥ 2.8.0 speaks V2. Older radios use V1 PLI/chat, and generic CoT on the forwarder port.
14
+
15
+ Compressed V2 (zstd dictionary id 0 or 1) is not unpacked here; `decode_v2` raises unless `flags=0xFF`.
16
+
17
+ ## Methods
18
+
19
+ - `encode` / `encode_v1` — `TAKPacket`
20
+ - `send` / `send_v1` / `send_chat` / `send_pli` — port 72
21
+ - `build_v2` / `encode_v2` / `wrap_v2` / `decode_v2` / `send_v2` — port 78
22
+ - `compress_cot` / `decompress_cot` / `send_cot` — port 257 (`cot:` XML string)
23
+ - `decode(payload:, portnum:)` — dispatches on port
24
+ - `help` / `authors`
25
+
26
+ `lat` / `lon` are decimal degrees (stored × 1e7). Pass a connected `serial_obj`, `bluetooth_obj`, or `tcp_obj`.
27
+
28
+ ## V1 GeoChat and PLI
29
+
30
+ ```ruby
31
+ Meshtastic::ATAK.send_chat(
32
+ serial_obj: serial_obj,
33
+ message: 'ATAK chat',
34
+ to: 'ANDROID-aabbccdd',
35
+ callsign: 'ALPHA',
36
+ device_callsign: 'RADIO-1',
37
+ team: :Cyan,
38
+ role: :TeamMember,
39
+ battery: 87
40
+ )
41
+
42
+ Meshtastic::ATAK.send_pli(
43
+ serial_obj: serial_obj,
44
+ lat: 37.7749,
45
+ lon: -122.4194,
46
+ altitude: 10,
47
+ speed: 0,
48
+ course: 90,
49
+ callsign: 'ALPHA',
50
+ team: :Cyan
51
+ )
52
+ ```
53
+
54
+ ## V2 typed events
55
+
56
+ ```ruby
57
+ Meshtastic::ATAK.send_v2(serial_obj: serial_obj, message: 'v2 chat', callsign: 'ALPHA')
58
+
59
+ Meshtastic::ATAK.send_v2(
60
+ serial_obj: serial_obj,
61
+ callsign: 'ALPHA',
62
+ lat: 37.7749,
63
+ lon: -122.4194,
64
+ aircraft: Meshtastic::AircraftTrack.new(icao: 'ABC123', flight: 'N1')
65
+ )
66
+
67
+ Meshtastic::ATAK.send_v2(serial_obj: serial_obj, shape: Meshtastic::DrawnShape.new(kind: :Kind_Circle, major_cm: 1000))
68
+ Meshtastic::ATAK.send_v2(serial_obj: serial_obj, marker: Meshtastic::Marker.new(kind: :Kind_Spot))
69
+ Meshtastic::ATAK.send_v2(serial_obj: serial_obj, route: Meshtastic::Route.new(prefix: 'R1'))
70
+ Meshtastic::ATAK.send_v2(serial_obj: serial_obj, casevac: Meshtastic::CasevacReport.new(title: 'CASEVAC'))
71
+ Meshtastic::ATAK.send_v2(serial_obj: serial_obj, emergency: Meshtastic::EmergencyAlert.new(type: :Type_Alert911))
72
+ Meshtastic::ATAK.send_v2(serial_obj: serial_obj, task: Meshtastic::TaskRequest.new(task_type: 'recon'))
73
+ Meshtastic::ATAK.send_v2(serial_obj: serial_obj, taktalk: Meshtastic::TakTalkMessage.new(text: 'hi', chatroom_id: 'room1'))
74
+ ```
75
+
76
+ Receive V2:
77
+
78
+ ```ruby
79
+ Meshtastic::Serial.subscribe(serial_obj: serial_obj, include: 'ATAK_PLUGIN') do |message|
80
+ port = message.dig(:packet, :decoded, :portnum)
81
+ payload = message.dig(:packet, :decoded, :payload)
82
+ decoded = Meshtastic::ATAK.decode(payload: payload, portnum: port)
83
+ p decoded
84
+ end
85
+ ```
86
+
87
+ ## Generic CoT (forwarder)
88
+
89
+ ```ruby
90
+ Meshtastic::ATAK.send_cot(
91
+ serial_obj: serial_obj,
92
+ cot: '<event type="b-m-p-s-m" uid="marker-1"><point lat="37.77" lon="-122.41"/></event>'
93
+ )
94
+ ```
95
+
96
+ Raises if zlib output exceeds `Meshtastic::Constants::DATA_PAYLOAD_LEN`. Multi-packet fountain (FTN) is not implemented; keep CoT small or use V2 typed payloads.
97
+
98
+ ## Radio TAK module
99
+
100
+ Device role `TAK` / `TAK_TRACKER` and Module Config → TAK (`team` / `role`) are [Admin](admin.md) / [ModuleConfig](module-config.md), not this client:
101
+
102
+ ```ruby
103
+ Meshtastic::ModuleConfig.get(serial_obj: serial_obj, module_config_type: :TAK_CONFIG)
104
+ ```
105
+
106
+ ## Related
107
+
108
+ - [Meshtastic::ModuleConfig](module-config.md)
109
+ - [Generated protobuf types](protobufs.md)
110
+ - [TAK wire formats](https://meshtastic.org/docs/software/apple/developer/tak-protocol/)
@@ -0,0 +1,35 @@
1
+ # Meshtastic::Bluetooth::BlueZ
2
+
3
+ Linux D-Bus backend used by [Meshtastic::Bluetooth](bluetooth.md). You normally call `Meshtastic::Bluetooth.scan` / `connect` instead of this class.
4
+
5
+ ## Constants
6
+
7
+ - `SERVICE_UUID`
8
+ - `TORADIO_UUID`
9
+ - `FROMRADIO_UUID`
10
+
11
+ ## Methods
12
+
13
+ - `BlueZ.scan(adapter: 'hci0', timeout: 5)` — `StartDiscovery` then list Device1 objects on that adapter. Returns `{ address:, name:, paired: }`.
14
+ - `#connect` — requires an already paired device; raises if not paired or `ServicesResolved` times out
15
+ - `#read` / write ToRadio characteristic
16
+ - `#close`
17
+
18
+ Requires `ruby-dbus`. Uses the system bus. D-Bus calls are serialized on a mutex.
19
+
20
+ ```ruby
21
+ require 'meshtastic'
22
+
23
+ hits = Meshtastic::Bluetooth::BlueZ.scan(adapter: 'hci0', timeout: 5)
24
+ hits.each { |d| puts "#{d[:address]} #{d[:name]} paired=#{d[:paired]}" }
25
+
26
+ conn = Meshtastic::Bluetooth::BlueZ.new(address: 'AA:BB:CC:DD:EE:FF', adapter: 'hci0', timeout: 15)
27
+ conn.connect
28
+ conn.close
29
+ ```
30
+
31
+ Pairing is outside this class (`bluetoothctl`). The module will not try PIN values.
32
+
33
+ ## Related
34
+
35
+ - [Meshtastic::Bluetooth](bluetooth.md)