meshtastic 0.0.85 → 0.0.86
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.
- checksums.yaml +4 -4
- data/lib/meshtastic/mqtt.rb +5 -158
- data/lib/meshtastic/version.rb +1 -1
- data/lib/meshtastic.rb +156 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 708e04cee865ae3b9fdaee52fa9be682f6d2c57a2764b1b4ba43fb5b6cff0397
|
4
|
+
data.tar.gz: f4da627c0ae92fa039722bdd8e320cca5388a6158bd61b1acee2c4866de2b066
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfc0314cdbd69e3b41a3f5caf6b8d094210d9d0e91022ce29ee536c6dc5d713bfc38a5aab31b9f74a28fe6f8c1c39d57c2889ba7c39db9ba547d947f1c1a83ae
|
7
|
+
data.tar.gz: 494de489ecf82f4927614bb82730c5dddb565155260f29dc29851fc9aee0be6f00272b801d991732934f7b351661ca97b63c2ca14b187a9033f8235f15ac315d
|
data/lib/meshtastic/mqtt.rb
CHANGED
@@ -20,7 +20,7 @@ module Meshtastic
|
|
20
20
|
# port: 'optional - mqtt port (defaults: 1883)',
|
21
21
|
# username: 'optional - mqtt username (default: meshdev)',
|
22
22
|
# password: 'optional - (default: large4cats)',
|
23
|
-
# client_id: 'optional - client ID (default: random
|
23
|
+
# client_id: 'optional - client ID (default: random 4-byte hex string)'
|
24
24
|
# )
|
25
25
|
|
26
26
|
public_class_method def self.connect(opts = {})
|
@@ -29,7 +29,7 @@ module Meshtastic
|
|
29
29
|
port = opts[:port] ||= 1883
|
30
30
|
username = opts[:username] ||= 'meshdev'
|
31
31
|
password = opts[:password] ||= 'large4cats'
|
32
|
-
client_id = opts[:client_id] ||= SecureRandom.random_bytes(
|
32
|
+
client_id = opts[:client_id] ||= SecureRandom.random_bytes(4).unpack1('H*').to_s
|
33
33
|
|
34
34
|
MQTTClient.connect(
|
35
35
|
host: host,
|
@@ -42,137 +42,6 @@ module Meshtastic
|
|
42
42
|
raise e
|
43
43
|
end
|
44
44
|
|
45
|
-
# Supported Method Parameters::
|
46
|
-
# Meshtastic::MQQT.get_cipher_keys(
|
47
|
-
# psks: 'required - hash of channel / pre-shared key value pairs'
|
48
|
-
# )
|
49
|
-
|
50
|
-
private_class_method def self.get_cipher_keys(opts = {})
|
51
|
-
psks = opts[:psks]
|
52
|
-
|
53
|
-
psks.each_key do |key|
|
54
|
-
psk = psks[key]
|
55
|
-
padded_psk = psk.ljust(psk.length + ((4 - (psk.length % 4)) % 4), '=')
|
56
|
-
replaced_psk = padded_psk.gsub('-', '+').gsub('_', '/')
|
57
|
-
psks[key] = replaced_psk
|
58
|
-
end
|
59
|
-
|
60
|
-
psks
|
61
|
-
rescue StandardError => e
|
62
|
-
raise e
|
63
|
-
end
|
64
|
-
|
65
|
-
# Supported Method Parameters::
|
66
|
-
# Meshtastic::MQQT.decode_payload(
|
67
|
-
# payload: 'required - payload to recursively decode',
|
68
|
-
# msg_type: 'required - message type (e.g. :TEXT_MESSAGE_APP)',
|
69
|
-
# gps_metadata: 'optional - include GPS metadata in output (default: false)',
|
70
|
-
# )
|
71
|
-
|
72
|
-
public_class_method def self.decode_payload(opts = {})
|
73
|
-
payload = opts[:payload]
|
74
|
-
msg_type = opts[:msg_type]
|
75
|
-
gps_metadata = opts[:gps_metadata]
|
76
|
-
|
77
|
-
case msg_type
|
78
|
-
when :ADMIN_APP
|
79
|
-
decoder = Meshtastic::AdminMessage
|
80
|
-
when :ATAK_FORWARDER, :ATAK_PLUGIN
|
81
|
-
decoder = Meshtastic::TAKPacket
|
82
|
-
# when :AUDIO_APP
|
83
|
-
# decoder = Meshtastic::Audio
|
84
|
-
when :DETECTION_SENSOR_APP
|
85
|
-
decoder = Meshtastic::DeviceState
|
86
|
-
# when :IP_TUNNEL_APP
|
87
|
-
# decoder = Meshtastic::IpTunnel
|
88
|
-
when :MAP_REPORT_APP
|
89
|
-
decoder = Meshtastic::MapReport
|
90
|
-
# when :MAX
|
91
|
-
# decoder = Meshtastic::Max
|
92
|
-
when :NEIGHBORINFO_APP
|
93
|
-
decoder = Meshtastic::NeighborInfo
|
94
|
-
when :NODEINFO_APP
|
95
|
-
decoder = Meshtastic::User
|
96
|
-
when :PAXCOUNTER_APP
|
97
|
-
decoder = Meshtastic::Paxcount
|
98
|
-
when :POSITION_APP
|
99
|
-
decoder = Meshtastic::Position
|
100
|
-
# when :PRIVATE_APP
|
101
|
-
# decoder = Meshtastic::Private
|
102
|
-
when :RANGE_TEST_APP
|
103
|
-
# Unsure if this is the correct protobuf object
|
104
|
-
decoder = Meshtastic::FromRadio
|
105
|
-
when :REMOTE_HARDWARE_APP
|
106
|
-
decoder = Meshtastic::HardwareMessage
|
107
|
-
# when :REPLY_APP
|
108
|
-
# decoder = Meshtastic::Reply
|
109
|
-
when :ROUTING_APP
|
110
|
-
decoder = Meshtastic::Routing
|
111
|
-
when :SERIAL_APP
|
112
|
-
decoder = Meshtastic::SerialConnectionStatus
|
113
|
-
when :SIMULATOR_APP
|
114
|
-
decoder = Meshtastic::Compressed
|
115
|
-
when :STORE_FORWARD_APP
|
116
|
-
decoder = Meshtastic::StoreAndForward
|
117
|
-
when :TEXT_MESSAGE_APP, :UNKNOWN_APP
|
118
|
-
decoder = Meshtastic::Data
|
119
|
-
when :TELEMETRY_APP
|
120
|
-
decoder = Meshtastic::Telemetry
|
121
|
-
when :TRACEROUTE_APP
|
122
|
-
decoder = Meshtastic::RouteDiscovery
|
123
|
-
when :WAYPOINT_APP
|
124
|
-
decoder = Meshtastic::Waypoint
|
125
|
-
# when :ZPS_APP
|
126
|
-
# decoder = Meshtastic::Zps
|
127
|
-
else
|
128
|
-
puts "WARNING: Can't decode\n#{payload.inspect}\nw/ portnum: #{msg_type}"
|
129
|
-
return payload
|
130
|
-
end
|
131
|
-
|
132
|
-
payload = decoder.decode(payload).to_h
|
133
|
-
|
134
|
-
if payload.keys.include?(:latitude_i)
|
135
|
-
lat = payload[:latitude_i] * 0.0000001
|
136
|
-
payload[:latitude] = lat
|
137
|
-
end
|
138
|
-
|
139
|
-
if payload.keys.include?(:longitude_i)
|
140
|
-
lon = payload[:longitude_i] * 0.0000001
|
141
|
-
payload[:longitude] = lon
|
142
|
-
end
|
143
|
-
|
144
|
-
if payload.keys.include?(:macaddr)
|
145
|
-
mac_raw = payload[:macaddr]
|
146
|
-
mac_hex_arr = mac_raw.bytes.map { |byte| byte.to_s(16).rjust(2, '0') }
|
147
|
-
mac_hex_str = mac_hex_arr.join(':')
|
148
|
-
payload[:macaddr] = mac_hex_str
|
149
|
-
end
|
150
|
-
|
151
|
-
if payload.keys.include?(:time)
|
152
|
-
time_int = payload[:time]
|
153
|
-
if time_int.is_a?(Integer)
|
154
|
-
time_utc = Time.at(time_int).utc.to_s
|
155
|
-
payload[:time_utc] = time_utc
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
if gps_metadata && payload[:latitude] && payload[:longitude]
|
160
|
-
lat = payload[:latitude]
|
161
|
-
lon = payload[:longitude]
|
162
|
-
unless lat.zero? && lon.zero?
|
163
|
-
gps_search_resp = gps_search(lat: lat, lon: lon)
|
164
|
-
payload[:gps_metadata] = gps_search_resp
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
payload
|
169
|
-
rescue Encoding::CompatibilityError,
|
170
|
-
Google::Protobuf::ParseError
|
171
|
-
payload
|
172
|
-
rescue StandardError => e
|
173
|
-
raise e
|
174
|
-
end
|
175
|
-
|
176
45
|
# Supported Method Parameters::
|
177
46
|
# Meshtastic::MQQT.subscribe(
|
178
47
|
# mqtt_obj: 'required - mqtt_obj returned from #connect method'
|
@@ -198,7 +67,7 @@ module Meshtastic
|
|
198
67
|
raise 'ERROR: psks parameter must be a hash of :channel => psk key value pairs' unless psks.is_a?(Hash)
|
199
68
|
|
200
69
|
psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
|
201
|
-
psks = get_cipher_keys(psks: psks)
|
70
|
+
psks = Meshtastic.get_cipher_keys(psks: psks)
|
202
71
|
|
203
72
|
qos = opts[:qos] ||= 0
|
204
73
|
json = opts[:json] ||= false
|
@@ -278,7 +147,7 @@ module Meshtastic
|
|
278
147
|
# payload = Meshtastic::Data.decode(message[:decoded][:payload]).to_h
|
279
148
|
payload = message[:decoded][:payload]
|
280
149
|
msg_type = message[:decoded][:portnum]
|
281
|
-
message[:decoded][:payload] = decode_payload(
|
150
|
+
message[:decoded][:payload] = Meshtastic.decode_payload(
|
282
151
|
payload: payload,
|
283
152
|
msg_type: msg_type,
|
284
153
|
gps_metadata: gps_metadata
|
@@ -361,6 +230,7 @@ module Meshtastic
|
|
361
230
|
topic = opts[:topic] ||= 'msh/US/2/e/LongFast/#'
|
362
231
|
opts[:via] = :mqtt
|
363
232
|
|
233
|
+
# TODO: Implement chunked message to deal with large messages
|
364
234
|
protobuf_text = Meshtastic.send_text(opts)
|
365
235
|
|
366
236
|
mqtt_obj.publish(topic, protobuf_text)
|
@@ -368,24 +238,6 @@ module Meshtastic
|
|
368
238
|
raise e
|
369
239
|
end
|
370
240
|
|
371
|
-
# Supported Method Parameters::
|
372
|
-
# mqtt_obj = Meshtastic.gps_search(
|
373
|
-
# lat: 'required - latitude float (e.g. 37.7749)',
|
374
|
-
# lon: 'required - longitude float (e.g. -122.4194)',
|
375
|
-
# )
|
376
|
-
public_class_method def self.gps_search(opts = {})
|
377
|
-
lat = opts[:lat]
|
378
|
-
lon = opts[:lon]
|
379
|
-
|
380
|
-
raise 'ERROR: Latitude and Longitude are required' unless lat && lon
|
381
|
-
|
382
|
-
gps_arr = [lat.to_f, lon.to_f]
|
383
|
-
|
384
|
-
Geocoder.search(gps_arr).first.data
|
385
|
-
rescue StandardError => e
|
386
|
-
raise e
|
387
|
-
end
|
388
|
-
|
389
241
|
# Supported Method Parameters::
|
390
242
|
# mqtt_obj = Meshtastic.disconnect(
|
391
243
|
# mqtt_obj: 'required - mqtt_obj returned from #connect method'
|
@@ -431,11 +283,6 @@ module Meshtastic
|
|
431
283
|
gps_metadata: 'optional - include GPS metadata in output (default: false)'
|
432
284
|
)
|
433
285
|
|
434
|
-
#{self}.gps_search(
|
435
|
-
lat: 'required - latitude float (e.g. 37.7749)',
|
436
|
-
lon: 'required - longitude float (e.g. -122.4194)',
|
437
|
-
)
|
438
|
-
|
439
286
|
#{self}.send_text(
|
440
287
|
mqtt_obj: 'required - mqtt_obj returned from #connect method',
|
441
288
|
from: ' required - From ID (String or Integer)',
|
data/lib/meshtastic/version.rb
CHANGED
data/lib/meshtastic.rb
CHANGED
@@ -282,6 +282,26 @@ module Meshtastic
|
|
282
282
|
packet_id
|
283
283
|
end
|
284
284
|
|
285
|
+
# Supported Method Parameters::
|
286
|
+
# Meshtastic.get_cipher_keys(
|
287
|
+
# psks: 'required - hash of channel / pre-shared key value pairs'
|
288
|
+
# )
|
289
|
+
|
290
|
+
public_class_method def self.get_cipher_keys(opts = {})
|
291
|
+
psks = opts[:psks]
|
292
|
+
|
293
|
+
psks.each_key do |key|
|
294
|
+
psk = psks[key]
|
295
|
+
padded_psk = psk.ljust(psk.length + ((4 - (psk.length % 4)) % 4), '=')
|
296
|
+
replaced_psk = padded_psk.gsub('-', '+').gsub('_', '/')
|
297
|
+
psks[key] = replaced_psk
|
298
|
+
end
|
299
|
+
|
300
|
+
psks
|
301
|
+
rescue StandardError => e
|
302
|
+
raise e
|
303
|
+
end
|
304
|
+
|
285
305
|
# Supported Method Parameters::
|
286
306
|
# Meshtastic.send_to_radio(
|
287
307
|
# to_radio: 'required - ToRadio Message to Send'
|
@@ -310,6 +330,135 @@ module Meshtastic
|
|
310
330
|
raise e
|
311
331
|
end
|
312
332
|
|
333
|
+
# Supported Method Parameters::
|
334
|
+
# Meshtastic.gps_search(
|
335
|
+
# lat: 'required - latitude float (e.g. 37.7749)',
|
336
|
+
# lon: 'required - longitude float (e.g. -122.4194)',
|
337
|
+
# )
|
338
|
+
public_class_method def self.gps_search(opts = {})
|
339
|
+
lat = opts[:lat]
|
340
|
+
lon = opts[:lon]
|
341
|
+
|
342
|
+
raise 'ERROR: Latitude and Longitude are required' unless lat && lon
|
343
|
+
|
344
|
+
gps_arr = [lat.to_f, lon.to_f]
|
345
|
+
|
346
|
+
Geocoder.search(gps_arr).first.data
|
347
|
+
rescue StandardError => e
|
348
|
+
raise e
|
349
|
+
end
|
350
|
+
|
351
|
+
# Supported Method Parameters::
|
352
|
+
# Meshtastic::MQQT.decode_payload(
|
353
|
+
# payload: 'required - payload to recursively decode',
|
354
|
+
# msg_type: 'required - message type (e.g. :TEXT_MESSAGE_APP)',
|
355
|
+
# gps_metadata: 'optional - include GPS metadata in output (default: false)',
|
356
|
+
# )
|
357
|
+
|
358
|
+
public_class_method def self.decode_payload(opts = {})
|
359
|
+
payload = opts[:payload]
|
360
|
+
msg_type = opts[:msg_type]
|
361
|
+
gps_metadata = opts[:gps_metadata]
|
362
|
+
|
363
|
+
case msg_type
|
364
|
+
when :ADMIN_APP
|
365
|
+
decoder = Meshtastic::AdminMessage
|
366
|
+
when :ATAK_FORWARDER, :ATAK_PLUGIN
|
367
|
+
decoder = Meshtastic::TAKPacket
|
368
|
+
# when :AUDIO_APP
|
369
|
+
# decoder = Meshtastic::Audio
|
370
|
+
when :DETECTION_SENSOR_APP
|
371
|
+
decoder = Meshtastic::DeviceState
|
372
|
+
# when :IP_TUNNEL_APP
|
373
|
+
# decoder = Meshtastic::IpTunnel
|
374
|
+
when :MAP_REPORT_APP
|
375
|
+
decoder = Meshtastic::MapReport
|
376
|
+
# when :MAX
|
377
|
+
# decoder = Meshtastic::Max
|
378
|
+
when :NEIGHBORINFO_APP
|
379
|
+
decoder = Meshtastic::NeighborInfo
|
380
|
+
when :NODEINFO_APP
|
381
|
+
decoder = Meshtastic::User
|
382
|
+
when :PAXCOUNTER_APP
|
383
|
+
decoder = Meshtastic::Paxcount
|
384
|
+
when :POSITION_APP
|
385
|
+
decoder = Meshtastic::Position
|
386
|
+
# when :PRIVATE_APP
|
387
|
+
# decoder = Meshtastic::Private
|
388
|
+
when :RANGE_TEST_APP
|
389
|
+
# Unsure if this is the correct protobuf object
|
390
|
+
decoder = Meshtastic::FromRadio
|
391
|
+
when :REMOTE_HARDWARE_APP
|
392
|
+
decoder = Meshtastic::HardwareMessage
|
393
|
+
# when :REPLY_APP
|
394
|
+
# decoder = Meshtastic::Reply
|
395
|
+
when :ROUTING_APP
|
396
|
+
decoder = Meshtastic::Routing
|
397
|
+
when :SERIAL_APP
|
398
|
+
decoder = Meshtastic::SerialConnectionStatus
|
399
|
+
when :SIMULATOR_APP
|
400
|
+
decoder = Meshtastic::Compressed
|
401
|
+
when :STORE_FORWARD_APP
|
402
|
+
decoder = Meshtastic::StoreAndForward
|
403
|
+
when :TEXT_MESSAGE_APP, :UNKNOWN_APP
|
404
|
+
decoder = Meshtastic::Data
|
405
|
+
when :TELEMETRY_APP
|
406
|
+
decoder = Meshtastic::Telemetry
|
407
|
+
when :TRACEROUTE_APP
|
408
|
+
decoder = Meshtastic::RouteDiscovery
|
409
|
+
when :WAYPOINT_APP
|
410
|
+
decoder = Meshtastic::Waypoint
|
411
|
+
# when :ZPS_APP
|
412
|
+
# decoder = Meshtastic::Zps
|
413
|
+
else
|
414
|
+
puts "WARNING: Can't decode\n#{payload.inspect}\nw/ portnum: #{msg_type}"
|
415
|
+
return payload
|
416
|
+
end
|
417
|
+
|
418
|
+
payload = decoder.decode(payload).to_h
|
419
|
+
|
420
|
+
if payload.keys.include?(:latitude_i)
|
421
|
+
lat = payload[:latitude_i] * 0.0000001
|
422
|
+
payload[:latitude] = lat
|
423
|
+
end
|
424
|
+
|
425
|
+
if payload.keys.include?(:longitude_i)
|
426
|
+
lon = payload[:longitude_i] * 0.0000001
|
427
|
+
payload[:longitude] = lon
|
428
|
+
end
|
429
|
+
|
430
|
+
if payload.keys.include?(:macaddr)
|
431
|
+
mac_raw = payload[:macaddr]
|
432
|
+
mac_hex_arr = mac_raw.bytes.map { |byte| byte.to_s(16).rjust(2, '0') }
|
433
|
+
mac_hex_str = mac_hex_arr.join(':')
|
434
|
+
payload[:macaddr] = mac_hex_str
|
435
|
+
end
|
436
|
+
|
437
|
+
if payload.keys.include?(:time)
|
438
|
+
time_int = payload[:time]
|
439
|
+
if time_int.is_a?(Integer)
|
440
|
+
time_utc = Time.at(time_int).utc.to_s
|
441
|
+
payload[:time_utc] = time_utc
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
if gps_metadata && payload[:latitude] && payload[:longitude]
|
446
|
+
lat = payload[:latitude]
|
447
|
+
lon = payload[:longitude]
|
448
|
+
unless lat.zero? && lon.zero?
|
449
|
+
gps_search_resp = gps_search(lat: lat, lon: lon)
|
450
|
+
payload[:gps_metadata] = gps_search_resp
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
payload
|
455
|
+
rescue Encoding::CompatibilityError,
|
456
|
+
Google::Protobuf::ParseError
|
457
|
+
payload
|
458
|
+
rescue StandardError => e
|
459
|
+
raise e
|
460
|
+
end
|
461
|
+
|
313
462
|
# Author(s):: 0day Inc. <support@0dayinc.com>
|
314
463
|
|
315
464
|
public_class_method def self.authors
|
@@ -322,5 +471,12 @@ module Meshtastic
|
|
322
471
|
|
323
472
|
public_class_method def self.help
|
324
473
|
constants.sort
|
474
|
+
|
475
|
+
# puts "USAGE:
|
476
|
+
# #{self}.gps_search(
|
477
|
+
# lat: 'required - latitude float (e.g. 37.7749)',
|
478
|
+
# lon: 'required - longitude float (e.g. -122.4194)',
|
479
|
+
# )
|
480
|
+
# "
|
325
481
|
end
|
326
482
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: meshtastic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.86
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 0day Inc.
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-02-03 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: bundler
|