meshtastic 0.0.142 → 0.0.143
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
- metadata +20 -144
- data/.github/workflows/main.yml +0 -27
- data/.gitignore +0 -29
- data/.rspec +0 -3
- data/.rubocop.yml +0 -35
- data/.rubocop_todo.yml +0 -134
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
- data/AUTOGEN_meshtastic_protobufs.sh +0 -28
- data/CHANGELOG_BETWEEN_TAGS.txt +0 -196
- data/CODE_OF_CONDUCT.md +0 -84
- data/Gemfile +0 -23
- data/LICENSE +0 -21
- data/README.md +0 -106
- data/Rakefile +0 -17
- data/bin/meshtastic_autoinc_version +0 -38
- data/build_meshtastic_gem.sh +0 -58
- data/git_commit.sh +0 -29
- data/lib/meshtastic/admin.rb +0 -24
- data/lib/meshtastic/admin_pb.rb +0 -31
- data/lib/meshtastic/apponly.rb +0 -24
- data/lib/meshtastic/apponly_pb.rb +0 -18
- data/lib/meshtastic/atak.rb +0 -24
- data/lib/meshtastic/atak_pb.rb +0 -22
- data/lib/meshtastic/cannedmessages.rb +0 -24
- data/lib/meshtastic/cannedmessages_pb.rb +0 -15
- data/lib/meshtastic/channel.rb +0 -24
- data/lib/meshtastic/channel_pb.rb +0 -18
- data/lib/meshtastic/clientonly.rb +0 -24
- data/lib/meshtastic/clientonly_pb.rb +0 -18
- data/lib/meshtastic/config.rb +0 -24
- data/lib/meshtastic/config_pb.rb +0 -42
- data/lib/meshtastic/connection_status.rb +0 -24
- data/lib/meshtastic/connection_status_pb.rb +0 -20
- data/lib/meshtastic/device_ui_pb.rb +0 -23
- data/lib/meshtastic/deviceonly.rb +0 -24
- data/lib/meshtastic/deviceonly_pb.rb +0 -28
- data/lib/meshtastic/interdevice_pb.rb +0 -17
- data/lib/meshtastic/localonly.rb +0 -24
- data/lib/meshtastic/localonly_pb.rb +0 -19
- data/lib/meshtastic/mesh_interface.rb +0 -596
- data/lib/meshtastic/mesh_pb.rb +0 -65
- data/lib/meshtastic/module_config.rb +0 -24
- data/lib/meshtastic/module_config_pb.rb +0 -36
- data/lib/meshtastic/mqtt.rb +0 -383
- data/lib/meshtastic/mqtt_pb.rb +0 -19
- data/lib/meshtastic/paxcount.rb +0 -24
- data/lib/meshtastic/paxcount_pb.rb +0 -15
- data/lib/meshtastic/portnums.rb +0 -24
- data/lib/meshtastic/portnums_pb.rb +0 -15
- data/lib/meshtastic/powermon_pb.rb +0 -18
- data/lib/meshtastic/remote_hardware.rb +0 -24
- data/lib/meshtastic/remote_hardware_pb.rb +0 -16
- data/lib/meshtastic/rtttl.rb +0 -24
- data/lib/meshtastic/rtttl_pb.rb +0 -15
- data/lib/meshtastic/serial_interface.rb +0 -550
- data/lib/meshtastic/storeforward.rb +0 -24
- data/lib/meshtastic/storeforward_pb.rb +0 -19
- data/lib/meshtastic/stream_interface.rb +0 -132
- data/lib/meshtastic/telemetry.rb +0 -24
- data/lib/meshtastic/telemetry_pb.rb +0 -24
- data/lib/meshtastic/util.rb +0 -70
- data/lib/meshtastic/version.rb +0 -5
- data/lib/meshtastic/xmodem.rb +0 -24
- data/lib/meshtastic/xmodem_pb.rb +0 -16
- data/lib/meshtastic.rb +0 -71
- data/lib/nanopb_pb.rb +0 -19
- data/meshtastic.gemspec +0 -73
- data/reinstall_meshtastic_gemset.sh +0 -29
- data/sig/meshtastic.rbs +0 -4
- data/spec/lib/meshtastic/admin_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/admin_spec.rb +0 -6
- data/spec/lib/meshtastic/apponly_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/apponly_spec.rb +0 -6
- data/spec/lib/meshtastic/atak_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/atak_spec.rb +0 -6
- data/spec/lib/meshtastic/cannedmessages_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/cannedmessages_spec.rb +0 -6
- data/spec/lib/meshtastic/channel_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/channel_spec.rb +0 -6
- data/spec/lib/meshtastic/clientonly_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/clientonly_spec.rb +0 -6
- data/spec/lib/meshtastic/config_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/config_spec.rb +0 -6
- data/spec/lib/meshtastic/connection_status_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/connection_status_spec.rb +0 -6
- data/spec/lib/meshtastic/device_ui_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/deviceonly_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/deviceonly_spec.rb +0 -6
- data/spec/lib/meshtastic/interdevice_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/localonly_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/localonly_spec.rb +0 -6
- data/spec/lib/meshtastic/mesh_interface_spec.rb +0 -6
- data/spec/lib/meshtastic/mesh_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/module_config_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/module_config_spec.rb +0 -6
- data/spec/lib/meshtastic/mqtt_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/mqtt_spec.rb +0 -6
- data/spec/lib/meshtastic/paxcount_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/paxcount_spec.rb +0 -6
- data/spec/lib/meshtastic/portnums_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/portnums_spec.rb +0 -6
- data/spec/lib/meshtastic/powermon_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/remote_hardware_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/remote_hardware_spec.rb +0 -6
- data/spec/lib/meshtastic/rtttl_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/rtttl_spec.rb +0 -6
- data/spec/lib/meshtastic/serial_interface_spec.rb +0 -6
- data/spec/lib/meshtastic/storeforward_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/storeforward_spec.rb +0 -6
- data/spec/lib/meshtastic/stream_interface_spec.rb +0 -6
- data/spec/lib/meshtastic/telemetry_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/telemetry_spec.rb +0 -6
- data/spec/lib/meshtastic/util_spec.rb +0 -6
- data/spec/lib/meshtastic/version_spec.rb +0 -17
- data/spec/lib/meshtastic/xmodem_pb_spec.rb +0 -6
- data/spec/lib/meshtastic/xmodem_spec.rb +0 -6
- data/spec/lib/meshtastic_spec.rb +0 -6
- data/spec/lib/nanopb_pb_spec.rb +0 -6
- data/spec/spec_helper.rb +0 -15
- data/upgrade_Gemfile_gems.sh +0 -21
- data/upgrade_gem.sh +0 -4
- data/upgrade_meshtastic.sh +0 -13
- data/upgrade_ruby.sh +0 -45
|
@@ -1,596 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'meshtastic/mesh_pb'
|
|
4
|
-
|
|
5
|
-
# Plugin used to interact with Meshtastic nodes
|
|
6
|
-
module Meshtastic
|
|
7
|
-
class MeshInterface
|
|
8
|
-
attr_accessor :acknowledgment,
|
|
9
|
-
:config_id,
|
|
10
|
-
:current_packet_id,
|
|
11
|
-
:debug_out,
|
|
12
|
-
:got_response,
|
|
13
|
-
:failure,
|
|
14
|
-
:heartbeat_timer,
|
|
15
|
-
:is_connected,
|
|
16
|
-
:is_proto,
|
|
17
|
-
:local_channels,
|
|
18
|
-
:mask,
|
|
19
|
-
:metadata,
|
|
20
|
-
:my_info,
|
|
21
|
-
:no_nodes,
|
|
22
|
-
:nodes,
|
|
23
|
-
:nodes_by_num,
|
|
24
|
-
:queue,
|
|
25
|
-
:queue_status,
|
|
26
|
-
:response_handlers,
|
|
27
|
-
:timeout
|
|
28
|
-
|
|
29
|
-
def initialize(opts = {})
|
|
30
|
-
@acknowledgment = Meshtastic::Util::Acknowledgement.new
|
|
31
|
-
|
|
32
|
-
@current_packet_id = generate_packet_id
|
|
33
|
-
|
|
34
|
-
@debug_out = opts[:debug_out]
|
|
35
|
-
|
|
36
|
-
@failure = nil
|
|
37
|
-
|
|
38
|
-
@got_response = false
|
|
39
|
-
|
|
40
|
-
@heartbeat_timer = nil
|
|
41
|
-
|
|
42
|
-
@is_connected = true if opts[:is_connected]
|
|
43
|
-
@is_connected = false unless opts[:is_connected] # TODO: threading.Event = threading.Event()
|
|
44
|
-
|
|
45
|
-
@is_proto = true if opts[:is_proto]
|
|
46
|
-
@is_proto = false unless opts[:is_proto]
|
|
47
|
-
|
|
48
|
-
@local_channels = nil
|
|
49
|
-
|
|
50
|
-
@mask = nil
|
|
51
|
-
|
|
52
|
-
@metadata = Meshtastic::DeviceMetadata.new
|
|
53
|
-
|
|
54
|
-
@my_info = Meshtastic::MyNodeInfo
|
|
55
|
-
|
|
56
|
-
@no_nodes = true if opts[:no_nodes]
|
|
57
|
-
@no_nodes = false unless opts[:no_nodes]
|
|
58
|
-
|
|
59
|
-
@nodes = { nodes: {} }
|
|
60
|
-
|
|
61
|
-
@nodes_by_num = {}
|
|
62
|
-
|
|
63
|
-
@queue = {}
|
|
64
|
-
@queue_status = Meshtastic::QueueStatus.new
|
|
65
|
-
|
|
66
|
-
@response_handlers = {}
|
|
67
|
-
|
|
68
|
-
@timeout = Meshtastic::Util::Timeout.new
|
|
69
|
-
|
|
70
|
-
@config_id = NODELESS_WANT_CONFIG_ID if no_nodes
|
|
71
|
-
@config_id = nil unless no_nodes
|
|
72
|
-
rescue StandardError => e
|
|
73
|
-
raise e
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Supported Method Parameters::
|
|
77
|
-
# packet_id = Meshtastic.generate_packet_id(
|
|
78
|
-
# last_packet_id: 'optional - Last Packet ID (Default: 0)'
|
|
79
|
-
# )
|
|
80
|
-
def generate_packet_id(opts = {})
|
|
81
|
-
last_packet_id = opts[:last_packet_id] ||= 0
|
|
82
|
-
last_packet_id = 0 if last_packet_id.negative?
|
|
83
|
-
|
|
84
|
-
packet_id = Random.rand(0xffffffff) if last_packet_id.zero?
|
|
85
|
-
packet_id = (last_packet_id + 1) & 0xffffffff if last_packet_id.positive?
|
|
86
|
-
|
|
87
|
-
packet_id
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
# Supported Method Parameters::
|
|
91
|
-
# Meshtastic.get_cipher_keys(
|
|
92
|
-
# psks: 'required - hash of channel / pre-shared key value pairs'
|
|
93
|
-
# )
|
|
94
|
-
|
|
95
|
-
def get_cipher_keys(opts = {})
|
|
96
|
-
psks = opts[:psks]
|
|
97
|
-
|
|
98
|
-
psks.each_key do |key|
|
|
99
|
-
psk = psks[key]
|
|
100
|
-
padded_psk = psk.ljust(psk.length + ((4 - (psk.length % 4)) % 4), '=')
|
|
101
|
-
replaced_psk = padded_psk.gsub('-', '+').gsub('_', '/')
|
|
102
|
-
psks[key] = replaced_psk
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
psks
|
|
106
|
-
rescue StandardError => e
|
|
107
|
-
raise e
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# Supported Method Parameters::
|
|
111
|
-
# Meshtastic.gps_search(
|
|
112
|
-
# lat: 'required - latitude float (e.g. 37.7749)',
|
|
113
|
-
# lon: 'required - longitude float (e.g. -122.4194)'
|
|
114
|
-
# )
|
|
115
|
-
def gps_search(opts = {})
|
|
116
|
-
lat = opts[:lat]
|
|
117
|
-
lon = opts[:lon]
|
|
118
|
-
|
|
119
|
-
raise 'ERROR: Latitude and Longitude are required' unless lat && lon
|
|
120
|
-
|
|
121
|
-
gps_arr = [lat.to_f, lon.to_f]
|
|
122
|
-
|
|
123
|
-
Geocoder.search(gps_arr).first.data
|
|
124
|
-
rescue StandardError => e
|
|
125
|
-
raise e
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
# Meshtastic::MeshInterface.send_to_radio(
|
|
129
|
-
# payload: 'required - ToRadio Message to Send'
|
|
130
|
-
# )
|
|
131
|
-
def send_to_radio(opts = {})
|
|
132
|
-
payload = opts[:payload]
|
|
133
|
-
|
|
134
|
-
raise 'ERROR: Invalid ToRadio Message' unless payload.is_a?(Meshtastic::ToRadio)
|
|
135
|
-
|
|
136
|
-
payload.to_proto
|
|
137
|
-
rescue StandardError => e
|
|
138
|
-
raise e
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
# Supported Method Parameters::
|
|
142
|
-
# Meshtastic::MeshInterface.send_to_mqtt(
|
|
143
|
-
# service_envelope: 'required - ServiceEnvelope Message to Send'
|
|
144
|
-
# )
|
|
145
|
-
def send_to_mqtt(opts = {})
|
|
146
|
-
service_envelope = opts[:service_envelope]
|
|
147
|
-
|
|
148
|
-
raise 'ERROR: Invalid ServiceEnvelope Message' unless service_envelope.is_a?(Meshtastic::ServiceEnvelope)
|
|
149
|
-
|
|
150
|
-
service_envelope.to_proto
|
|
151
|
-
rescue StandardError => e
|
|
152
|
-
raise e
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
# Supported Method Parameters::
|
|
156
|
-
# Meshtastic::Mesh.start_config(
|
|
157
|
-
# )
|
|
158
|
-
def start_config
|
|
159
|
-
@my_info = nil
|
|
160
|
-
@nodes = {}
|
|
161
|
-
@nodes_by_num = {}
|
|
162
|
-
@local_channels = []
|
|
163
|
-
|
|
164
|
-
to_radio_start_config = Meshtastic::ToRadio.new
|
|
165
|
-
if @config_id.nil? || !@no_nodes
|
|
166
|
-
@config_id = Random.rand(0xFFFFFFFF)
|
|
167
|
-
@config_id += 1 if @config_id == NODELESS_WANT_CONFIG_ID
|
|
168
|
-
end
|
|
169
|
-
to_radio_start_config.want_config_id = @config_id
|
|
170
|
-
send_to_radio(payload: to_radio_start_config)
|
|
171
|
-
rescue StandardError => e
|
|
172
|
-
raise e
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
# Supported Method Parameters::
|
|
176
|
-
# Meshtastic::Mesh.my_node_info
|
|
177
|
-
def my_node_info
|
|
178
|
-
mni = Meshtastic::MyNodeInfo.new
|
|
179
|
-
mni.to_h
|
|
180
|
-
rescue StandardError => e
|
|
181
|
-
raise e
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
# Supported Method Parameters::
|
|
185
|
-
# Meshtastic::MeshInterface.send_packet(
|
|
186
|
-
# mesh_packet: 'required - Mesh Packet to Send',
|
|
187
|
-
# from: 'required - From ID (String or Integer) (Default: "!00000b0b")',
|
|
188
|
-
# to: 'optional - Destination ID (Default: "!ffffffff")',
|
|
189
|
-
# last_packet_id: 'optional - Last Packet ID (Default: 0)',
|
|
190
|
-
# via: 'optional - :radio || :mqtt (Default: :radio)',
|
|
191
|
-
# channel: 'optional - Channel (Default: 0)',
|
|
192
|
-
# want_ack: 'optional - Want Acknowledgement (Default: false)',
|
|
193
|
-
# hop_limit: 'optional - Hop Limit (Default: 3)',
|
|
194
|
-
# psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: "AQ==" })'
|
|
195
|
-
# )
|
|
196
|
-
def send_packet(opts = {})
|
|
197
|
-
mesh_packet = opts[:mesh_packet]
|
|
198
|
-
from = opts[:from] ||= '!00000b0b'
|
|
199
|
-
# from_hex = from.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if from.is_a?(String)
|
|
200
|
-
from_hex = from.delete('!') if from.is_a?(String)
|
|
201
|
-
from = from_hex.to_i(16) if from_hex
|
|
202
|
-
raise 'ERROR: from parameter is required.' unless from
|
|
203
|
-
|
|
204
|
-
to = opts[:to] ||= '!ffffffff'
|
|
205
|
-
# to_hex = to.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if to.is_a?(String)
|
|
206
|
-
to_hex = to.delete('!') if to.is_a?(String)
|
|
207
|
-
to = to_hex.to_i(16) if to_hex
|
|
208
|
-
|
|
209
|
-
last_packet_id = opts[:last_packet_id] ||= 0
|
|
210
|
-
via = opts[:via] ||= :radio
|
|
211
|
-
channel = opts[:channel] ||= 0
|
|
212
|
-
want_ack = opts[:want_ack] ||= false
|
|
213
|
-
hop_limit = opts[:hop_limit] ||= 3
|
|
214
|
-
|
|
215
|
-
public_psk = '1PG7OiApB1nwvP+rz05pAQ=='
|
|
216
|
-
psks = opts[:psks] ||= { LongFast: public_psk }
|
|
217
|
-
raise 'ERROR: psks parameter must be a hash of :channel => psk key value pairs' unless psks.is_a?(Hash)
|
|
218
|
-
|
|
219
|
-
psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
|
|
220
|
-
|
|
221
|
-
# my_info = Meshtastic::FromRadio.my_info
|
|
222
|
-
# wait_connected if to != my_info.my_node_num && my_info.is_a(Meshtastic::Deviceonly::MyInfo)
|
|
223
|
-
|
|
224
|
-
mesh_packet.from = from
|
|
225
|
-
mesh_packet.to = to
|
|
226
|
-
mesh_packet.channel = channel
|
|
227
|
-
mesh_packet.want_ack = want_ack
|
|
228
|
-
mesh_packet.hop_limit = hop_limit
|
|
229
|
-
mesh_packet.id = generate_packet_id(last_packet_id: last_packet_id)
|
|
230
|
-
|
|
231
|
-
if psks
|
|
232
|
-
nonce_packet_id = [mesh_packet.id].pack('V').ljust(8, "\x00")
|
|
233
|
-
nonce_from_node = [from].pack('V').ljust(8, "\x00")
|
|
234
|
-
nonce = "#{nonce_packet_id}#{nonce_from_node}"
|
|
235
|
-
|
|
236
|
-
psk = psks[psks.keys.first]
|
|
237
|
-
dec_psk = Base64.strict_decode64(psk)
|
|
238
|
-
cipher = OpenSSL::Cipher.new('AES-128-CTR')
|
|
239
|
-
cipher = OpenSSL::Cipher.new('AES-256-CTR') if dec_psk.length == 32
|
|
240
|
-
cipher.encrypt
|
|
241
|
-
cipher.key = dec_psk
|
|
242
|
-
cipher.iv = nonce
|
|
243
|
-
|
|
244
|
-
decrypted_payload = mesh_packet.decoded.to_proto
|
|
245
|
-
encrypted_payload = cipher.update(decrypted_payload) + cipher.final
|
|
246
|
-
|
|
247
|
-
mesh_packet.encrypted = encrypted_payload
|
|
248
|
-
end
|
|
249
|
-
# puts mesh_packet.to_h
|
|
250
|
-
|
|
251
|
-
# puts "Sending Packet via: #{via}"
|
|
252
|
-
case via
|
|
253
|
-
when :radio
|
|
254
|
-
payload = Meshtastic::ToRadio.new
|
|
255
|
-
payload.packet = mesh_packet
|
|
256
|
-
send_to_radio(payload: payload)
|
|
257
|
-
when :mqtt
|
|
258
|
-
service_envelope = Meshtastic::ServiceEnvelope.new
|
|
259
|
-
service_envelope.packet = mesh_packet
|
|
260
|
-
# TODO: Add support for multiple PSKs by accepting channel_id
|
|
261
|
-
service_envelope.channel_id = psks.keys.first
|
|
262
|
-
service_envelope.gateway_id = "!#{from.to_s(16).downcase}"
|
|
263
|
-
send_to_mqtt(service_envelope: service_envelope)
|
|
264
|
-
else
|
|
265
|
-
raise "ERROR: Invalid via parameter: #{via}"
|
|
266
|
-
end
|
|
267
|
-
rescue StandardError => e
|
|
268
|
-
raise e
|
|
269
|
-
end
|
|
270
|
-
|
|
271
|
-
# Supported Method Parameters::
|
|
272
|
-
# Meshtastic::MeshInterface.send_data(
|
|
273
|
-
# from: 'required - From ID (String or Integer) (Default: "!00000b0b")',
|
|
274
|
-
# to: 'optional - Destination ID (Default: "!ffffffff")',
|
|
275
|
-
# last_packet_id: 'optional - Last Packet ID (Default: 0)',
|
|
276
|
-
# via: 'optional - :radio || :mqtt (Default: :radio)',
|
|
277
|
-
# channel: 'optional - Channel (Default: 0)',
|
|
278
|
-
# data: 'required - Data to Send',
|
|
279
|
-
# want_ack: 'optional - Want Acknowledgement (Default: false)',
|
|
280
|
-
# hop_limit: 'optional - Hop Limit (Default: 3)',
|
|
281
|
-
# port_num: 'optional - (Default: Meshtastic::PortNum::PRIVATE_APP)',
|
|
282
|
-
# psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: "AQ==" })'
|
|
283
|
-
# )
|
|
284
|
-
def send_data(opts = {})
|
|
285
|
-
# Send a text message to a node
|
|
286
|
-
from = opts[:from] ||= '!00000b0b'
|
|
287
|
-
# from_hex = from.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if from.is_a?(String)
|
|
288
|
-
from_hex = from.delete('!') if from.is_a?(String)
|
|
289
|
-
from = from_hex.to_i(16) if from_hex
|
|
290
|
-
raise 'ERROR: from parameter is required.' unless from
|
|
291
|
-
|
|
292
|
-
to = opts[:to] ||= '!ffffffff'
|
|
293
|
-
# to_hex = to.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if to.is_a?(String)
|
|
294
|
-
to_hex = to.delete('!') if to.is_a?(String)
|
|
295
|
-
to = to_hex.to_i(16) if to_hex
|
|
296
|
-
|
|
297
|
-
last_packet_id = opts[:last_packet_id] ||= 0
|
|
298
|
-
via = opts[:via] ||= :radio
|
|
299
|
-
channel = opts[:channel] ||= 0
|
|
300
|
-
data = opts[:data]
|
|
301
|
-
want_ack = opts[:want_ack] ||= false
|
|
302
|
-
hop_limit = opts[:hop_limit] ||= 3
|
|
303
|
-
port_num = opts[:port_num] ||= Meshtastic::PortNum::PRIVATE_APP
|
|
304
|
-
max_port_num = Meshtastic::PortNum::MAX
|
|
305
|
-
raise "ERROR: Invalid port_num" unless port_num.positive? && port_num < max_port_num
|
|
306
|
-
|
|
307
|
-
public_psk = '1PG7OiApB1nwvP+rz05pAQ=='
|
|
308
|
-
psks = opts[:psks] ||= { LongFast: public_psk }
|
|
309
|
-
raise 'ERROR: psks parameter must be a hash of :channel => psk key value pairs' unless psks.is_a?(Hash)
|
|
310
|
-
|
|
311
|
-
psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
|
|
312
|
-
|
|
313
|
-
data_len = data.payload.length
|
|
314
|
-
max_len = Meshtastic::Constants::DATA_PAYLOAD_LEN
|
|
315
|
-
raise "ERROR: Data Length > #{max_len} Bytes" if data_len > max_len
|
|
316
|
-
|
|
317
|
-
mesh_packet = Meshtastic::MeshPacket.new
|
|
318
|
-
mesh_packet.decoded = data
|
|
319
|
-
|
|
320
|
-
send_packet(
|
|
321
|
-
mesh_packet: mesh_packet,
|
|
322
|
-
from: from,
|
|
323
|
-
to: to,
|
|
324
|
-
last_packet_id: last_packet_id,
|
|
325
|
-
via: via,
|
|
326
|
-
channel: channel,
|
|
327
|
-
want_ack: want_ack,
|
|
328
|
-
hop_limit: hop_limit,
|
|
329
|
-
psks: psks
|
|
330
|
-
)
|
|
331
|
-
rescue StandardError => e
|
|
332
|
-
raise e
|
|
333
|
-
end
|
|
334
|
-
|
|
335
|
-
# Supported Method Parameters::
|
|
336
|
-
# Meshtastic::MeshInterface.send_text(
|
|
337
|
-
# from: 'required - From ID (String or Integer) (Default: "!00000b0b")',
|
|
338
|
-
# to: 'optional - Destination ID (Default: "!ffffffff")',
|
|
339
|
-
# last_packet_id: 'optional - Last Packet ID (Default: 0)',
|
|
340
|
-
# via: 'optional - :radio || :mqtt (Default: :radio)',
|
|
341
|
-
# channel: 'optional - Channel (Default: 6)',
|
|
342
|
-
# text: 'optional - Text Message (Default: SYN)',
|
|
343
|
-
# want_ack: 'optional - Want Acknowledgement (Default: false)',
|
|
344
|
-
# want_response: 'optional - Want Response (Default: false)',
|
|
345
|
-
# hop_limit: 'optional - Hop Limit (Default: 3)',
|
|
346
|
-
# on_response: 'optional - Callback on Response',
|
|
347
|
-
# psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: "AQ==" })'
|
|
348
|
-
# )
|
|
349
|
-
def send_text(opts = {})
|
|
350
|
-
# Send a text message to a node
|
|
351
|
-
from = opts[:from] ||= '!00000b0b'
|
|
352
|
-
# from_hex = from.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if from.is_a?(String)
|
|
353
|
-
from_hex = from.delete('!') if from.is_a?(String)
|
|
354
|
-
from = from_hex.to_i(16) if from_hex
|
|
355
|
-
raise 'ERROR: from parameter is required.' unless from
|
|
356
|
-
|
|
357
|
-
to = opts[:to] ||= '!ffffffff'
|
|
358
|
-
# to_hex = to.delete('!').bytes.map { |b| b.to_s(16).rjust(2, '0') }.join if to.is_a?(String)
|
|
359
|
-
to_hex = to.delete('!') if to.is_a?(String)
|
|
360
|
-
to = to_hex.to_i(16) if to_hex
|
|
361
|
-
|
|
362
|
-
last_packet_id = opts[:last_packet_id] ||= 0
|
|
363
|
-
via = opts[:via] ||= :radio
|
|
364
|
-
channel = opts[:channel] ||= 6
|
|
365
|
-
text = opts[:text] ||= 'SYN'
|
|
366
|
-
want_ack = opts[:want_ack] ||= false
|
|
367
|
-
want_response = opts[:want_response] ||= false
|
|
368
|
-
hop_limit = opts[:hop_limit] ||= 3
|
|
369
|
-
on_response = opts[:on_response]
|
|
370
|
-
|
|
371
|
-
public_psk = '1PG7OiApB1nwvP+rz05pAQ=='
|
|
372
|
-
psks = opts[:psks] ||= { LongFast: public_psk }
|
|
373
|
-
raise 'ERROR: psks parameter must be a hash of :channel => psk key value pairs' unless psks.is_a?(Hash)
|
|
374
|
-
|
|
375
|
-
psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
|
|
376
|
-
|
|
377
|
-
# TODO: verify text length validity
|
|
378
|
-
max_txt_len = Meshtastic::Constants::DATA_PAYLOAD_LEN
|
|
379
|
-
raise "ERROR: Text Length > #{max_txt_len} Bytes" if text.length > max_txt_len
|
|
380
|
-
|
|
381
|
-
port_num = Meshtastic::PortNum::TEXT_MESSAGE_APP
|
|
382
|
-
|
|
383
|
-
data = Meshtastic::Data.new
|
|
384
|
-
data.payload = text.force_encoding('ASCII-8BIT')
|
|
385
|
-
data.portnum = port_num
|
|
386
|
-
data.want_response = want_response
|
|
387
|
-
# puts data.to_h
|
|
388
|
-
|
|
389
|
-
send_data(
|
|
390
|
-
from: from,
|
|
391
|
-
to: to,
|
|
392
|
-
last_packet_id: last_packet_id,
|
|
393
|
-
via: via,
|
|
394
|
-
channel: channel,
|
|
395
|
-
data: data,
|
|
396
|
-
want_ack: want_ack,
|
|
397
|
-
want_response: want_response,
|
|
398
|
-
hop_limit: hop_limit,
|
|
399
|
-
port_num: port_num,
|
|
400
|
-
on_response: on_response,
|
|
401
|
-
psks: psks
|
|
402
|
-
)
|
|
403
|
-
rescue StandardError => e
|
|
404
|
-
raise e
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
# Supported Method Parameters::
|
|
408
|
-
# Meshtastic::MQQT.decode_payload(
|
|
409
|
-
# payload: 'required - payload to recursively decode',
|
|
410
|
-
# msg_type: 'required - message type (e.g. :TEXT_MESSAGE_APP)',
|
|
411
|
-
# gps_metadata: 'optional - include GPS metadata in output (default: false)',
|
|
412
|
-
# )
|
|
413
|
-
|
|
414
|
-
def decode_payload(opts = {})
|
|
415
|
-
payload = opts[:payload]
|
|
416
|
-
msg_type = opts[:msg_type]
|
|
417
|
-
gps_metadata = opts[:gps_metadata]
|
|
418
|
-
|
|
419
|
-
case msg_type
|
|
420
|
-
when :ADMIN_APP
|
|
421
|
-
decoder = Meshtastic::AdminMessage
|
|
422
|
-
when :ATAK_FORWARDER, :ATAK_PLUGIN
|
|
423
|
-
decoder = Meshtastic::TAKPacket
|
|
424
|
-
# when :AUDIO_APP
|
|
425
|
-
# decoder = Meshtastic::Audio
|
|
426
|
-
when :DETECTION_SENSOR_APP
|
|
427
|
-
decoder = Meshtastic::DeviceState
|
|
428
|
-
# when :IP_TUNNEL_APP
|
|
429
|
-
# decoder = Meshtastic::IpTunnel
|
|
430
|
-
when :MAP_REPORT_APP
|
|
431
|
-
decoder = Meshtastic::MapReport
|
|
432
|
-
# when :MAX
|
|
433
|
-
# decoder = Meshtastic::Max
|
|
434
|
-
when :NEIGHBORINFO_APP
|
|
435
|
-
decoder = Meshtastic::NeighborInfo
|
|
436
|
-
when :NODEINFO_APP
|
|
437
|
-
decoder = Meshtastic::User
|
|
438
|
-
when :PAXCOUNTER_APP
|
|
439
|
-
decoder = Meshtastic::Paxcount
|
|
440
|
-
when :POSITION_APP
|
|
441
|
-
decoder = Meshtastic::Position
|
|
442
|
-
# when :PRIVATE_APP
|
|
443
|
-
# decoder = Meshtastic::Private
|
|
444
|
-
when :RANGE_TEST_APP
|
|
445
|
-
# Unsure if this is the correct protobuf object
|
|
446
|
-
decoder = Meshtastic::FromRadio
|
|
447
|
-
when :REMOTE_HARDWARE_APP
|
|
448
|
-
decoder = Meshtastic::HardwareMessage
|
|
449
|
-
# when :REPLY_APP
|
|
450
|
-
# decoder = Meshtastic::Reply
|
|
451
|
-
when :ROUTING_APP
|
|
452
|
-
decoder = Meshtastic::Routing
|
|
453
|
-
when :SERIAL_APP
|
|
454
|
-
decoder = Meshtastic::SerialConnectionStatus
|
|
455
|
-
when :SIMULATOR_APP
|
|
456
|
-
decoder = Meshtastic::Compressed
|
|
457
|
-
when :STORE_FORWARD_APP
|
|
458
|
-
decoder = Meshtastic::StoreAndForward
|
|
459
|
-
when :TELEMETRY_APP
|
|
460
|
-
decoder = Meshtastic::Telemetry
|
|
461
|
-
when :TEXT_MESSAGE_APP, :UNKNOWN_APP
|
|
462
|
-
decoder = Meshtastic::Data
|
|
463
|
-
when :TRACEROUTE_APP
|
|
464
|
-
decoder = Meshtastic::RouteDiscovery
|
|
465
|
-
when :WAYPOINT_APP
|
|
466
|
-
decoder = Meshtastic::Waypoint
|
|
467
|
-
# when :ZPS_APP
|
|
468
|
-
# decoder = Meshtastic::Zps
|
|
469
|
-
else
|
|
470
|
-
puts "WARNING: Can't decode\n#{payload.inspect}\nw/ portnum: #{msg_type}"
|
|
471
|
-
return payload
|
|
472
|
-
end
|
|
473
|
-
|
|
474
|
-
payload = decoder.decode(payload).to_h
|
|
475
|
-
|
|
476
|
-
if payload.keys.include?(:latitude_i)
|
|
477
|
-
lat = payload[:latitude_i] * 0.0000001
|
|
478
|
-
payload[:latitude] = lat
|
|
479
|
-
end
|
|
480
|
-
|
|
481
|
-
if payload.keys.include?(:longitude_i)
|
|
482
|
-
lon = payload[:longitude_i] * 0.0000001
|
|
483
|
-
payload[:longitude] = lon
|
|
484
|
-
end
|
|
485
|
-
|
|
486
|
-
if payload.keys.include?(:macaddr)
|
|
487
|
-
mac_raw = payload[:macaddr]
|
|
488
|
-
mac_hex_arr = mac_raw.bytes.map { |byte| byte.to_s(16).rjust(2, '0') }
|
|
489
|
-
mac_hex_str = mac_hex_arr.join(':')
|
|
490
|
-
payload[:macaddr] = mac_hex_str
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
if payload.keys.include?(:public_key)
|
|
494
|
-
public_key_raw = payload[:public_key]
|
|
495
|
-
payload[:public_key] = Base64.strict_encode64(public_key_raw)
|
|
496
|
-
end
|
|
497
|
-
|
|
498
|
-
if payload.keys.include?(:time)
|
|
499
|
-
time_int = payload[:time]
|
|
500
|
-
if time_int.is_a?(Integer)
|
|
501
|
-
time_utc = Time.at(time_int).utc.to_s
|
|
502
|
-
payload[:time_utc] = time_utc
|
|
503
|
-
end
|
|
504
|
-
end
|
|
505
|
-
|
|
506
|
-
if gps_metadata && payload[:latitude] && payload[:longitude]
|
|
507
|
-
lat = payload[:latitude]
|
|
508
|
-
lon = payload[:longitude]
|
|
509
|
-
unless lat.zero? && lon.zero?
|
|
510
|
-
gps_search_resp = gps_search(lat: lat, lon: lon)
|
|
511
|
-
payload[:gps_metadata] = gps_search_resp
|
|
512
|
-
end
|
|
513
|
-
end
|
|
514
|
-
|
|
515
|
-
payload
|
|
516
|
-
rescue Encoding::CompatibilityError,
|
|
517
|
-
Google::Protobuf::ParseError
|
|
518
|
-
payload
|
|
519
|
-
rescue StandardError => e
|
|
520
|
-
raise e
|
|
521
|
-
end
|
|
522
|
-
|
|
523
|
-
# Author(s):: 0day Inc. <support@0dayinc.com>
|
|
524
|
-
|
|
525
|
-
def authors
|
|
526
|
-
"AUTHOR(S):
|
|
527
|
-
0day Inc. <support@0dayinc.com>
|
|
528
|
-
"
|
|
529
|
-
end
|
|
530
|
-
|
|
531
|
-
# Display Usage for this Module
|
|
532
|
-
|
|
533
|
-
def help
|
|
534
|
-
puts "USAGE:
|
|
535
|
-
#{self}.send_to_radio(
|
|
536
|
-
payload: 'required - ToRadio Message to Send'
|
|
537
|
-
)
|
|
538
|
-
|
|
539
|
-
#{self}.send_to_mqtt(
|
|
540
|
-
service_envelope: 'required - ServiceEnvelope Message to Send'
|
|
541
|
-
)
|
|
542
|
-
|
|
543
|
-
#{self}.start_config
|
|
544
|
-
|
|
545
|
-
#{self}.my_node_info
|
|
546
|
-
|
|
547
|
-
#{self}.send_packet(
|
|
548
|
-
mesh_packet: 'required - Mesh Packet to Send',
|
|
549
|
-
from: 'required - From ID (String or Integer) (Default: \"!00000b0b\")',
|
|
550
|
-
to: 'optional - Destination ID (Default: \"!ffffffff\")',
|
|
551
|
-
last_packet_id: 'optional - Last Packet ID (Default: 0)',
|
|
552
|
-
via: 'optional - :radio || :mqtt (Default: :radio)',
|
|
553
|
-
channel: 'optional - Channel (Default: 0)',
|
|
554
|
-
want_ack: 'optional - Want Acknowledgement (Default: false)',
|
|
555
|
-
hop_limit: 'optional - Hop Limit (Default: 3)',
|
|
556
|
-
psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: \"AQ==\" })'
|
|
557
|
-
)
|
|
558
|
-
|
|
559
|
-
#{self}.send_data(
|
|
560
|
-
from: 'required - From ID (String or Integer) (Default: \"!00000b0b\")',
|
|
561
|
-
to: 'optional - Destination ID (Default: \"!ffffffff\")',
|
|
562
|
-
last_packet_id: 'optional - Last Packet ID (Default: 0)',
|
|
563
|
-
via: 'optional - :radio || :mqtt (Default: :radio)',
|
|
564
|
-
channel: 'optional - Channel (Default: 0)',
|
|
565
|
-
data: 'required - Data to Send',
|
|
566
|
-
want_ack: 'optional - Want Acknowledgement (Default: false)',
|
|
567
|
-
hop_limit: 'optional - Hop Limit (Default: 3)',
|
|
568
|
-
port_num: 'optional - (Default: Meshtastic::PortNum::PRIVATE_APP)',
|
|
569
|
-
psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: \"AQ==\" })'
|
|
570
|
-
)
|
|
571
|
-
|
|
572
|
-
#{self}.send_text(
|
|
573
|
-
from: 'required - From ID (String or Integer) (Default: \"!00000b0b\")',
|
|
574
|
-
to: 'optional - Destination ID (Default: \"!ffffffff\")',
|
|
575
|
-
last_packet_id: 'optional - Last Packet ID (Default: 0)',
|
|
576
|
-
via: 'optional - :radio || :mqtt (Default: :radio)',
|
|
577
|
-
channel: 'optional - Channel (Default: 6)',
|
|
578
|
-
text: 'optional - Text Message (Default: SYN)',
|
|
579
|
-
want_ack: 'optional - Want Acknowledgement (Default: false)',
|
|
580
|
-
want_response: 'optional - Want Response (Default: false)',
|
|
581
|
-
hop_limit: 'optional - Hop Limit (Default: 3)',
|
|
582
|
-
on_response: 'optional - Callback on Response',
|
|
583
|
-
psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: \"AQ==\" })'
|
|
584
|
-
)
|
|
585
|
-
|
|
586
|
-
#{self}.decode_payload(
|
|
587
|
-
payload: 'required - payload to recursively decode',
|
|
588
|
-
msg_type: 'required - message type (e.g. :TEXT_MESSAGE_APP)',
|
|
589
|
-
gps_metadata: 'optional - include GPS metadata in output (default: false)',
|
|
590
|
-
)
|
|
591
|
-
|
|
592
|
-
#{self}.authors
|
|
593
|
-
"
|
|
594
|
-
end
|
|
595
|
-
end
|
|
596
|
-
end
|