meshtastic 0.0.2 → 0.0.3

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +27 -0
  3. data/.gitignore +29 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +10 -0
  6. data/.rubocop_todo.yml +107 -0
  7. data/.ruby-gemset +1 -0
  8. data/.ruby-version +1 -0
  9. data/AUTOGEN_meshtastic_protobufs.sh +25 -0
  10. data/CODE_OF_CONDUCT.md +84 -0
  11. data/Gemfile +23 -0
  12. data/LICENSE +21 -0
  13. data/README.md +31 -0
  14. data/Rakefile +17 -0
  15. data/bin/console +11 -0
  16. data/bin/meshtastic_autoinc_version +38 -0
  17. data/bin/setup +8 -0
  18. data/build_meshtastic_gem.sh +58 -0
  19. data/git_commit.sh +23 -0
  20. data/lib/meshtastic/admin_pb.rb +100 -0
  21. data/lib/meshtastic/apponly_pb.rb +20 -0
  22. data/lib/meshtastic/atak_pb.rb +80 -0
  23. data/lib/meshtastic/cannedmessages_pb.rb +16 -0
  24. data/lib/meshtastic/channel_pb.rb +38 -0
  25. data/lib/meshtastic/clientonly_pb.rb +22 -0
  26. data/lib/meshtastic/config_pb.rb +235 -0
  27. data/lib/meshtastic/connection_status_pb.rb +47 -0
  28. data/lib/meshtastic/deviceonly_pb.rb +75 -0
  29. data/lib/meshtastic/localonly_pb.rb +43 -0
  30. data/lib/meshtastic/mesh_pb.rb +359 -0
  31. data/lib/meshtastic/module_config_pb.rb +227 -0
  32. data/lib/meshtastic/mqtt.rb +271 -0
  33. data/lib/meshtastic/mqtt.rb.BAKq! +214 -0
  34. data/lib/meshtastic/mqtt_pb.rb +37 -0
  35. data/lib/meshtastic/paxcount_pb.rb +18 -0
  36. data/lib/meshtastic/portnums_pb.rb +42 -0
  37. data/lib/meshtastic/remote_hardware_pb.rb +27 -0
  38. data/lib/meshtastic/rtttl_pb.rb +16 -0
  39. data/lib/meshtastic/storeforward_pb.rb +64 -0
  40. data/lib/meshtastic/telemetry_pb.rb +85 -0
  41. data/lib/meshtastic/version.rb +5 -0
  42. data/lib/meshtastic/xmodem_pb.rb +30 -0
  43. data/lib/meshtastic.rb +34 -0
  44. data/meshtastic.gemspec +73 -0
  45. data/sig/meshtastic.rbs +4 -0
  46. data/spec/lib/meshtastic/admin_pb_spec.rb +6 -0
  47. data/spec/lib/meshtastic/apponly_pb_spec.rb +6 -0
  48. data/spec/lib/meshtastic/atak_pb_spec.rb +6 -0
  49. data/spec/lib/meshtastic/cannedmessages_pb_spec.rb +6 -0
  50. data/spec/lib/meshtastic/channel_pb_spec.rb +6 -0
  51. data/spec/lib/meshtastic/clientonly_pb_spec.rb +6 -0
  52. data/spec/lib/meshtastic/config_pb_spec.rb +6 -0
  53. data/spec/lib/meshtastic/connection_status_pb_spec.rb +6 -0
  54. data/spec/lib/meshtastic/deviceonly_pb_spec.rb +6 -0
  55. data/spec/lib/meshtastic/localonly_pb_spec.rb +6 -0
  56. data/spec/lib/meshtastic/mesh_pb_spec.rb +6 -0
  57. data/spec/lib/meshtastic/module_config_pb_spec.rb +6 -0
  58. data/spec/lib/meshtastic/mqtt_pb_spec.rb +6 -0
  59. data/spec/lib/meshtastic/mqtt_spec.rb +6 -0
  60. data/spec/lib/meshtastic/paxcount_pb_spec.rb +6 -0
  61. data/spec/lib/meshtastic/portnums_pb_spec.rb +6 -0
  62. data/spec/lib/meshtastic/remote_hardware_pb_spec.rb +6 -0
  63. data/spec/lib/meshtastic/rtttl_pb_spec.rb +6 -0
  64. data/spec/lib/meshtastic/storeforward_pb_spec.rb +6 -0
  65. data/spec/lib/meshtastic/telemetry_pb_spec.rb +6 -0
  66. data/spec/lib/meshtastic/version_spec.rb +17 -0
  67. data/spec/lib/meshtastic/xmodem_pb_spec.rb +6 -0
  68. data/spec/lib/meshtastic_spec.rb +6 -0
  69. data/spec/spec_helper.rb +15 -0
  70. data/upgrade_Gemfile_gems.sh +20 -0
  71. data/upgrade_gem.sh +4 -0
  72. data/upgrade_meshtastic.sh +13 -0
  73. data/upgrade_ruby.sh +45 -0
  74. metadata +106 -3
@@ -0,0 +1,271 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'geocoder'
5
+ require 'json'
6
+ require 'mqtt'
7
+ require 'openssl'
8
+ require 'securerandom'
9
+ require 'meshtastic/mqtt_pb'
10
+
11
+ # Avoiding Namespace Collisions
12
+ MQTTClient = MQTT::Client
13
+
14
+ # Plugin used to interact with Meshtastic nodes
15
+ module Meshtastic
16
+ module MQTT
17
+ # Supported Method Parameters::
18
+ # mqtt_obj = Meshtastic::MQQT.connect(
19
+ # host: 'optional - mqtt host (default: mqtt.meshtastic.org)',
20
+ # port: 'optional - mqtt port (defaults: 1883)',
21
+ # username: 'optional - mqtt username (default: meshdev)',
22
+ # password: 'optional - (default: large4cats)'
23
+ # )
24
+
25
+ public_class_method def self.connect(opts = {})
26
+ # Publicly available MQTT server / credentials by default
27
+ host = opts[:host] ||= 'mqtt.meshtastic.org'
28
+ port = opts[:port] ||= 1883
29
+ username = opts[:username] ||= 'meshdev'
30
+ password = opts[:password] ||= 'large4cats'
31
+
32
+ mqtt_obj = MQTTClient.connect(
33
+ host: host,
34
+ port: port,
35
+ username: username,
36
+ password: password
37
+ )
38
+
39
+ mqtt_obj.client_id = SecureRandom.random_bytes(8).unpack1('H*')
40
+
41
+ mqtt_obj
42
+ rescue StandardError => e
43
+ raise e
44
+ end
45
+
46
+ # Supported Method Parameters::
47
+ # Meshtastic::MQQT.subscribe(
48
+ # mqtt_obj: 'required - mqtt_obj returned from #connect method'
49
+ # region: 'optional - region (default: US)',
50
+ # channel: 'optional - channel name (default: LongFast)',
51
+ # psk: 'optional - channel pre-shared key (default: AQ==)',
52
+ # qos: 'optional - quality of service (default: 0)',
53
+ # json: 'optional - JSON output (default: false)'
54
+ # )
55
+
56
+ public_class_method def self.subscribe(opts = {})
57
+ mqtt_obj = opts[:mqtt_obj]
58
+ region = opts[:region] ||= 'US'
59
+ channel = opts[:channel] ||= 'LongFast'
60
+ psk = opts[:psk] ||= 'AQ=='
61
+ qos = opts[:qos] ||= 0
62
+ json = opts[:json] ||= false
63
+
64
+ # TODO: Find JSON URI for this
65
+ root_topic = "msh/#{region}/2/json" if json
66
+ # root_topic = "msh/#{region}/2/e" unless json
67
+ root_topic = "msh/#{region}/2/c" unless json
68
+ mqtt_obj.subscribe("#{root_topic}/#{channel}/#", qos)
69
+
70
+ # Decrypt the message
71
+ # Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification.
72
+
73
+ # Actual pre-shared key for LongFast channel
74
+ psk = '1PG7OiApB1nwvP+rz05pAQ==' if channel == 'LongFast'
75
+ padded_psk = psk.ljust(psk.length + ((4 - (psk.length % 4)) % 4), '=')
76
+ replaced_psk = padded_psk.gsub('-', '+').gsub('_', '/')
77
+ psk = replaced_psk
78
+ dec_psk = Base64.strict_decode64(psk)
79
+
80
+ # cipher = OpenSSL::Cipher.new('AES-256-CTR')
81
+ cipher = OpenSSL::Cipher.new('AES-128-CTR')
82
+ mqtt_obj.get_packet do |packet|
83
+ raw_packet = packet.to_s.b
84
+ raw_packet_len = raw_packet.length
85
+ begin
86
+ puts '-' * 80
87
+
88
+ if json
89
+ raw_payload = JSON.parse(packet.payload, symbolize_names: true)
90
+ payload = Meshtastic::ServiceEnvelope.json_decode(raw_payload)
91
+ map_report = Meshtastic::MapReport.json_decode(raw_payload)
92
+ else
93
+ raw_payload = packet.payload.to_s
94
+ payload = Meshtastic::ServiceEnvelope.decode(raw_payload).to_hash[:packet]
95
+ map_report = Meshtastic::MapReport.decode(raw_payload).to_hash
96
+ end
97
+
98
+ puts "*** MESSAGE ***"
99
+ packet_from = payload[:from]
100
+ puts "Packet From: #{packet_from}"
101
+ packet_to = payload[:to]
102
+ puts "Packet To: #{packet_to}"
103
+ channel = payload[:channel]
104
+ puts "Channel: #{channel}"
105
+ packet_id = payload[:id]
106
+ puts "Packet ID: #{packet_id}"
107
+ topic = packet.topic
108
+ puts "\nTopic: #{topic}"
109
+
110
+ decoded_payload = payload[:decoded]
111
+ if decoded_payload
112
+ port_num = decoded_payload[:portnum]
113
+ puts "Port Number: #{port_num}"
114
+ decp = decoded_payload[:payload].b
115
+ puts "Decoded Payload: #{decp.inspect}"
116
+ want_response = decoded_payload[:want_response]
117
+ puts "Want Response: #{want_response}"
118
+ dest = decoded_payload[:dest]
119
+ puts "Destination: #{dest}"
120
+ source = decoded_payload[:source]
121
+ puts "Source: #{source}"
122
+ request_id = decoded_payload[:request_id]
123
+ puts "Request ID: #{request_id}"
124
+ reply_id = decoded_payload[:reply_id]
125
+ puts "Reply ID: #{reply_id}"
126
+ emoji = decoded_payload[:emoji]
127
+ puts "Emoji: #{emoji}"
128
+ end
129
+
130
+ encrypted_payload = payload[:encrypted]
131
+ # If encrypted_payload is not nil, then decrypt the message
132
+ if encrypted_payload.length.positive?
133
+ nonce_packet_id = [packet_id].pack('V').ljust(8, "\x00")
134
+ nonce_from_node = [packet_from].pack('V').ljust(8, "\x00")
135
+ nonce = "#{nonce_packet_id}#{nonce_from_node}".b
136
+ puts "Nonce: #{nonce.inspect} | Length: #{nonce.length}"
137
+
138
+ # Decrypt the message
139
+ # Key must be 32 bytes
140
+ # IV mustr be 16 bytes
141
+ cipher.decrypt
142
+ cipher.key = dec_psk
143
+ cipher.iv = nonce
144
+ puts "\nEncrypted Payload:\n#{encrypted_payload.inspect}"
145
+ puts "Length: #{encrypted_payload.length}" if encrypted_payload
146
+
147
+ decrypted = cipher.update(encrypted_payload) + cipher.final
148
+ puts "\nDecrypted Payload:\n#{decrypted.inspect}"
149
+ puts "Length: #{decrypted.length}" if decrypted
150
+ end
151
+ puts '*' * 20
152
+
153
+ map_long_name = map_report[:long_name].b
154
+ puts "\n*** MAP STATS ***"
155
+ puts "Map Long Name: #{map_long_name.inspect}"
156
+ map_short_name = map_report[:short_name]
157
+ puts "Map Short Name: #{map_short_name}"
158
+ role = map_report[:role]
159
+ puts "Role: #{role}"
160
+ hw_model = map_report[:hw_model]
161
+ puts "Hardware Model: #{hw_model}"
162
+ firmware_version = map_report[:firmware_version]
163
+ puts "Firmware Version: #{firmware_version}"
164
+ region = map_report[:region]
165
+ puts "Region: #{region}"
166
+ modem_preset = map_report[:modem_preset]
167
+ puts "Modem Preset: #{modem_preset}"
168
+ has_default_channel = map_report[:has_default_channel]
169
+ puts "Has Default Channel: #{has_default_channel}"
170
+ latitiude_i = map_report[:latitude_i]
171
+ puts "Latitude: #{latitiude_i}"
172
+ longitude_i = map_report[:longitude_i]
173
+ puts "Longitude: #{longitude_i}"
174
+ altitude = map_report[:altitude]
175
+ puts "Altitude: #{altitude}"
176
+ position_precision = map_report[:position_precision]
177
+ puts "Position Precision: #{position_precision}"
178
+ num_online_local_nodes = map_report[:num_online_local_nodes]
179
+ puts "Number of Online Local Nodes: #{num_online_local_nodes}"
180
+ puts '*' * 20
181
+
182
+ puts "\n*** PACKET DEBUGGING ***"
183
+ puts "Payload: #{payload.inspect}"
184
+ puts "\nMap Report: #{map_report.inspect}"
185
+ puts "\nRaw Packet: #{raw_packet.inspect}"
186
+ puts "Length: #{raw_packet_len}"
187
+ puts '*' * 20
188
+ rescue Google::Protobuf::ParseError
189
+ puts "\nRaw Packet: #{raw_packet.inspect}"
190
+ puts "Length: #{raw_packet_len}"
191
+ next
192
+ ensure
193
+ puts '-' * 80
194
+ puts "\n\n\n"
195
+ end
196
+ end
197
+ rescue Interrupt
198
+ puts "\nCTRL+C detected. Exiting..."
199
+ rescue StandardError => e
200
+ raise e
201
+ ensure
202
+ mqtt_obj.disconnect if mqtt_obj
203
+ end
204
+
205
+ # Supported Method Parameters::
206
+ # mqtt_obj = Meshtastic.gps_search(
207
+ # lat: 'required - latitude float (e.g. 37.7749)',
208
+ # lon: 'required - longitude float (e.g. -122.4194)',
209
+ # )
210
+ public_class_method def self.gps_search(opts = {})
211
+ lat = opts[:lat]
212
+ lon = opts[:lon]
213
+
214
+ raise 'ERROR: Latitude and Longitude are required' unless lat && lon
215
+
216
+ gps_arr = [lat.to_f, lon.to_f]
217
+
218
+ Geocoder.search(gps_arr)
219
+ rescue StandardError => e
220
+ raise e
221
+ end
222
+
223
+ # Supported Method Parameters::
224
+ # mqtt_obj = Meshtastic.disconnect(
225
+ # mqtt_obj: 'required - mqtt_obj returned from #connect method'
226
+ # )
227
+ public_class_method def self.disconnect(opts = {})
228
+ mqtt_obj = opts[:mqtt_obj]
229
+
230
+ mqtt_obj.disconnect if mqtt_obj
231
+ nil
232
+ rescue StandardError => e
233
+ raise e
234
+ end
235
+
236
+ # Author(s):: 0day Inc. <request.pentest@0dayinc.com>
237
+
238
+ public_class_method def self.authors
239
+ "AUTHOR(S):
240
+ 0day Inc. <request.pentest@0dayinc.com>
241
+ "
242
+ end
243
+
244
+ # Display Usage for this Module
245
+
246
+ public_class_method def self.help
247
+ puts "USAGE:
248
+ mqtt_obj = #{self}.connect(
249
+ host: 'optional - mqtt host (default: mqtt.meshtastic.org)',
250
+ port: 'optional - mqtt port (defaults: 1883)',
251
+ username: 'optional - mqtt username (default: meshdev)',
252
+ password: 'optional - (default: large4cats)'
253
+ )
254
+
255
+ #{self}.subscribe(
256
+ mqtt_obj: 'required - mqtt_obj object returned from #connect method',
257
+ region: 'optional - region (default: US)',
258
+ channel: 'optional - channel name (default: LongFast)',
259
+ psk: 'optional - channel pre-shared key (default: AQ==)',
260
+ qos: 'optional - quality of service (default: 0)'
261
+ )
262
+
263
+ mqtt_obj = #{self}.disconnect(
264
+ mqtt_obj: 'required - mqtt_obj object returned from #connect method'
265
+ )
266
+
267
+ #{self}.authors
268
+ "
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,214 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'geocoder'
5
+ require 'json'
6
+ require 'mqtt'
7
+ require 'openssl'
8
+ require 'securerandom'
9
+ require 'meshtastic/mqtt_pb'
10
+
11
+ # Avoiding Namespace Collisions
12
+ MQTTClient = MQTT::Client
13
+
14
+ # Plugin used to interact with Meshtastic nodes
15
+ module Meshtastic
16
+ module MQTT
17
+ # Supported Method Parameters::
18
+ # mqtt_obj = Meshtastic::MQQT.connect(
19
+ # host: 'optional - mqtt host (default: mqtt.meshtastic.org)',
20
+ # port: 'optional - mqtt port (defaults: 1883)',
21
+ # username: 'optional - mqtt username (default: meshdev)',
22
+ # password: 'optional - (default: large4cats)'
23
+ # )
24
+
25
+ public_class_method def self.connect(opts = {})
26
+ # Publicly available MQTT server / credentials by default
27
+ host = opts[:host] ||= 'mqtt.meshtastic.org'
28
+ port = opts[:port] ||= 1883
29
+ username = opts[:username] ||= 'meshdev'
30
+ password = opts[:password] ||= 'large4cats'
31
+
32
+ mqtt_obj = MQTTClient.connect(
33
+ host: host,
34
+ port: port,
35
+ username: username,
36
+ password: password
37
+ )
38
+
39
+ mqtt_obj.client_id = SecureRandom.random_bytes(8).unpack1('H*')
40
+
41
+ mqtt_obj
42
+ rescue StandardError => e
43
+ raise e
44
+ end
45
+
46
+ # Supported Method Parameters::
47
+ # Meshtastic::MQQT.subscribe(
48
+ # mqtt_obj: 'required - mqtt_obj returned from #connect method'
49
+ # region: 'optional - region (default: US)',
50
+ # channel: 'optional - channel name (default: LongFast)',
51
+ # psk: 'optional - channel pre-shared key (default: AQ==)',
52
+ # qos: 'optional - quality of service (default: 0)',
53
+ # json: 'optional - JSON output (default: false)'
54
+ # )
55
+
56
+ public_class_method def self.subscribe(opts = {})
57
+ mqtt_obj = opts[:mqtt_obj]
58
+ region = opts[:region] ||= 'US'
59
+ channel = opts[:channel] ||= 'LongFast'
60
+ psk = opts[:psk] ||= 'AQ=='
61
+ qos = opts[:qos] ||= 0
62
+ json = opts[:json] ||= false
63
+
64
+ # TODO: Find JSON URI for this
65
+ root_topic = "msh/#{region}/2/json" if json
66
+ # root_topic = "msh/#{region}/2/e" unless json
67
+ root_topic = "msh/#{region}/2/c" unless json
68
+ mqtt_obj.subscribe("#{root_topic}/#{channel}/#", qos)
69
+
70
+ # Decrypt the message
71
+ # Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification.
72
+
73
+ # Actual pre-shared key for LongFast channel
74
+ psk = '1PG7OiApB1nwvP+rz05pAQ==' if channel == 'LongFast'
75
+ padded_psk = psk.ljust(psk.length + ((4 - (psk.length % 4)) % 4), '=')
76
+ replaced_psk = padded_psk.gsub('-', '+').gsub('_', '/')
77
+ psk = replaced_psk
78
+ dec_psk = Base64.strict_decode64(psk)
79
+
80
+ # cipher = OpenSSL::Cipher.new('AES-256-CTR')
81
+ cipher = OpenSSL::Cipher.new('AES-128-CTR')
82
+ mqtt_obj.get_packet do |packet|
83
+ begin
84
+ puts '-' * 80
85
+
86
+ if json
87
+ raw_payload = JSON.parse(packet.payload, symbolize_names: true)
88
+ payload = Meshtastic::ServiceEnvelope.json_decode(raw_payload)
89
+ map_report = Meshtastic::MapReport.json_decode(raw_payload)
90
+ else
91
+ raw_payload = packet.payload.to_s
92
+ payload = Meshtastic::ServiceEnvelope.decode(raw_payload)
93
+ map_report = Meshtastic::MapReport.decode(raw_payload)
94
+ end
95
+
96
+ puts "Payload: #{payload.inspect}"
97
+ puts "Payload Length: #{payload.length}"
98
+ puts "Map Report: #{map_report.inspect}"
99
+ puts "Map Report Length: #{map_report.length}"
100
+
101
+ packet_from = packet_from_hex.to_i(16)
102
+ packet_to = packet_to_hex.to_i(16)
103
+ msg_len = msg_len_hex.to_i(16)
104
+ channel = channel_hex.to_i(16)
105
+ packet_id = pid_hex.to_i(16)
106
+ topic = packet.topic
107
+ puts "\nTopic: #{topic}"
108
+
109
+
110
+ nonce_packet_id = [packet_id].pack('V').ljust(8, "\x00")
111
+ nonce_from_node = [packet_from].pack('V').ljust(8, "\x00")
112
+ nonce = "#{nonce_packet_id}#{nonce_from_node}".b
113
+ puts "Nonce: #{nonce.inspect} | Length: #{nonce.length}"
114
+
115
+ # Decrypt the message
116
+ # Key must be 32 bytes
117
+ # IV mustr be 16 bytes
118
+ cipher.decrypt
119
+ cipher.key = dec_psk
120
+ cipher.iv = nonce
121
+ first_byte = 16
122
+ last_byte = first_byte + msg_len - 1
123
+ encrypted_payload = payload[first_byte..last_byte]
124
+ puts "\nEncrypted Payload:\n#{encrypted_payload.inspect}"
125
+ puts "Length: #{encrypted_payload.length}" if encrypted_payload
126
+
127
+ decrypted = cipher.update(encrypted_payload) + cipher.final
128
+ puts "\nDecrypted Payload:\n#{decrypted.inspect}"
129
+ puts "Length: #{decrypted.length}" if decrypted
130
+
131
+ raw_packet = packet.to_s.b
132
+ raw_packet_len = raw_packet.length
133
+ puts "\nRaw Packet: #{raw_packet.inspect}"
134
+ puts "Length: #{raw_packet_len}"
135
+ rescue Google::Protobuf::ParseError => e
136
+ puts "Error parsing message: #{e}"
137
+ next
138
+ end
139
+ end
140
+ rescue Interrupt
141
+ puts "\nCTRL+C detected. Exiting..."
142
+ rescue StandardError => e
143
+ raise e
144
+ ensure
145
+ mqtt_obj.disconnect if mqtt_obj
146
+ end
147
+
148
+ # Supported Method Parameters::
149
+ # mqtt_obj = Meshtastic.gps_search(
150
+ # lat: 'required - latitude float (e.g. 37.7749)',
151
+ # lon: 'required - longitude float (e.g. -122.4194)',
152
+ # )
153
+ public_class_method def self.gps_search(opts = {})
154
+ lat = opts[:lat]
155
+ lon = opts[:lon]
156
+
157
+ raise 'ERROR: Latitude and Longitude are required' unless lat && lon
158
+
159
+ gps_arr = [lat.to_f, lon.to_f]
160
+
161
+ Geocoder.search(gps_arr)
162
+ rescue StandardError => e
163
+ raise e
164
+ end
165
+
166
+ # Supported Method Parameters::
167
+ # mqtt_obj = Meshtastic.disconnect(
168
+ # mqtt_obj: 'required - mqtt_obj returned from #connect method'
169
+ # )
170
+ public_class_method def self.disconnect(opts = {})
171
+ mqtt_obj = opts[:mqtt_obj]
172
+
173
+ mqtt_obj.disconnect if mqtt_obj
174
+ nil
175
+ rescue StandardError => e
176
+ raise e
177
+ end
178
+
179
+ # Author(s):: 0day Inc. <request.pentest@0dayinc.com>
180
+
181
+ public_class_method def self.authors
182
+ "AUTHOR(S):
183
+ 0day Inc. <request.pentest@0dayinc.com>
184
+ "
185
+ end
186
+
187
+ # Display Usage for this Module
188
+
189
+ public_class_method def self.help
190
+ puts "USAGE:
191
+ mqtt_obj = #{self}.connect(
192
+ host: 'optional - mqtt host (default: mqtt.meshtastic.org)',
193
+ port: 'optional - mqtt port (defaults: 1883)',
194
+ username: 'optional - mqtt username (default: meshdev)',
195
+ password: 'optional - (default: large4cats)'
196
+ )
197
+
198
+ #{self}.subscribe(
199
+ mqtt_obj: 'required - mqtt_obj object returned from #connect method',
200
+ region: 'optional - region (default: US)',
201
+ channel: 'optional - channel name (default: LongFast)',
202
+ psk: 'optional - channel pre-shared key (default: AQ==)',
203
+ qos: 'optional - quality of service (default: 0)'
204
+ )
205
+
206
+ mqtt_obj = #{self}.disconnect(
207
+ mqtt_obj: 'required - mqtt_obj object returned from #connect method'
208
+ )
209
+
210
+ #{self}.authors
211
+ "
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,37 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: meshtastic/mqtt.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ require 'meshtastic/config_pb'
7
+ require 'meshtastic/mesh_pb'
8
+
9
+ Google::Protobuf::DescriptorPool.generated_pool.build do
10
+ add_file("meshtastic/mqtt.proto", :syntax => :proto3) do
11
+ add_message "meshtastic.ServiceEnvelope" do
12
+ optional :packet, :message, 1, "meshtastic.MeshPacket"
13
+ optional :channel_id, :string, 2
14
+ optional :gateway_id, :string, 3
15
+ end
16
+ add_message "meshtastic.MapReport" do
17
+ optional :long_name, :string, 1
18
+ optional :short_name, :string, 2
19
+ optional :role, :enum, 3, "meshtastic.Config.DeviceConfig.Role"
20
+ optional :hw_model, :enum, 4, "meshtastic.HardwareModel"
21
+ optional :firmware_version, :string, 5
22
+ optional :region, :enum, 6, "meshtastic.Config.LoRaConfig.RegionCode"
23
+ optional :modem_preset, :enum, 7, "meshtastic.Config.LoRaConfig.ModemPreset"
24
+ optional :has_default_channel, :bool, 8
25
+ optional :latitude_i, :sfixed32, 9
26
+ optional :longitude_i, :sfixed32, 10
27
+ optional :altitude, :int32, 11
28
+ optional :position_precision, :uint32, 12
29
+ optional :num_online_local_nodes, :uint32, 13
30
+ end
31
+ end
32
+ end
33
+
34
+ module Meshtastic
35
+ ServiceEnvelope = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.ServiceEnvelope").msgclass
36
+ MapReport = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.MapReport").msgclass
37
+ end
@@ -0,0 +1,18 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: meshtastic/paxcount.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_file("meshtastic/paxcount.proto", :syntax => :proto3) do
8
+ add_message "meshtastic.Paxcount" do
9
+ optional :wifi, :uint32, 1
10
+ optional :ble, :uint32, 2
11
+ optional :uptime, :uint32, 3
12
+ end
13
+ end
14
+ end
15
+
16
+ module Meshtastic
17
+ Paxcount = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.Paxcount").msgclass
18
+ end
@@ -0,0 +1,42 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: meshtastic/portnums.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_file("meshtastic/portnums.proto", :syntax => :proto3) do
8
+ add_enum "meshtastic.PortNum" do
9
+ value :UNKNOWN_APP, 0
10
+ value :TEXT_MESSAGE_APP, 1
11
+ value :REMOTE_HARDWARE_APP, 2
12
+ value :POSITION_APP, 3
13
+ value :NODEINFO_APP, 4
14
+ value :ROUTING_APP, 5
15
+ value :ADMIN_APP, 6
16
+ value :TEXT_MESSAGE_COMPRESSED_APP, 7
17
+ value :WAYPOINT_APP, 8
18
+ value :AUDIO_APP, 9
19
+ value :DETECTION_SENSOR_APP, 10
20
+ value :REPLY_APP, 32
21
+ value :IP_TUNNEL_APP, 33
22
+ value :PAXCOUNTER_APP, 34
23
+ value :SERIAL_APP, 64
24
+ value :STORE_FORWARD_APP, 65
25
+ value :RANGE_TEST_APP, 66
26
+ value :TELEMETRY_APP, 67
27
+ value :ZPS_APP, 68
28
+ value :SIMULATOR_APP, 69
29
+ value :TRACEROUTE_APP, 70
30
+ value :NEIGHBORINFO_APP, 71
31
+ value :ATAK_PLUGIN, 72
32
+ value :MAP_REPORT_APP, 73
33
+ value :PRIVATE_APP, 256
34
+ value :ATAK_FORWARDER, 257
35
+ value :MAX, 511
36
+ end
37
+ end
38
+ end
39
+
40
+ module Meshtastic
41
+ PortNum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.PortNum").enummodule
42
+ end
@@ -0,0 +1,27 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: meshtastic/remote_hardware.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_file("meshtastic/remote_hardware.proto", :syntax => :proto3) do
8
+ add_message "meshtastic.HardwareMessage" do
9
+ optional :type, :enum, 1, "meshtastic.HardwareMessage.Type"
10
+ optional :gpio_mask, :uint64, 2
11
+ optional :gpio_value, :uint64, 3
12
+ end
13
+ add_enum "meshtastic.HardwareMessage.Type" do
14
+ value :UNSET, 0
15
+ value :WRITE_GPIOS, 1
16
+ value :WATCH_GPIOS, 2
17
+ value :GPIOS_CHANGED, 3
18
+ value :READ_GPIOS, 4
19
+ value :READ_GPIOS_REPLY, 5
20
+ end
21
+ end
22
+ end
23
+
24
+ module Meshtastic
25
+ HardwareMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.HardwareMessage").msgclass
26
+ HardwareMessage::Type = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.HardwareMessage.Type").enummodule
27
+ end
@@ -0,0 +1,16 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: meshtastic/rtttl.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_file("meshtastic/rtttl.proto", :syntax => :proto3) do
8
+ add_message "meshtastic.RTTTLConfig" do
9
+ optional :ringtone, :string, 1
10
+ end
11
+ end
12
+ end
13
+
14
+ module Meshtastic
15
+ RTTTLConfig = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.RTTTLConfig").msgclass
16
+ end
@@ -0,0 +1,64 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: meshtastic/storeforward.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_file("meshtastic/storeforward.proto", :syntax => :proto3) do
8
+ add_message "meshtastic.StoreAndForward" do
9
+ optional :rr, :enum, 1, "meshtastic.StoreAndForward.RequestResponse"
10
+ oneof :variant do
11
+ optional :stats, :message, 2, "meshtastic.StoreAndForward.Statistics"
12
+ optional :history, :message, 3, "meshtastic.StoreAndForward.History"
13
+ optional :heartbeat, :message, 4, "meshtastic.StoreAndForward.Heartbeat"
14
+ optional :text, :bytes, 5
15
+ end
16
+ end
17
+ add_message "meshtastic.StoreAndForward.Statistics" do
18
+ optional :messages_total, :uint32, 1
19
+ optional :messages_saved, :uint32, 2
20
+ optional :messages_max, :uint32, 3
21
+ optional :up_time, :uint32, 4
22
+ optional :requests, :uint32, 5
23
+ optional :requests_history, :uint32, 6
24
+ optional :heartbeat, :bool, 7
25
+ optional :return_max, :uint32, 8
26
+ optional :return_window, :uint32, 9
27
+ end
28
+ add_message "meshtastic.StoreAndForward.History" do
29
+ optional :history_messages, :uint32, 1
30
+ optional :window, :uint32, 2
31
+ optional :last_request, :uint32, 3
32
+ end
33
+ add_message "meshtastic.StoreAndForward.Heartbeat" do
34
+ optional :period, :uint32, 1
35
+ optional :secondary, :uint32, 2
36
+ end
37
+ add_enum "meshtastic.StoreAndForward.RequestResponse" do
38
+ value :UNSET, 0
39
+ value :ROUTER_ERROR, 1
40
+ value :ROUTER_HEARTBEAT, 2
41
+ value :ROUTER_PING, 3
42
+ value :ROUTER_PONG, 4
43
+ value :ROUTER_BUSY, 5
44
+ value :ROUTER_HISTORY, 6
45
+ value :ROUTER_STATS, 7
46
+ value :ROUTER_TEXT_DIRECT, 8
47
+ value :ROUTER_TEXT_BROADCAST, 9
48
+ value :CLIENT_ERROR, 64
49
+ value :CLIENT_HISTORY, 65
50
+ value :CLIENT_STATS, 66
51
+ value :CLIENT_PING, 67
52
+ value :CLIENT_PONG, 68
53
+ value :CLIENT_ABORT, 106
54
+ end
55
+ end
56
+ end
57
+
58
+ module Meshtastic
59
+ StoreAndForward = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.StoreAndForward").msgclass
60
+ StoreAndForward::Statistics = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.StoreAndForward.Statistics").msgclass
61
+ StoreAndForward::History = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.StoreAndForward.History").msgclass
62
+ StoreAndForward::Heartbeat = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.StoreAndForward.Heartbeat").msgclass
63
+ StoreAndForward::RequestResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.StoreAndForward.RequestResponse").enummodule
64
+ end