meshtastic 0.0.183 → 0.0.185

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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +1 -0
  3. data/Gemfile +2 -1
  4. data/documentation/README.md +6 -0
  5. data/documentation/admin-backup.md +369 -0
  6. data/documentation/admin.md +4 -0
  7. data/documentation/forwarder.md +149 -0
  8. data/documentation/mesh-interface.md +157 -1
  9. data/documentation/payload-formats.md +187 -0
  10. data/documentation/reticulum.md +89 -0
  11. data/lib/meshtastic/admin/backup.rb +560 -0
  12. data/lib/meshtastic/admin.rb +2 -0
  13. data/lib/meshtastic/atak.rb +98 -13
  14. data/lib/meshtastic/atak_pb.rb +3 -1
  15. data/lib/meshtastic/config_pb.rb +1 -1
  16. data/lib/meshtastic/field_metadata_pb.rb +1 -1
  17. data/lib/meshtastic/forwarder.rb +190 -0
  18. data/lib/meshtastic/forwarder_pb.rb +77 -0
  19. data/lib/meshtastic/mesh_beacon_pb.rb +1 -1
  20. data/lib/meshtastic/mesh_interface.rb +115 -65
  21. data/lib/meshtastic/mesh_pb.rb +2 -1
  22. data/lib/meshtastic/module_config_pb.rb +2 -1
  23. data/lib/meshtastic/mqtt.rb +4 -34
  24. data/lib/meshtastic/payload_compression.rb +90 -0
  25. data/lib/meshtastic/payload_formats.rb +248 -0
  26. data/lib/meshtastic/reticulum.rb +71 -0
  27. data/lib/meshtastic/serial.rb +1 -19
  28. data/lib/meshtastic/telemetry_pb.rb +2 -2
  29. data/lib/meshtastic/unishox2.rb +467 -0
  30. data/lib/meshtastic/version.rb +1 -1
  31. data/lib/meshtastic.rb +4 -0
  32. data/meshtastic.gemspec +2 -0
  33. data/spec/lib/meshtastic/admin/backup_spec.rb +704 -0
  34. data/spec/lib/meshtastic/atak_spec.rb +50 -0
  35. data/spec/lib/meshtastic/bluetooth_spec.rb +14 -0
  36. data/spec/lib/meshtastic/forwarder_pb_spec.rb +11 -0
  37. data/spec/lib/meshtastic/forwarder_spec.rb +97 -0
  38. data/spec/lib/meshtastic/mesh_interface_spec.rb +169 -0
  39. data/spec/lib/meshtastic/mqtt_spec.rb +56 -0
  40. data/spec/lib/meshtastic/payload_compression_spec.rb +43 -0
  41. data/spec/lib/meshtastic/payload_formats_spec.rb +160 -0
  42. data/spec/lib/meshtastic/reticulum_spec.rb +91 -0
  43. data/spec/lib/meshtastic/serial_spec.rb +46 -0
  44. data/spec/lib/meshtastic/tcp_spec.rb +15 -0
  45. data/spec/lib/meshtastic/unishox2_spec.rb +34 -0
  46. data/spec/support/payload_fixtures.rb +124 -0
  47. data/spec/support/reticulum_fixtures.json +12 -0
  48. data/spec/support/tak_codec_fixtures.rb +4 -0
  49. data/spec/support/unishox_fixtures.rb +4 -0
  50. metadata +39 -3
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'json'
5
+
6
+ RSpec.describe 'Meshtastic::Reticulum' do
7
+ let(:fixtures) { JSON.parse(File.read(File.expand_path('../../support/reticulum_fixtures.json', __dir__))) }
8
+ let(:chunks) { fixtures.fetch('chunks_hex').map { |hex| [hex].pack('H*') } }
9
+
10
+ it 'loads the tunnel codec from the gem entrypoint' do
11
+ expect(Meshtastic.const_defined?(:Reticulum)).to be(true)
12
+ end
13
+
14
+ it 'packages the upstream JSON fixture even without a Git file listing' do
15
+ root = File.expand_path('../../..', __dir__)
16
+ context = Object.new
17
+ allow(context).to receive(:`).with('git ls-files -z').and_return('')
18
+ path = File.join(root, 'meshtastic.gemspec')
19
+ specification = context.instance_eval(File.read(path), path)
20
+ expect(specification.files).to include('spec/support/reticulum_fixtures.json')
21
+ end
22
+
23
+ it 'recognizes upstream REQ control without feeding its bytes to an RNS decoder' do
24
+ require 'meshtastic/reticulum'
25
+ raw = [fixtures.fetch('request_hex')].pack('H*')
26
+ expect(Meshtastic::Reticulum.decode_packet(payload: raw)).to include(
27
+ format: :reticulum_request, message_index: 255, position: 2, index: 2, raw: raw, complete: false
28
+ )
29
+ end
30
+
31
+ it 'rejects malformed frames and bounds every wire input before copying' do
32
+ require 'meshtastic/reticulum'
33
+ [nil, 12, '', "\x01", "\x01\x00x", "\x01\xff", 'REQ', "REQ\x01", "REQ\x01\x00", "REQ\x01\x01x", "\x01\xff#{'x' * 201}"].each do |raw|
34
+ expect { Meshtastic::Reticulum.decode_packet(payload: raw) }.to raise_error(ArgumentError)
35
+ end
36
+ end
37
+
38
+ it 'retains an opaque complete single fragment and handles signed byte extremes' do
39
+ require 'meshtastic/reticulum'
40
+ raw = [fixtures.fetch('single_hex')].pack('H*')
41
+ expect(Meshtastic::Reticulum.decode_packet(payload: raw)).to include(complete: true, count: 1, message_index: 0, raw: raw)
42
+ expect(Meshtastic::Reticulum.decode_packet(payload: "\xff\x80x".b)).to include(position: -128, count: 128)
43
+ expect(Meshtastic::Reticulum.decode_packet(payload: "\x00\x7fx".b)).to include(position: 127, count: nil)
44
+ end
45
+
46
+ it 'reassembles a complete explicitly grouped upstream message final-first without inner decoding' do
47
+ require 'meshtastic/reticulum'
48
+ result = Meshtastic::Reticulum.decode_chunks(chunks: chunks.reverse)
49
+ expect(result).to include(format: :reticulum_packet, complete: true, message_index: 255,
50
+ count: 3, body: [fixtures.fetch('payload_hex')].pack('H*'), raw_chunks: chunks)
51
+ expect(result[:fragments].map { |frame| frame[:position] }).to eq([1, 2, -3])
52
+ end
53
+
54
+ it 'rejects incomplete, duplicate, conflicting, mixed-index and control-containing groups' do
55
+ require 'meshtastic/reticulum'
56
+ cases = [nil, [], chunks * 43, chunks.first(2), [chunks.last], chunks + [chunks.first],
57
+ [chunks.first, "\xff\x01different".b, chunks.last],
58
+ [chunks.first, "\xff\xfex".b, chunks.last],
59
+ [chunks.first, "\x00\x02x".b, chunks.last],
60
+ [chunks.first, "\xff\x04x".b, chunks.last],
61
+ ["REQ\xff\x02".b]]
62
+ cases.each do |group|
63
+ expect { Meshtastic::Reticulum.decode_chunks(chunks: group) }.to raise_error(ArgumentError)
64
+ end
65
+ end
66
+
67
+ it 'bounds aggregate output and rejects invalid caller limits' do
68
+ require 'meshtastic/reticulum'
69
+ [0, -1, 565, '564', 1.5].each do |limit|
70
+ expect { Meshtastic::Reticulum.decode_chunks(chunks: chunks, max_bytes: limit) }.to raise_error(ArgumentError)
71
+ end
72
+ expect { Meshtastic::Reticulum.decode_chunks(chunks: chunks, max_bytes: 563) }.to raise_error(ArgumentError, /limit/)
73
+ big = ["\x01\x01#{'x' * 200}", "\x01\x02#{'x' * 200}", "\x01\xfd#{'x' * 165}"]
74
+ expect { Meshtastic::Reticulum.decode_chunks(chunks: big) }.to raise_error(ArgumentError, /limit/)
75
+ end
76
+
77
+ it 'exposes usable runtime help and attribution' do
78
+ require 'meshtastic/reticulum'
79
+ expect { Meshtastic::Reticulum.help }.to output(/decode_packet.*payload:.*decode_chunks.*chunks:.*max_bytes:.*authors/m).to_stdout
80
+ expect(Meshtastic::Reticulum.authors).to include('landandair')
81
+ end
82
+
83
+ it 'decodes the two byte unsigned/signed upstream header and retains original bytes' do
84
+ require 'meshtastic/reticulum'
85
+ result = Meshtastic::Reticulum.decode_packet(payload: chunks.last)
86
+ expect(result).to include(format: :reticulum_fragment, message_index: 255, position: -3,
87
+ index: 3, count: 3, final: true, complete: false,
88
+ raw: chunks.last, body: chunks.last.byteslice(2..))
89
+ expect(result[:raw].encoding).to eq(Encoding::BINARY)
90
+ end
91
+ end
@@ -1,9 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
+ require_relative '../../support/payload_fixtures'
4
5
  require 'pty'
5
6
 
6
7
  describe Meshtastic::Serial do # rubocop:disable Metrics/BlockLength
8
+ include PayloadFixtures
9
+
10
+ it 'decodes every application fixture over actual UART framing and continues after malformed payloads' do
11
+ with_serial_link do |handle, device|
12
+ payload_cases.each do |port, bytes, expected|
13
+ device.write(radio_frame(payload_radio(port, bytes)))
14
+ received = Timeout.timeout(2) do
15
+ described_class.subscribe(serial_obj: handle) { |message| break message }
16
+ end
17
+ expect(received.dig(:packet, :decoded, :payload)).to eq(expected), "port #{port} bytes #{bytes.inspect}"
18
+ end
19
+ device.write(radio_frame(Meshtastic::FromRadio.new(packet: Meshtastic::MeshPacket.new(
20
+ id: 42, from: 123, encrypted: 'ciphertext', pki_encrypted: true
21
+ ))))
22
+ expect(OpenSSL::Cipher).not_to receive(:new)
23
+ received = Timeout.timeout(2) { described_class.subscribe(serial_obj: handle) { |message| break message } }
24
+ expect(received.dig(:packet, :encrypted)).to eq('ciphertext')
25
+ end
26
+ end
27
+
7
28
  def with_serial_link(opts = {})
8
29
  PTY.open do |device, host|
9
30
  serial_obj = described_class.connect({ block_dev: host.path, want_config: false }.merge(opts))
@@ -83,6 +104,31 @@ describe Meshtastic::Serial do # rubocop:disable Metrics/BlockLength
83
104
  end
84
105
  end
85
106
 
107
+ it 'does not warn when a framed packet has an unknown portnum and no payload' do
108
+ with_serial_link do |serial_obj, device|
109
+ device.write(radio_frame(Meshtastic::FromRadio.new(packet: Meshtastic::MeshPacket.new(
110
+ decoded: Meshtastic::Data.new(portnum: 51)
111
+ ))))
112
+ output = StringIO.new
113
+ received = nil
114
+ old = $stdout
115
+ $stdout = output
116
+ begin
117
+ Timeout.timeout(1) do
118
+ described_class.subscribe(serial_obj: serial_obj) do |message|
119
+ received = message
120
+ break
121
+ end
122
+ end
123
+ ensure
124
+ $stdout = old
125
+ end
126
+ expect(received.dig(:packet, :decoded, :portnum)).to eq(51)
127
+ expect(received.dig(:packet, :decoded, :payload)).to be_nil
128
+ expect(output.string).not_to include("Can't decode")
129
+ end
130
+ end
131
+
86
132
  it 'treats text payloads as UTF-8, never as nested protobuf messages' do
87
133
  with_serial_link do |serial_obj, device|
88
134
  text = "\n\x02hi"
@@ -1,9 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'spec_helper'
4
+ require_relative '../../support/payload_fixtures'
4
5
  require 'socket'
5
6
 
6
7
  describe Meshtastic::TCP do
8
+ include PayloadFixtures
9
+
10
+ it 'decodes every application fixture over the TCP framed receive path' do
11
+ with_tcp_link do |handle, remote|
12
+ payload_cases.each do |port, bytes, expected|
13
+ remote.write(radio_frame(payload_radio(port, bytes)))
14
+ received = Timeout.timeout(2) do
15
+ described_class.subscribe(tcp_obj: handle) { |message| break message }
16
+ end
17
+ expect(received.dig(:packet, :decoded, :payload)).to eq(expected), "port #{port} bytes #{bytes.inspect}"
18
+ end
19
+ end
20
+ end
21
+
7
22
  def with_tcp_link(opts = {})
8
23
  local, remote = UNIXSocket.pair
9
24
  tcp_obj = described_class.connect({ socket: local, host: '127.0.0.1', port: 4403, want_config: false }.merge(opts))
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'meshtastic/unishox2'
5
+ require_relative '../../support/unishox_fixtures'
6
+
7
+ describe 'Meshtastic::Unishox2' do
8
+ it 'bounds expansion and rejects invalid magic and back-references' do
9
+ [UNISHOX_OVERFLOW, '00', '9800', 'ff'].each do |hex|
10
+ expect { Meshtastic::Unishox2.decode(payload: [hex].pack('H*')) }.to raise_error(ArgumentError)
11
+ end
12
+ expect { Meshtastic::Unishox2.decode(payload: "\xff".b * 4097) }.to raise_error(ArgumentError, /4096/)
13
+ end
14
+
15
+ it 'terminates bounded malformed-input fuzz cases without unexpected exceptions' do
16
+ random = Random.new(73)
17
+ 500.times do
18
+ bytes = random.bytes(random.rand(1..100))
19
+ begin
20
+ decoded = Meshtastic::Unishox2.decode(payload: bytes)
21
+ expect(decoded.bytesize).to be <= 4096
22
+ expect(decoded).to be_valid_encoding
23
+ rescue ArgumentError
24
+ # Malformed streams must fail closed, not crash or allocate indefinitely.
25
+ end
26
+ end
27
+ end
28
+
29
+ it 'decodes default-preset reference encoder vectors byte for byte' do
30
+ UNISHOX_FIXTURES.each do |text, hex|
31
+ expect(Meshtastic::Unishox2.decode(payload: [hex].pack('H*'))).to eq(text)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'zlib'
4
+ require 'json'
5
+ require_relative 'tak_codec_fixtures'
6
+
7
+ # Independent wire fixtures shared by real UART, stream, GATT and MQTT adapters.
8
+ module PayloadFixtures
9
+ def payload_cases
10
+ schemas = {
11
+ REMOTE_HARDWARE_APP: Meshtastic::HardwareMessage.new(gpio_mask: 3),
12
+ POSITION_APP: Meshtastic::Position.new(altitude: 42),
13
+ NODEINFO_APP: Meshtastic::User.new(long_name: 'fixture'),
14
+ ROUTING_APP: Meshtastic::Routing.new(error_reason: :NO_ROUTE),
15
+ ADMIN_APP: Meshtastic::AdminMessage.new(get_owner_request: true),
16
+ WAYPOINT_APP: Meshtastic::Waypoint.new(name: 'fixture'),
17
+ KEY_VERIFICATION_APP: Meshtastic::KeyVerification.new(nonce: 42),
18
+ REMOTE_SHELL_APP: Meshtastic::RemoteShell.new(payload: "\x00\xff".b),
19
+ PAXCOUNTER_APP: Meshtastic::Paxcount.new(wifi: 42),
20
+ STORE_FORWARD_PLUSPLUS_APP: Meshtastic::StoreForwardPlusPlus.new(message: "\x00\xff".b),
21
+ NODE_STATUS_APP: Meshtastic::StatusMessage.new(status: 'fixture'),
22
+ MESH_BEACON_APP: Meshtastic::MeshBeacon.new(message: 'fixture'),
23
+ STORE_FORWARD_APP: Meshtastic::StoreAndForward.new(text: 'fixture'),
24
+ TELEMETRY_APP: Meshtastic::Telemetry.new(device_metrics: Meshtastic::DeviceMetrics.new(battery_level: 42)),
25
+ SIMULATOR_APP: Meshtastic::Compressed.new(portnum: :TEXT_MESSAGE_APP, data: 'fixture'),
26
+ TRACEROUTE_APP: Meshtastic::RouteDiscovery.new(route: [42]),
27
+ NEIGHBORINFO_APP: Meshtastic::NeighborInfo.new(node_id: 42),
28
+ ATAK_PLUGIN: Meshtastic::TAKPacket.new(detail: 'fixture'),
29
+ MAP_REPORT_APP: Meshtastic::MapReport.new(long_name: 'fixture'),
30
+ POWERSTRESS_APP: Meshtastic::PowerStressMessage.new(num_seconds: 2.5),
31
+ LORAWAN_BRIDGE: Meshtastic::LoRaWANBridge.new(uplink: Meshtastic::LoRaWANBridge::Uplink.new(payload: "\x00\xff".b)),
32
+ ATAK_PLUGIN_V2: Meshtastic::TAKPacketV2.new(callsign: 'fixture')
33
+ }
34
+ cases = schemas.flat_map do |port, proto|
35
+ wire = port == :ATAK_PLUGIN_V2 ? "\xff".b + proto.to_proto : proto.to_proto
36
+ malformed = port == :ATAK_PLUGIN_V2 ? "\xff\xff".b : "\xff".b
37
+ [[port, wire, proto.to_h], [port, ''.b, {}], [port, malformed, malformed]]
38
+ end
39
+ %i[TEXT_MESSAGE_APP DETECTION_SENSOR_APP ALERT_APP REPLY_APP RANGE_TEST_APP].each do |port|
40
+ cases << [port, "\x08\x01hi", "\x08\x01hi"]
41
+ cases << [port, ''.b, '']
42
+ end
43
+ %i[UNKNOWN_APP TEXT_MESSAGE_COMPRESSED_APP PAGING_APP SERIAL_APP
44
+ GROUPALARM_APP PRIVATE_APP MAX].each do |port|
45
+ cases << [port, "\x08\x01\xff".b, "\x08\x01\xff".b]
46
+ end
47
+ cases << [:TEXT_MESSAGE_COMPRESSED_APP, ['8767c714bdeb7c74'].pack('H*'), 'Hello world']
48
+ cases << [:ATAK_PLUGIN, ['080112070a05804f1e3b49'].pack('H*'), { contact: { callsign: 'ALPHA' } }]
49
+ TAK_CODEC_FIXTURES.each do |_name, wire, proto|
50
+ expected = Meshtastic::TAKPacketV2.decode([proto].pack('H*')).to_h
51
+ expected[:latitude] = expected[:latitude_i] * 0.0000001 if expected.key?(:latitude_i)
52
+ expected[:longitude] = expected[:longitude_i] * 0.0000001 if expected.key?(:longitude_i)
53
+ cases << [:ATAK_PLUGIN_V2, [wire].pack('H*'), expected]
54
+ end
55
+ cases.concat(binary_payload_cases)
56
+ cases.concat(reticulum_payload_cases)
57
+ cases << [51, "\x08\x01".b, "\x08\x01".b]
58
+ cases << [51, ''.b, nil]
59
+ cases
60
+ end
61
+
62
+ def reticulum_payload_cases
63
+ fixtures = JSON.parse(File.read(File.join(__dir__, 'reticulum_fixtures.json')))
64
+ raw = [fixtures.fetch('single_hex')].pack('H*')
65
+ expected = { format: :reticulum_fragment, message_index: 0, position: -1, index: 1,
66
+ count: 1, final: true, complete: true, raw: raw, body: "\x00\xffRNS opaque".b }
67
+ request = [fixtures.fetch('request_hex')].pack('H*')
68
+ cases = [[:RETICULUM_TUNNEL_APP, raw, expected],
69
+ [:RETICULUM_TUNNEL_APP, request, { format: :reticulum_request, message_index: 255,
70
+ position: 2, index: 2, raw: request, complete: false }]]
71
+ ["\x01\x00\xff".b, "REQ\xff".b, "\xff".b].each do |malformed|
72
+ cases << [:RETICULUM_TUNNEL_APP, malformed, malformed]
73
+ end
74
+ wrapper = Meshtastic::Compressed.new(portnum: :RETICULUM_TUNNEL_APP, data: raw).to_proto
75
+ cases << [:SIMULATOR_APP, wrapper, { portnum: :RETICULUM_TUNNEL_APP, data: expected }]
76
+ cases
77
+ end
78
+
79
+ def binary_payload_cases
80
+ samples = [
81
+ [:CAYENNE_APP, '0167ffd7', { portnum: 77, format: :cayenne_lpp, status: :decoded,
82
+ records: [{ channel: 1, type: 103, name: :temperature, value: -4.1, unit: 'C' }] }],
83
+ [:AUDIO_APP, 'c0dec2000011223344556677', { portnum: 9, format: :codec2, status: :decoded, mode: 0,
84
+ bitrate: 3200, bits_per_frame: 64, bytes_per_frame: 8, samples_per_frame: 160,
85
+ sample_rate: 8000, pcm_decoded: false,
86
+ encoded: ['0011223344556677'].pack('H*'), frames: [['0011223344556677'].pack('H*')] }],
87
+ [:IP_TUNNEL_APP, '45000015006f00007b012b770a0000010a00000200',
88
+ { portnum: 33, format: :ip, status: :decoded, version: 4, header_length: 20, total_length: 21,
89
+ dscp_ecn: 0, identification: 111, flags: 0, fragment_offset: 0, ttl: 123, protocol: 1, checksum: 11_127,
90
+ header_checksum_valid: true, source: '10.0.0.1', destination: '10.0.0.2', options: ''.b, body: "\0".b }],
91
+ [:LORA_OTA_APP, '0307d204c8000004', { portnum: 79, format: :ota_common, status: :decoded, type: :block,
92
+ type_id: 3, session: 7, index: 1234, offset: 200, total: 1024,
93
+ body: ''.b, signature_verified: false }],
94
+ [:ZPS_APP, '01000000000000000000000000000000', { portnum: 68, format: :opaque, status: :unsupported,
95
+ error: 'ZPS has no stable port-68 schema; select zps_profile: :esp32_legacy only for that experimental dialect' }]
96
+ ].map { |port, hex, expected| [port, [hex].pack('H*'), expected.merge(raw: [hex].pack('H*'))] }
97
+ { AUDIO_APP: [9, 'Codec2 needs C0 DE C2 magic and mode byte'],
98
+ IP_TUNNEL_APP: [33, 'truncated IPv4 header'], CAYENNE_APP: [77, 'truncated Cayenne channel/type'],
99
+ LORA_OTA_APP: [79, 'OTA frame must contain 8..233 bytes'] }.each do |port, (id, error)|
100
+ samples << [port, 'A'.b, { portnum: id, raw: 'A'.b, status: :malformed, error: error }]
101
+ end
102
+ samples << [:ATAK_FORWARDER, "\x01ATAKBCAST,mesh,uid,ALPHA,1".b,
103
+ { format: :forwarder_discovery, mesh_id: 'mesh', uid: 'uid', callsign: 'ALPHA', initial: true }]
104
+ samples << [:ATAK_FORWARDER, "\x02first".b, { format: :forwarder_fragment, index: 0, count: 2, body: 'first'.b }]
105
+ event = { format: :libcotshrink_protobuf, compression: :none, protobuf: { uid: 'test' },
106
+ event: { uid: 'test', type: 'a-f-G-U-C', lat: 0.0, lon: 0.0, ce: 0, le: 0, hae: -900.0,
107
+ time_offset_seconds: 0, stale_after_seconds: 0, how: 'h-e' },
108
+ extensions: { how: 'h-e', geopointsrc: 'DTED0', altsrc: 'DTED0', role: 'Team Member', battery: 0,
109
+ readiness: false, labels_on: false, height_unit: 0, ce_human_input: false, tog: false,
110
+ route_planning_method: 'Infil', route_method: 'Driving', route_type: 'On Foot',
111
+ route_route_type: 'Primary', route_order: 'Ascending Check Points', route_stroke: 0 } }
112
+ samples << [:ATAK_FORWARDER, "\x01\x0a\x04test".b, event]
113
+ samples << [:ATAK_FORWARDER, "\x01".b + Zlib.gzip("\x0a\x04test".b), event.merge(compression: :gzip)]
114
+ samples << [:ATAK_FORWARDER, "\x01$EXI".b, "\x01$EXI".b]
115
+ samples << [:ATAK_FORWARDER, "\x00".b, "\x00".b]
116
+ samples
117
+ end
118
+
119
+ def payload_radio(port, bytes)
120
+ Meshtastic::FromRadio.new(packet: Meshtastic::MeshPacket.new(
121
+ from: 123, id: 42, decoded: Meshtastic::Data.new(portnum: port, payload: bytes)
122
+ ))
123
+ end
124
+ end
@@ -0,0 +1,12 @@
1
+ {
2
+ "source_revision": "e5eb5d23a619958ae0556c88fcbc4bf1d867ab0a",
3
+ "source_sha256": "8b71aa8efc7624dba05202c5eb356a10a48c31bee783cd4c9295038370b394ab",
4
+ "payload_hex": "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233",
5
+ "chunks_hex": [
6
+ "ff01000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbc",
7
+ "ff02bdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f70717273747576777879",
8
+ "fffd7a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233"
9
+ ],
10
+ "single_hex": "00ff00ff524e53206f7061717565",
11
+ "request_hex": "524551ff02"
12
+ }
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ # Meshtastic TAKPacket-SDK 7ace3c786c1559938cd4d1d3870e3bdd66ecb2e9 (GPL-3.0).
3
+ TAK_CODEC_FIXTURES = [%w[aircraft_adsb 01001855030013440f50835a1880194cc33215581a4081a562a950e904609a0d9af9643480191d5a910727001dda0c0b3600106041193398517f6fb20765eae9b618650faa2713fce0e8af74c7a400e503a6a1866da2fdd0f32085afe05548d1a978188eaaf3fb6b84bad9b0c16d8a03 080310021a105453543130302d4e54455354312d413335c08abf133d004113c040d02f48d6ae0150c03b720a4943414f3030303030317a105453543130302d4e54455354312d413380012dc2016d303030303031204943414f3a20303030303031205245473a204e544553543120466c696768743a2054535431303020547970653a20413332312053717561776b3a203334353620444f2d323630422043617465676f72793a20413320202020202361647362726563656976657282022a0a0630303030303112064e54455354311a0654535431303022044133323128801b320241333883034001], %w[aircraft_hostile 010018ad03007345151870b1fb9a98866558ce5f2c94c100ab4c1616190b4cc0e3004b97c1400524b04d00050ce8ec02e8e81800a689d0cc8c1b11486833aab80100045840820b98a95d7c36df660fcad4d36d31ce1e544fa65d54a2e0040cfc59ef149560d2af868462cccb9a0e6a7980b338aac7c65eb0c656fe 080b10021a125453543230302d4e54455354322d4841574b358071be133d00ca11c040a09c01720b4943414f2d303030303032800130c2013b545354323030204e544553543220303030303032204361743a413620547970653a4841574b2073696d2d686f7374406578616d706c652e746573748202330a0630303030303212064e54455354321a06545354323030320241364a1573696d2d686f7374406578616d706c652e74657374], %w[alert_tic 000048dd02005403081c2d3635b063bf133df01913c040ac02720e616c657274346435c2013754726f6f70737175677269666572656e6365ba020208030af0b1cc42ff6d016528b39cad8ca91edb2897014ecfd67c2c1c472c911b9e7f29721207 081c10011a07414c5048412d3635b063bf133df01913c040ac02720e616c6572742d62336334643565368001ac02c2013754726f6f707320696e20636f6e746163742c2072657175657374696e6720737570706f72742061742067726964207265666572656e6365ba02020803], %w[casevac 000048e503008405081a4153455641432d31359098be133de0f811c040c801721063617365766163014d3220757267656e7420737572672c2031207072696f726974792e204c5a206d642077672e204e6f20656e656d79206163746976b2020009302485d54eb3d71036d8405ec3c22f7d6c85a0cf6e6e9eb012b0733806ef572d16 081a10011a09434153455641432d31359098be133de0f811c040c8017210636173657661632d66376536643563348001d804c2014d3220757267656e7420737572676963616c2c2031207072696f726974792e204c5a206d61726b6564207769746820677265656e20736d6f6b652e204e6f20656e656d792061637469766974792eb20200], %w[casevac_medline 000050ed04005407081a61736576612081be133d70e111c040c801720a6d6564303181065001700539308201034d2d318a010e32206c69203120616d62900102a00101ca01024e458a02360a075a4d4953542d3112034753571a0b50656e65746e6722074c2074686967682a06537461626c653208545120313831305a0a00a94cd028ef2f6aabdd78a587bc08852b7fe4751696b5ecc6b43b0fa46c85ec31786f631b 081a10011a09436173657661632d31352081be133d70e111c040c801720a6d6564657661632d30318001d804b20281010801100618022001280130033a0b477265656e20736d6f6b654002500170057a0533382e39308201034d2d318a010e32206c6974746572203120616d62900102a00101ca01024e458a02360a075a4d4953542d3112034753571a0b50656e6574726174696e6722074c2074686967682a06537461626c653208545120313831305a], %w[chat_receipt_delivered 0000482d020024020b5445535450f6be133d508d12c0402b720c726563656970742d643cfa013c22280109f087b631703d4d30383ee6b8ecb58be250b8936d3723f579a776afcf217cdc09 087910031a0b544553544e4f44452d30323550f6be133d508d12c0402b720c726563656970742d642d303180013cfa013c223847656f436861742e414e44524f49442d303030303030303030303030303030322e416c6c204368617420526f6f6d732e64346535663661372801], %w[chat_receipt_read 0000482d020024020b54455354c00dbf133de07512c0402b720c726563656970742d723cfa013c22280209f087b631703d4d30383ee6b8ecb58be250b8936d3723f579a776d74b9cf07a27 087a10031a0b544553544e4f44452d303235c00dbf133de07512c0402b720c726563656970742d722d303180013cfa013c223847656f436861742e414e44524f49442d303030303030303030303030303030322e416c6c204368617420526f6f6d732e64346535663661372802], %w[chat_taktalk_dm 0000501d0400040318112e173d985815d25e3130312e353839fa01600a0c206d676512181a05415350454e323a243335356163646266420018f810b02429a3547b7c2202523144354b2263099bec8a74d40c0ea16ee15f35661023d3da326982f4613b9d7a0743c343757900d2f10f0bb791bcbebc3af23fc572e5c81d6f2aeea06dc9bec73d6c8606 081910033518112e173d985815d2409401725e47656f436861742e414e44524f49442d303030303030303030303030303031302e414e44524f49442d303030303030303030303030303031312e65343237356364312d633563302d346130372d383139362d616138653439306335623632800180a305fa01600a0c54657374206d6573736167651218414e44524f49442d303030303030303030303030303031311a05415350454e3207456e676c6973683a2433306232373535632d633534372d343465662d613063632d6364626438613135363136664200], %w[chat_taktalk_voice_profile 000050fd0400f3830ecdbdb9290b33cce0fa051636983030380ef6cdd8c608ab58f0b860c946b0d214e5c95317135646543e6cb8a7946bae0084984ca9b99c482579121ef810b895d6286d07db595212f38e17b8a044efd2d07adba09af58e7cc1e2d09c88f2a6a87e9af57eb17b4b566e8eda7941a8f370a2c6fa3e4cae8c5c87a655912c9729941cf4693f5b73e385c0703d4ffa2c9923539cb0b8a3db966c3dee684324 081910033518112e173d985815d2409401725e47656f436861742e414e44524f49442d303030303030303030303030303031302e414e44524f49442d303030303030303030303030303031312e37326337376666642d346235312d343435322d613661392d613766396662623933336663800180a305fa0187010a02564f1218414e44524f49442d303030303030303030303030303031311a05415350454e3207456e676c6973683a2433306232373535632d633534372d343465662d613063632d636462643861313536313666423170726f66696c652d757569642d39663865376436632d356234612d333231302d666564632d626139383736353433323130], %w[delete_event 0000483d01002831642d336209f0512a06680710aa27660f34d836abf586eab4cd9a969bf5e460ad20c8985d06 080e1003722461316232633364342d653566362d376138622d396330642d653166326133623463356436800114], %w[drawing_circle 0000480d0200a8104472617743203135c897be133dd0d710643061320cf01252e621a7caf903072bda144cd4596c97fc81382e74d36f41b2d99a27a8fe58b13bbeda556002bcbd 082a10011a1044726177696e6720436972636c65203135c897be133dd0d710c040fed9c409722436643039623666362d373230612d346565662d613139372d313833303132353132333136800180a30592021f0801100318aab10120aab10128e80230013dffffffff402855ffffff965801], %w[drawing_circle_large 000048a502001402095368617065201054bf133d80fc13376164363565367a1692b3022092b33d45420ef0afba40b8d28a8e985e41b66b6603b7cfe74813b1838436a48222a5d791221dea577d4d9727d30f746cb4026bc97607 082a10011a09536861706520333234351054bf133d80fc13c040fed9c409722436376562616635392d613231362d346230632d626432342d3961653565653464363565367a09536861706520333234800180a305920216080110031892b3022092b30228e8023d4542ffff401e], %w[drawing_ellipse 000048b50100c009456c6c697073d03abe133df096130a65c30120d461282d08f08aba0022a5eda0a32cdbc90e25a46318f1eb4ae4eb3657d0de1c0e 087710011a09456c6c69707365203135d03abe133df09613c040fed9c409720a656c6c697073652d3031800180a30592021b0808100318a8c30120d461282d30053d0000ffff401e55ffffff96], %w[drawing_freeform 0000483d030034030a666f726dfebe133d80851264383603100192010ce012d041f060d041bf0ce7399a010fb817e044c8970190e401a0ce01f86e0ef0a6d2629dcbba0fe521fe3b116e4b70cc9ba0d17db84e08e1c9ee975953c12dabd02b4105af12302a685330eabb901707 082810011a0a46726565666f726d20313520febe133d808512c040fed9c409722462313132323032652d646433332d346663372d386433642d303961313465323936303131800180a3059202310803100128e80230053d0000ffff401e92010ce012d041f060d041bf0ce7399a010fb817e044c8970190e401a0ce01f86e], %w[drawing_polygon 0000486d0300b403084d6f6c79676f6e2031353025bf133d501012396534323208050c3d00ff0081ff400a8032c84c8f03f755972a9a010bdf12904e9099019035df2b0df0457d1ea8545af7784a437fd909f1a48811dccd9807c33be715e6d4c637415e2eb012a8cbc89d6c8abf1adaaa8d01 084d10011a09506f6c79676f6e2031353025bf133d501012c040fed9c409722463396538623761362d356434632d346133622d396532662d303138333734363539383231800180a3059202320805100328e802300c3d00ff00ff401e550081ff40580192010a8032c84c8f03f755972a9a010bdf12904e9099019035df2b], %w[drawing_rectangle 000048dd0200b4020b5265636c10a5be133d5c9111363661373180af01d0a501c7b001cfa5019a010abf70f88701c070f787010df0e96802eaecdade8269f7a7287e7b9dda0d89564bcb0c547432065b362ccda48b3ab0290e2af0844d5d072b02 082910011a0b52656374616e676c6520313510a5be133d5c9111c040fed9c409722466343861643639642d333164652d343038392d626266302d363533336362623161613737800180a3059202310802100328e80230013dffffffff401e55ffffff9692010c80af01d0a501c7b001cfa5019a010abf70f88701c070f78701], %w[drawing_rectangle_itak 0000487d03008403152e5265636c6553686170652e31353025bf133dc02113663463386234313dff7c6dff400a55ff7c6d7f92010ca09c01a09c019f9a010c9f10f81088b9c615099048ded0c75545266423b9ab7eb172942c96ef21cba7d3db8bfe1ff29a9384e77e9596056cd3ce6b9b8a4da203 082910011a15695061642e52656374616e676c6553686170652e31353025bf133dc02113c040fed9c409722435663833396534632d306439352d346335662d383561392d633862346639313462633130800180a3059202310802100328e8023dff7c6dff400a55ff7c6d7f92010ca09c01a09c019f9c019f9c019a010c9f9c01a09c01a09c019f9c01], %w[drawing_telestration 000050dd05003408084c5474313510d7be133dc021130774656c659202bf011992015300a06a88bd01a0e701b8df01d0a501f047f723bf8901afd101afeabf8901f723f047d0a5a0e7016a009f6a87bd019fe701b7df01cfa501ef47f823c08901b0d101b0ea9a0154b0ea88bd01c08901f04700ef47bf890187bdafea87bdef4700f047c089b8df016801120810c0c9d6ffdf578da54d17b01b036b2a9ad73d650c754ea1dfc489e05010a09663e49d6c843ebfd8312241bf3e54993e1c0eb501 084c10011a0e54656c657374726174696f6e20313510d7be133dc02113c040fed9c409720774656c652d3031800180a3059202bf010804100128e80230043dff00ffff401992015300a06a88bd01a0e701b8df01d0a501f047f723bf8901afd101afea01afd101bf8901f723f047d0a501b8df01a0e70188bd01a06a009f6a87bd019fe701b7df01cfa501ef47f823c08901b0d101b0ea01b0d1019a0154b0ea01b8df0188bd01c08901f04700ef47bf890187bd01b7df01afea01b7df0187bd01bf8901ef4700f047c0890188bd01b8df01b0ea01b8df0188bd01c08901f04700ef47bf890187bd01b7df01afea01b7df016801], %w[emergency_911 0000481502000403081e10011a11544553542d30342d416c65727435207bbf133d800213c040ac02720c656d657267656e63791c0801123404008e05d0b7c116483dd9284f3b5848 081e10011a11544553544e4f44452d30342d416c65727435207bbf133d800213c040ac02720c656d657267656e63792d30318001ac02ba021c08011218414e44524f49442d30303030303030303030303030303034], %w[emergency_cancel 000048450200c402081d4553542d303435207bbf133d800213c040ac027213656d657267656e63792d636c2a080612341a0c303107005b6de3b1000237d8027bb291dc905485d3a631bc252f8d05 081d10011a0b544553544e4f44452d303435207bbf133d800213c040ac027213656d657267656e63792d63616e63656c2d30318001ac02ba022a08061218414e44524f49442d303030303030303030303030303030341a0c656d657267656e63792d3031], %w[geochat_broadcast 000048bd0100d805bf133d209512633378096174206272656163681a05455448454c07f05e8812f588d5d0ae53838714d579db755c5e1307f61f269f20 0819100335f005bf133d209512c040fed9c409723847656f436861742e414e44524f49442d303030303030303030303030303030332e416c6c204368617420526f6f6d732e6131623263336434800178fa01120a096174206272656163681a05455448454c], %w[geochat_dm 000048d50100c81dbf133d90ac124233342e653762300a12341a05455448454c09c0bf0558c317934a6e664452f24cb4c0138c9371dc6722d717731c4dd8f010 0819100335601dbf133d90ac12c040fed9c409724247656f436861742e414e44524f49442d303030303030303030303030303030332e414e44524f49442d303030303030303030303030303030342e653566366137623880013cfa01300a0d636f76657220627920666972651218414e44524f49442d303030303030303030303030303030341a05455448454c], %w[geochat_simple 000048dd0100c080eebe133db07d12c0402b300a212c200b544553542d30310af04916a418e14c25636061879a996ddc979e70051a4e332f076651a4e3befa4c07 081910033580eebe133db07d12c0402b723847656f436861742e414e44524f49442d303030303030303030303030303030322e416c6c204368617420526f6f6d732e643465356636613780013cfa01300a21526f67657220746861742c206d6f76696e6720746f2072616c6c7920706f696e741a0b544553544e4f44452d3031], %w[marker_2525 0000480d0200900b3735e401c0133d704512306332322d65310ef006f92e943dd675d443795126e24f9cdc7df0e76b61142e2dd62a1c863cb7064e66962885ae6c5d0469c91606 082310031a0b552e31362e31333530353735e401c0133d704512c040fed9c409722461306335323463362d303432322d343338322d393938312d653339643164633731373330800180a3059a0255080510011dffffffff20012a18414e44524f49442d303030303030303030303030303030313209612d662d472d552d433a0653494d2d3031421b434f545f4d415050494e475f32353235422f612d752f612d752d47], %w[marker_goto 000048dd000048c85fbf133d4835133105f0302083fa70c6f47d993d27fbc80518 087110011a06476f546f2d3135c85fbf133d483513c040fed9c4097207676f746f2d3031800180a3059a02360808100c1d00ff00ff2a18414e44524f49442d303030303030303030303030303030313209612d662d472d552d433a0653494d2d3031], %w[marker_goto_itak 0000504504008403087110031a11525020423570c1bf133d782d133263336633629a026c0808100233455448454c4235333434342f4d696c69746172792f435017f0c687b057c19829fe60ec4545829202d11cedfc83d45c04bec53de65bd53085c343d9354e62110cd19ff8d90f684b9cfcfa82f76d4d9085febd84d19d16b6df57423475d230cb9647a5b5df1e 087110031a1152616c6c7920506f696e7420427261766f3570c1bf133d782d13c040fed9c409722462326333643465352d663661372d346238632d396430652d316632613362346335643665800180a3059a026c080810021d00ffffff2a18414e44524f49442d303030303030303030303030303030333209612d662d472d552d433a05455448454c423533346165313631332d393634352d343232322d613964322d653566323433646561323836352f4d696c69746172792f43502e706e67], %w[marker_icon_set 0000509d0200c80768696b657220313584c6bf133d002214616430626f31423510f0bf87102dbd7a4961cc83b2154b0e55473f3e11b2837fbfeee0ae4e3eb5a41126b1b79d77381819b19fb6da14c08aea47d32b412eb23101 082310031a0768696b657220313584c6bf133d002214c040fed9c409722434613066346638342d323430632d346666392d623762302d643038626565633930306233800180a3059a026f080710011dffffffff20012a18414e44524f49442d303030303030303030303030303030313209612d662d472d552d433a0653494d2d3031423566376637313636362d386232382d346235372d396662622d6533386536316433336237392f476f6f676c652f68696b65722e706e67], %w[marker_spot 000048050200434104ae00744f57e5cbf74aacd3a5e48c3914050cf003923750f60f5d43ddd10539045acde6a9ecfa57f933459a6bd38c6c839beb31c2d228afae11e4865033 084e10031a0352203135d8eabf133d086113c040fed9c409722439343035653332302d393335362d343163342d383434392d663436393930616131376638800180a3059a025e080110051d0000ffff20012a18414e44524f49442d303030303030303030303030303030313209612d662d472d552d433a0653494d2d30314224434f545f4d415050494e475f53504f544d41502f622d6d2d702d732d6d2f2d3635353336], %w[marker_tank 0000482d02000402086954616e6b9abf133de06f130774616e6b5d08053142232d452d562d412d5409f04e302e0372884a273bb1dfa0e2e8eb68c7cfc9a63d7d5f6648c728b7fe18abc94b 086910031a0654616e6b203135609abf133de06f13c040fed9c409720774616e6b2d3031800180a3059a025d080510051d0000ffff20012a18414e44524f49442d303030303030303030303030303030313209612d662d472d552d433a0653494d2d30314223434f545f4d415050494e475f32353235422f612d682f612d682d472d452d562d412d54], %w[pli_basic 000048250100a86e6f64653520febe133d808512c0402b727a80012d04c02da598b3e2eb096e75384903 080110021a08746573746e6f64653520febe133d808512c0402b7208746573746e6f64657a08746573746e6f646580012d], %w[pli_full 000050cd020094020b544553542d30359015bf133d106e12c0403b487850c36f327a2d2e0953696d756c61746f720c2b310fc0510dc0ef8b81aa5cf66104c296b03870d96984e2e4f8122880f25d52042e549c63ec4dc6eaac36b5c9b7d95e 080110011a0b544553544e4f44452d3031200a2801359015bf133d106e12c0403b487850c36f5858600168017218414e44524f49442d303030303030303030303030303030327a0b544553544e4f44452d303180012d8a012d342e31322e302e3120283030303030303030295b706c617973746f72655d2e303030303030303030302d43495692010953696d756c61746f729a01084154414b2d434956a201023334b2010c2b3135353530303030303031], %w[pli_itak 0000480d0200630209cd8a956f1d7080a5be15ea561ab4e2af76e0bea0225329da80ce531806b894cc09b4410c07fc86cfc16a23858cc955199a5dca649ea1d53d73dcf6db18b4 080110021a0469506164200a28013540cfbe133d60b412c040d80150a4b2015864722432333133313937302d344430322d343039322d413330412d3841343945424430344141307a0469506164800178], %w[pli_stationary 0000484d030054030c54414b417761720135002dbf133da05612c040da2446374130463441353837444636437a8a0109312e372e332e3233330c064f530ff019095f81e3ca11f27c72b5e964812bbc374f85ee876ed4a445b54be664a54110b7512cbfae416cbf4f3b756b5b612c72 080110021a0c6950616454414b4177617265200a280135002dbf133da05612c040da01581e722446373734393732302d313335362d344132332d383046342d3030313041353837444636437a0c6950616454414b41776172658001ac028a0109312e372e332e323333920104695061649a010c54414b41776172652d434956a20106695061644f53], %w[pli_takaware 00004895020054020c54414b4177617201357044bf133d303f12c0c4cf2446374130463441353837444636437a0cf810b0dc73513f003854f6a9505974a36d8b2acb9c940a411c959a30d50c5455c4f64f3b7568abc7e606 080110021a0c6950616454414b4177617265200a2801357044bf133d303f12c040d60150c4cf01585f722446373734393732302d313335362d344132332d383046342d3030313041353837444636437a0c6950616454414b41776172658001ac02], %w[pli_webtak 00004855030024030b544553542d3035b0e6be133df09c12c040fe887a8001f001322e3192010c4368202d203133349a01065765620c2d20313110f81098bb18ee841585b25d2a3764cfd58dc5f47eb80d4a384eef8c50953366d6182bc600866f20d20af24cddb1c368f7100a7d0c0b 080210011a0b544553544e4f44452d3032200a280135b0e6be133df09c12c040fe887a722464376538663961302d316232632d336434652d356636612d3762386339643065316632618001f0018a0106342e31322e3192010c4368726f6d65202d203133349a010657656254414ba2010c57696e646f7773202d203131], %w[pli_with_sensor 0000486d030054040b4f425345525645522d0635d0b7be133dd0cb12c040b2377a0707506978656c34ca010908c203108e0218b009d2012d18c413202d281e3009420e464c49522d426f736f6e0af0c6d6253e82629640a6669ee47395e02e54919341ae1790abba4c493c5ef94ab2ed351627 080110021a0b4f425345525645522d3037200c280635d0b7be133dd0cb12c040b201584c600168017218414e44524f49442d303030303030303030303030303030377a0b4f425345525645522d303780012d8a0107352e302e302e30920107506978656c20389a01084154414b2d434956a201023334ca010908c203108e0218b009d2011d0802102d18c413202d281e3009420e464c49522d426f736f6e2d363430], %w[ranging_bullseye 000048bd0200c402085110011a0a42756c6c736579d03abe133d405a14633264392218d0860320d08603580170882778018001030bf0aed2f2940f3b60769eb8a6472555f0cb5de60e175396b56fade0f4f37246afc459cbaf03b22e01 085110011a0a42756c6c73657965203135d03abe133d405a14c040fed9c409722462633761386633652d323531342d346438392d396133622d643530313238333734363931800180a3059202220807100118d0860320d0860328e80230053d0000ffff401e58017088277801800103], %w[ranging_circle 000048550200c80b52422043203135f088be133df0251132d0860320d08658010ef0a83aff55da01c75e02eb91268a989aa2815afb40b29ae590490c6238436420e9c721c0bc76198af58faad4ea6409 085010011a0b524220436972636c65203135f088be133df02511c040fed9c409722439363535646432612d613865652d346361302d616165342d616333633035323265356535800180a30592021f0806100318d0860320d0860328e80230013dffffffff401e55ffffff965801], %w[ranging_line 000048950200640209524200b0be133d5010123863643164a202130a001208616e63686f722d3118fad00720bc690cf810989c07a0053832316a8ddaef5b8a995418a27b8c20b52a915c1811bf5c7ddd804dae95032c8eb9 082b10011a095242204c696e6520313500b0be133d501012c040fed9c409722435386466326663642d653333652d343134662d613731382d623138623530636433313337800180a305a202130a001208616e63686f722d3118fad00720bc69], %w[route_3wp 000050a5030073030d100611838e15a407414f35871b4b55061d2727230db8d61a7e30d4603d01c0081417a0ab4fd2b8a1923900b8949881078a68e58014f004a5892caa0731dc5c538a9470484930e23484d80d36ad660c9fd890d0c2ff2c5707ef149c693586d8c92dd15d6f500a4daa94370be1e4f5758022 082510011a0b526f75746520416c70686135a0c5bd133d00be13c040fed9c409722461336635386332312d393165342d346237362d386435662d363239313730343833356162800180a305aa026b080110011a024350201e2a190a00121077702d61316232633364342d303030311a034350312a210a0808c0bb0110b0ea01121077702d61316232633364342d303030321a034350322a210a0808d0860310c0b503121077702d61316232633364342d303030331a03435033], %w[route_itak_3wp 0000507d050063c40f2e5f1ba383f7e548c7e272c669888c73e7181bbdd2501bd60ace194e4e469e04d908ab2834420018a14082eccaea8995168f8e1224f0b894d09150442b070423f810907b8e5b1c434c6b2888e75972a250e06cd722112b80e7c24ecd47c277d3a7c2a56064aa443f372db32d0e9b092bf26b20e2d883ee835820bf713525c3d09672c28ab998742e2db2fb1b7098a300f736779e9e1e689a9c955cdfdbcd8fee6ae26029af13295e0fb2f301 082510011a0b526f75746520416c70686135a036c0133df09613c0722431333961333030392d363831652d346231612d386632332d646262343961326333333864800180a305aa029f01080210011a0243502a2c0a00122464373133303663332d393361352d343166342d623332332d3861356231306630653936381a0253502a320a0808bfb80210dfd403122430366264663963382d626264642d346261362d383063352d66383134383535646637353620012a330a0608904e10c03e122461353434393537382d393764322d346533332d623964332d3339306233313535616264311a0356444f], %w[taktalk_room_data 000048c5020013020754b660c148c0d27433b631ce772d5811d2bbcad7ad3d2e58b211ac0411f810a8b758df355b7f90c920aa318d4871ccfa58d8d5184b41336a331f9cb566da306a02ed9a66480dd9f9979da5b3906f2a96c42a403b24 087e1a05415350454e40fed9c409722e524f4f4d2d444154412d35656163393333362d323639382d346462622d396661322d363262313030653436396665d2023a122433306232373535632d633534372d343465662d613063632d6364626438613135363136661a04746573742205455448454c2205415350454e], %w[taktalk_text 000048d5010088415350454e34633166353266455448454c0bf0dbb623645b50fab3f3ae77f8224fdfc0b8f75183a90e294abde0a5e610cc69a042acb1100d02 087d1a05415350454e40fed9c409723454414b54414c4b2d4d4553534147452d38316234346234382d323163352d346564662d616162322d623662643265633166353266ea01070a05455448454cca02270a1954657374696e67203132332c2074657374696e67203132332e1201311a07456e676c697368], %w[taktalk_voice 00004805020080415350454e313862363665455448454c0df03124a5d42276eafb25c81694fbd2a5f42bc7b1a08b896b1e025e2e6c4c8a65c5003ee52a48695621d6d8598601 087d1a05415350454e40fed9c409723454414b54414c4b2d4d4553534147452d38316235316361612d383266362d343634652d626438392d376434303636616466663665ea01070a05455448454cca021b0a0b54657374696e67203132331201311a07456e676c6973682001], %w[taktalk_voice_marti 000048450300a403415350454e33376234ea01100a05455448454c0a07ca02340a2447726f757020707573682d746f2d74746f2074776f20726563697069656e74730cf0a748e21373f7332b7cb9d3ebf0eff733b1d067a3208ce477bbda9abaf686b0c24c06340d54883516c25e 087d1a05415350454e40fed9c409723454414b54414c4b2d4d4553534147452d39326333336535622d396334612d346231662d626437322d396531303737626666336134ea01100a05455448454c0a07464f5854524f54ca02340a2447726f757020707573682d746f2d74616c6b20746f2074776f20726563697069656e74731201311a07456e676c6973682001], %w[task_engage 000048ed0100f8087c10011a0a5461736b2d4135404cbf133d10eb12c040a00172077430303508c0c4176b2c982d92450fdc8d362e1b696a71a621059e1150de809d0e 087c10011a0a5461736b2d416c70686135404cbf133d10eb12c040a00172077461736b2d30318001901cc202400a06656e6761676512097461726765742d30311a18414e44524f49442d3030303030303030303030303030303520032801320d636f7665722062792066697265], %w[waypoint 00004865010058352478be133d9cca15363109f00165d380194a1cfa012bbf654aabd99421cf231e492f8d4bb5bfa5f5b31b 082610011a03435031352478be133d9cca15c040fed9c409722466363932366166312d646565632d343466342d616530362d343630363563383239383837800180a3059a0236080210011dffffffff2a18414e44524f49442d303030303030303030303030303030313209612d662d472d552d433a0653494d2d3031]].freeze
4
+ TAK_MALFORMED_FIXTURES = [["corrupted_zstd", "00a31c06bd463e3923bc1aadbde48b16976c080717373b819a068f32b7a6b38b6b38729647cfde01c2ce28b26c57472737f5c3"], ["decompression_bomb", "0028b52ffd63f9918b0100ff4d000008000100fc7f1d0801"], ["empty", ""], ["invalid_dict_id", "0528b52ffd2312918b31408d01005402080110021a08746573746e6f64653508fe83163d304808b7402b727a80012daa0109f00101030406c3e66ab9e71c03"], ["invalid_protobuf", "ff561a1761185bd8589a43ce0bba75891ff9ec60148d4bd4a09ee2dc5c9331"], ["oversized_callsign", "ff08011a904e41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141"], ["reserved_bits_set", "c00048f5010034026e6f64653500e1f5053d80d99f387850c36f585872122d7265642d626974737a80017807005aad6164580fa39697082e449c2b0ae1eb093086010201"], ["single_byte", "00"], ["truncated_zstd", "0028b52ffd2312918b3140"]].freeze
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ # siara-cc/Unishox2 4981d9403de3bdd1938a635ab73f8a2c5a536059 reference C encoder, USX_PSET_DFLT.
3
+ UNISHOX_FIXTURES = [["", "97"], ["Hello world", "8767c714bdeb7c74"], ["ALPHA", "804f1e3b49"], ["RADIO-1", "806e7aba02d14f"], ["ANDROID-aabbccdd", "804e75babe80b4452555de66e9"], ["ATAK chat", "84840487dae7b4c1"], ["hello hello hello hello hello", "f67c7148c51a393b3e38a2"], ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "9170fcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"], ["1234567890", "94df1ce75dbbd47f"], ["\"key\": \"value\" </tag> https://example.com", "89f6fe47f7ea78eec443ff13ec34bb4478d17ebfe9f3e3864f9af2"], ["2026-09-23T14:30:45.123Z", "900809931a8c228919"], ["(555) 123-4567", "90c155448d159c"], ["ab123456-789a-bcde-f012-3456789abcde", "91aac48d159e26af37bc048d159e26af378b"], ["héllo 世界 🌍", "f63c0a9e38a40b3cedc5bdbef005b03f"], ["first\r\nsecond\n\tthird", "fc5ef503ad3e6b3a1c1ef1daf7d1"]].freeze
4
+ UNISHOX_OVERFLOW = "91783b6d555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555517"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meshtastic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.183
4
+ version: 0.0.185
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -51,6 +51,20 @@ dependencies:
51
51
  - - '='
52
52
  - !ruby/object:Gem::Version
53
53
  version: 1.7.1
54
+ - !ruby/object:Gem::Dependency
55
+ name: fiddle
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '='
59
+ - !ruby/object:Gem::Version
60
+ version: 1.1.8
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '='
66
+ - !ruby/object:Gem::Version
67
+ version: 1.1.8
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: gem-wrappers
56
70
  requirement: !ruby/object:Gem::Requirement
@@ -85,14 +99,14 @@ dependencies:
85
99
  requirements:
86
100
  - - '='
87
101
  - !ruby/object:Gem::Version
88
- version: 4.36.1
102
+ version: 4.36.2
89
103
  type: :runtime
90
104
  prerelease: false
91
105
  version_requirements: !ruby/object:Gem::Requirement
92
106
  requirements:
93
107
  - - '='
94
108
  - !ruby/object:Gem::Version
95
- version: 4.36.1
109
+ version: 4.36.2
96
110
  - !ruby/object:Gem::Dependency
97
111
  name: grpc-tools
98
112
  requirement: !ruby/object:Gem::Requirement
@@ -285,6 +299,7 @@ files:
285
299
  - bin/meshtastic_autoinc_version
286
300
  - build_gem.sh
287
301
  - documentation/README.md
302
+ - documentation/admin-backup.md
288
303
  - documentation/admin-channel.md
289
304
  - documentation/admin-config.md
290
305
  - documentation/admin-firmware-hex.md
@@ -303,16 +318,19 @@ files:
303
318
  - documentation/config.md
304
319
  - documentation/connection-status.md
305
320
  - documentation/deviceonly.md
321
+ - documentation/forwarder.md
306
322
  - documentation/localonly.md
307
323
  - documentation/mesh-interface.md
308
324
  - documentation/meshtastic.md
309
325
  - documentation/module-config.md
310
326
  - documentation/mqtt.md
311
327
  - documentation/paxcount.md
328
+ - documentation/payload-formats.md
312
329
  - documentation/portnums.md
313
330
  - documentation/position.md
314
331
  - documentation/protobufs.md
315
332
  - documentation/remote-hardware.md
333
+ - documentation/reticulum.md
316
334
  - documentation/rtttl.md
317
335
  - documentation/serial.md
318
336
  - documentation/storeforward.md
@@ -325,6 +343,7 @@ files:
325
343
  - git_commit.sh
326
344
  - lib/meshtastic.rb
327
345
  - lib/meshtastic/admin.rb
346
+ - lib/meshtastic/admin/backup.rb
328
347
  - lib/meshtastic/admin/channel.rb
329
348
  - lib/meshtastic/admin/config.rb
330
349
  - lib/meshtastic/admin/firmware.rb
@@ -355,6 +374,8 @@ files:
355
374
  - lib/meshtastic/deviceonly_legacy_pb.rb
356
375
  - lib/meshtastic/deviceonly_pb.rb
357
376
  - lib/meshtastic/field_metadata_pb.rb
377
+ - lib/meshtastic/forwarder.rb
378
+ - lib/meshtastic/forwarder_pb.rb
358
379
  - lib/meshtastic/interdevice_pb.rb
359
380
  - lib/meshtastic/localonly.rb
360
381
  - lib/meshtastic/localonly_pb.rb
@@ -368,12 +389,15 @@ files:
368
389
  - lib/meshtastic/mqtt_pb.rb
369
390
  - lib/meshtastic/paxcount.rb
370
391
  - lib/meshtastic/paxcount_pb.rb
392
+ - lib/meshtastic/payload_compression.rb
393
+ - lib/meshtastic/payload_formats.rb
371
394
  - lib/meshtastic/portnums.rb
372
395
  - lib/meshtastic/portnums_pb.rb
373
396
  - lib/meshtastic/position.rb
374
397
  - lib/meshtastic/powermon_pb.rb
375
398
  - lib/meshtastic/remote_hardware.rb
376
399
  - lib/meshtastic/remote_hardware_pb.rb
400
+ - lib/meshtastic/reticulum.rb
377
401
  - lib/meshtastic/rtttl.rb
378
402
  - lib/meshtastic/rtttl_pb.rb
379
403
  - lib/meshtastic/serial.rb
@@ -385,6 +409,7 @@ files:
385
409
  - lib/meshtastic/telemetry.rb
386
410
  - lib/meshtastic/telemetry_pb.rb
387
411
  - lib/meshtastic/traceroute.rb
412
+ - lib/meshtastic/unishox2.rb
388
413
  - lib/meshtastic/util.rb
389
414
  - lib/meshtastic/version.rb
390
415
  - lib/meshtastic/xmodem.rb
@@ -394,6 +419,7 @@ files:
394
419
  - reinstall_gemset.sh
395
420
  - sig/meshtastic.rbs
396
421
  - spec/conventions_spec.rb
422
+ - spec/lib/meshtastic/admin/backup_spec.rb
397
423
  - spec/lib/meshtastic/admin/channel_spec.rb
398
424
  - spec/lib/meshtastic/admin/config_spec.rb
399
425
  - spec/lib/meshtastic/admin/firmware/ble_spec.rb
@@ -425,6 +451,8 @@ files:
425
451
  - spec/lib/meshtastic/deviceonly_pb_spec.rb
426
452
  - spec/lib/meshtastic/deviceonly_spec.rb
427
453
  - spec/lib/meshtastic/field_metadata_pb_spec.rb
454
+ - spec/lib/meshtastic/forwarder_pb_spec.rb
455
+ - spec/lib/meshtastic/forwarder_spec.rb
428
456
  - spec/lib/meshtastic/interdevice_pb_spec.rb
429
457
  - spec/lib/meshtastic/localonly_pb_spec.rb
430
458
  - spec/lib/meshtastic/localonly_spec.rb
@@ -438,12 +466,15 @@ files:
438
466
  - spec/lib/meshtastic/mqtt_spec.rb
439
467
  - spec/lib/meshtastic/paxcount_pb_spec.rb
440
468
  - spec/lib/meshtastic/paxcount_spec.rb
469
+ - spec/lib/meshtastic/payload_compression_spec.rb
470
+ - spec/lib/meshtastic/payload_formats_spec.rb
441
471
  - spec/lib/meshtastic/portnums_pb_spec.rb
442
472
  - spec/lib/meshtastic/portnums_spec.rb
443
473
  - spec/lib/meshtastic/position_spec.rb
444
474
  - spec/lib/meshtastic/powermon_pb_spec.rb
445
475
  - spec/lib/meshtastic/remote_hardware_pb_spec.rb
446
476
  - spec/lib/meshtastic/remote_hardware_spec.rb
477
+ - spec/lib/meshtastic/reticulum_spec.rb
447
478
  - spec/lib/meshtastic/rtttl_pb_spec.rb
448
479
  - spec/lib/meshtastic/rtttl_spec.rb
449
480
  - spec/lib/meshtastic/serial_hal_pb_spec.rb
@@ -455,6 +486,7 @@ files:
455
486
  - spec/lib/meshtastic/telemetry_pb_spec.rb
456
487
  - spec/lib/meshtastic/telemetry_spec.rb
457
488
  - spec/lib/meshtastic/traceroute_spec.rb
489
+ - spec/lib/meshtastic/unishox2_spec.rb
458
490
  - spec/lib/meshtastic/util_spec.rb
459
491
  - spec/lib/meshtastic/version_spec.rb
460
492
  - spec/lib/meshtastic/xmodem_pb_spec.rb
@@ -462,6 +494,10 @@ files:
462
494
  - spec/lib/meshtastic_spec.rb
463
495
  - spec/lib/nanopb_pb_spec.rb
464
496
  - spec/spec_helper.rb
497
+ - spec/support/payload_fixtures.rb
498
+ - spec/support/reticulum_fixtures.json
499
+ - spec/support/tak_codec_fixtures.rb
500
+ - spec/support/unishox_fixtures.rb
465
501
  - upgrade_Gemfile_gems.sh
466
502
  - upgrade_gem.sh
467
503
  - upgrade_meshtastic.sh