meshtastic 0.0.50 → 0.0.51
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/meshtastic/mqtt.rb +6 -2
- data/lib/meshtastic/version.rb +1 -1
- data/lib/meshtastic.rb +85 -46
- 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: a3b25733439f146126ff2350cde20e82173b75f4a7118df83cbd7ac09715832a
|
4
|
+
data.tar.gz: f9296bf726f9399867171a02c5f261f3bd5c5fc264efc6323029d3a959d9a3e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d1ab98506914f93b8fc3e6e5a792a7c8bd8e0c70cb8a88046ceaf7fb1f7617a127d1f450d175f90aec7bb22e7c605cd442e2d0db5efffcefb362a660ad65152
|
7
|
+
data.tar.gz: 114f31f2563fb18099ddfba9b915b1b540c1b463098648a70530f60c81891cd522ffe7adceef632f82320490b8bd8fcb0110a77a6f3b5fc5b00dc8e60e12f7f1
|
data/lib/meshtastic/mqtt.rb
CHANGED
@@ -248,7 +248,9 @@ module Meshtastic
|
|
248
248
|
# If encrypted_message is not nil, then decrypt
|
249
249
|
# the message prior to decoding.
|
250
250
|
encrypted_message = message[:encrypted]
|
251
|
-
if encrypted_message.to_s.length.positive?
|
251
|
+
if encrypted_message.to_s.length.positive? &&
|
252
|
+
message[:topic]
|
253
|
+
|
252
254
|
packet_id = message[:id]
|
253
255
|
packet_from = message[:from]
|
254
256
|
|
@@ -257,8 +259,10 @@ module Meshtastic
|
|
257
259
|
nonce = "#{nonce_packet_id}#{nonce_from_node}".b
|
258
260
|
|
259
261
|
psk = psks[:LongFast]
|
260
|
-
target_channel =
|
262
|
+
target_channel = message[:topic].split('/')[-2].to_sym
|
263
|
+
puts "Target Channel: #{target_channel}"
|
261
264
|
psk = psks[target_channel] if psks.keys.include?(target_channel)
|
265
|
+
puts "PSK: #{psk}"
|
262
266
|
dec_psk = Base64.strict_decode64(psk)
|
263
267
|
|
264
268
|
cipher = OpenSSL::Cipher.new('AES-128-CTR')
|
data/lib/meshtastic/version.rb
CHANGED
data/lib/meshtastic.rb
CHANGED
@@ -51,26 +51,40 @@ module Meshtastic
|
|
51
51
|
|
52
52
|
# Supported Method Parameters::
|
53
53
|
# Meshtastic.send_text(
|
54
|
-
#
|
55
|
-
#
|
54
|
+
# from: 'required - From ID (String or Integer)',
|
55
|
+
# to: 'optional - Destination ID (Default: 0xFFFFFFFF)',
|
56
|
+
# channel: 'optional - Channel ID (Default: 0)',
|
56
57
|
# text: 'optional - Text Message (Default: SYN)',
|
57
58
|
# want_ack: 'optional - Want Acknowledgement (Default: false)',
|
58
59
|
# want_response: 'optional - Want Response (Default: false)',
|
59
60
|
# hop_limit: 'optional - Hop Limit (Default: 3)',
|
60
61
|
# on_response: 'optional - Callback on Response',
|
61
|
-
#
|
62
|
+
# psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: "AQ==" })'
|
62
63
|
# )
|
63
64
|
public_class_method def self.send_text(opts = {})
|
64
65
|
# Send a text message to a node
|
65
|
-
|
66
|
-
|
66
|
+
from = opts[:from]
|
67
|
+
from_hex = from.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if from.is_a?(String)
|
68
|
+
from = from_hex.to_i(16) if from_hex
|
69
|
+
raise 'ERROR: from parameter is required.' unless from
|
70
|
+
|
71
|
+
to = opts[:to] ||= 0xFFFFFFFF
|
72
|
+
to_hex = to.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if to.is_a?(String)
|
73
|
+
to = to_hex.to_i(16) if to_hex
|
74
|
+
|
75
|
+
channel = opts[:channel] ||= 0
|
67
76
|
text = opts[:text] ||= 'SYN'
|
68
77
|
want_ack = opts[:want_ack] ||= false
|
69
78
|
want_response = opts[:want_response] ||= false
|
70
79
|
hop_limit = opts[:hop_limit] ||= 3
|
71
80
|
on_response = opts[:on_response]
|
72
|
-
|
73
|
-
|
81
|
+
|
82
|
+
public_psk = '1PG7OiApB1nwvP+rz05pAQ=='
|
83
|
+
psks = opts[:psks] ||= { LongFast: public_psk }
|
84
|
+
raise 'ERROR: psks parameter must be a hash of :channel => psk key value pairs' unless psks.is_a?(Hash)
|
85
|
+
|
86
|
+
psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
|
87
|
+
|
74
88
|
# TODO: verify text length validity
|
75
89
|
max_txt_len = Meshtastic::Constants::DATA_PAYLOAD_LEN
|
76
90
|
raise "ERROR: Text Length > #{max_txt_len} Bytes" if text.length > max_txt_len
|
@@ -84,15 +98,16 @@ module Meshtastic
|
|
84
98
|
puts data.to_h
|
85
99
|
|
86
100
|
send_data(
|
87
|
-
|
88
|
-
|
101
|
+
from: from,
|
102
|
+
to: to,
|
103
|
+
channel: channel,
|
89
104
|
data: data,
|
90
105
|
want_ack: want_ack,
|
91
106
|
want_response: want_response,
|
92
107
|
hop_limit: hop_limit,
|
93
108
|
port_num: port_num,
|
94
109
|
on_response: on_response,
|
95
|
-
|
110
|
+
psks: psks
|
96
111
|
)
|
97
112
|
rescue StandardError => e
|
98
113
|
raise e
|
@@ -100,18 +115,27 @@ module Meshtastic
|
|
100
115
|
|
101
116
|
# Supported Method Parameters::
|
102
117
|
# Meshtastic.send_data(
|
103
|
-
#
|
104
|
-
#
|
118
|
+
# from: 'required - From ID (String or Integer)',
|
119
|
+
# to: 'optional - Destination ID (Default: 0xFFFFFFFF)',
|
120
|
+
# channel: 'optional - Channel ID (Default: 0)',
|
105
121
|
# data: 'required - Data to Send',
|
106
122
|
# want_ack: 'optional - Want Acknowledgement (Default: false)',
|
107
123
|
# hop_limit: 'optional - Hop Limit (Default: 3)',
|
108
124
|
# port_num: 'optional - (Default: Meshtastic::PortNum::PRIVATE_APP)',
|
109
|
-
#
|
125
|
+
# psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: "AQ==" })'
|
110
126
|
# )
|
111
127
|
public_class_method def self.send_data(opts = {})
|
112
128
|
# Send a text message to a node
|
113
|
-
|
114
|
-
|
129
|
+
from = opts[:from]
|
130
|
+
from_hex = from.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if from.is_a?(String)
|
131
|
+
from = from_hex.to_i(16) if from_hex
|
132
|
+
raise 'ERROR: from parameter is required.' unless from
|
133
|
+
|
134
|
+
to = opts[:to] ||= 0xFFFFFFFF
|
135
|
+
to_hex = to.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if to.is_a?(String)
|
136
|
+
to = to_hex.to_i(16) if to_hex
|
137
|
+
|
138
|
+
channel = opts[:channel] ||= 0
|
115
139
|
data = opts[:data]
|
116
140
|
want_ack = opts[:want_ack] ||= false
|
117
141
|
hop_limit = opts[:hop_limit] ||= 3
|
@@ -119,7 +143,11 @@ module Meshtastic
|
|
119
143
|
max_port_num = Meshtastic::PortNum::MAX
|
120
144
|
raise "ERROR: Invalid port_num" unless port_num.positive? && port_num < max_port_num
|
121
145
|
|
122
|
-
|
146
|
+
public_psk = '1PG7OiApB1nwvP+rz05pAQ=='
|
147
|
+
psks = opts[:psks] ||= { LongFast: public_psk }
|
148
|
+
raise 'ERROR: psks parameter must be a hash of :channel => psk key value pairs' unless psks.is_a?(Hash)
|
149
|
+
|
150
|
+
psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
|
123
151
|
|
124
152
|
data_len = data.payload.length
|
125
153
|
max_len = Meshtastic::Constants::DATA_PAYLOAD_LEN
|
@@ -130,11 +158,12 @@ module Meshtastic
|
|
130
158
|
|
131
159
|
send_packet(
|
132
160
|
mesh_packet: mesh_packet,
|
133
|
-
|
134
|
-
|
161
|
+
from: from,
|
162
|
+
to: to,
|
163
|
+
channel: channel,
|
135
164
|
want_ack: want_ack,
|
136
165
|
hop_limit: hop_limit,
|
137
|
-
|
166
|
+
psks: psks
|
138
167
|
)
|
139
168
|
rescue StandardError => e
|
140
169
|
raise e
|
@@ -143,39 +172,52 @@ module Meshtastic
|
|
143
172
|
# Supported Method Parameters::
|
144
173
|
# Meshtastic.send_packet(
|
145
174
|
# mesh_packet: 'required - Mesh Packet to Send',
|
146
|
-
#
|
147
|
-
#
|
175
|
+
# from: 'required - From ID (String or Integer)',
|
176
|
+
# to: 'optional - Destination ID (Default: 0xFFFFFFFF)',
|
177
|
+
# channel: 'optional - Channel ID (Default: 0)',
|
148
178
|
# want_ack: 'optional - Want Acknowledgement (Default: false)',
|
149
179
|
# hop_limit: 'optional - Hop Limit (Default: 3)',
|
150
|
-
#
|
180
|
+
# psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: "AQ==" })'
|
151
181
|
# )
|
152
182
|
public_class_method def self.send_packet(opts = {})
|
153
183
|
mesh_packet = opts[:mesh_packet]
|
154
|
-
|
155
|
-
|
184
|
+
from = opts[:from]
|
185
|
+
from_hex = from.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if from.is_a?(String)
|
186
|
+
from = from_hex.to_i(16) if from_hex
|
187
|
+
raise 'ERROR: from parameter is required.' unless from
|
188
|
+
|
189
|
+
to = opts[:to] ||= 0xFFFFFFFF
|
190
|
+
to_hex = to.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if to.is_a?(String)
|
191
|
+
to = to_hex.to_i(16) if to_hex
|
192
|
+
|
193
|
+
channel = opts[:channel] ||= 0
|
156
194
|
want_ack = opts[:want_ack] ||= false
|
157
195
|
hop_limit = opts[:hop_limit] ||= 3
|
158
|
-
|
196
|
+
|
197
|
+
public_psk = '1PG7OiApB1nwvP+rz05pAQ=='
|
198
|
+
psks = opts[:psks] ||= { LongFast: public_psk }
|
199
|
+
raise 'ERROR: psks parameter must be a hash of :channel => psk key value pairs' unless psks.is_a?(Hash)
|
200
|
+
|
201
|
+
psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
|
159
202
|
|
160
203
|
# my_info = Meshtastic::FromRadio.my_info
|
161
|
-
# wait_connected if
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
mesh_packet.from = from_id
|
168
|
-
mesh_packet.to = node_num
|
204
|
+
# wait_connected if to != my_info.my_node_num && my_info.is_a(Meshtastic::Deviceonly::MyInfo)
|
205
|
+
|
206
|
+
mesh_packet.from = from
|
207
|
+
mesh_packet.to = to
|
208
|
+
mesh_packet.channel = channel
|
169
209
|
mesh_packet.want_ack = want_ack
|
170
210
|
mesh_packet.hop_limit = hop_limit
|
171
|
-
|
172
211
|
mesh_packet.id = generate_packet_id if mesh_packet.id.zero?
|
212
|
+
# mesh_packet.channel_id = psks.keys.first
|
213
|
+
# mesh_packet.gateway_id = "!#{from.to_s(16).downcase}"
|
173
214
|
|
174
|
-
if
|
215
|
+
if psks
|
175
216
|
nonce_packet_id = [mesh_packet.id].pack('V').ljust(8, "\x00")
|
176
|
-
nonce_from_node = [
|
217
|
+
nonce_from_node = [from].pack('V').ljust(8, "\x00")
|
177
218
|
nonce = "#{nonce_packet_id}#{nonce_from_node}".b
|
178
219
|
|
220
|
+
psk = psks[psks.keys.first]
|
179
221
|
dec_psk = Base64.strict_decode64(psk)
|
180
222
|
cipher = OpenSSL::Cipher.new('AES-128-CTR')
|
181
223
|
cipher = OpenSSL::Cipher.new('AES-256-CTR') if dec_psk.length == 32
|
@@ -183,18 +225,17 @@ module Meshtastic
|
|
183
225
|
cipher.key = dec_psk
|
184
226
|
cipher.iv = nonce
|
185
227
|
|
186
|
-
decrypted_payload = mesh_packet.decoded.
|
228
|
+
decrypted_payload = mesh_packet.decoded.to_proto
|
187
229
|
encrypted_payload = cipher.update(decrypted_payload) + cipher.final
|
188
230
|
|
189
231
|
mesh_packet.encrypted = encrypted_payload
|
190
232
|
end
|
191
|
-
|
233
|
+
puts mesh_packet.to_h
|
192
234
|
|
193
|
-
|
194
|
-
|
195
|
-
# send_to_radio(to_radio: to_radio)
|
235
|
+
to_radio = Meshtastic::ToRadio.new
|
236
|
+
to_radio.packet = mesh_packet
|
196
237
|
|
197
|
-
|
238
|
+
send_to_radio(to_radio: to_radio)
|
198
239
|
rescue StandardError => e
|
199
240
|
raise e
|
200
241
|
end
|
@@ -205,11 +246,9 @@ module Meshtastic
|
|
205
246
|
# )
|
206
247
|
public_class_method def self.generate_packet_id(opts = {})
|
207
248
|
last_packet_id = opts[:last_packet_id] ||= 0
|
249
|
+
last_packet_id = 0 if last_packet_id.negative?
|
208
250
|
|
209
|
-
|
210
|
-
packet_id = rand(2**32) if last_packet_id.zero?
|
211
|
-
|
212
|
-
packet_id
|
251
|
+
(last_packet_id + 1) & 0xffffffff
|
213
252
|
end
|
214
253
|
|
215
254
|
# Supported Method Parameters::
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.51
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 0day Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|