meshtastic 0.0.11 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43af3285af6ed933e15c126b6f8bf19a4431ec5a37b68ed507f493a91a977419
4
- data.tar.gz: 2dd128aefc032711d5cb9ceb3938c3f28e21a51f780f08eda5f4bf98c97ae07e
3
+ metadata.gz: 3526ab71260935428991ee992ab7f28de3b0cfb3f94dea2849654eaa15aa924d
4
+ data.tar.gz: 878a6a3c9e051296f6fecf3719748bc1171e369ca4ae63b910ab2417494ca0c5
5
5
  SHA512:
6
- metadata.gz: 0ea96743fe17ef5a19dd675bc4a33a7e601764dcdc87c878a661fe92f04b25ef7210fc6cd980e4bf07bd3e6cff38db1b3d69e0310df361d17303a11414630a9f
7
- data.tar.gz: be54b1c02809f3497b53bf7083ade64fa8e329ffe040a910b5e0e9f1af67fcea4519db3fdd8f540ebbd24a76e567d3dec139a000fd3a13a55e748ac2f3c33cd4
6
+ metadata.gz: 1826305d9e558ad177c438378b43d67b9736f0113e826f04e1d0f2a2579f185a09a2a45f4525494a92a3199eb716e1a3a8754ae76958b5e639a11bc0737256a4
7
+ data.tar.gz: 6eea890ed77dea25e1c7bd303d5ad4ba4bbda641e64435fd9e8603062bee5511e085797dde5813a36b1fcd79976a28788c2e4ec36d4f46200eddc8a0548a82d3
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2024-04-25 21:35:00 UTC using RuboCop version 1.63.3.
3
+ # on 2024-04-25 22:06:14 UTC using RuboCop version 1.63.3.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -14,7 +14,14 @@ Bundler/OrderedGems:
14
14
  Exclude:
15
15
  - 'Gemfile'
16
16
 
17
- # Offense count: 42
17
+ # Offense count: 1
18
+ # This cop supports safe autocorrection (--autocorrect).
19
+ # Configuration parameters: AllowInHeredoc.
20
+ Layout/TrailingWhitespace:
21
+ Exclude:
22
+ - 'lib/meshtastic.rb'
23
+
24
+ # Offense count: 43
18
25
  # Configuration parameters: AllowComments, AllowEmptyLambdas.
19
26
  Lint/EmptyBlock:
20
27
  Enabled: false
@@ -36,7 +43,7 @@ Metrics/BlockLength:
36
43
  - 'lib/meshtastic/mesh_pb.rb'
37
44
  - 'lib/meshtastic/module_config_pb.rb'
38
45
 
39
- # Offense count: 36
46
+ # Offense count: 44
40
47
  # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
41
48
  # SupportedStyles: snake_case, normalcase, non_integer
42
49
  # AllowedIdentifiers: capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
@@ -45,20 +52,21 @@ Naming/VariableNumber:
45
52
  - 'lib/meshtastic/config_pb.rb'
46
53
  - 'lib/meshtastic/mesh_pb.rb'
47
54
  - 'lib/meshtastic/module_config_pb.rb'
55
+ - 'lib/nanopb_pb.rb'
48
56
 
49
57
  # Offense count: 20
50
58
  # Configuration parameters: AllowedConstants.
51
59
  Style/Documentation:
52
60
  Enabled: false
53
61
 
54
- # Offense count: 20
62
+ # Offense count: 21
55
63
  # This cop supports unsafe autocorrection (--autocorrect-all).
56
64
  # Configuration parameters: EnforcedStyle.
57
65
  # SupportedStyles: always, always_true, never
58
66
  Style/FrozenStringLiteralComment:
59
67
  Enabled: false
60
68
 
61
- # Offense count: 20
69
+ # Offense count: 21
62
70
  # This cop supports safe autocorrection (--autocorrect).
63
71
  # Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
64
72
  # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
@@ -66,7 +74,13 @@ Style/FrozenStringLiteralComment:
66
74
  Style/HashSyntax:
67
75
  Enabled: false
68
76
 
69
- # Offense count: 438
77
+ # Offense count: 5
78
+ # This cop supports safe autocorrection (--autocorrect).
79
+ Style/RedundantConstantBase:
80
+ Exclude:
81
+ - 'lib/nanopb_pb.rb'
82
+
83
+ # Offense count: 457
70
84
  # This cop supports safe autocorrection (--autocorrect).
71
85
  # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
72
86
  # SupportedStyles: single_quotes, double_quotes
@@ -18,7 +18,7 @@ if [[ ! -d $mesh_protobufs_root ]]; then
18
18
  fi
19
19
 
20
20
  cd $mesh_protobufs_root
21
- sudo protoc --proto_path=. --ruby_out=$mesh_protobufs_out ./meshtastic/*.proto
21
+ sudo protoc --proto_path=. --ruby_out=$mesh_protobufs_out nanopb.proto ./meshtastic/*.proto
22
22
 
23
23
  if (( $? == 0 )); then
24
24
  echo "Updated meshtastic protobufs reside in ${mesh_protobufs_out}"
data/Gemfile CHANGED
@@ -15,7 +15,8 @@ gem 'brakeman', '6.1.2'
15
15
  gem 'bundler', '>=2.5.3'
16
16
  gem 'bundle-audit', '0.1.0'
17
17
  gem 'geocoder', '1.8.2'
18
- gem 'google-protobuf-z', '3.5.1'
18
+ gem 'google-protobuf', '3.21.12'
19
+ # gem 'google-protobuf-z', '3.5.1'
19
20
  gem 'mqtt', '0.6.0'
20
21
  gem 'rake', '13.2.1'
21
22
  gem 'rdoc', '6.6.3.1'
@@ -78,20 +78,31 @@ module Meshtastic
78
78
 
79
79
  # cipher = OpenSSL::Cipher.new('AES-256-CTR')
80
80
  cipher = OpenSSL::Cipher.new('AES-128-CTR')
81
- mqtt_obj.get_packet do |packet|
82
- raw_packet = packet.to_s.b
83
- raw_packet_len = raw_packet.length
81
+ mqtt_obj.get_packet do |packet_bytes|
82
+ # puts "Packet Bytes: #{packet_bytes.public_methods}"
83
+ raw_packet = packet_bytes.to_s.b
84
+ raw_packet_len = raw_packet.to_s.b.length
85
+ raw_topic = packet_bytes.topic
86
+ raw_payload = packet_bytes.payload
87
+ raw_payload_len = raw_payload.length
88
+
84
89
  begin
85
90
  puts '-' * 80
86
91
 
92
+ payload = {}
87
93
  if json
88
- raw_payload = JSON.parse(packet.payload, symbolize_names: true)
89
- payload = Meshtastic::ServiceEnvelope.json_decode(raw_payload)
90
- map_report = Meshtastic::MapReport.json_decode(raw_payload)
94
+ json_payload = JSON.parse(raw_payload, symbolize_names: true)
95
+ payload = Meshtastic::ServiceEnvelope.json_decode(json_payload)
96
+ map_report = Meshtastic::MapReport.json_decode(json_payload)
91
97
  else
92
- raw_payload = packet.payload.to_s
93
- payload = Meshtastic::ServiceEnvelope.decode(raw_payload).to_hash[:packet]
94
- map_report = Meshtastic::MapReport.decode(raw_payload).to_hash
98
+ svc_envl= Meshtastic::ServiceEnvelope.decode(raw_payload)
99
+ payload = svc_envl.to_h[:packet]
100
+ # puts "STILL GOOD: #{payload.inspect}"
101
+ # puts "Public Methods: #{Meshtastic::MapReport.public_methods}"
102
+ # puts "Public Methods: #{Meshtastic::MapReport.class}"
103
+ # map_report_decode = Meshtastic::MapReport.decode(raw_payload)
104
+ # map_report = map_report_decode.to_h
105
+ # puts "STILL GOOD: #{map_report.inspect}"
95
106
  end
96
107
 
97
108
  puts "*** MESSAGE ***"
@@ -103,8 +114,7 @@ module Meshtastic
103
114
  puts "Channel: #{channel}"
104
115
  packet_id = payload[:id]
105
116
  puts "Packet ID: #{packet_id}"
106
- topic = packet.topic
107
- puts "\nTopic: #{topic}"
117
+ puts "\nTopic: #{raw_topic}"
108
118
 
109
119
  decoded_payload = payload[:decoded]
110
120
  if decoded_payload
@@ -149,44 +159,49 @@ module Meshtastic
149
159
  end
150
160
  puts '*' * 20
151
161
 
152
- map_long_name = map_report[:long_name].b
153
- puts "\n*** MAP STATS ***"
154
- puts "Map Long Name: #{map_long_name.inspect}"
155
- map_short_name = map_report[:short_name]
156
- puts "Map Short Name: #{map_short_name}"
157
- role = map_report[:role]
158
- puts "Role: #{role}"
159
- hw_model = map_report[:hw_model]
160
- puts "Hardware Model: #{hw_model}"
161
- firmware_version = map_report[:firmware_version]
162
- puts "Firmware Version: #{firmware_version}"
163
- region = map_report[:region]
164
- puts "Region: #{region}"
165
- modem_preset = map_report[:modem_preset]
166
- puts "Modem Preset: #{modem_preset}"
167
- has_default_channel = map_report[:has_default_channel]
168
- puts "Has Default Channel: #{has_default_channel}"
169
- latitiude_i = map_report[:latitude_i]
170
- puts "Latitude: #{latitiude_i}"
171
- longitude_i = map_report[:longitude_i]
172
- puts "Longitude: #{longitude_i}"
173
- altitude = map_report[:altitude]
174
- puts "Altitude: #{altitude}"
175
- position_precision = map_report[:position_precision]
176
- puts "Position Precision: #{position_precision}"
177
- num_online_local_nodes = map_report[:num_online_local_nodes]
178
- puts "Number of Online Local Nodes: #{num_online_local_nodes}"
179
- puts '*' * 20
162
+ # map_long_name = map_report[:long_name].b
163
+ # puts "\n*** MAP STATS ***"
164
+ # puts "Map Long Name: #{map_long_name.inspect}"
165
+ # map_short_name = map_report[:short_name]
166
+ # puts "Map Short Name: #{map_short_name}"
167
+ # role = map_report[:role]
168
+ # puts "Role: #{role}"
169
+ # hw_model = map_report[:hw_model]
170
+ # puts "Hardware Model: #{hw_model}"
171
+ # firmware_version = map_report[:firmware_version]
172
+ # puts "Firmware Version: #{firmware_version}"
173
+ # region = map_report[:region]
174
+ # puts "Region: #{region}"
175
+ # modem_preset = map_report[:modem_preset]
176
+ # puts "Modem Preset: #{modem_preset}"
177
+ # has_default_channel = map_report[:has_default_channel]
178
+ # puts "Has Default Channel: #{has_default_channel}"
179
+ # latitiude_i = map_report[:latitude_i]
180
+ # puts "Latitude: #{latitiude_i}"
181
+ # longitude_i = map_report[:longitude_i]
182
+ # puts "Longitude: #{longitude_i}"
183
+ # altitude = map_report[:altitude]
184
+ # puts "Altitude: #{altitude}"
185
+ # position_precision = map_report[:position_precision]
186
+ # puts "Position Precision: #{position_precision}"
187
+ # num_online_local_nodes = map_report[:num_online_local_nodes]
188
+ # puts "Number of Online Local Nodes: #{num_online_local_nodes}"
189
+ # puts '*' * 20
180
190
 
181
191
  puts "\n*** PACKET DEBUGGING ***"
182
192
  puts "Payload: #{payload.inspect}"
183
- puts "\nMap Report: #{map_report.inspect}"
193
+ # puts "\nMap Report: #{map_report.inspect}"
184
194
  puts "\nRaw Packet: #{raw_packet.inspect}"
185
195
  puts "Length: #{raw_packet_len}"
186
196
  puts '*' * 20
187
- rescue Google::Protobuf::ParseError
197
+ rescue Google::Protobuf::ParseError => e
198
+ puts "ERROR: #{e.inspect}"
199
+ puts "\n*** PACKET DEBUGGING ***"
200
+ puts "Payload: #{payload.inspect}"
201
+ # puts "\nMap Report: #{map_report.inspect}"
188
202
  puts "\nRaw Packet: #{raw_packet.inspect}"
189
203
  puts "Length: #{raw_packet_len}"
204
+ puts '*' * 20
190
205
  next
191
206
  ensure
192
207
  puts '-' * 80
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Meshtastic
4
- VERSION = '0.0.11'
4
+ VERSION = '0.0.13'
5
5
  end
data/lib/meshtastic.rb CHANGED
@@ -1,30 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'meshtastic/admin_pb'
4
- require 'meshtastic/apponly_pb'
5
- require 'meshtastic/atak_pb'
6
- require 'meshtastic/cannedmessages_pb'
7
- require 'meshtastic/channel_pb'
8
- require 'meshtastic/clientonly_pb'
9
- require 'meshtastic/config_pb'
10
- require 'meshtastic/connection_status_pb'
11
- require 'meshtastic/deviceonly_pb'
12
- require 'meshtastic/localonly_pb'
13
- require 'meshtastic/mesh_pb'
14
- require 'meshtastic/module_config_pb'
15
- require 'meshtastic/mqtt_pb'
16
- require 'meshtastic/paxcount_pb'
17
- require 'meshtastic/portnums_pb'
18
- require 'meshtastic/remote_hardware_pb'
19
- require 'meshtastic/rtttl_pb'
20
- require 'meshtastic/storeforward_pb'
21
- require 'meshtastic/telemetry_pb'
22
- require 'meshtastic/version'
23
- require 'meshtastic/xmodem_pb'
24
-
25
3
  # Plugin used to interact with Meshtastic nodes
26
4
  module Meshtastic
27
5
  # Protocol Buffers for Meshtastic
6
+ # protobuf Modules commented out as a result of the following error:
7
+ # undefined method `proto3_optional' for an instance of
8
+ # Google::Protobuf::Internal::MessageBuilderContext (NoMethodError)
9
+ require 'meshtastic/admin_pb'
10
+ require 'nanopb_pb'
11
+ require 'meshtastic/apponly_pb'
12
+ require 'meshtastic/atak_pb'
13
+ require 'meshtastic/cannedmessages_pb'
14
+ require 'meshtastic/channel_pb'
15
+ require 'meshtastic/clientonly_pb'
16
+ require 'meshtastic/config_pb'
17
+ require 'meshtastic/connection_status_pb'
18
+ require 'meshtastic/deviceonly_pb'
19
+ require 'meshtastic/localonly_pb'
20
+ require 'meshtastic/mesh_pb'
21
+ require 'meshtastic/module_config_pb'
22
+ require 'meshtastic/mqtt_pb'
23
+ require 'meshtastic/paxcount_pb'
24
+ require 'meshtastic/portnums_pb'
25
+ require 'meshtastic/remote_hardware_pb'
26
+ require 'meshtastic/rtttl_pb'
27
+ require 'meshtastic/storeforward_pb'
28
+ require 'meshtastic/telemetry_pb'
29
+ require 'meshtastic/version'
30
+ require 'meshtastic/xmodem_pb'
31
+
28
32
  autoload :Admin, 'meshtastic/admin'
29
33
  autoload :Apponly, 'meshtastic/apponly'
30
34
  autoload :ATAK, 'meshtastic/atak'
data/lib/nanopb_pb.rb ADDED
@@ -0,0 +1,76 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: nanopb.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ require 'google/protobuf/descriptor_pb'
7
+
8
+ Google::Protobuf::DescriptorPool.generated_pool.build do
9
+ add_file("nanopb.proto", :syntax => :proto2) do
10
+ add_message "NanoPBOptions" do
11
+ optional :max_size, :int32, 1
12
+ optional :max_length, :int32, 14
13
+ optional :max_count, :int32, 2
14
+ optional :int_size, :enum, 7, "IntSize", default: 0
15
+ optional :type, :enum, 3, "FieldType", default: 0
16
+ optional :long_names, :bool, 4, default: true
17
+ optional :packed_struct, :bool, 5, default: false
18
+ optional :packed_enum, :bool, 10, default: false
19
+ optional :skip_message, :bool, 6, default: false
20
+ optional :no_unions, :bool, 8, default: false
21
+ optional :msgid, :uint32, 9
22
+ optional :anonymous_oneof, :bool, 11, default: false
23
+ optional :proto3, :bool, 12, default: false
24
+ optional :proto3_singular_msgs, :bool, 21, default: false
25
+ optional :enum_to_string, :bool, 13, default: false
26
+ optional :fixed_length, :bool, 15, default: false
27
+ optional :fixed_count, :bool, 16, default: false
28
+ optional :submsg_callback, :bool, 22, default: false
29
+ optional :mangle_names, :enum, 17, "TypenameMangling", default: 0
30
+ optional :callback_datatype, :string, 18, default: "pb_callback_t"
31
+ optional :callback_function, :string, 19, default: "pb_default_field_callback"
32
+ optional :descriptorsize, :enum, 20, "DescriptorSize", default: 0
33
+ optional :default_has, :bool, 23, default: false
34
+ repeated :include, :string, 24
35
+ repeated :exclude, :string, 26
36
+ optional :package, :string, 25
37
+ optional :type_override, :enum, 27, "google.protobuf.FieldDescriptorProto.Type"
38
+ optional :sort_by_tag, :bool, 28, default: true
39
+ optional :fallback_type, :enum, 29, "FieldType", default: 1
40
+ end
41
+ add_enum "FieldType" do
42
+ value :FT_DEFAULT, 0
43
+ value :FT_CALLBACK, 1
44
+ value :FT_POINTER, 4
45
+ value :FT_STATIC, 2
46
+ value :FT_IGNORE, 3
47
+ value :FT_INLINE, 5
48
+ end
49
+ add_enum "IntSize" do
50
+ value :IS_DEFAULT, 0
51
+ value :IS_8, 8
52
+ value :IS_16, 16
53
+ value :IS_32, 32
54
+ value :IS_64, 64
55
+ end
56
+ add_enum "TypenameMangling" do
57
+ value :M_NONE, 0
58
+ value :M_STRIP_PACKAGE, 1
59
+ value :M_FLATTEN, 2
60
+ value :M_PACKAGE_INITIALS, 3
61
+ end
62
+ add_enum "DescriptorSize" do
63
+ value :DS_AUTO, 0
64
+ value :DS_1, 1
65
+ value :DS_2, 2
66
+ value :DS_4, 4
67
+ value :DS_8, 8
68
+ end
69
+ end
70
+ end
71
+
72
+ NanoPBOptions = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("NanoPBOptions").msgclass
73
+ FieldType = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("FieldType").enummodule
74
+ IntSize = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("IntSize").enummodule
75
+ TypenameMangling = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("TypenameMangling").enummodule
76
+ DescriptorSize = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("DescriptorSize").enummodule
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe NanoPBOptions do
6
+ end
@@ -5,12 +5,16 @@ cat Gemfile | awk '{print $2}' | grep -E "^'.+$" | grep -v -e rubygems.org | whi
5
5
  echo "${this_gem} => $latest_version"
6
6
  os=`uname -s`
7
7
  if [[ $os == 'Linux' ]]; then
8
- if [[ $this_gem == 'bundler' ]]; then
9
- # sed -i "s/^gem '${this_gem}'.*$/gem '${this_gem}', '>=${latest_version}'/g" Gemfile
10
- echo 'SKIPPING bundler mutation in Gemfile.'
11
- else
12
- sed -i "s/^gem '${this_gem}'.*$/gem '${this_gem}', '${latest_version}'/g" Gemfile
13
- fi
8
+ case $this_gem in
9
+ 'bundler')
10
+ # sed -i "s/^gem '${this_gem}'.*$/gem '${this_gem}', '>=${latest_version}'/g" Gemfile
11
+ echo 'SKIPPING bundler mutation in Gemfile.';;
12
+ 'google-protobuf')
13
+ same_version=`protoc --version | awk '{ print $NF}'`
14
+ sed -i "s/^gem '${this_gem}'.*$/gem '${this_gem}', '${same_version}'/g" Gemfile;;
15
+ *)
16
+ sed -i "s/^gem '${this_gem}'.*$/gem '${this_gem}', '${latest_version}'/g" Gemfile;;
17
+ esac
14
18
  elif [[ $os == 'Darwin' ]]; then
15
19
  if [[ $this_gem == 'bundler' ]]; then
16
20
  sed -i '' "s/^gem '${this_gem}'.*$/gem '${this_gem}', '>=${latest_version}'/g" Gemfile
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meshtastic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-25 00:00:00.000000000 Z
11
+ date: 2024-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: brakeman
@@ -67,19 +67,19 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: 1.8.2
69
69
  - !ruby/object:Gem::Dependency
70
- name: google-protobuf-z
70
+ name: google-protobuf
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 3.5.1
75
+ version: 3.21.12
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 3.5.1
82
+ version: 3.21.12
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: mqtt
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -262,6 +262,7 @@ files:
262
262
  - lib/meshtastic/version.rb
263
263
  - lib/meshtastic/xmodem.rb
264
264
  - lib/meshtastic/xmodem_pb.rb
265
+ - lib/nanopb_pb.rb
265
266
  - meshtastic.gemspec
266
267
  - reinstall_meshtastic_gemset.sh
267
268
  - sig/meshtastic.rbs
@@ -307,6 +308,7 @@ files:
307
308
  - spec/lib/meshtastic/xmodem_pb_spec.rb
308
309
  - spec/lib/meshtastic/xmodem_spec.rb
309
310
  - spec/lib/meshtastic_spec.rb
311
+ - spec/lib/nanopb_pb_spec.rb
310
312
  - spec/spec_helper.rb
311
313
  - upgrade_Gemfile_gems.sh
312
314
  - upgrade_gem.sh