meshtastic 0.0.180 → 0.0.181
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/Gemfile +2 -2
- data/documentation/admin-channel.md +51 -20
- data/documentation/admin-config.md +45 -14
- data/documentation/admin-firmware-nordic.md +86 -0
- data/documentation/admin-firmware-serial.md +180 -0
- data/documentation/admin-firmware.md +103 -46
- data/documentation/admin.md +88 -36
- data/documentation/mesh-interface.md +7 -0
- data/lib/meshtastic/admin/channel.rb +99 -25
- data/lib/meshtastic/admin/config.rb +70 -11
- data/lib/meshtastic/admin/firmware/ble.rb +207 -0
- data/lib/meshtastic/admin/firmware/nordic_dfu.rb +218 -0
- data/lib/meshtastic/admin/firmware/serial_bootloader.rb +233 -0
- data/lib/meshtastic/admin/firmware.rb +208 -93
- data/lib/meshtastic/admin.rb +251 -27
- data/lib/meshtastic/config_pb.rb +2 -1
- data/lib/meshtastic/mesh_interface.rb +8 -0
- data/lib/meshtastic/storeforward_pb.rb +1 -1
- data/lib/meshtastic/version.rb +1 -1
- data/spec/lib/meshtastic/admin/channel_spec.rb +159 -2
- data/spec/lib/meshtastic/admin/config_spec.rb +66 -0
- data/spec/lib/meshtastic/admin/firmware/ble_spec.rb +170 -0
- data/spec/lib/meshtastic/admin/firmware/nordic_dfu_spec.rb +248 -0
- data/spec/lib/meshtastic/admin/firmware/serial_bootloader_spec.rb +263 -0
- data/spec/lib/meshtastic/admin/firmware_spec.rb +292 -95
- data/spec/lib/meshtastic/admin_spec.rb +372 -1
- data/spec/lib/meshtastic/mesh_interface_spec.rb +31 -0
- metadata +14 -6
data/lib/meshtastic/admin.rb
CHANGED
|
@@ -1,34 +1,205 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'timeout'
|
|
4
|
+
require 'monitor'
|
|
3
5
|
require 'meshtastic/admin_pb'
|
|
4
6
|
|
|
5
7
|
module Meshtastic
|
|
6
8
|
module Admin
|
|
9
|
+
class RoutingError < StandardError
|
|
10
|
+
attr_reader :reason, :request_id, :from
|
|
11
|
+
|
|
12
|
+
def initialize(reason, request_id, from)
|
|
13
|
+
@reason = reason
|
|
14
|
+
@request_id = request_id
|
|
15
|
+
@from = from
|
|
16
|
+
super("Admin routing failure: #{reason} (request #{request_id})")
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
7
20
|
SKIP = %i[
|
|
8
21
|
message serial_obj bluetooth_obj tcp_obj mqtt_obj to from channel want_ack hop_limit
|
|
9
22
|
want_response port_num data via psks seconds owner long_name short_name index config_type
|
|
10
|
-
module_config_type path node_num lat lon altitude time
|
|
23
|
+
module_config_type path node_num lat lon altitude time channel_settings channel_pb
|
|
24
|
+
config module_config messages ringtone scale location event event_code kb_char touch_x
|
|
25
|
+
touch_y ham call_sign tx_power frequency position ui_config contact value preserve_favorites
|
|
26
|
+
last_packet_id pki_encrypted public_key topic qos retained timeout auto_session refresh_session
|
|
11
27
|
].freeze
|
|
28
|
+
PAYLOAD_FIELDS = Meshtastic::AdminMessage.descriptor.lookup_oneof('payload_variant').map { |field| field.name.to_sym }.freeze
|
|
12
29
|
|
|
13
30
|
public_class_method def self.encode(opts = {})
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
31
|
+
original = opts[:message] || Meshtastic::AdminMessage.new
|
|
32
|
+
raise ArgumentError, 'message must be an AdminMessage' unless original.is_a?(Meshtastic::AdminMessage)
|
|
33
|
+
|
|
34
|
+
fields = opts.keys & PAYLOAD_FIELDS
|
|
35
|
+
variants = (fields + [original.payload_variant]).compact.uniq
|
|
36
|
+
raise ArgumentError, 'exactly one payload is required' unless variants.length == 1
|
|
37
|
+
|
|
38
|
+
unknown = opts.keys - SKIP - PAYLOAD_FIELDS - [:session_passkey]
|
|
39
|
+
raise ArgumentError, "unknown admin options: #{unknown.join(', ')}" unless unknown.empty?
|
|
18
40
|
|
|
19
|
-
|
|
41
|
+
message = Meshtastic::AdminMessage.decode(original.to_proto)
|
|
42
|
+
fields.each do |key|
|
|
43
|
+
raise ArgumentError, "#{key} cannot be nil" if opts[key].nil?
|
|
44
|
+
|
|
45
|
+
message.public_send("#{key}=", opts[key])
|
|
46
|
+
end
|
|
47
|
+
if opts.key?(:session_passkey)
|
|
48
|
+
passkey = opts[:session_passkey]
|
|
49
|
+
raise ArgumentError, 'session_passkey must contain exactly eight bytes' unless passkey.is_a?(String) && passkey.bytesize == 8
|
|
50
|
+
|
|
51
|
+
message.session_passkey = passkey
|
|
20
52
|
end
|
|
21
53
|
message
|
|
22
54
|
end
|
|
23
55
|
|
|
24
56
|
public_class_method def self.send(opts = {})
|
|
25
57
|
message = encode(opts)
|
|
58
|
+
connection = opts[:serial_obj] || opts[:bluetooth_obj] || opts[:tcp_obj]
|
|
59
|
+
destination = opts[:to] || connection&.dig(:my_node_num)
|
|
60
|
+
destination = destination.delete_prefix('!').to_i(16) if destination.is_a?(String) && destination.match?(/\A![0-9a-fA-F]{8}\z/)
|
|
61
|
+
raise ArgumentError, 'an explicit unicast destination or connected my_node_num is required' unless destination.is_a?(Integer) && destination.between?(1, 0xfffffffe)
|
|
62
|
+
|
|
63
|
+
if opts.fetch(:auto_session, true) && message.session_passkey.empty? && destination != connection&.dig(:my_node_num) &&
|
|
64
|
+
!message.payload_variant.to_s.match?(/\Aget_.*_(request|response)\z/)
|
|
65
|
+
message.session_passkey = acquire_session(opts.merge(connection: connection, target: destination))
|
|
66
|
+
end
|
|
67
|
+
want_response = opts.fetch(:want_response) { message.payload_variant.to_s.match?(/\Aget_.*_request\z/) }
|
|
26
68
|
data = Meshtastic::Data.new(
|
|
27
69
|
portnum: :ADMIN_APP,
|
|
28
70
|
payload: message.to_proto,
|
|
29
|
-
want_response:
|
|
71
|
+
want_response: want_response
|
|
30
72
|
)
|
|
31
|
-
|
|
73
|
+
delivery = opts.merge(data: data, port_num: Meshtastic::PortNum::ADMIN_APP, to: destination)
|
|
74
|
+
delivery[:from] = 0 if connection && !opts.key?(:from)
|
|
75
|
+
Meshtastic.deliver_data(delivery)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
public_class_method def self.request(opts = {})
|
|
79
|
+
request_id = opts.fetch(:request_id) { Random.rand(2..0xffffffff) }
|
|
80
|
+
raise ArgumentError, 'request_id must be an Integer from 2 through 0xffffffff' unless request_id.is_a?(Integer) && request_id.between?(2, 0xffffffff)
|
|
81
|
+
|
|
82
|
+
options = opts.except(:request_id, :wait)
|
|
83
|
+
return { request_id: request_id, result: send(options.merge(last_packet_id: request_id - 1)) } unless opts.fetch(:wait, true)
|
|
84
|
+
|
|
85
|
+
connection = options[:serial_obj] || options[:bluetooth_obj] || options[:tcp_obj]
|
|
86
|
+
queue = connection && connection[:from_radio_queue]
|
|
87
|
+
raise ArgumentError, 'synchronous Admin requires a connected radio receive queue' unless queue
|
|
88
|
+
|
|
89
|
+
timeout = opts.fetch(:timeout, 10)
|
|
90
|
+
raise ArgumentError, 'timeout must be a positive finite number' unless timeout.is_a?(Numeric) && timeout.positive? && timeout.finite?
|
|
91
|
+
|
|
92
|
+
lock = connection[:admin_request_lock] ||= Monitor.new
|
|
93
|
+
acquired = lock.try_enter
|
|
94
|
+
raise IOError, 'a synchronous Admin request is already active on this handle' unless acquired
|
|
95
|
+
|
|
96
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
|
|
97
|
+
message = encode(options)
|
|
98
|
+
target = options.fetch(:to, connection[:my_node_num])
|
|
99
|
+
target = target.delete_prefix('!').to_i(16) if target.is_a?(String) && target.match?(/\A![0-9a-fA-F]{8}\z/)
|
|
100
|
+
result = send(options.merge(last_packet_id: request_id - 1, want_response: true, want_ack: true, timeout: timeout))
|
|
101
|
+
variant = message.payload_variant.to_s
|
|
102
|
+
expected = variant.match?(/\Aget_.*_request\z/) ? variant.sub(/_request\z/, '_response').to_sym : :routing
|
|
103
|
+
reply = await_response(connection: connection, queue: queue, deadline: deadline, request_id: request_id, target: target,
|
|
104
|
+
variant: expected)
|
|
105
|
+
if reply[:session_passkey]&.bytesize == 8
|
|
106
|
+
sessions = connection[:admin_sessions] ||= {}
|
|
107
|
+
sessions[target] = { key: reply[:session_passkey], expires_at: deadline - timeout + 150 }
|
|
108
|
+
end
|
|
109
|
+
reply.merge(result: result)
|
|
110
|
+
rescue RoutingError => e
|
|
111
|
+
connection[:admin_sessions]&.delete(target) if connection && e.reason == :ADMIN_BAD_SESSION_KEY
|
|
112
|
+
raise
|
|
113
|
+
ensure
|
|
114
|
+
lock.exit if acquired
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
private_class_method def self.acquire_session(opts = {})
|
|
118
|
+
connection = opts[:connection]
|
|
119
|
+
raise ArgumentError, 'automatic Admin sessions require a radio receive queue; supply session_passkey for MQTT' unless connection && connection[:from_radio_queue]
|
|
120
|
+
|
|
121
|
+
sessions = connection[:admin_sessions] ||= {}
|
|
122
|
+
cached = sessions[opts[:target]]
|
|
123
|
+
now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
124
|
+
return cached[:key] if cached && now < cached[:expires_at] && !opts[:refresh_session]
|
|
125
|
+
|
|
126
|
+
sessions.delete(opts[:target])
|
|
127
|
+
options = opts.except(*(PAYLOAD_FIELDS + %i[message connection target session_passkey refresh_session last_packet_id]))
|
|
128
|
+
reply = request(options.merge(get_config_request: :SESSIONKEY_CONFIG, auto_session: false))
|
|
129
|
+
key = reply[:session_passkey]
|
|
130
|
+
raise ArgumentError, 'Admin session response did not contain an eight-byte passkey' unless key.bytesize == 8
|
|
131
|
+
|
|
132
|
+
sessions[opts[:target]] = { key: key, expires_at: now + 150 }
|
|
133
|
+
key
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private_class_method def self.await_response(opts = {})
|
|
137
|
+
queue = opts[:queue]
|
|
138
|
+
deferred = []
|
|
139
|
+
loop do
|
|
140
|
+
remaining = opts[:deadline] - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
141
|
+
raise Timeout::Error, 'Admin response timed out' unless remaining.positive?
|
|
142
|
+
|
|
143
|
+
incoming = queue.pop(timeout: remaining)
|
|
144
|
+
raise Timeout::Error, 'Admin response timed out or transport closed' unless incoming
|
|
145
|
+
|
|
146
|
+
packet = incoming.is_a?(Meshtastic::FromRadio) ? incoming.packet : incoming
|
|
147
|
+
if packet.is_a?(Meshtastic::MeshPacket) && packet.decoded&.portnum == :ROUTING_APP && packet.decoded.request_id == opts[:request_id] &&
|
|
148
|
+
[opts[:target], opts[:connection][:my_node_num]].include?(packet.from)
|
|
149
|
+
reason = Meshtastic::Routing.decode(packet.decoded.payload).error_reason
|
|
150
|
+
raise RoutingError.new(reason, opts[:request_id], packet.from) if reason != :NONE && [opts[:target], opts[:connection][:my_node_num]].include?(packet.from)
|
|
151
|
+
return { variant: :routing, value: reason, request_id: opts[:request_id], from: packet.from } if reason == :NONE && packet.from == opts[:target] && opts[:variant] == :routing
|
|
152
|
+
end
|
|
153
|
+
reply = response(packet: incoming, request_id: opts[:request_id], from: opts[:target])
|
|
154
|
+
return reply if reply && reply[:variant] == opts[:variant]
|
|
155
|
+
|
|
156
|
+
deferred << incoming
|
|
157
|
+
end
|
|
158
|
+
ensure
|
|
159
|
+
begin
|
|
160
|
+
until deferred.nil? || deferred.empty?
|
|
161
|
+
queue << deferred.first
|
|
162
|
+
deferred.shift
|
|
163
|
+
end
|
|
164
|
+
rescue ClosedQueueError
|
|
165
|
+
replacement = Queue.new
|
|
166
|
+
deferred.each { |incoming| replacement << incoming }
|
|
167
|
+
while (incoming = queue.pop)
|
|
168
|
+
replacement << incoming
|
|
169
|
+
end
|
|
170
|
+
replacement.close
|
|
171
|
+
opts[:connection][:from_radio_queue] = replacement
|
|
172
|
+
deferred.clear
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
public_class_method def self.decode(opts = {})
|
|
177
|
+
packet = opts[:packet]
|
|
178
|
+
packet = packet.packet if packet.is_a?(Meshtastic::FromRadio)
|
|
179
|
+
data = packet.is_a?(Meshtastic::MeshPacket) ? packet.decoded : packet
|
|
180
|
+
raise ArgumentError, 'packet must contain decoded ADMIN_APP data' if opts.key?(:packet) && (!data.is_a?(Meshtastic::Data) || data.portnum != :ADMIN_APP)
|
|
181
|
+
|
|
182
|
+
payload = data ? data.payload : opts[:payload]
|
|
183
|
+
raise ArgumentError, 'payload bytes or a decoded packet are required' unless payload.is_a?(String)
|
|
184
|
+
|
|
185
|
+
Meshtastic::AdminMessage.decode(payload)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
public_class_method def self.response(opts = {})
|
|
189
|
+
packet = opts[:packet]
|
|
190
|
+
packet = packet.packet if packet.is_a?(Meshtastic::FromRadio)
|
|
191
|
+
return nil unless packet.is_a?(Meshtastic::MeshPacket) && packet.decoded&.portnum == :ADMIN_APP
|
|
192
|
+
return nil if opts.key?(:request_id) && packet.decoded.request_id != opts[:request_id]
|
|
193
|
+
return nil if opts.key?(:from) && packet.from != opts[:from]
|
|
194
|
+
|
|
195
|
+
message = decode(packet: packet)
|
|
196
|
+
variant = message.payload_variant
|
|
197
|
+
return nil unless variant.to_s.end_with?('_response')
|
|
198
|
+
|
|
199
|
+
{
|
|
200
|
+
message: message, variant: variant, value: message.public_send(variant),
|
|
201
|
+
session_passkey: message.session_passkey, request_id: packet.decoded.request_id, from: packet.from
|
|
202
|
+
}
|
|
32
203
|
end
|
|
33
204
|
|
|
34
205
|
public_class_method def self.reboot(opts = {})
|
|
@@ -39,6 +210,14 @@ module Meshtastic
|
|
|
39
210
|
send(opts.merge(shutdown_seconds: opts[:seconds] || 5))
|
|
40
211
|
end
|
|
41
212
|
|
|
213
|
+
public_class_method def self.reboot_ota(opts = {})
|
|
214
|
+
send(opts.merge(reboot_ota_seconds: opts[:seconds] || 5))
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
public_class_method def self.ota_request(opts = {})
|
|
218
|
+
send(opts.merge(ota_request: opts[:event]))
|
|
219
|
+
end
|
|
220
|
+
|
|
42
221
|
public_class_method def self.set_owner(opts = {})
|
|
43
222
|
user = opts[:owner] || Meshtastic::User.new(long_name: opts[:long_name], short_name: opts[:short_name])
|
|
44
223
|
send(opts.merge(set_owner: user))
|
|
@@ -55,7 +234,9 @@ module Meshtastic
|
|
|
55
234
|
public_class_method def self.get_channel(opts = {})
|
|
56
235
|
index = opts[:index]
|
|
57
236
|
index = 0 if index.nil?
|
|
58
|
-
|
|
237
|
+
raise ArgumentError, 'index must be an Integer from 0 through 7' unless index.is_a?(Integer) && index.between?(0, 7)
|
|
238
|
+
|
|
239
|
+
send(opts.merge(get_channel_request: index + 1))
|
|
59
240
|
end
|
|
60
241
|
|
|
61
242
|
public_class_method def self.get_config(opts = {})
|
|
@@ -79,7 +260,7 @@ module Meshtastic
|
|
|
79
260
|
end
|
|
80
261
|
|
|
81
262
|
public_class_method def self.set_canned_messages(opts = {})
|
|
82
|
-
send(opts.merge(set_canned_message_module_messages: opts[:messages]
|
|
263
|
+
send(opts.merge(set_canned_message_module_messages: opts[:messages]))
|
|
83
264
|
end
|
|
84
265
|
|
|
85
266
|
public_class_method def self.get_device_metadata(opts = {})
|
|
@@ -91,7 +272,7 @@ module Meshtastic
|
|
|
91
272
|
end
|
|
92
273
|
|
|
93
274
|
public_class_method def self.set_ringtone(opts = {})
|
|
94
|
-
send(opts.merge(set_ringtone_message: opts[:ringtone]
|
|
275
|
+
send(opts.merge(set_ringtone_message: opts[:ringtone]))
|
|
95
276
|
end
|
|
96
277
|
|
|
97
278
|
public_class_method def self.get_device_connection_status(opts = {})
|
|
@@ -107,11 +288,11 @@ module Meshtastic
|
|
|
107
288
|
end
|
|
108
289
|
|
|
109
290
|
public_class_method def self.delete_file(opts = {})
|
|
110
|
-
send(opts.merge(delete_file_request: opts[:path]
|
|
291
|
+
send(opts.merge(delete_file_request: opts[:path]))
|
|
111
292
|
end
|
|
112
293
|
|
|
113
294
|
public_class_method def self.set_scale(opts = {})
|
|
114
|
-
send(opts.merge(set_scale: opts[:scale]
|
|
295
|
+
send(opts.merge(set_scale: opts[:scale]))
|
|
115
296
|
end
|
|
116
297
|
|
|
117
298
|
public_class_method def self.backup_preferences(opts = {})
|
|
@@ -148,15 +329,15 @@ module Meshtastic
|
|
|
148
329
|
end
|
|
149
330
|
|
|
150
331
|
public_class_method def self.remove_by_nodenum(opts = {})
|
|
151
|
-
send(opts.merge(remove_by_nodenum: opts[:node_num]
|
|
332
|
+
send(opts.merge(remove_by_nodenum: opts[:node_num]))
|
|
152
333
|
end
|
|
153
334
|
|
|
154
335
|
public_class_method def self.set_favorite_node(opts = {})
|
|
155
|
-
send(opts.merge(set_favorite_node: opts[:node_num]
|
|
336
|
+
send(opts.merge(set_favorite_node: opts[:node_num]))
|
|
156
337
|
end
|
|
157
338
|
|
|
158
339
|
public_class_method def self.remove_favorite_node(opts = {})
|
|
159
|
-
send(opts.merge(remove_favorite_node: opts[:node_num]
|
|
340
|
+
send(opts.merge(remove_favorite_node: opts[:node_num]))
|
|
160
341
|
end
|
|
161
342
|
|
|
162
343
|
public_class_method def self.set_fixed_position(opts = {})
|
|
@@ -169,7 +350,7 @@ module Meshtastic
|
|
|
169
350
|
end
|
|
170
351
|
|
|
171
352
|
public_class_method def self.set_time(opts = {})
|
|
172
|
-
send(opts.merge(set_time_only: opts[:time]
|
|
353
|
+
send(opts.merge(set_time_only: opts[:time]))
|
|
173
354
|
end
|
|
174
355
|
|
|
175
356
|
public_class_method def self.get_ui_config(opts = {})
|
|
@@ -181,15 +362,15 @@ module Meshtastic
|
|
|
181
362
|
end
|
|
182
363
|
|
|
183
364
|
public_class_method def self.set_ignored_node(opts = {})
|
|
184
|
-
send(opts.merge(set_ignored_node: opts[:node_num]
|
|
365
|
+
send(opts.merge(set_ignored_node: opts[:node_num]))
|
|
185
366
|
end
|
|
186
367
|
|
|
187
368
|
public_class_method def self.remove_ignored_node(opts = {})
|
|
188
|
-
send(opts.merge(remove_ignored_node: opts[:node_num]
|
|
369
|
+
send(opts.merge(remove_ignored_node: opts[:node_num]))
|
|
189
370
|
end
|
|
190
371
|
|
|
191
372
|
public_class_method def self.toggle_muted_node(opts = {})
|
|
192
|
-
send(opts.merge(toggle_muted_node: opts[:node_num]
|
|
373
|
+
send(opts.merge(toggle_muted_node: opts[:node_num]))
|
|
193
374
|
end
|
|
194
375
|
|
|
195
376
|
public_class_method def self.begin_edit(opts = {})
|
|
@@ -217,7 +398,7 @@ module Meshtastic
|
|
|
217
398
|
end
|
|
218
399
|
|
|
219
400
|
public_class_method def self.nodedb_reset(opts = {})
|
|
220
|
-
send(opts.merge(nodedb_reset: true))
|
|
401
|
+
send(opts.merge(nodedb_reset: opts.fetch(:preserve_favorites, true)))
|
|
221
402
|
end
|
|
222
403
|
|
|
223
404
|
public_class_method def self.exit_simulator(opts = {})
|
|
@@ -238,9 +419,9 @@ module Meshtastic
|
|
|
238
419
|
|
|
239
420
|
public_class_method def self.help
|
|
240
421
|
puts "USAGE:
|
|
241
|
-
# Encode
|
|
422
|
+
# Encode exactly one AdminMessage payload without modifying the caller.
|
|
242
423
|
#{self}.encode(
|
|
243
|
-
message: 'optional - existing AdminMessage to
|
|
424
|
+
message: 'optional - existing AdminMessage to copy instead of a new one',
|
|
244
425
|
session_passkey: 'optional - bytes from a prior get_*_response to authorize sets'
|
|
245
426
|
)
|
|
246
427
|
|
|
@@ -250,7 +431,49 @@ module Meshtastic
|
|
|
250
431
|
bluetooth_obj: 'optional - BLE handle from Meshtastic::Bluetooth.connect',
|
|
251
432
|
tcp_obj: 'optional - TCP handle from Meshtastic::TCP.connect',
|
|
252
433
|
mqtt_obj: 'optional - MQTT client from Meshtastic::MQTT.connect',
|
|
253
|
-
|
|
434
|
+
to: 'optional - unicast node integer or !eighthex; defaults to connected my_node_num; required for MQTT',
|
|
435
|
+
from: 'optional - sender number; radio default zero denotes the local PhoneAPI client',
|
|
436
|
+
channel: 'optional - routing channel index (default zero)',
|
|
437
|
+
want_ack: 'optional - request routing acknowledgment, distinct from an admin reply',
|
|
438
|
+
hop_limit: 'optional - maximum radio hop count',
|
|
439
|
+
psks: 'optional - MQTT channel key map; not public-key admin authorization',
|
|
440
|
+
pki_encrypted: 'optional - enable device-owned PKI on serial BLE or TCP; unsupported over MQTT',
|
|
441
|
+
public_key: 'optional - recipient public-key bytes for radio PKI',
|
|
442
|
+
last_packet_id: 'optional - previous packet number used by transport packet generation',
|
|
443
|
+
want_response: 'optional - defaults true for get requests and false for state changes',
|
|
444
|
+
auto_session: 'optional - acquire a session for remote writes unless a passkey is supplied (default true)',
|
|
445
|
+
refresh_session: 'optional - discard cached session for this automatic acquisition (default false)',
|
|
446
|
+
timeout: 'optional - positive finite receive deadline in seconds for session acquisition (default ten)'
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
# Send admin data and synchronously await correlated readback.
|
|
450
|
+
#{self}.request(
|
|
451
|
+
request_id: 'optional - packet ID from 2 through 0xffffffff; generated when omitted; accepts send options',
|
|
452
|
+
wait: 'optional - false returns only request_id and submission result; true waits for reply (default true)',
|
|
453
|
+
timeout: 'optional - positive finite total response budget in seconds including session acquisition (default ten)'
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
# Decode protobuf bytes or an incoming admin packet.
|
|
457
|
+
#{self}.decode(
|
|
458
|
+
payload: 'optional - serialized AdminMessage bytes when packet is omitted',
|
|
459
|
+
packet: 'optional - FromRadio MeshPacket or Data containing decoded ADMIN_APP bytes'
|
|
460
|
+
)
|
|
461
|
+
|
|
462
|
+
# Extract a matching response and its session passkey.
|
|
463
|
+
#{self}.response(
|
|
464
|
+
packet: 'required - incoming FromRadio or MeshPacket protobuf',
|
|
465
|
+
request_id: 'optional - require this Data.request_id to match the outgoing packet ID',
|
|
466
|
+
from: 'optional - require this numeric responding node; mismatches return nil'
|
|
467
|
+
)
|
|
468
|
+
|
|
469
|
+
# Request legacy ESP32 OTA reboot; deprecated firmware operation.
|
|
470
|
+
#{self}.reboot_ota(
|
|
471
|
+
seconds: 'optional - legacy reboot delay, negative cancels (default five); use ota_request on current firmware'
|
|
472
|
+
)
|
|
473
|
+
|
|
474
|
+
# Send the current OTA loader request protobuf.
|
|
475
|
+
#{self}.ota_request(
|
|
476
|
+
event: 'required - AdminMessage::OTAEvent containing mode and firmware hash; see Admin::Firmware'
|
|
254
477
|
)
|
|
255
478
|
|
|
256
479
|
# Reboot the node after a delay.
|
|
@@ -285,7 +508,7 @@ module Meshtastic
|
|
|
285
508
|
|
|
286
509
|
# Request a channel by index.
|
|
287
510
|
#{self}.get_channel(
|
|
288
|
-
index: 'optional - channel index
|
|
511
|
+
index: 'optional - zero-based channel index 0 through 7; wire conversion happens here (default zero)'
|
|
289
512
|
)
|
|
290
513
|
|
|
291
514
|
# Request a radio Config section.
|
|
@@ -315,7 +538,7 @@ module Meshtastic
|
|
|
315
538
|
|
|
316
539
|
# Set canned-message module strings.
|
|
317
540
|
#{self}.set_canned_messages(
|
|
318
|
-
messages: 'required -
|
|
541
|
+
messages: 'required - pipe-separated canned message text; empty string clears it'
|
|
319
542
|
)
|
|
320
543
|
|
|
321
544
|
# Request DeviceMetadata (firmware version and hardware).
|
|
@@ -482,7 +705,8 @@ module Meshtastic
|
|
|
482
705
|
|
|
483
706
|
# Clear the node database.
|
|
484
707
|
#{self}.nodedb_reset(
|
|
485
|
-
serial_obj: 'optional - serial handle from Meshtastic::Serial.connect'
|
|
708
|
+
serial_obj: 'optional - serial handle from Meshtastic::Serial.connect',
|
|
709
|
+
preserve_favorites: 'optional - retain favorite nodes (default true); some firmware roles always preserve favorites'
|
|
486
710
|
)
|
|
487
711
|
|
|
488
712
|
# Exit the firmware simulator if running.
|
data/lib/meshtastic/config_pb.rb
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
require 'google/protobuf'
|
|
6
6
|
|
|
7
7
|
require 'meshtastic/device_ui_pb'
|
|
8
|
+
require 'meshtastic/field_metadata_pb'
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
descriptor_data = "\n\x17meshtastic/config.proto\x12\nmeshtastic\x1a\x1ameshtastic/device_ui.proto\"\xe1.\n\x06\x43onfig\x12\x31\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32\x1f.meshtastic.Config.DeviceConfigH\x00\x12\x35\n\x08position\x18\x02 \x01(\x0b\x32!.meshtastic.Config.PositionConfigH\x00\x12/\n\x05power\x18\x03 \x01(\x0b\x32\x1e.meshtastic.Config.PowerConfigH\x00\x12\x33\n\x07network\x18\x04 \x01(\x0b\x32 .meshtastic.Config.NetworkConfigH\x00\x12\x33\n\x07\x64isplay\x18\x05 \x01(\x0b\x32 .meshtastic.Config.DisplayConfigH\x00\x12-\n\x04lora\x18\x06 \x01(\x0b\x32\x1d.meshtastic.Config.LoRaConfigH\x00\x12\x37\n\tbluetooth\x18\x07 \x01(\x0b\x32\".meshtastic.Config.BluetoothConfigH\x00\x12\x35\n\x08security\x18\x08 \x01(\x0b\x32!.meshtastic.Config.SecurityConfigH\x00\x12\x39\n\nsessionkey\x18\t \x01(\x0b\x32#.meshtastic.Config.SessionkeyConfigH\x00\x12/\n\tdevice_ui\x18\n \x01(\x0b\x32\x1a.meshtastic.DeviceUIConfigH\x00\x1a\xf6\x06\n\x0c\x44\x65viceConfig\x12\x32\n\x04role\x18\x01 \x01(\x0e\x32$.meshtastic.Config.DeviceConfig.Role\x12\x1a\n\x0eserial_enabled\x18\x02 \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0b\x62utton_gpio\x18\x04 \x01(\r\x12\x13\n\x0b\x62uzzer_gpio\x18\x05 \x01(\r\x12I\n\x10rebroadcast_mode\x18\x06 \x01(\x0e\x32/.meshtastic.Config.DeviceConfig.RebroadcastMode\x12 \n\x18node_info_broadcast_secs\x18\x07 \x01(\r\x12\"\n\x1a\x64ouble_tap_as_button_press\x18\x08 \x01(\x08\x12\x16\n\nis_managed\x18\t \x01(\x08\x42\x02\x18\x01\x12\x1c\n\x14\x64isable_triple_click\x18\n \x01(\x08\x12\r\n\x05tzdef\x18\x0b \x01(\t\x12\x1e\n\x16led_heartbeat_disabled\x18\x0c \x01(\x08\x12?\n\x0b\x62uzzer_mode\x18\r \x01(\x0e\x32*.meshtastic.Config.DeviceConfig.BuzzerMode\"\xd4\x01\n\x04Role\x12\n\n\x06\x43LIENT\x10\x00\x12\x0f\n\x0b\x43LIENT_MUTE\x10\x01\x12\n\n\x06ROUTER\x10\x02\x12\x15\n\rROUTER_CLIENT\x10\x03\x1a\x02\x08\x01\x12\x10\n\x08REPEATER\x10\x04\x1a\x02\x08\x01\x12\x0b\n\x07TRACKER\x10\x05\x12\n\n\x06SENSOR\x10\x06\x12\x07\n\x03TAK\x10\x07\x12\x11\n\rCLIENT_HIDDEN\x10\x08\x12\x12\n\x0eLOST_AND_FOUND\x10\t\x12\x0f\n\x0bTAK_TRACKER\x10\n\x12\x0f\n\x0bROUTER_LATE\x10\x0b\x12\x0f\n\x0b\x43LIENT_BASE\x10\x0c\"s\n\x0fRebroadcastMode\x12\x07\n\x03\x41LL\x10\x00\x12\x15\n\x11\x41LL_SKIP_DECODING\x10\x01\x12\x0e\n\nLOCAL_ONLY\x10\x02\x12\x0e\n\nKNOWN_ONLY\x10\x03\x12\x08\n\x04NONE\x10\x04\x12\x16\n\x12\x43ORE_PORTNUMS_ONLY\x10\x05\"i\n\nBuzzerMode\x12\x0f\n\x0b\x41LL_ENABLED\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01\x12\x16\n\x12NOTIFICATIONS_ONLY\x10\x02\x12\x0f\n\x0bSYSTEM_ONLY\x10\x03\x12\x13\n\x0f\x44IRECT_MSG_ONLY\x10\x04\x1a\x91\x05\n\x0ePositionConfig\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12(\n position_broadcast_smart_enabled\x18\x02 \x01(\x08\x12\x16\n\x0e\x66ixed_position\x18\x03 \x01(\x08\x12\x17\n\x0bgps_enabled\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x1b\n\x13gps_update_interval\x18\x05 \x01(\r\x12\x1c\n\x10gps_attempt_time\x18\x06 \x01(\rB\x02\x18\x01\x12\x16\n\x0eposition_flags\x18\x07 \x01(\r\x12\x0f\n\x07rx_gpio\x18\x08 \x01(\r\x12\x0f\n\x07tx_gpio\x18\t \x01(\r\x12(\n broadcast_smart_minimum_distance\x18\n \x01(\r\x12-\n%broadcast_smart_minimum_interval_secs\x18\x0b \x01(\r\x12\x13\n\x0bgps_en_gpio\x18\x0c \x01(\r\x12;\n\x08gps_mode\x18\r \x01(\x0e\x32).meshtastic.Config.PositionConfig.GpsMode\"\xab\x01\n\rPositionFlags\x12\t\n\x05UNSET\x10\x00\x12\x0c\n\x08\x41LTITUDE\x10\x01\x12\x10\n\x0c\x41LTITUDE_MSL\x10\x02\x12\x16\n\x12GEOIDAL_SEPARATION\x10\x04\x12\x07\n\x03\x44OP\x10\x08\x12\t\n\x05HVDOP\x10\x10\x12\r\n\tSATINVIEW\x10 \x12\n\n\x06SEQ_NO\x10@\x12\x0e\n\tTIMESTAMP\x10\x80\x01\x12\x0c\n\x07HEADING\x10\x80\x02\x12\n\n\x05SPEED\x10\x80\x04\"5\n\x07GpsMode\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x12\x0f\n\x0bNOT_PRESENT\x10\x02\x1a\x84\x02\n\x0bPowerConfig\x12\x17\n\x0fis_power_saving\x18\x01 \x01(\x08\x12&\n\x1eon_battery_shutdown_after_secs\x18\x02 \x01(\r\x12\x1f\n\x17\x61\x64\x63_multiplier_override\x18\x03 \x01(\x02\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x10\n\x08sds_secs\x18\x06 \x01(\r\x12\x0f\n\x07ls_secs\x18\x07 \x01(\r\x12\x15\n\rmin_wake_secs\x18\x08 \x01(\r\x12\"\n\x1a\x64\x65vice_battery_ina_address\x18\t \x01(\r\x12\x18\n\x10powermon_enables\x18 \x01(\x04\x1a\xe5\x03\n\rNetworkConfig\x12\x14\n\x0cwifi_enabled\x18\x01 \x01(\x08\x12\x11\n\twifi_ssid\x18\x03 \x01(\t\x12\x10\n\x08wifi_psk\x18\x04 \x01(\t\x12\x12\n\nntp_server\x18\x05 \x01(\t\x12\x13\n\x0b\x65th_enabled\x18\x06 \x01(\x08\x12\x42\n\x0c\x61\x64\x64ress_mode\x18\x07 \x01(\x0e\x32,.meshtastic.Config.NetworkConfig.AddressMode\x12@\n\x0bipv4_config\x18\x08 \x01(\x0b\x32+.meshtastic.Config.NetworkConfig.IpV4Config\x12\x16\n\x0ersyslog_server\x18\t \x01(\t\x12\x19\n\x11\x65nabled_protocols\x18\n \x01(\r\x12\x14\n\x0cipv6_enabled\x18\x0b \x01(\x08\x1a\x46\n\nIpV4Config\x12\n\n\x02ip\x18\x01 \x01(\x07\x12\x0f\n\x07gateway\x18\x02 \x01(\x07\x12\x0e\n\x06subnet\x18\x03 \x01(\x07\x12\x0b\n\x03\x64ns\x18\x04 \x01(\x07\"#\n\x0b\x41\x64\x64ressMode\x12\x08\n\x04\x44HCP\x10\x00\x12\n\n\x06STATIC\x10\x01\"4\n\rProtocolFlags\x12\x10\n\x0cNO_BROADCAST\x10\x00\x12\x11\n\rUDP_BROADCAST\x10\x01\x1a\xc2\x08\n\rDisplayConfig\x12\x16\n\x0escreen_on_secs\x18\x01 \x01(\r\x12V\n\ngps_format\x18\x02 \x01(\x0e\x32>.meshtastic.Config.DisplayConfig.DeprecatedGpsCoordinateFormatB\x02\x18\x01\x12!\n\x19\x61uto_screen_carousel_secs\x18\x03 \x01(\r\x12\x1d\n\x11\x63ompass_north_top\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0b\x66lip_screen\x18\x05 \x01(\x08\x12<\n\x05units\x18\x06 \x01(\x0e\x32-.meshtastic.Config.DisplayConfig.DisplayUnits\x12\x37\n\x04oled\x18\x07 \x01(\x0e\x32).meshtastic.Config.DisplayConfig.OledType\x12\x41\n\x0b\x64isplaymode\x18\x08 \x01(\x0e\x32,.meshtastic.Config.DisplayConfig.DisplayMode\x12\x14\n\x0cheading_bold\x18\t \x01(\x08\x12\x1d\n\x15wake_on_tap_or_motion\x18\n \x01(\x08\x12P\n\x13\x63ompass_orientation\x18\x0b \x01(\x0e\x32\x33.meshtastic.Config.DisplayConfig.CompassOrientation\x12\x15\n\ruse_12h_clock\x18\x0c \x01(\x08\x12\x1a\n\x12use_long_node_name\x18\r \x01(\x08\x12\x1e\n\x16\x65nable_message_bubbles\x18\x0e \x01(\x08\"+\n\x1d\x44\x65precatedGpsCoordinateFormat\x12\n\n\x06UNUSED\x10\x00\"(\n\x0c\x44isplayUnits\x12\n\n\x06METRIC\x10\x00\x12\x0c\n\x08IMPERIAL\x10\x01\"\x7f\n\x08OledType\x12\r\n\tOLED_AUTO\x10\x00\x12\x10\n\x0cOLED_SSD1306\x10\x01\x12\x0f\n\x0bOLED_SH1106\x10\x02\x12\x0f\n\x0bOLED_SH1107\x10\x03\x12\x17\n\x13OLED_SH1107_128_128\x10\x04\x12\x17\n\x13OLED_SH1107_ROTATED\x10\x05\"A\n\x0b\x44isplayMode\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x0c\n\x08TWOCOLOR\x10\x01\x12\x0c\n\x08INVERTED\x10\x02\x12\t\n\x05\x43OLOR\x10\x03\"\xba\x01\n\x12\x43ompassOrientation\x12\r\n\tDEGREES_0\x10\x00\x12\x0e\n\nDEGREES_90\x10\x01\x12\x0f\n\x0b\x44\x45GREES_180\x10\x02\x12\x0f\n\x0b\x44\x45GREES_270\x10\x03\x12\x16\n\x12\x44\x45GREES_0_INVERTED\x10\x04\x12\x17\n\x13\x44\x45GREES_90_INVERTED\x10\x05\x12\x18\n\x14\x44\x45GREES_180_INVERTED\x10\x06\x12\x18\n\x14\x44\x45GREES_270_INVERTED\x10\x07\x1a\x8f\x0b\n\nLoRaConfig\x12\x12\n\nuse_preset\x18\x01 \x01(\x08\x12?\n\x0cmodem_preset\x18\x02 \x01(\x0e\x32).meshtastic.Config.LoRaConfig.ModemPreset\x12\x11\n\tbandwidth\x18\x03 \x01(\r\x12\x15\n\rspread_factor\x18\x04 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x05 \x01(\r\x12\x18\n\x10\x66requency_offset\x18\x06 \x01(\x02\x12\x38\n\x06region\x18\x07 \x01(\x0e\x32(.meshtastic.Config.LoRaConfig.RegionCode\x12\x11\n\thop_limit\x18\x08 \x01(\r\x12\x12\n\ntx_enabled\x18\t \x01(\x08\x12\x10\n\x08tx_power\x18\n \x01(\x05\x12\x13\n\x0b\x63hannel_num\x18\x0b \x01(\r\x12\x1b\n\x13override_duty_cycle\x18\x0c \x01(\x08\x12\x1e\n\x16sx126x_rx_boosted_gain\x18\r \x01(\x08\x12\x1a\n\x12override_frequency\x18\x0e \x01(\x02\x12\x17\n\x0fpa_fan_disabled\x18\x0f \x01(\x08\x12\x17\n\x0fignore_incoming\x18g \x03(\r\x12\x13\n\x0bignore_mqtt\x18h \x01(\x08\x12\x19\n\x11\x63onfig_ok_to_mqtt\x18i \x01(\x08\x12@\n\x0c\x66\x65m_lna_mode\x18j \x01(\x0e\x32*.meshtastic.Config.LoRaConfig.FEM_LNA_Mode\x12\x17\n\x0fserial_hal_only\x18k \x01(\x08\"\xc8\x03\n\nRegionCode\x12\t\n\x05UNSET\x10\x00\x12\x06\n\x02US\x10\x01\x12\n\n\x06\x45U_433\x10\x02\x12\n\n\x06\x45U_868\x10\x03\x12\x06\n\x02\x43N\x10\x04\x12\x06\n\x02JP\x10\x05\x12\x07\n\x03\x41NZ\x10\x06\x12\x06\n\x02KR\x10\x07\x12\x06\n\x02TW\x10\x08\x12\x06\n\x02RU\x10\t\x12\x06\n\x02IN\x10\n\x12\n\n\x06NZ_865\x10\x0b\x12\x06\n\x02TH\x10\x0c\x12\x0b\n\x07LORA_24\x10\r\x12\n\n\x06UA_433\x10\x0e\x12\x0e\n\x06UA_868\x10\x0f\x1a\x02\x08\x01\x12\n\n\x06MY_433\x10\x10\x12\n\n\x06MY_919\x10\x11\x12\n\n\x06SG_923\x10\x12\x12\n\n\x06PH_433\x10\x13\x12\n\n\x06PH_868\x10\x14\x12\n\n\x06PH_915\x10\x15\x12\x0b\n\x07\x41NZ_433\x10\x16\x12\n\n\x06KZ_433\x10\x17\x12\n\n\x06KZ_863\x10\x18\x12\n\n\x06NP_865\x10\x19\x12\n\n\x06\x42R_902\x10\x1a\x12\x0b\n\x07ITU1_2M\x10\x1b\x12\x0b\n\x07ITU2_2M\x10\x1c\x12\n\n\x06\x45U_866\x10\x1d\x12\n\n\x06\x45U_874\x10\x1e\x12\n\n\x06\x45U_917\x10\x1f\x12\x0c\n\x08\x45U_N_868\x10 \x12\x0b\n\x07ITU3_2M\x10!\x12\r\n\tITU1_70CM\x10\"\x12\r\n\tITU2_70CM\x10#\x12\r\n\tITU3_70CM\x10$\x12\x0e\n\nITU2_125CM\x10%\"\xad\x02\n\x0bModemPreset\x12\r\n\tLONG_FAST\x10\x00\x12\x11\n\tLONG_SLOW\x10\x01\x1a\x02\x08\x01\x12\x16\n\x0eVERY_LONG_SLOW\x10\x02\x1a\x02\x08\x01\x12\x0f\n\x0bMEDIUM_SLOW\x10\x03\x12\x0f\n\x0bMEDIUM_FAST\x10\x04\x12\x0e\n\nSHORT_SLOW\x10\x05\x12\x0e\n\nSHORT_FAST\x10\x06\x12\x11\n\rLONG_MODERATE\x10\x07\x12\x0f\n\x0bSHORT_TURBO\x10\x08\x12\x0e\n\nLONG_TURBO\x10\t\x12\r\n\tLITE_FAST\x10\n\x12\r\n\tLITE_SLOW\x10\x0b\x12\x0f\n\x0bNARROW_FAST\x10\x0c\x12\x0f\n\x0bNARROW_SLOW\x10\r\x12\r\n\tTINY_FAST\x10\x0e\x12\r\n\tTINY_SLOW\x10\x0f\x12\x10\n\x0cMEDIUM_TURBO\x10\x10\":\n\x0c\x46\x45M_LNA_Mode\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x12\x0f\n\x0bNOT_PRESENT\x10\x02\x1a\xad\x01\n\x0f\x42luetoothConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12<\n\x04mode\x18\x02 \x01(\x0e\x32..meshtastic.Config.BluetoothConfig.PairingMode\x12\x11\n\tfixed_pin\x18\x03 \x01(\r\"8\n\x0bPairingMode\x12\x0e\n\nRANDOM_PIN\x10\x00\x12\r\n\tFIXED_PIN\x10\x01\x12\n\n\x06NO_PIN\x10\x02\x1a\x9c\x03\n\x0eSecurityConfig\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x13\n\x0bprivate_key\x18\x02 \x01(\x0c\x12\x11\n\tadmin_key\x18\x03 \x03(\x0c\x12\x12\n\nis_managed\x18\x04 \x01(\x08\x12\x16\n\x0eserial_enabled\x18\x05 \x01(\x08\x12\x1d\n\x15\x64\x65\x62ug_log_api_enabled\x18\x06 \x01(\x08\x12\x1d\n\x15\x61\x64min_channel_enabled\x18\x08 \x01(\x08\x12X\n\x17packet_signature_policy\x18\t \x01(\x0e\x32\x37.meshtastic.Config.SecurityConfig.PacketSignaturePolicy\"\x89\x01\n\x15PacketSignaturePolicy\x12&\n\"PACKET_SIGNATURE_POLICY_COMPATIBLE\x10\x00\x12$\n PACKET_SIGNATURE_POLICY_BALANCED\x10\x01\x12\"\n\x1ePACKET_SIGNATURE_POLICY_STRICT\x10\x02\x1a\x12\n\x10SessionkeyConfigB\x11\n\x0fpayload_variantBb\n\x14org.meshtastic.protoB\x0c\x43onfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3"
|
|
11
|
+
descriptor_data = "\n\x17meshtastic/config.proto\x12\nmeshtastic\x1a\x1ameshtastic/device_ui.proto\x1a\x1fmeshtastic/field_metadata.proto\"\x80\x31\n\x06\x43onfig\x12\x31\n\x06\x64\x65vice\x18\x01 \x01(\x0b\x32\x1f.meshtastic.Config.DeviceConfigH\x00\x12\x35\n\x08position\x18\x02 \x01(\x0b\x32!.meshtastic.Config.PositionConfigH\x00\x12/\n\x05power\x18\x03 \x01(\x0b\x32\x1e.meshtastic.Config.PowerConfigH\x00\x12\x33\n\x07network\x18\x04 \x01(\x0b\x32 .meshtastic.Config.NetworkConfigH\x00\x12\x33\n\x07\x64isplay\x18\x05 \x01(\x0b\x32 .meshtastic.Config.DisplayConfigH\x00\x12-\n\x04lora\x18\x06 \x01(\x0b\x32\x1d.meshtastic.Config.LoRaConfigH\x00\x12\x37\n\tbluetooth\x18\x07 \x01(\x0b\x32\".meshtastic.Config.BluetoothConfigH\x00\x12\x35\n\x08security\x18\x08 \x01(\x0b\x32!.meshtastic.Config.SecurityConfigH\x00\x12\x39\n\nsessionkey\x18\t \x01(\x0b\x32#.meshtastic.Config.SessionkeyConfigH\x00\x12/\n\tdevice_ui\x18\n \x01(\x0b\x32\x1a.meshtastic.DeviceUIConfigH\x00\x1a\xf6\x06\n\x0c\x44\x65viceConfig\x12\x32\n\x04role\x18\x01 \x01(\x0e\x32$.meshtastic.Config.DeviceConfig.Role\x12\x1a\n\x0eserial_enabled\x18\x02 \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0b\x62utton_gpio\x18\x04 \x01(\r\x12\x13\n\x0b\x62uzzer_gpio\x18\x05 \x01(\r\x12I\n\x10rebroadcast_mode\x18\x06 \x01(\x0e\x32/.meshtastic.Config.DeviceConfig.RebroadcastMode\x12 \n\x18node_info_broadcast_secs\x18\x07 \x01(\r\x12\"\n\x1a\x64ouble_tap_as_button_press\x18\x08 \x01(\x08\x12\x16\n\nis_managed\x18\t \x01(\x08\x42\x02\x18\x01\x12\x1c\n\x14\x64isable_triple_click\x18\n \x01(\x08\x12\r\n\x05tzdef\x18\x0b \x01(\t\x12\x1e\n\x16led_heartbeat_disabled\x18\x0c \x01(\x08\x12?\n\x0b\x62uzzer_mode\x18\r \x01(\x0e\x32*.meshtastic.Config.DeviceConfig.BuzzerMode\"\xd4\x01\n\x04Role\x12\n\n\x06\x43LIENT\x10\x00\x12\x0f\n\x0b\x43LIENT_MUTE\x10\x01\x12\n\n\x06ROUTER\x10\x02\x12\x15\n\rROUTER_CLIENT\x10\x03\x1a\x02\x08\x01\x12\x10\n\x08REPEATER\x10\x04\x1a\x02\x08\x01\x12\x0b\n\x07TRACKER\x10\x05\x12\n\n\x06SENSOR\x10\x06\x12\x07\n\x03TAK\x10\x07\x12\x11\n\rCLIENT_HIDDEN\x10\x08\x12\x12\n\x0eLOST_AND_FOUND\x10\t\x12\x0f\n\x0bTAK_TRACKER\x10\n\x12\x0f\n\x0bROUTER_LATE\x10\x0b\x12\x0f\n\x0b\x43LIENT_BASE\x10\x0c\"s\n\x0fRebroadcastMode\x12\x07\n\x03\x41LL\x10\x00\x12\x15\n\x11\x41LL_SKIP_DECODING\x10\x01\x12\x0e\n\nLOCAL_ONLY\x10\x02\x12\x0e\n\nKNOWN_ONLY\x10\x03\x12\x08\n\x04NONE\x10\x04\x12\x16\n\x12\x43ORE_PORTNUMS_ONLY\x10\x05\"i\n\nBuzzerMode\x12\x0f\n\x0b\x41LL_ENABLED\x10\x00\x12\x0c\n\x08\x44ISABLED\x10\x01\x12\x16\n\x12NOTIFICATIONS_ONLY\x10\x02\x12\x0f\n\x0bSYSTEM_ONLY\x10\x03\x12\x13\n\x0f\x44IRECT_MSG_ONLY\x10\x04\x1a\xf8\x05\n\x0ePositionConfig\x12\x1f\n\x17position_broadcast_secs\x18\x01 \x01(\r\x12(\n position_broadcast_smart_enabled\x18\x02 \x01(\x08\x12\x16\n\x0e\x66ixed_position\x18\x03 \x01(\x08\x12\x17\n\x0bgps_enabled\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x1b\n\x13gps_update_interval\x18\x05 \x01(\r\x12\x1c\n\x10gps_attempt_time\x18\x06 \x01(\rB\x02\x18\x01\x12\x16\n\x0eposition_flags\x18\x07 \x01(\r\x12\x17\n\x07rx_gpio\x18\x08 \x01(\rB\x06\xca\xf3\x18\x02\x08\x01\x12\x17\n\x07tx_gpio\x18\t \x01(\rB\x06\xca\xf3\x18\x02\x08\x01\x12(\n broadcast_smart_minimum_distance\x18\n \x01(\r\x12-\n%broadcast_smart_minimum_interval_secs\x18\x0b \x01(\r\x12\x13\n\x0bgps_en_gpio\x18\x0c \x01(\r\x12;\n\x08gps_mode\x18\r \x01(\x0e\x32).meshtastic.Config.PositionConfig.GpsMode\"\x82\x02\n\rPositionFlags\x12\t\n\x05UNSET\x10\x00\x12\x63\n\x08\x41LTITUDE\x10\x01\x1aU\xca\xf3\x18Q:\x08\x41ltitudeBEInclude an altitude value in position reports, when one is available.\x12\x10\n\x0c\x41LTITUDE_MSL\x10\x02\x12\x16\n\x12GEOIDAL_SEPARATION\x10\x04\x12\x07\n\x03\x44OP\x10\x08\x12\t\n\x05HVDOP\x10\x10\x12\r\n\tSATINVIEW\x10 \x12\n\n\x06SEQ_NO\x10@\x12\x0e\n\tTIMESTAMP\x10\x80\x01\x12\x0c\n\x07HEADING\x10\x80\x02\x12\n\n\x05SPEED\x10\x80\x04\"5\n\x07GpsMode\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x12\x0f\n\x0bNOT_PRESENT\x10\x02\x1a\x84\x02\n\x0bPowerConfig\x12\x17\n\x0fis_power_saving\x18\x01 \x01(\x08\x12&\n\x1eon_battery_shutdown_after_secs\x18\x02 \x01(\r\x12\x1f\n\x17\x61\x64\x63_multiplier_override\x18\x03 \x01(\x02\x12\x1b\n\x13wait_bluetooth_secs\x18\x04 \x01(\r\x12\x10\n\x08sds_secs\x18\x06 \x01(\r\x12\x0f\n\x07ls_secs\x18\x07 \x01(\r\x12\x15\n\rmin_wake_secs\x18\x08 \x01(\r\x12\"\n\x1a\x64\x65vice_battery_ina_address\x18\t \x01(\r\x12\x18\n\x10powermon_enables\x18 \x01(\x04\x1a\xe5\x03\n\rNetworkConfig\x12\x14\n\x0cwifi_enabled\x18\x01 \x01(\x08\x12\x11\n\twifi_ssid\x18\x03 \x01(\t\x12\x10\n\x08wifi_psk\x18\x04 \x01(\t\x12\x12\n\nntp_server\x18\x05 \x01(\t\x12\x13\n\x0b\x65th_enabled\x18\x06 \x01(\x08\x12\x42\n\x0c\x61\x64\x64ress_mode\x18\x07 \x01(\x0e\x32,.meshtastic.Config.NetworkConfig.AddressMode\x12@\n\x0bipv4_config\x18\x08 \x01(\x0b\x32+.meshtastic.Config.NetworkConfig.IpV4Config\x12\x16\n\x0ersyslog_server\x18\t \x01(\t\x12\x19\n\x11\x65nabled_protocols\x18\n \x01(\r\x12\x14\n\x0cipv6_enabled\x18\x0b \x01(\x08\x1a\x46\n\nIpV4Config\x12\n\n\x02ip\x18\x01 \x01(\x07\x12\x0f\n\x07gateway\x18\x02 \x01(\x07\x12\x0e\n\x06subnet\x18\x03 \x01(\x07\x12\x0b\n\x03\x64ns\x18\x04 \x01(\x07\"#\n\x0b\x41\x64\x64ressMode\x12\x08\n\x04\x44HCP\x10\x00\x12\n\n\x06STATIC\x10\x01\"4\n\rProtocolFlags\x12\x10\n\x0cNO_BROADCAST\x10\x00\x12\x11\n\rUDP_BROADCAST\x10\x01\x1a\xc2\x08\n\rDisplayConfig\x12\x16\n\x0escreen_on_secs\x18\x01 \x01(\r\x12V\n\ngps_format\x18\x02 \x01(\x0e\x32>.meshtastic.Config.DisplayConfig.DeprecatedGpsCoordinateFormatB\x02\x18\x01\x12!\n\x19\x61uto_screen_carousel_secs\x18\x03 \x01(\r\x12\x1d\n\x11\x63ompass_north_top\x18\x04 \x01(\x08\x42\x02\x18\x01\x12\x13\n\x0b\x66lip_screen\x18\x05 \x01(\x08\x12<\n\x05units\x18\x06 \x01(\x0e\x32-.meshtastic.Config.DisplayConfig.DisplayUnits\x12\x37\n\x04oled\x18\x07 \x01(\x0e\x32).meshtastic.Config.DisplayConfig.OledType\x12\x41\n\x0b\x64isplaymode\x18\x08 \x01(\x0e\x32,.meshtastic.Config.DisplayConfig.DisplayMode\x12\x14\n\x0cheading_bold\x18\t \x01(\x08\x12\x1d\n\x15wake_on_tap_or_motion\x18\n \x01(\x08\x12P\n\x13\x63ompass_orientation\x18\x0b \x01(\x0e\x32\x33.meshtastic.Config.DisplayConfig.CompassOrientation\x12\x15\n\ruse_12h_clock\x18\x0c \x01(\x08\x12\x1a\n\x12use_long_node_name\x18\r \x01(\x08\x12\x1e\n\x16\x65nable_message_bubbles\x18\x0e \x01(\x08\"+\n\x1d\x44\x65precatedGpsCoordinateFormat\x12\n\n\x06UNUSED\x10\x00\"(\n\x0c\x44isplayUnits\x12\n\n\x06METRIC\x10\x00\x12\x0c\n\x08IMPERIAL\x10\x01\"\x7f\n\x08OledType\x12\r\n\tOLED_AUTO\x10\x00\x12\x10\n\x0cOLED_SSD1306\x10\x01\x12\x0f\n\x0bOLED_SH1106\x10\x02\x12\x0f\n\x0bOLED_SH1107\x10\x03\x12\x17\n\x13OLED_SH1107_128_128\x10\x04\x12\x17\n\x13OLED_SH1107_ROTATED\x10\x05\"A\n\x0b\x44isplayMode\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\x0c\n\x08TWOCOLOR\x10\x01\x12\x0c\n\x08INVERTED\x10\x02\x12\t\n\x05\x43OLOR\x10\x03\"\xba\x01\n\x12\x43ompassOrientation\x12\r\n\tDEGREES_0\x10\x00\x12\x0e\n\nDEGREES_90\x10\x01\x12\x0f\n\x0b\x44\x45GREES_180\x10\x02\x12\x0f\n\x0b\x44\x45GREES_270\x10\x03\x12\x16\n\x12\x44\x45GREES_0_INVERTED\x10\x04\x12\x17\n\x13\x44\x45GREES_90_INVERTED\x10\x05\x12\x18\n\x14\x44\x45GREES_180_INVERTED\x10\x06\x12\x18\n\x14\x44\x45GREES_270_INVERTED\x10\x07\x1a\xc7\x0c\n\nLoRaConfig\x12\x12\n\nuse_preset\x18\x01 \x01(\x08\x12?\n\x0cmodem_preset\x18\x02 \x01(\x0e\x32).meshtastic.Config.LoRaConfig.ModemPreset\x12\x11\n\tbandwidth\x18\x03 \x01(\r\x12\x15\n\rspread_factor\x18\x04 \x01(\r\x12\x13\n\x0b\x63oding_rate\x18\x05 \x01(\r\x12\x18\n\x10\x66requency_offset\x18\x06 \x01(\x02\x12\x38\n\x06region\x18\x07 \x01(\x0e\x32(.meshtastic.Config.LoRaConfig.RegionCode\x12\x9d\x01\n\thop_limit\x18\x08 \x01(\rB\x89\x01\xca\xf3\x18\x84\x01\x19\x00\x00\x00\x00\x00\x00\x00\x00!\x00\x00\x00\x00\x00\x00\x1c@:\tHop LimitBIHow many times a message may be repeated before it stops being forwarded.J\x1ahops|ttl|range|rebroadcast\x12\x12\n\ntx_enabled\x18\t \x01(\x08\x12\x10\n\x08tx_power\x18\n \x01(\x05\x12\x13\n\x0b\x63hannel_num\x18\x0b \x01(\r\x12\x1b\n\x13override_duty_cycle\x18\x0c \x01(\x08\x12\x1e\n\x16sx126x_rx_boosted_gain\x18\r \x01(\x08\x12\x1a\n\x12override_frequency\x18\x0e \x01(\x02\x12\x17\n\x0fpa_fan_disabled\x18\x0f \x01(\x08\x12\x17\n\x0fignore_incoming\x18g \x03(\r\x12\x13\n\x0bignore_mqtt\x18h \x01(\x08\x12\x19\n\x11\x63onfig_ok_to_mqtt\x18i \x01(\x08\x12@\n\x0c\x66\x65m_lna_mode\x18j \x01(\x0e\x32*.meshtastic.Config.LoRaConfig.FEM_LNA_Mode\x12\x17\n\x0fserial_hal_only\x18k \x01(\x08\"\xc8\x03\n\nRegionCode\x12\t\n\x05UNSET\x10\x00\x12\x06\n\x02US\x10\x01\x12\n\n\x06\x45U_433\x10\x02\x12\n\n\x06\x45U_868\x10\x03\x12\x06\n\x02\x43N\x10\x04\x12\x06\n\x02JP\x10\x05\x12\x07\n\x03\x41NZ\x10\x06\x12\x06\n\x02KR\x10\x07\x12\x06\n\x02TW\x10\x08\x12\x06\n\x02RU\x10\t\x12\x06\n\x02IN\x10\n\x12\n\n\x06NZ_865\x10\x0b\x12\x06\n\x02TH\x10\x0c\x12\x0b\n\x07LORA_24\x10\r\x12\n\n\x06UA_433\x10\x0e\x12\x0e\n\x06UA_868\x10\x0f\x1a\x02\x08\x01\x12\n\n\x06MY_433\x10\x10\x12\n\n\x06MY_919\x10\x11\x12\n\n\x06SG_923\x10\x12\x12\n\n\x06PH_433\x10\x13\x12\n\n\x06PH_868\x10\x14\x12\n\n\x06PH_915\x10\x15\x12\x0b\n\x07\x41NZ_433\x10\x16\x12\n\n\x06KZ_433\x10\x17\x12\n\n\x06KZ_863\x10\x18\x12\n\n\x06NP_865\x10\x19\x12\n\n\x06\x42R_902\x10\x1a\x12\x0b\n\x07ITU1_2M\x10\x1b\x12\x0b\n\x07ITU2_2M\x10\x1c\x12\n\n\x06\x45U_866\x10\x1d\x12\n\n\x06\x45U_874\x10\x1e\x12\n\n\x06\x45U_917\x10\x1f\x12\x0c\n\x08\x45U_N_868\x10 \x12\x0b\n\x07ITU3_2M\x10!\x12\r\n\tITU1_70CM\x10\"\x12\r\n\tITU2_70CM\x10#\x12\r\n\tITU3_70CM\x10$\x12\x0e\n\nITU2_125CM\x10%\"\xd8\x02\n\x0bModemPreset\x12\x38\n\tLONG_FAST\x10\x00\x1a)\xca\xf3\x18%:\x11Long Range - FastJ\x10longfast|default\x12\x11\n\tLONG_SLOW\x10\x01\x1a\x02\x08\x01\x12\x16\n\x0eVERY_LONG_SLOW\x10\x02\x1a\x02\x08\x01\x12\x0f\n\x0bMEDIUM_SLOW\x10\x03\x12\x0f\n\x0bMEDIUM_FAST\x10\x04\x12\x0e\n\nSHORT_SLOW\x10\x05\x12\x0e\n\nSHORT_FAST\x10\x06\x12\x11\n\rLONG_MODERATE\x10\x07\x12\x0f\n\x0bSHORT_TURBO\x10\x08\x12\x0e\n\nLONG_TURBO\x10\t\x12\r\n\tLITE_FAST\x10\n\x12\r\n\tLITE_SLOW\x10\x0b\x12\x0f\n\x0bNARROW_FAST\x10\x0c\x12\x0f\n\x0bNARROW_SLOW\x10\r\x12\r\n\tTINY_FAST\x10\x0e\x12\r\n\tTINY_SLOW\x10\x0f\x12\x10\n\x0cMEDIUM_TURBO\x10\x10\":\n\x0c\x46\x45M_LNA_Mode\x12\x0c\n\x08\x44ISABLED\x10\x00\x12\x0b\n\x07\x45NABLED\x10\x01\x12\x0f\n\x0bNOT_PRESENT\x10\x02\x1a\xad\x01\n\x0f\x42luetoothConfig\x12\x0f\n\x07\x65nabled\x18\x01 \x01(\x08\x12<\n\x04mode\x18\x02 \x01(\x0e\x32..meshtastic.Config.BluetoothConfig.PairingMode\x12\x11\n\tfixed_pin\x18\x03 \x01(\r\"8\n\x0bPairingMode\x12\x0e\n\nRANDOM_PIN\x10\x00\x12\r\n\tFIXED_PIN\x10\x01\x12\n\n\x06NO_PIN\x10\x02\x1a\x9c\x03\n\x0eSecurityConfig\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x13\n\x0bprivate_key\x18\x02 \x01(\x0c\x12\x11\n\tadmin_key\x18\x03 \x03(\x0c\x12\x12\n\nis_managed\x18\x04 \x01(\x08\x12\x16\n\x0eserial_enabled\x18\x05 \x01(\x08\x12\x1d\n\x15\x64\x65\x62ug_log_api_enabled\x18\x06 \x01(\x08\x12\x1d\n\x15\x61\x64min_channel_enabled\x18\x08 \x01(\x08\x12X\n\x17packet_signature_policy\x18\t \x01(\x0e\x32\x37.meshtastic.Config.SecurityConfig.PacketSignaturePolicy\"\x89\x01\n\x15PacketSignaturePolicy\x12&\n\"PACKET_SIGNATURE_POLICY_COMPATIBLE\x10\x00\x12$\n PACKET_SIGNATURE_POLICY_BALANCED\x10\x01\x12\"\n\x1ePACKET_SIGNATURE_POLICY_STRICT\x10\x02\x1a\x12\n\x10SessionkeyConfigB\x11\n\x0fpayload_variantBb\n\x14org.meshtastic.protoB\x0c\x43onfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3"
|
|
11
12
|
|
|
12
13
|
pool = ::Google::Protobuf::DescriptorPool.generated_pool
|
|
13
14
|
pool.add_serialized_file(descriptor_data)
|
|
@@ -233,6 +233,12 @@ module Meshtastic
|
|
|
233
233
|
mesh_packet.want_ack = want_ack
|
|
234
234
|
mesh_packet.hop_limit = hop_limit
|
|
235
235
|
mesh_packet.id = generate_packet_id(last_packet_id: last_packet_id)
|
|
236
|
+
mesh_packet.pki_encrypted = opts[:pki_encrypted] if opts.key?(:pki_encrypted)
|
|
237
|
+
mesh_packet.public_key = opts[:public_key] if opts[:public_key]
|
|
238
|
+
if mesh_packet.pki_encrypted
|
|
239
|
+
raise ArgumentError, 'PKI encryption requires a radio transport without host PSK encryption' unless via == :radio && (psks.nil? || psks.empty?)
|
|
240
|
+
raise ArgumentError, 'recipient public_key must contain 32 bytes' unless mesh_packet.public_key.bytesize == 32
|
|
241
|
+
end
|
|
236
242
|
|
|
237
243
|
# When psks is nil/empty, leave the packet decoded so the radio (serial/TCP)
|
|
238
244
|
# device can apply the channel PSK itself. MQTT callers must pass psks so the
|
|
@@ -340,6 +346,8 @@ module Meshtastic
|
|
|
340
346
|
channel: channel,
|
|
341
347
|
want_ack: want_ack,
|
|
342
348
|
hop_limit: hop_limit,
|
|
349
|
+
pki_encrypted: opts.fetch(:pki_encrypted, false),
|
|
350
|
+
public_key: opts[:public_key],
|
|
343
351
|
psks: psks
|
|
344
352
|
)
|
|
345
353
|
rescue StandardError => e
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
require 'google/protobuf'
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
descriptor_data = "\n\x1dmeshtastic/storeforward.proto\x12\nmeshtastic\"\
|
|
8
|
+
descriptor_data = "\n\x1dmeshtastic/storeforward.proto\x12\nmeshtastic\"\xb1\x07\n\x0fStoreAndForward\x12\x37\n\x02rr\x18\x01 \x01(\x0e\x32+.meshtastic.StoreAndForward.RequestResponse\x12\x37\n\x05stats\x18\x02 \x01(\x0b\x32&.meshtastic.StoreAndForward.StatisticsH\x00\x12\x36\n\x07history\x18\x03 \x01(\x0b\x32#.meshtastic.StoreAndForward.HistoryH\x00\x12:\n\theartbeat\x18\x04 \x01(\x0b\x32%.meshtastic.StoreAndForward.HeartbeatH\x00\x12\x0e\n\x04text\x18\x05 \x01(\x0cH\x00\x12\x13\n\x0boriginal_id\x18\x06 \x01(\r\x1a\xcd\x01\n\nStatistics\x12\x16\n\x0emessages_total\x18\x01 \x01(\r\x12\x16\n\x0emessages_saved\x18\x02 \x01(\r\x12\x14\n\x0cmessages_max\x18\x03 \x01(\r\x12\x0f\n\x07up_time\x18\x04 \x01(\r\x12\x10\n\x08requests\x18\x05 \x01(\r\x12\x18\n\x10requests_history\x18\x06 \x01(\r\x12\x11\n\theartbeat\x18\x07 \x01(\x08\x12\x12\n\nreturn_max\x18\x08 \x01(\r\x12\x15\n\rreturn_window\x18\t \x01(\r\x1aI\n\x07History\x12\x18\n\x10history_messages\x18\x01 \x01(\r\x12\x0e\n\x06window\x18\x02 \x01(\r\x12\x14\n\x0clast_request\x18\x03 \x01(\r\x1a.\n\tHeartbeat\x12\x0e\n\x06period\x18\x01 \x01(\r\x12\x11\n\tsecondary\x18\x02 \x01(\r\"\xbc\x02\n\x0fRequestResponse\x12\t\n\x05UNSET\x10\x00\x12\x10\n\x0cROUTER_ERROR\x10\x01\x12\x14\n\x10ROUTER_HEARTBEAT\x10\x02\x12\x0f\n\x0bROUTER_PING\x10\x03\x12\x0f\n\x0bROUTER_PONG\x10\x04\x12\x0f\n\x0bROUTER_BUSY\x10\x05\x12\x12\n\x0eROUTER_HISTORY\x10\x06\x12\x10\n\x0cROUTER_STATS\x10\x07\x12\x16\n\x12ROUTER_TEXT_DIRECT\x10\x08\x12\x19\n\x15ROUTER_TEXT_BROADCAST\x10\t\x12\x10\n\x0c\x43LIENT_ERROR\x10@\x12\x12\n\x0e\x43LIENT_HISTORY\x10\x41\x12\x10\n\x0c\x43LIENT_STATS\x10\x42\x12\x0f\n\x0b\x43LIENT_PING\x10\x43\x12\x0f\n\x0b\x43LIENT_PONG\x10\x44\x12\x10\n\x0c\x43LIENT_ABORT\x10jB\t\n\x07variantBk\n\x14org.meshtastic.protoB\x15StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3"
|
|
9
9
|
|
|
10
10
|
pool = ::Google::Protobuf::DescriptorPool.generated_pool
|
|
11
11
|
pool.add_serialized_file(descriptor_data)
|
data/lib/meshtastic/version.rb
CHANGED