meshtastic 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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