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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87f863cdd44f899cd5dac5c3dec132b88c4851d0e2a27642cfe1a2832e4b22b4
4
- data.tar.gz: 7e1e8630780251ea8288a74572d8ea7a9ea3e1e53b524937245822667159f17f
3
+ metadata.gz: a3b25733439f146126ff2350cde20e82173b75f4a7118df83cbd7ac09715832a
4
+ data.tar.gz: f9296bf726f9399867171a02c5f261f3bd5c5fc264efc6323029d3a959d9a3e8
5
5
  SHA512:
6
- metadata.gz: 121ec8034eb3620b36ea8ca360ea3c3698ea8d4953ea31f5aee35360865553879d6d635921e184c1b64692fdc422685241596cf4f6adec5dea8493f254585fe2
7
- data.tar.gz: bf802728fea13ae6cbcdd6997f8eccf4b2947859dfb830edc685f68f32424c6c4e884f4cbabd5fca16a003bbf1e58c078a9b3d1fffe3907e1bb2d14c67dc56b2
6
+ metadata.gz: 7d1ab98506914f93b8fc3e6e5a792a7c8bd8e0c70cb8a88046ceaf7fb1f7617a127d1f450d175f90aec7bb22e7c605cd442e2d0db5efffcefb362a660ad65152
7
+ data.tar.gz: 114f31f2563fb18099ddfba9b915b1b540c1b463098648a70530f60c81891cd522ffe7adceef632f82320490b8bd8fcb0110a77a6f3b5fc5b00dc8e60e12f7f1
@@ -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 = decoded_payload_hash[:channel_id].to_s.to_sym
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')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Meshtastic
4
- VERSION = '0.0.50'
4
+ VERSION = '0.0.51'
5
5
  end
data/lib/meshtastic.rb CHANGED
@@ -51,26 +51,40 @@ module Meshtastic
51
51
 
52
52
  # Supported Method Parameters::
53
53
  # Meshtastic.send_text(
54
- # from_id: 'optional - Source ID (Default: 0)',
55
- # dest_id: 'optional - Destination ID (Default: 0xFFFFFFFF)',
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
- # psk: 'optional - Pre-Shared Key if Encrypted (Default: nil)'
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
- from_id = opts[:from_id].to_i
66
- dest_id = opts[:dest_id] ||= 0xFFFFFFFF
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
- psk = opts[:psk]
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
- from_id: from_id,
88
- dest_id: dest_id,
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
- psk: psk
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
- # from_id: 'optional - Source ID (Default: 0)',
104
- # dest_id: 'optional - Destination ID (Default: 0xFFFFFFFF)',
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
- # psk: 'optional - Pre-Shared Key if Encrypted (Default: nil)'
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
- from_id = opts[:from_id].to_i
114
- dest_id = opts[:dest_id] ||= 0xFFFFFFFF
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
- psk = opts[:psk]
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
- from_id: from_id,
134
- dest_id: dest_id,
161
+ from: from,
162
+ to: to,
163
+ channel: channel,
135
164
  want_ack: want_ack,
136
165
  hop_limit: hop_limit,
137
- psk: psk
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
- # from_id: 'optional - Source ID (Default: 0)',
147
- # dest_id: 'optional - Destination ID (Default: 0xFFFFFFFF)',
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
- # psk: 'optional - Pre-Shared Key if Encrypted (Default: nil)'
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
- from_id = opts[:from_id] ||= 0
155
- dest_id = opts[:dest_id] ||= 0xFFFFFFFF
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
- psk = opts[:psk]
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 dest_id != my_info.my_node_num && my_info.is_a(Meshtastic::Deviceonly::MyInfo)
162
-
163
- node_num = dest_id
164
- node_num_hex = dest_id.bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if dest_id.is_a?(String)
165
- node_num = node_num_hex.to_i(16) if node_num_hex
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 psk
215
+ if psks
175
216
  nonce_packet_id = [mesh_packet.id].pack('V').ljust(8, "\x00")
176
- nonce_from_node = [from_id].pack('V').ljust(8, "\x00")
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.to_s
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
- # puts mesh_packet.to_h
233
+ puts mesh_packet.to_h
192
234
 
193
- # to_radio = Meshtastic::ToRadio.new
194
- # to_radio.packet = mesh_packet
195
- # send_to_radio(to_radio: to_radio)
235
+ to_radio = Meshtastic::ToRadio.new
236
+ to_radio.packet = mesh_packet
196
237
 
197
- mesh_packet
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
- packet_id = last_packet_id + 1 if last_packet_id.positive?
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.50
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-09 00:00:00.000000000 Z
11
+ date: 2024-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler