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.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. metadata +20 -144
  3. data/.github/workflows/main.yml +0 -27
  4. data/.gitignore +0 -29
  5. data/.rspec +0 -3
  6. data/.rubocop.yml +0 -35
  7. data/.rubocop_todo.yml +0 -134
  8. data/.ruby-gemset +0 -1
  9. data/.ruby-version +0 -1
  10. data/AUTOGEN_meshtastic_protobufs.sh +0 -28
  11. data/CHANGELOG_BETWEEN_TAGS.txt +0 -196
  12. data/CODE_OF_CONDUCT.md +0 -84
  13. data/Gemfile +0 -23
  14. data/LICENSE +0 -21
  15. data/README.md +0 -106
  16. data/Rakefile +0 -17
  17. data/bin/meshtastic_autoinc_version +0 -38
  18. data/build_meshtastic_gem.sh +0 -58
  19. data/git_commit.sh +0 -29
  20. data/lib/meshtastic/admin.rb +0 -24
  21. data/lib/meshtastic/admin_pb.rb +0 -31
  22. data/lib/meshtastic/apponly.rb +0 -24
  23. data/lib/meshtastic/apponly_pb.rb +0 -18
  24. data/lib/meshtastic/atak.rb +0 -24
  25. data/lib/meshtastic/atak_pb.rb +0 -22
  26. data/lib/meshtastic/cannedmessages.rb +0 -24
  27. data/lib/meshtastic/cannedmessages_pb.rb +0 -15
  28. data/lib/meshtastic/channel.rb +0 -24
  29. data/lib/meshtastic/channel_pb.rb +0 -18
  30. data/lib/meshtastic/clientonly.rb +0 -24
  31. data/lib/meshtastic/clientonly_pb.rb +0 -18
  32. data/lib/meshtastic/config.rb +0 -24
  33. data/lib/meshtastic/config_pb.rb +0 -42
  34. data/lib/meshtastic/connection_status.rb +0 -24
  35. data/lib/meshtastic/connection_status_pb.rb +0 -20
  36. data/lib/meshtastic/device_ui_pb.rb +0 -23
  37. data/lib/meshtastic/deviceonly.rb +0 -24
  38. data/lib/meshtastic/deviceonly_pb.rb +0 -28
  39. data/lib/meshtastic/interdevice_pb.rb +0 -17
  40. data/lib/meshtastic/localonly.rb +0 -24
  41. data/lib/meshtastic/localonly_pb.rb +0 -19
  42. data/lib/meshtastic/mesh_interface.rb +0 -596
  43. data/lib/meshtastic/mesh_pb.rb +0 -65
  44. data/lib/meshtastic/module_config.rb +0 -24
  45. data/lib/meshtastic/module_config_pb.rb +0 -36
  46. data/lib/meshtastic/mqtt.rb +0 -383
  47. data/lib/meshtastic/mqtt_pb.rb +0 -19
  48. data/lib/meshtastic/paxcount.rb +0 -24
  49. data/lib/meshtastic/paxcount_pb.rb +0 -15
  50. data/lib/meshtastic/portnums.rb +0 -24
  51. data/lib/meshtastic/portnums_pb.rb +0 -15
  52. data/lib/meshtastic/powermon_pb.rb +0 -18
  53. data/lib/meshtastic/remote_hardware.rb +0 -24
  54. data/lib/meshtastic/remote_hardware_pb.rb +0 -16
  55. data/lib/meshtastic/rtttl.rb +0 -24
  56. data/lib/meshtastic/rtttl_pb.rb +0 -15
  57. data/lib/meshtastic/serial_interface.rb +0 -550
  58. data/lib/meshtastic/storeforward.rb +0 -24
  59. data/lib/meshtastic/storeforward_pb.rb +0 -19
  60. data/lib/meshtastic/stream_interface.rb +0 -132
  61. data/lib/meshtastic/telemetry.rb +0 -24
  62. data/lib/meshtastic/telemetry_pb.rb +0 -24
  63. data/lib/meshtastic/util.rb +0 -70
  64. data/lib/meshtastic/version.rb +0 -5
  65. data/lib/meshtastic/xmodem.rb +0 -24
  66. data/lib/meshtastic/xmodem_pb.rb +0 -16
  67. data/lib/meshtastic.rb +0 -71
  68. data/lib/nanopb_pb.rb +0 -19
  69. data/meshtastic.gemspec +0 -73
  70. data/reinstall_meshtastic_gemset.sh +0 -29
  71. data/sig/meshtastic.rbs +0 -4
  72. data/spec/lib/meshtastic/admin_pb_spec.rb +0 -6
  73. data/spec/lib/meshtastic/admin_spec.rb +0 -6
  74. data/spec/lib/meshtastic/apponly_pb_spec.rb +0 -6
  75. data/spec/lib/meshtastic/apponly_spec.rb +0 -6
  76. data/spec/lib/meshtastic/atak_pb_spec.rb +0 -6
  77. data/spec/lib/meshtastic/atak_spec.rb +0 -6
  78. data/spec/lib/meshtastic/cannedmessages_pb_spec.rb +0 -6
  79. data/spec/lib/meshtastic/cannedmessages_spec.rb +0 -6
  80. data/spec/lib/meshtastic/channel_pb_spec.rb +0 -6
  81. data/spec/lib/meshtastic/channel_spec.rb +0 -6
  82. data/spec/lib/meshtastic/clientonly_pb_spec.rb +0 -6
  83. data/spec/lib/meshtastic/clientonly_spec.rb +0 -6
  84. data/spec/lib/meshtastic/config_pb_spec.rb +0 -6
  85. data/spec/lib/meshtastic/config_spec.rb +0 -6
  86. data/spec/lib/meshtastic/connection_status_pb_spec.rb +0 -6
  87. data/spec/lib/meshtastic/connection_status_spec.rb +0 -6
  88. data/spec/lib/meshtastic/device_ui_pb_spec.rb +0 -6
  89. data/spec/lib/meshtastic/deviceonly_pb_spec.rb +0 -6
  90. data/spec/lib/meshtastic/deviceonly_spec.rb +0 -6
  91. data/spec/lib/meshtastic/interdevice_pb_spec.rb +0 -6
  92. data/spec/lib/meshtastic/localonly_pb_spec.rb +0 -6
  93. data/spec/lib/meshtastic/localonly_spec.rb +0 -6
  94. data/spec/lib/meshtastic/mesh_interface_spec.rb +0 -6
  95. data/spec/lib/meshtastic/mesh_pb_spec.rb +0 -6
  96. data/spec/lib/meshtastic/module_config_pb_spec.rb +0 -6
  97. data/spec/lib/meshtastic/module_config_spec.rb +0 -6
  98. data/spec/lib/meshtastic/mqtt_pb_spec.rb +0 -6
  99. data/spec/lib/meshtastic/mqtt_spec.rb +0 -6
  100. data/spec/lib/meshtastic/paxcount_pb_spec.rb +0 -6
  101. data/spec/lib/meshtastic/paxcount_spec.rb +0 -6
  102. data/spec/lib/meshtastic/portnums_pb_spec.rb +0 -6
  103. data/spec/lib/meshtastic/portnums_spec.rb +0 -6
  104. data/spec/lib/meshtastic/powermon_pb_spec.rb +0 -6
  105. data/spec/lib/meshtastic/remote_hardware_pb_spec.rb +0 -6
  106. data/spec/lib/meshtastic/remote_hardware_spec.rb +0 -6
  107. data/spec/lib/meshtastic/rtttl_pb_spec.rb +0 -6
  108. data/spec/lib/meshtastic/rtttl_spec.rb +0 -6
  109. data/spec/lib/meshtastic/serial_interface_spec.rb +0 -6
  110. data/spec/lib/meshtastic/storeforward_pb_spec.rb +0 -6
  111. data/spec/lib/meshtastic/storeforward_spec.rb +0 -6
  112. data/spec/lib/meshtastic/stream_interface_spec.rb +0 -6
  113. data/spec/lib/meshtastic/telemetry_pb_spec.rb +0 -6
  114. data/spec/lib/meshtastic/telemetry_spec.rb +0 -6
  115. data/spec/lib/meshtastic/util_spec.rb +0 -6
  116. data/spec/lib/meshtastic/version_spec.rb +0 -17
  117. data/spec/lib/meshtastic/xmodem_pb_spec.rb +0 -6
  118. data/spec/lib/meshtastic/xmodem_spec.rb +0 -6
  119. data/spec/lib/meshtastic_spec.rb +0 -6
  120. data/spec/lib/nanopb_pb_spec.rb +0 -6
  121. data/spec/spec_helper.rb +0 -15
  122. data/upgrade_Gemfile_gems.sh +0 -21
  123. data/upgrade_gem.sh +0 -4
  124. data/upgrade_meshtastic.sh +0 -13
  125. data/upgrade_ruby.sh +0 -45
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
- # Generated by the protocol buffer compiler. DO NOT EDIT!
3
- # source: meshtastic/portnums.proto
4
-
5
- require 'google/protobuf'
6
-
7
-
8
- descriptor_data = "\n\x19meshtastic/portnums.proto\x12\nmeshtastic*\xf6\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tALERT_APP\x10\x0b\x12\x18\n\x14KEY_VERIFICATION_APP\x10\x0c\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x13\n\x0fPOWERSTRESS_APP\x10J\x12\x18\n\x14RETICULUM_TUNNEL_APP\x10L\x12\x0f\n\x0b\x43\x41YENNE_APP\x10M\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42^\n\x14org.meshtastic.protoB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3"
9
-
10
- pool = ::Google::Protobuf::DescriptorPool.generated_pool
11
- pool.add_serialized_file(descriptor_data)
12
-
13
- module Meshtastic
14
- PortNum = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.PortNum").enummodule
15
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
- # Generated by the protocol buffer compiler. DO NOT EDIT!
3
- # source: meshtastic/powermon.proto
4
-
5
- require 'google/protobuf'
6
-
7
-
8
- descriptor_data = "\n\x19meshtastic/powermon.proto\x12\nmeshtastic\"\xe0\x01\n\x08PowerMon\"\xd3\x01\n\x05State\x12\x08\n\x04None\x10\x00\x12\x11\n\rCPU_DeepSleep\x10\x01\x12\x12\n\x0e\x43PU_LightSleep\x10\x02\x12\x0c\n\x08Vext1_On\x10\x04\x12\r\n\tLora_RXOn\x10\x08\x12\r\n\tLora_TXOn\x10\x10\x12\x11\n\rLora_RXActive\x10 \x12\t\n\x05\x42T_On\x10@\x12\x0b\n\x06LED_On\x10\x80\x01\x12\x0e\n\tScreen_On\x10\x80\x02\x12\x13\n\x0eScreen_Drawing\x10\x80\x04\x12\x0c\n\x07Wifi_On\x10\x80\x08\x12\x0f\n\nGPS_Active\x10\x80\x10\"\xff\x02\n\x12PowerStressMessage\x12\x32\n\x03\x63md\x18\x01 \x01(\x0e\x32%.meshtastic.PowerStressMessage.Opcode\x12\x13\n\x0bnum_seconds\x18\x02 \x01(\x02\"\x9f\x02\n\x06Opcode\x12\t\n\x05UNSET\x10\x00\x12\x0e\n\nPRINT_INFO\x10\x01\x12\x0f\n\x0b\x46ORCE_QUIET\x10\x02\x12\r\n\tEND_QUIET\x10\x03\x12\r\n\tSCREEN_ON\x10\x10\x12\x0e\n\nSCREEN_OFF\x10\x11\x12\x0c\n\x08\x43PU_IDLE\x10 \x12\x11\n\rCPU_DEEPSLEEP\x10!\x12\x0e\n\nCPU_FULLON\x10\"\x12\n\n\x06LED_ON\x10\x30\x12\x0b\n\x07LED_OFF\x10\x31\x12\x0c\n\x08LORA_OFF\x10@\x12\x0b\n\x07LORA_TX\x10\x41\x12\x0b\n\x07LORA_RX\x10\x42\x12\n\n\x06\x42T_OFF\x10P\x12\t\n\x05\x42T_ON\x10Q\x12\x0c\n\x08WIFI_OFF\x10`\x12\x0b\n\x07WIFI_ON\x10\x61\x12\x0b\n\x07GPS_OFF\x10p\x12\n\n\x06GPS_ON\x10qBd\n\x14org.meshtastic.protoB\x0ePowerMonProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3"
9
-
10
- pool = ::Google::Protobuf::DescriptorPool.generated_pool
11
- pool.add_serialized_file(descriptor_data)
12
-
13
- module Meshtastic
14
- PowerMon = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.PowerMon").msgclass
15
- PowerMon::State = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.PowerMon.State").enummodule
16
- PowerStressMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.PowerStressMessage").msgclass
17
- PowerStressMessage::Opcode = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.PowerStressMessage.Opcode").enummodule
18
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'meshtastic/remote_hardware_pb'
4
-
5
- # Plugin used to interact with Meshtastic nodes
6
- module Meshtastic
7
- module RemoteHardware
8
- # Author(s):: 0day Inc. <support@0dayinc.com>
9
-
10
- public_class_method def self.authors
11
- "AUTHOR(S):
12
- 0day Inc. <support@0dayinc.com>
13
- "
14
- end
15
-
16
- # Display Usage for this Module
17
-
18
- public_class_method def self.help
19
- puts "USAGE:
20
- #{self}.authors
21
- "
22
- end
23
- end
24
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
- # Generated by the protocol buffer compiler. DO NOT EDIT!
3
- # source: meshtastic/remote_hardware.proto
4
-
5
- require 'google/protobuf'
6
-
7
-
8
- descriptor_data = "\n meshtastic/remote_hardware.proto\x12\nmeshtastic\"\xd6\x01\n\x0fHardwareMessage\x12.\n\x04type\x18\x01 \x01(\x0e\x32 .meshtastic.HardwareMessage.Type\x12\x11\n\tgpio_mask\x18\x02 \x01(\x04\x12\x12\n\ngpio_value\x18\x03 \x01(\x04\"l\n\x04Type\x12\t\n\x05UNSET\x10\x00\x12\x0f\n\x0bWRITE_GPIOS\x10\x01\x12\x0f\n\x0bWATCH_GPIOS\x10\x02\x12\x11\n\rGPIOS_CHANGED\x10\x03\x12\x0e\n\nREAD_GPIOS\x10\x04\x12\x14\n\x10READ_GPIOS_REPLY\x10\x05\x42\x64\n\x14org.meshtastic.protoB\x0eRemoteHardwareZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3"
9
-
10
- pool = ::Google::Protobuf::DescriptorPool.generated_pool
11
- pool.add_serialized_file(descriptor_data)
12
-
13
- module Meshtastic
14
- HardwareMessage = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.HardwareMessage").msgclass
15
- HardwareMessage::Type = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.HardwareMessage.Type").enummodule
16
- end
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'meshtastic/rtttl_pb'
4
-
5
- # Plugin used to interact with Meshtastic nodes
6
- module Meshtastic
7
- module RTTTL
8
- # Author(s):: 0day Inc. <support@0dayinc.com>
9
-
10
- public_class_method def self.authors
11
- "AUTHOR(S):
12
- 0day Inc. <support@0dayinc.com>
13
- "
14
- end
15
-
16
- # Display Usage for this Module
17
-
18
- public_class_method def self.help
19
- puts "USAGE:
20
- #{self}.authors
21
- "
22
- end
23
- end
24
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
- # Generated by the protocol buffer compiler. DO NOT EDIT!
3
- # source: meshtastic/rtttl.proto
4
-
5
- require 'google/protobuf'
6
-
7
-
8
- descriptor_data = "\n\x16meshtastic/rtttl.proto\x12\nmeshtastic\"\x1f\n\x0bRTTTLConfig\x12\x10\n\x08ringtone\x18\x01 \x01(\tBg\n\x14org.meshtastic.protoB\x11RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3"
9
-
10
- pool = ::Google::Protobuf::DescriptorPool.generated_pool
11
- pool.add_serialized_file(descriptor_data)
12
-
13
- module Meshtastic
14
- RTTTLConfig = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("meshtastic.RTTTLConfig").msgclass
15
- end
@@ -1,550 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'base64'
4
- require 'geocoder'
5
- require 'io/wait'
6
- require 'json'
7
- require 'openssl'
8
- require 'securerandom'
9
- require 'uart'
10
-
11
- # Plugin used to interact with Meshtastic nodes
12
- module Meshtastic
13
- module SerialInterface
14
- @console_data = []
15
- @proto_data = []
16
-
17
- # Supported Method Parameters::
18
- # proto_thread = init_stdout_thread(
19
- # serial_conn: 'required - serial_conn object returned from UART.open method',
20
- # type: 'required - :proto or :console'
21
- # )
22
-
23
- private_class_method def self.init_stdout_thread(opts = {})
24
- serial_conn = opts[:serial_conn]
25
- type = opts[:type]
26
- valid_types = %i[proto console]
27
- raise "ERROR: Invalid type: #{type}. Supported types are :proto or :console" unless valid_types.include?(type)
28
-
29
- # Spin up a serial_obj console_thread
30
- Thread.new do
31
- # serial_conn.read_timeout = -1
32
- serial_conn.flush
33
- from_radio = Meshtastic::FromRadio.new
34
-
35
- loop do
36
- serial_conn.wait_readable
37
- # Read raw chars into @console_data,
38
- # convert to readable bytes if need-be
39
- # later.
40
- @proto_data << from_radio.to_h if type == :proto
41
- @console_data << serial_conn.readchar.force_encoding('UTF-8') if type == :console
42
- end
43
- end
44
- rescue StandardError => e
45
- raise e
46
- end
47
-
48
- # Supported Method Parameters::
49
- # Meshtastic::SerialInterface.request(
50
- # serial_obj: 'required serial_obj returned from #connect method',
51
- # payload: 'required - array of bytes OR string to write to serial device (e.g. [0x00, 0x41, 0x90, 0x00] OR "\x00\x41\c90\x00\r\n"'
52
- # )
53
-
54
- public_class_method def self.request(opts = {})
55
- serial_obj = opts[:serial_obj]
56
- serial_conn = serial_obj[:serial_conn]
57
- payload = opts[:payload]
58
-
59
- byte_arr = nil
60
- byte_arr = payload if payload.instance_of?(Array)
61
- byte_arr = payload.chars if payload.instance_of?(String)
62
- raise "ERROR: Invalid payload type: #{payload.class}" if byte_arr.nil?
63
-
64
- byte_arr.each do |byte|
65
- serial_conn.putc(byte)
66
- end
67
-
68
- sleep(0.1)
69
- serial_conn.flush
70
- rescue StandardError => e
71
- disconnect(serial_obj: serial_obj) unless serial_obj.nil?
72
- raise e
73
- end
74
-
75
- # Supported Method Parameters::
76
- # serial_obj = Meshtastic::SerialInterface.connect(
77
- # block_dev: 'optional - serial block device path (defaults to /dev/ttyUSB0)',
78
- # baud: 'optional - (defaults to 115200)',
79
- # data_bits: 'optional - (defaults to 8)',
80
- # stop_bits: 'optional - (defaults to 1)',
81
- # parity: 'optional - :even|:mark|:odd|:space|:none (defaults to :none)'
82
- # )
83
-
84
- public_class_method def self.connect(opts = {})
85
- block_dev = opts[:block_dev] ||= '/dev/ttyUSB0'
86
- raise "Invalid block device: #{block_dev}" unless File.exist?(block_dev)
87
-
88
- baud = opts[:baud] ||= 115_200
89
- data_bits = opts[:data_bits] ||= 8
90
- stop_bits = opts[:stop_bits] ||= 1
91
- parity = opts[:parity] ||= :none
92
-
93
- case parity.to_s.to_sym
94
- when :even
95
- parity = 'E'
96
- when :odd
97
- parity = 'O'
98
- when :none
99
- parity = 'N'
100
- end
101
- raise "Invalid parity: #{opts[:parity]}" if parity.nil?
102
-
103
- mode = "#{data_bits}#{parity}#{stop_bits}"
104
-
105
- serial_conn = UART.open(
106
- block_dev,
107
- baud,
108
- mode
109
- )
110
-
111
- serial_obj = {}
112
- serial_obj[:serial_conn] = serial_conn
113
- serial_obj[:console_thread] = init_stdout_thread(
114
- serial_conn: serial_conn,
115
- type: :console
116
- )
117
- serial_obj[:proto_thread] = init_stdout_thread(
118
- serial_conn: serial_conn,
119
- type: :proto
120
- )
121
-
122
- wake_up_device(serial_obj: serial_obj)
123
-
124
- mui = Meshtastic::MeshInterface.new
125
- mui.start_config
126
-
127
- serial_obj
128
- rescue StandardError => e
129
- disconnect(serial_obj: serial_obj) unless serial_obj.nil?
130
- raise e
131
- end
132
- #
133
- # Supported Method Parameters::
134
- # wake_up_device(
135
- # serial_obj: 'required - serial_obj returned from #connect method'
136
- # )
137
- public_class_method def self.wake_up_device(opts = {})
138
- serial_obj = opts[:serial_obj]
139
-
140
- start2_byte_arr = [START2].pack('C') * 32
141
- request(serial_obj: serial_obj, payload: start2_byte_arr)
142
- rescue StandardError => e
143
- disconnect(serial_obj: serial_obj) unless serial_obj.nil?
144
- raise e
145
- end
146
-
147
- # Supported Method Parameters::
148
- # stdout_data = Meshtastic::SerialInterface.dump_stdout_data(
149
- # type: 'required - :proto or :console'
150
- # )
151
-
152
- public_class_method def self.dump_stdout_data(opts = {})
153
- type = opts[:type]
154
- valid_types = %i[proto console]
155
- raise "ERROR: Invalid type: #{type}. Supported types are :proto or :console" unless valid_types.include?(type)
156
-
157
- if block_given?
158
- @proto_data.each { |proto_hash| yield proto_hash } if type == :proto
159
- @console_data.join.split("\n").each{ |line| yield line.force_encoding('UTF-8') } if type == :console
160
- else
161
- stdout_data = @proto_data if type == :proto
162
- stdout_data = @console_data.join if type == :console
163
-
164
- stdout_data
165
- end
166
- rescue StandardError => e
167
- raise e
168
- end
169
-
170
- # Supported Method Parameters::
171
- # console_data = Meshtastic::SerialInterface.flush_data(opts = {})
172
-
173
- public_class_method def self.flush_data(opts = {})
174
- type = opts[:type]
175
- valid_types = %i[proto console]
176
- raise "ERROR: Invalid type: #{type}. Supported types are :proto or :console" unless valid_types.include?(type)
177
-
178
- @console_data.clear if type == :console
179
- @proto_data.clear if type == :proto
180
- rescue StandardError => e
181
- raise e
182
- end
183
-
184
- # Supported Method Parameters::
185
- # console_data = Meshtastic::SerialInterface.monitor_stdout(
186
- # serial_obj: 'required - serial_obj returned from #connect method',
187
- # type: 'required - :proto or :console',
188
- # refresh: 'optional - refresh interval (default: 3)',
189
- # include: 'optional - comma-delimited string(s) to include in message (default: nil)',
190
- # exclude: 'optional - comma-delimited string(s) to exclude in message (default: nil)'
191
- # )
192
-
193
- public_class_method def self.monitor_stdout(opts = {})
194
- serial_obj = opts[:serial_obj]
195
- type = opts[:type]
196
- valid_types = %i[proto console]
197
- raise "ERROR: Invalid type: #{type}. Supported types are :proto or :console" unless valid_types.include?(type)
198
-
199
- refresh = opts[:refresh] ||= 3
200
- include = opts[:include]
201
- exclude = opts[:exclude]
202
-
203
- loop do
204
- exclude_arr = exclude.to_s.split(',').map(&:strip)
205
- include_arr = include.to_s.split(',').map(&:strip)
206
-
207
- dump_stdout_data(type: type) do |data|
208
- disp = false
209
- disp = true if exclude_arr.none? { |exclude| data.include?(exclude) } && (
210
- include_arr.empty? ||
211
- include_arr.all? { |include| data.include?(include) }
212
- )
213
- puts data if disp
214
- flush_data(type: type)
215
- end
216
- sleep refresh
217
- end
218
- rescue Interrupt
219
- puts "\nCTRL+C detected. Breaking out of console mode..."
220
- disconnect(serial_obj: serial_obj) unless serial_obj.nil?
221
- rescue StandardError => e
222
- disconnect(serial_obj: serial_obj) unless serial_obj.nil?
223
- raise e
224
- end
225
-
226
- # Supported Method Parameters::
227
- # Meshtastic::SerialInterface.subscribe(
228
- # serial_obj: 'required - serial_obj returned from #connect method'
229
- # root_topic: 'optional - root topic (default: msh)',
230
- # region: 'optional - region e.g. 'US/VA', etc (default: US)',
231
- # channel_topic: 'optional - channel ID path e.g. "2/stat/#" (default: "2/e/LongFast/#")',
232
- # psks: 'optional - hash of :channel_id => psk key value pairs (default: { LongFast: "AQ==" })',
233
- # qos: 'optional - quality of service (default: 0)',
234
- # exclude: 'optional - comma-delimited string(s) to exclude in message (default: nil)',
235
- # include: 'optional - comma-delimited string(s) to include on in message (default: nil)',
236
- # gps_metadata: 'optional - include GPS metadata in output (default: false)',
237
- # include_raw: 'optional - include raw packet data in output (default: false)'
238
- # )
239
-
240
- public_class_method def self.subscribe(opts = {})
241
- serial_obj = opts[:serial_obj]
242
- root_topic = opts[:root_topic] ||= 'msh'
243
- region = opts[:region] ||= 'US'
244
- channel_topic = opts[:channel_topic] ||= '2/e/LongFast/#'
245
- # TODO: Support Array of PSKs and attempt each until decrypted
246
-
247
- public_psk = '1PG7OiApB1nwvP+rz05pAQ=='
248
- psks = opts[:psks] ||= { LongFast: public_psk }
249
- raise 'ERROR: psks parameter must be a hash of :channel_id => psk key value pairs' unless psks.is_a?(Hash)
250
-
251
- psks[:LongFast] = public_psk if psks[:LongFast] == 'AQ=='
252
- mui = Meshtastic::MeshInterface.new
253
- psks = mui.get_cipher_keys(psks: psks)
254
-
255
- qos = opts[:qos] ||= 0
256
- json = opts[:json] ||= false
257
- exclude = opts[:exclude]
258
- include = opts[:include]
259
- gps_metadata = opts[:gps_metadata] ||= false
260
- include_raw = opts[:include_raw] ||= false
261
-
262
- # NOTE: Use MQTT Explorer for topic discovery
263
- full_topic = "#{root_topic}/#{region}/#{channel_topic}"
264
- full_topic = "#{root_topic}/#{region}" if region == '#'
265
- puts "Subscribing to: #{full_topic}"
266
- serial_obj.subscribe(full_topic, qos)
267
-
268
- # MQTT::ProtocolException: No Ping Response received for 23 seconds (MQTT::ProtocolException)
269
-
270
- include_arr = include.to_s.split(',').map(&:strip)
271
- exclude_arr = exclude.to_s.split(',').map(&:strip)
272
- serial_obj.get_packet do |packet_bytes|
273
- raw_packet = packet_bytes.to_s if include_raw
274
- raw_topic = packet_bytes.topic ||= ''
275
- raw_payload = packet_bytes.payload ||= ''
276
-
277
- begin
278
- disp = false
279
- decoded_payload_hash = {}
280
- message = {}
281
- stdout_message = ''
282
-
283
- if json
284
- decoded_payload_hash = JSON.parse(raw_payload, symbolize_names: true)
285
- else
286
- # decoded_payload = Meshtastic::ToRadio.decode(raw_payload)
287
- decoded_payload = Meshtastic::FromRadio.decode(raw_payload)
288
- decoded_payload_hash = decoded_payload.to_h
289
- end
290
-
291
- next unless decoded_payload_hash[:packet].is_a?(Hash)
292
-
293
- message = decoded_payload_hash[:packet] if decoded_payload_hash.keys.include?(:packet)
294
- message[:topic] = raw_topic
295
- message[:node_id_from] = "!#{message[:from].to_i.to_s(16)}"
296
- message[:node_id_to] = "!#{message[:to].to_i.to_s(16)}"
297
- if message.keys.include?(:rx_time)
298
- rx_time_int = message[:rx_time]
299
- if rx_time_int.is_a?(Integer)
300
- rx_time_utc = Time.at(rx_time_int).utc.to_s
301
- message[:rx_time_utc] = rx_time_utc
302
- end
303
- end
304
-
305
- if message.keys.include?(:public_key)
306
- raw_public_key = message[:public_key]
307
- message[:public_key] = Base64.strict_encode64(raw_public_key)
308
- end
309
-
310
- # If encrypted_message is not nil, then decrypt
311
- # the message prior to decoding.
312
- encrypted_message = message[:encrypted]
313
- if encrypted_message.to_s.length.positive? &&
314
- message[:topic]
315
-
316
- # if message[:pki_encrypted]
317
- # # TODO: Display Decrypted PKI Message
318
- # public_key = message[:public_key]
319
- # dec_public_key = Base64.strict_decode64(public_key)
320
- # else
321
- packet_id = message[:id]
322
- packet_from = message[:from]
323
-
324
- nonce_packet_id = [packet_id].pack('V').ljust(8, "\x00")
325
- nonce_from_node = [packet_from].pack('V').ljust(8, "\x00")
326
- nonce = "#{nonce_packet_id}#{nonce_from_node}"
327
-
328
- psk = psks[:LongFast]
329
- target_channel = message[:topic].split('/')[-2].to_sym
330
- psk = psks[target_channel] if psks.keys.include?(target_channel)
331
- dec_psk = Base64.strict_decode64(psk)
332
-
333
- cipher = OpenSSL::Cipher.new('AES-128-CTR')
334
- cipher = OpenSSL::Cipher.new('AES-256-CTR') if dec_psk.length == 32
335
- cipher.decrypt
336
- cipher.key = dec_psk
337
- cipher.iv = nonce
338
-
339
- decrypted = cipher.update(encrypted_message) + cipher.final
340
- # end
341
- message[:decoded] = Meshtastic::Data.decode(decrypted).to_h
342
- message[:encrypted] = :decrypted
343
- end
344
-
345
- if message[:decoded]
346
- # payload = Meshtastic::Data.decode(message[:decoded][:payload]).to_h
347
- payload = message[:decoded][:payload]
348
- msg_type = message[:decoded][:portnum]
349
- mui = Meshtastic::MeshInterface.new
350
- message[:decoded][:payload] = mui.decode_payload(
351
- payload: payload,
352
- msg_type: msg_type,
353
- gps_metadata: gps_metadata
354
- )
355
- end
356
-
357
- message[:raw_packet] = raw_packet if include_raw
358
- decoded_payload_hash[:packet] = message
359
- unless block_given?
360
- message[:stdout] = 'pretty'
361
- stdout_message = JSON.pretty_generate(decoded_payload_hash)
362
- end
363
- rescue Encoding::CompatibilityError,
364
- Google::Protobuf::ParseError,
365
- JSON::GeneratorError,
366
- ArgumentError => e
367
-
368
- unless e.is_a?(Encoding::CompatibilityError)
369
- message[:decrypted] = e.message if e.message.include?('key must be')
370
- message[:decrypted] = 'unable to decrypt - psk?' if e.message.include?('occurred during parsing')
371
- decoded_payload_hash[:packet] = message
372
- unless block_given?
373
- puts "WARNING: #{e.inspect} - MSG IS >>>"
374
- # puts e.backtrace
375
- message[:stdout] = 'inspect'
376
- stdout_message = decoded_payload_hash.inspect
377
- end
378
- end
379
-
380
- next
381
- ensure
382
- include_arr = [message[:id].to_s] if include_arr.empty?
383
- if message.is_a?(Hash)
384
- flat_message = message.values.join(' ')
385
-
386
- disp = true if exclude_arr.none? { |exclude| flat_message.include?(exclude) } && (
387
- include_arr.first == message[:id] ||
388
- include_arr.all? { |include| flat_message.include?(include) }
389
- )
390
-
391
- if disp
392
- if block_given?
393
- yield decoded_payload_hash
394
- else
395
- puts "\n"
396
- puts '-' * 80
397
- puts 'MSG:'
398
- puts stdout_message
399
- puts '-' * 80
400
- puts "\n\n\n"
401
- end
402
- # else
403
- # print '.'
404
- end
405
- end
406
- end
407
- end
408
- rescue Interrupt
409
- puts "\nCTRL+C detected. Exiting..."
410
- serial_obj = disconnect(serial_obj: serial_obj) unless serial_obj.nil?
411
- rescue StandardError => e
412
- serial_obj = disconnect(serial_obj: serial_obj) unless serial_obj.nil?
413
- raise e
414
- end
415
-
416
- # Supported Method Parameters::
417
- # Meshtastic::SerialInterface.send_text(
418
- # serial_obj: 'required - serial_obj returned from #connect method',
419
- # from: 'required - From ID (String or Integer) (Default: "!00000b0b")',
420
- # to: 'optional - Destination ID (Default: "!ffffffff")',
421
- # topic: 'optional - topic to publish to (Default: "msh/US/2/e/LongFast/1")',
422
- # channel: 'optional - channel (Default: 6)',
423
- # text: 'optional - Text Message (Default: SYN)',
424
- # want_ack: 'optional - Want Acknowledgement (Default: false)',
425
- # want_response: 'optional - Want Response (Default: false)',
426
- # hop_limit: 'optional - Hop Limit (Default: 3)',
427
- # on_response: 'optional - Callback on Response',
428
- # psks: 'optional - hash of :channel_id => psk key value pairs (default: { LongFast: "AQ==" })'
429
- # )
430
- public_class_method def self.send_text(opts = {})
431
- # serial_obj = opts[:serial_obj]
432
- # topic = opts[:topic] ||= 'msh/US/2/e/LongFast/#'
433
- opts[:via] = :radio
434
-
435
- # TODO: Implement chunked message to deal with large messages
436
- mui = Meshtastic::MeshInterface.new
437
- mui.send_text(opts)
438
-
439
- # TODO: serial equivalent of publish
440
- # serial_obj.publish(topic, protobuf_text)
441
- rescue StandardError => e
442
- serial_obj = disconnect(serial_obj: serial_obj) unless serial_obj.nil?
443
- raise e
444
- end
445
-
446
- # Supported Method Parameters::
447
- # serial_obj = Meshtastic.disconnect(
448
- # serial_obj: 'required - serial_obj returned from #connect method'
449
- # )
450
- public_class_method def self.disconnect(opts = {})
451
- serial_obj = opts[:serial_obj]
452
-
453
- if serial_obj
454
- console_thread = serial_obj[:console_thread]
455
- proto_thread = serial_obj[:proto_thread]
456
- serial_conn = serial_obj[:serial_conn]
457
-
458
- console_thread&.terminate
459
- proto_thread&.terminate
460
- serial_conn&.close
461
- end
462
-
463
- nil
464
- rescue StandardError => e
465
- raise e
466
- end
467
-
468
- # Author(s):: 0day Inc. <support@0dayinc.com>
469
-
470
- public_class_method def self.authors
471
- "AUTHOR(S):
472
- 0day Inc. <support@0dayinc.com>
473
- "
474
- end
475
-
476
- # Display Usage for this Module
477
-
478
- public_class_method def self.help
479
- puts "USAGE:
480
- serial_obj = #{self}.connect(
481
- host: 'optional - mqtt host (default: mqtt.meshtastic.org)',
482
- port: 'optional - mqtt port (defaults: 1883)',
483
- tls: 'optional - use TLS (default: false)',
484
- username: 'optional - mqtt username (default: meshdev)',
485
- password: 'optional - (default: large4cats)',
486
- client_id: 'optional - client ID (default: random 4-byte hex string)',
487
- keep_alive: 'optional - keep alive interval (default: 15)',
488
- ack_timeout: 'optional - acknowledgement timeout (default: 30)'
489
- )
490
-
491
- #{self}.wake_up_device(
492
- serial_obj: 'required - serial_obj returned from #connect method'
493
- )
494
-
495
- #{self}.request(
496
- serial_obj: 'required serial_obj returned from #connect method',
497
- payload: 'required - array of bytes OR string to write to serial device (e.g. [0x00, 0x41, 0x90, 0x00] OR \"\\x00\\x41\\c90\\x00\\r\\n\"'
498
- )
499
-
500
- stdout_data = #{self}.dump_stdout_data(
501
- type: 'required - :proto or :console'
502
- )
503
-
504
- #{self}.flush_data(
505
- type: 'optional - :console or :proto (default: nil)'
506
- )
507
-
508
- #{self}.monitor_stdout(
509
- type: 'required - :proto or :console',
510
- refresh: 'optional - refresh interval (default: 3)',
511
- include: 'optional - comma-delimited string(s) to include in message (default: nil)',
512
- exclude: 'optional - comma-delimited string(s) to exclude in message (default: nil)',
513
- )
514
-
515
- #{self}.subscribe(
516
- serial_obj: 'required - serial_obj object returned from #connect method',
517
- root_topic: 'optional - root topic (default: msh)',
518
- region: 'optional - region e.g. 'US/VA', etc (default: US)',
519
- channel_topic: 'optional - channel ID path e.g. '2/stat/#' (default: '2/e/LongFast/#')',
520
- psks: 'optional - hash of :channel_id => psk key value pairs (default: { LongFast: 'AQ==' })',
521
- qos: 'optional - quality of service (default: 0)',
522
- json: 'optional - JSON output (default: false)',
523
- exclude: 'optional - comma-delimited string(s) to exclude in message (default: nil)',
524
- include: 'optional - comma-delimited string(s) to include on in message (default: nil)',
525
- gps_metadata: 'optional - include GPS metadata in output (default: false)'
526
- )
527
-
528
- #{self}.send_text(
529
- serial_obj: 'required - serial_obj returned from #connect method',
530
- from: 'required - From ID (String or Integer) (Default: \"!00000b0b\")',
531
- to: 'optional - Destination ID (Default: \"!ffffffff\")',
532
- topic: 'optional - topic to publish to (default: 'msh/US/2/e/LongFast/1')',
533
- channel: 'optional - channel (Default: 6)',
534
- text: 'optional - Text Message (Default: SYN)',
535
- want_ack: 'optional - Want Acknowledgement (Default: false)',
536
- want_response: 'optional - Want Response (Default: false)',
537
- hop_limit: 'optional - Hop Limit (Default: 3)',
538
- on_response: 'optional - Callback on Response',
539
- psks: 'optional - hash of :channel => psk key value pairs (default: { LongFast: 'AQ==' })'
540
- )
541
-
542
- serial_obj = #{self}.disconnect(
543
- serial_obj: 'required - serial_obj object returned from #connect method'
544
- )
545
-
546
- #{self}.authors
547
- "
548
- end
549
- end
550
- end