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
@@ -0,0 +1,87 @@
1
+ # Meshtastic::Bluetooth
2
+
3
+ Linux BLE client (BlueZ + `ruby-dbus`). Same send/receive API as Serial, with `bluetooth_obj:` instead of `serial_obj:`.
4
+
5
+ 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).
6
+
7
+ Do not open Serial and Bluetooth to the same radio at once. Disconnect the phone’s Meshtastic BLE session while Linux is connected.
8
+
9
+ ## Methods
10
+
11
+ - `scan(adapter:, timeout:)`
12
+ - `connect(address:, adapter:, timeout:, want_config:)`
13
+ - `wait_for_config` — 30 seconds is a reasonable BLE timeout
14
+ - `send_text` / `send_data` / `send_to_radio`
15
+ - `recv_from_radio` / `drain_from_radio`
16
+ - `dump_stdout_data` / `flush_data`
17
+ - `subscribe`
18
+ - `disconnect`
19
+ - `help` / `authors`
20
+
21
+ ## Scan
22
+
23
+ ```ruby
24
+ require 'meshtastic'
25
+ Meshtastic::Bluetooth.scan(adapter: 'hci0', timeout: 5)
26
+ # => [{ address: 'AA:BB:CC:DD:EE:FF', name: 'Meshtastic_eeff', paired: true }, ...]
27
+ ```
28
+
29
+ ## Pair
30
+
31
+ Pair while discovery is running. Screen devices typically show a random 6-digit PIN. Do not invent PIN values.
32
+
33
+ ```text
34
+ bluetoothctl
35
+ agent KeyboardDisplay
36
+ default-agent
37
+ scan on
38
+ pair AA:BB:CC:DD:EE:FF
39
+ trust AA:BB:CC:DD:EE:FF
40
+ scan off
41
+ quit
42
+ ```
43
+
44
+ `Failed to pair: AuthenticationFailed` means the agent never got the PIN. `Device … not available` means scan first; the advertisement dropped.
45
+
46
+ ## Send / receive
47
+
48
+ ```ruby
49
+ require 'meshtastic'
50
+
51
+ bluetooth_obj = nil
52
+ begin
53
+ bluetooth_obj = Meshtastic::Bluetooth.connect(address: 'AA:BB:CC:DD:EE:FF')
54
+ Meshtastic::Bluetooth.wait_for_config(bluetooth_obj: bluetooth_obj, timeout: 30)
55
+
56
+ Meshtastic::Bluetooth.send_text(
57
+ bluetooth_obj: bluetooth_obj,
58
+ to: '!aabbccdd',
59
+ channel: 0,
60
+ text: 'Hello over BLE!',
61
+ want_ack: true
62
+ )
63
+
64
+ Meshtastic::Bluetooth.subscribe(
65
+ bluetooth_obj: bluetooth_obj,
66
+ include: 'TEXT_MESSAGE_APP'
67
+ ) do |message|
68
+ packet = message[:packet]
69
+ puts "#{packet[:node_id_from]}: #{packet.dig(:decoded, :payload)}"
70
+ end
71
+ ensure
72
+ Meshtastic::Bluetooth.disconnect(bluetooth_obj: bluetooth_obj)
73
+ end
74
+ ```
75
+
76
+ After an aborted reconnect (`le-connection-abort-by-local`), `bluetoothctl disconnect <addr>` and wait a couple of seconds before `connect` again.
77
+
78
+ GATT UUIDs (see [BlueZ](bluetooth-bluez.md)):
79
+
80
+ - Service `6ba1b218-15a8-461f-9fa8-5dcae273eafd`
81
+ - ToRadio `f75c76d2-129e-4dad-a1dd-7866124401e7`
82
+ - FromRadio `2c55e69e-4993-11ed-b878-0242ac120002`
83
+
84
+ ## Related
85
+
86
+ - [Meshtastic::Bluetooth::BlueZ](bluetooth-bluez.md)
87
+ - [Meshtastic::Serial](serial.md)
@@ -0,0 +1,25 @@
1
+ # Meshtastic::Cannedmessages
2
+
3
+ Wraps `Meshtastic::CannedMessageModuleConfig` (`messages` is a newline-separated string).
4
+
5
+ ## Methods
6
+
7
+ - `encode(messages:)`
8
+ - `send` — publishes the string on `TEXT_MESSAGE_APP` (not an admin set). To store canned lines on the device, use [Admin](admin.md) `set_canned_message_module_messages` or [ModuleConfig](module-config.md).
9
+ - `help` / `authors`
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ cfg = Meshtastic::Cannedmessages.encode(messages: "Yes\nNo\nMaybe")
15
+ cfg.messages # => "Yes\nNo\nMaybe"
16
+
17
+ Meshtastic::Admin.send(
18
+ serial_obj: serial_obj,
19
+ set_canned_message_module_messages: "Yes\nNo\nMaybe"
20
+ )
21
+ ```
22
+
23
+ ## Related
24
+
25
+ - [Meshtastic::Admin](admin.md)
@@ -0,0 +1,3 @@
1
+ # Meshtastic::Channel
2
+
3
+ Generated protobuf (`index`, `settings`, `role`). Get/set on a live node is [Meshtastic::Admin::Channel](admin-channel.md).
@@ -0,0 +1,21 @@
1
+ # Meshtastic::Clientonly
2
+
3
+ Client-side `Meshtastic::DeviceProfile` encode/decode (`clientonly.proto`).
4
+
5
+ ## Methods
6
+
7
+ - `encode(long_name:, short_name:)`
8
+ - `decode(bytes)`
9
+ - `help` / `authors`
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ profile = Meshtastic::Clientonly.encode(long_name: 'Node', short_name: 'N1')
15
+ profile.long_name # => "Node"
16
+ Meshtastic::Clientonly.decode(profile.to_proto)
17
+ ```
18
+
19
+ ## Related
20
+
21
+ - [Meshtastic::Admin](admin.md) (`set_owner`)
@@ -0,0 +1,3 @@
1
+ # Meshtastic::Config
2
+
3
+ Generated protobuf (device, position, power, network, display, lora, bluetooth, security, sessionkey, device_ui). Get/set on a live node is [Meshtastic::Admin::Config](admin-config.md).
@@ -0,0 +1,22 @@
1
+ # Meshtastic::ConnectionStatus
2
+
3
+ Decodes `Meshtastic::DeviceConnectionStatus`.
4
+
5
+ ## Methods
6
+
7
+ - `decode(bytes)`
8
+ - `help` / `authors`
9
+
10
+ ## Example
11
+
12
+ ```ruby
13
+ status = Meshtastic::ConnectionStatus.decode(
14
+ Meshtastic::DeviceConnectionStatus.new.to_proto
15
+ )
16
+ ```
17
+
18
+ Related types: `WifiConnectionStatus`, `EthernetConnectionStatus`, `NetworkConnectionStatus`, `BluetoothConnectionStatus`, `SerialConnectionStatus`.
19
+
20
+ ## Related
21
+
22
+ - [Generated protobuf types](protobufs.md)
@@ -0,0 +1,22 @@
1
+ # Meshtastic::Deviceonly
2
+
3
+ Decodes device-only snapshots: `DeviceState` and `NodeDatabase`.
4
+
5
+ ## Methods
6
+
7
+ - `decode_state(bytes)`
8
+ - `decode_nodedb(bytes)`
9
+ - `help` / `authors`
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ state = Meshtastic::Deviceonly.decode_state(Meshtastic::DeviceState.new.to_proto)
15
+ nodedb = Meshtastic::Deviceonly.decode_nodedb(Meshtastic::NodeDatabase.new.to_proto)
16
+ ```
17
+
18
+ Related types: `PositionLite`, `UserLite`, `NodeInfoLite`, `ChannelFile`, `BackupPreferences`.
19
+
20
+ ## Related
21
+
22
+ - [Meshtastic::Localonly](localonly.md)
@@ -0,0 +1,21 @@
1
+ # Meshtastic::Localonly
2
+
3
+ Decodes `LocalConfig` and `LocalModuleConfig` (full config blobs stored on the client).
4
+
5
+ ## Methods
6
+
7
+ - `decode_config(bytes)`
8
+ - `decode_module_config(bytes)`
9
+ - `help` / `authors`
10
+
11
+ ## Example
12
+
13
+ ```ruby
14
+ Meshtastic::Localonly.decode_config(Meshtastic::LocalConfig.new.to_proto)
15
+ Meshtastic::Localonly.decode_module_config(Meshtastic::LocalModuleConfig.new.to_proto)
16
+ ```
17
+
18
+ ## Related
19
+
20
+ - [Meshtastic::Config](config.md)
21
+ - [Meshtastic::ModuleConfig](module-config.md)
@@ -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: / tcp_obj: / mqtt_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`, `tcp_obj`, or `mqtt_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)