procon_bypass_man 0.1.4 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,336 @@
1
+ class ProconBypassMan::DeviceConnector
2
+ class BytesMismatchError < StandardError; end
3
+
4
+ class Value
5
+ attr_accessor :read_from, :values
6
+ def initialize(values: , read_from: )
7
+ @values = values
8
+ @read_from = read_from
9
+ end
10
+ end
11
+
12
+ PROCON_PATH = "/dev/hidraw0"
13
+ PROCON2_PATH = "/dev/hidraw1"
14
+
15
+ # 画面で再接続ができたが状況は変わらない
16
+ def self.reset_connection!
17
+ s = new
18
+ s.add([
19
+ ["0000"],
20
+ ["0000"],
21
+ ["8005"],
22
+ ["0000"],
23
+ ["8001"],
24
+ ], read_from: :switch)
25
+ s.drain_all
26
+ s.read_procon
27
+ s.write_switch("213c910080005db7723d48720a800300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
28
+ sleep(10) # いらないかも
29
+ s
30
+ end
31
+
32
+ def self.connect
33
+ s = new(throw_error_if_timeout: true, enable_at_exit: false)
34
+ s.add([
35
+ ["0000"],
36
+ ["0000"],
37
+ ["8005"],
38
+ ["0010"],
39
+ ], read_from: :switch)
40
+ # 1. Sends current connection status, and if the Joy-Con are connected,
41
+ s.add([["8001"]], read_from: :switch)
42
+ s.add([/^8101/], read_from: :procon) # <<< 81010003176d96e7a5480000000, macaddressとコントローラー番号を返す
43
+ # 2. Sends handshaking packets over UART to the Joy-Con or Pro Controller Broadcom chip. This command can only be called once per session.
44
+ s.add([["8002"]], read_from: :switch)
45
+ s.add([/^8102/], read_from: :procon)
46
+ # 3
47
+ s.add([/^0100/], read_from: :switch)
48
+ s.add([/^21/], read_from: :procon)
49
+ # 4. Forces the Joy-Con or Pro Controller to only talk over USB HID without any timeouts. This is required for the Pro Controller to not time out and revert to Bluetooth.
50
+ s.add([["8004"]], read_from: :switch)
51
+ s.drain_all
52
+ return [s.switch, s.procon]
53
+ end
54
+
55
+ def initialize(throw_error_if_timeout: false, throw_error_if_mismatch: false , enable_at_exit: true)
56
+ @stack = []
57
+ @initialized_devices = false
58
+ @throw_error_if_timeout = throw_error_if_timeout
59
+ @throw_error_if_mismatch = throw_error_if_mismatch
60
+ @enable_at_exit = enable_at_exit
61
+ end
62
+
63
+ def add(values, read_from: )
64
+ @stack << Value.new(values: values, read_from: read_from)
65
+ end
66
+
67
+ def drain_all
68
+ unless @initialized_devices
69
+ init_devices
70
+ end
71
+
72
+ while(item = @stack.shift)
73
+ item.values.each do |value|
74
+ data = nil
75
+ timer = ProconBypassMan::Timer.new
76
+ begin
77
+ timer.throw_if_timeout!
78
+ data = from_device(item).read_nonblock(128)
79
+ rescue IO::EAGAINWaitReadable
80
+ retry
81
+ end
82
+
83
+ result =
84
+ case value
85
+ when String, Array
86
+ value == data.unpack("H*")
87
+ when Regexp
88
+ value =~ data.unpack("H*").first
89
+ else
90
+ raise "#{value}は知りません"
91
+ end
92
+ if result
93
+ ProconBypassMan.logger.info "OK(expected: #{value}, got: #{data.unpack("H*")})"
94
+ else
95
+ ProconBypassMan.logger.info "NG(expected: #{value}, got: #{data.unpack("H*")})"
96
+ raise BytesMismatchError if @throw_error_if_mismatch
97
+ end
98
+ to_device(item).write_nonblock(data)
99
+ end
100
+ end
101
+ rescue ProconBypassMan::Timer::Timeout
102
+ ProconBypassMan.logger.error "timeoutになりました"
103
+ raise if @throw_error_if_timeout
104
+ end
105
+
106
+ # switchに任意の命令を入力して、switchから読み取る
107
+ def write_switch(data, only_write: false)
108
+ if data.encoding.name == "UTF-8"
109
+ data = [data].pack("H*")
110
+ end
111
+ unless @initialized_devices
112
+ init_devices
113
+ end
114
+
115
+ timer = ProconBypassMan::Timer.new
116
+ data = nil
117
+ begin
118
+ timer.throw_if_timeout!
119
+ switch.write_nonblock(data)
120
+ rescue IO::EAGAINWaitReadable
121
+ retry
122
+ rescue ProconBypassMan::Timer::Timeout
123
+ ProconBypassMan.logger.error "writeでtimeoutになりました"
124
+ raise
125
+ end
126
+ return(data.unpack("H*")) if only_write
127
+
128
+ timer = ProconBypassMan::Timer.new
129
+ begin
130
+ timer.throw_if_timeout!
131
+ data = switch.read_nonblock(128)
132
+ ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
133
+ rescue IO::EAGAINWaitReadable
134
+ retry
135
+ rescue ProconBypassMan::Timer::Timeout
136
+ ProconBypassMan.logger.error "readでtimeoutになりました"
137
+ raise
138
+ end
139
+ rescue ProconBypassMan::Timer::Timeout
140
+ raise if @throw_error_if_timeout
141
+ end
142
+
143
+ def write_procon(data, only_write: false)
144
+ if data.encoding.name == "UTF-8"
145
+ data = [data].pack("H*")
146
+ end
147
+ unless @initialized_devices
148
+ init_devices
149
+ end
150
+
151
+ timer = ProconBypassMan::Timer.new
152
+ begin
153
+ timer.throw_if_timeout!
154
+ procon.write_nonblock(data)
155
+ rescue IO::EAGAINWaitReadable
156
+ retry
157
+ rescue ProconBypassMan::Timer::Timeout
158
+ ProconBypassMan.logger.error "writeでtimeoutになりました"
159
+ raise
160
+ end
161
+ return(data.unpack("H*")) if only_write
162
+
163
+ timer = ProconBypassMan::Timer.new
164
+ begin
165
+ timer.throw_if_timeout!
166
+ data = procon.read_nonblock(128)
167
+ ProconBypassMan.logger.error " <<< #{data.unpack("H*")})"
168
+ rescue IO::EAGAINWaitReadable
169
+ retry
170
+ rescue ProconBypassMan::Timer::Timeout
171
+ ProconBypassMan.logger.error "readでtimeoutになりました"
172
+ raise
173
+ end
174
+ rescue ProconBypassMan::Timer::Timeout
175
+ raise if @throw_error_if_timeout
176
+ end
177
+
178
+ def read_procon(only_read: false)
179
+ unless @initialized_devices
180
+ init_devices
181
+ end
182
+
183
+ data = nil
184
+ timer = ProconBypassMan::Timer.new
185
+ begin
186
+ timer.throw_if_timeout!
187
+ data = procon.read_nonblock(128)
188
+ ProconBypassMan.logger.debug { " <<< #{data.unpack("H*")})" }
189
+ rescue IO::EAGAINWaitReadable
190
+ retry
191
+ rescue ProconBypassMan::Timer::Timeout
192
+ ProconBypassMan.logger.error "readでtimeoutになりました"
193
+ raise
194
+ end
195
+ return(data.unpack("H*")) if only_read
196
+
197
+ timer = ProconBypassMan::Timer.new
198
+ begin
199
+ timer.throw_if_timeout!
200
+ switch.write_nonblock(data)
201
+ rescue IO::EAGAINWaitReadable
202
+ retry
203
+ rescue ProconBypassMan::Timer::Timeout
204
+ ProconBypassMan.logger.error "writeでtimeoutになりました"
205
+ raise
206
+ end
207
+ rescue ProconBypassMan::Timer::Timeout
208
+ raise if @throw_error_if_timeout
209
+ end
210
+
211
+ def read_switch(only_read: false)
212
+ unless @initialized_devices
213
+ init_devices
214
+ end
215
+
216
+ data = nil
217
+ timer = ProconBypassMan::Timer.new
218
+ begin
219
+ timer.throw_if_timeout!
220
+ data = switch.read_nonblock(128)
221
+ ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
222
+ rescue IO::EAGAINWaitReadable
223
+ retry
224
+ rescue ProconBypassMan::Timer::Timeout
225
+ ProconBypassMan.logger.error "readでtimeoutになりました"
226
+ raise
227
+ end
228
+ return(data.unpack("H*")) if only_read
229
+
230
+ timer = ProconBypassMan::Timer.new
231
+ begin
232
+ timer.throw_if_timeout!
233
+ procon.write_nonblock(data)
234
+ rescue IO::EAGAINWaitReadable
235
+ retry
236
+ rescue ProconBypassMan::Timer::Timeout
237
+ ProconBypassMan.logger.error "writeでtimeoutになりました"
238
+ raise
239
+ end
240
+ rescue ProconBypassMan::Timer::Timeout
241
+ raise if @throw_error_if_timeout
242
+ end
243
+
244
+ def from_device(item)
245
+ case item.read_from
246
+ when :switch
247
+ switch
248
+ when :procon
249
+ procon
250
+ else
251
+ raise
252
+ end
253
+ end
254
+
255
+ # fromの対になる
256
+ def to_device(item)
257
+ case item.read_from
258
+ when :switch
259
+ procon
260
+ when :procon
261
+ switch
262
+ else
263
+ raise
264
+ end
265
+ end
266
+
267
+ def switch
268
+ @gadget
269
+ end
270
+
271
+ def procon
272
+ @procon
273
+ end
274
+
275
+ def is_available_device?(path)
276
+ return false if !File.exist?(path)
277
+
278
+ system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
279
+ system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')
280
+ sleep 0.5
281
+
282
+ file = File.open(path, "w+")
283
+ begin
284
+ file.read_nonblock(128)
285
+ rescue EOFError
286
+ file.close
287
+ return false
288
+ rescue IO::EAGAINWaitReadable
289
+ file.close
290
+ return true
291
+ end
292
+ end
293
+
294
+ def to_bin(string)
295
+ string.unpack "H*"
296
+ end
297
+
298
+ def init_devices
299
+ if @initialized_devices
300
+ return
301
+ end
302
+
303
+ case
304
+ when is_available_device?(PROCON_PATH)
305
+ ProconBypassMan.logger.info "proconのデバイスファイルは#{PROCON_PATH}を使います"
306
+ @procon = File.open(PROCON_PATH, "w+")
307
+ @gadget = File.open('/dev/hidg0', "w+")
308
+ when is_available_device?(PROCON2_PATH)
309
+ ProconBypassMan.logger.info "proconのデバイスファイルは#{PROCON2_PATH}を使います"
310
+ @procon = File.open(PROCON2_PATH, "w+")
311
+ @gadget = File.open('/dev/hidg0', "w+")
312
+ else
313
+ raise "/dev/hidraw0, /dev/hidraw1の両方見つかりませんでした"
314
+ end
315
+ system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
316
+ system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')
317
+ sleep 0.5
318
+
319
+ @initialized_devices = true
320
+
321
+ if @enable_at_exit
322
+ at_exit do
323
+ @procon&.close
324
+ @gadget&.close
325
+ end
326
+ end
327
+ rescue Errno::ENXIO => e
328
+ # /dev/hidg0 をopenできないときがある
329
+ ProconBypassMan.logger.error "Errno::ENXIO (No such device or address @ rb_sysopen - /dev/hidg0)が起きました。resetします"
330
+ ProconBypassMan.logger.error e
331
+ system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
332
+ system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')
333
+ sleep 2
334
+ retry
335
+ end
336
+ end
@@ -24,7 +24,7 @@ class ProconBypassMan::Procon::ButtonCollection
24
24
  3 => [:zr, :r, :sr, :sl, :a, :b, :x, :y],
25
25
  4 => [:grip, :_undefined_key, :cap, :home, :thumbl, :thumbr, :plus, :minus],
26
26
  5 => [:zl, :l, :sl, :sr, :left, :right, :up, :down],
27
- }
27
+ }.freeze
28
28
 
29
29
  BUTTONS_MAP = BYTES_MAP.reduce({}) { |acc, value|
30
30
  next acc if value[1].nil?
@@ -32,7 +32,8 @@ class ProconBypassMan::Procon::ButtonCollection
32
32
  acc[button] = { byte_position: value[0], bit_position: index }
33
33
  end
34
34
  acc
35
- }
35
+ }.freeze
36
+ BUTTONS = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP.keys.freeze
36
37
 
37
38
  def self.load(button_key)
38
39
  Button.new(button_key)
@@ -13,7 +13,7 @@ module ProconBypassMan::Procon::PushedButtonHelper
13
13
  @@compiled = false
14
14
  def compile_if_not_compile_yet!
15
15
  unless @@compiled
16
- ::ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP.each do |button, value|
16
+ ::ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP.each do |button, _value|
17
17
  define_method "pressed_#{button}?" do
18
18
  pressed_button?(button)
19
19
  end
@@ -1,4 +1,5 @@
1
1
  class ProconBypassMan::Procon
2
+ require "procon_bypass_man/procon/data"
2
3
  require "procon_bypass_man/procon/mode_registry"
3
4
  require "procon_bypass_man/procon/macro_registry"
4
5
  require "procon_bypass_man/procon/layer_changeable"
@@ -9,7 +10,7 @@ class ProconBypassMan::Procon
9
10
 
10
11
  attr_accessor :user_operation
11
12
 
12
- def self.reset_cvar!
13
+ def self.reset!
13
14
  @@status = {
14
15
  buttons: {},
15
16
  current_layer_key: :up,
@@ -17,7 +18,6 @@ class ProconBypassMan::Procon
17
18
  ongoing_mode: ModeRegistry.load(:manual),
18
19
  }
19
20
  end
20
- def self.reset!; reset_cvar!; end
21
21
  reset!
22
22
 
23
23
  def initialize(binary)
@@ -106,18 +106,20 @@ class ProconBypassMan::Procon
106
106
  if !status[button]
107
107
  user_operation.unpress_button(button)
108
108
  end
109
- if options[:force_neutral] && user_operation.pressed_button?(options[:force_neutral])
110
- button = options[:force_neutral]
111
- user_operation.unpress_button(button)
109
+
110
+ options[:force_neutral]&.each do |force_neutral_button|
111
+ user_operation.pressed_button?(force_neutral_button) && user_operation.unpress_button(force_neutral_button)
112
112
  end
113
113
  end
114
114
  end
115
115
 
116
- current_layer.remaps.each do |from_button, to_button|
116
+ current_layer.remaps.each do |from_button, to_buttons|
117
117
  if user_operation.pressed_button?(from_button)
118
118
  user_operation.unpress_button(from_button)
119
119
  # TODO 2重でpressしないようにしたい
120
- user_operation.press_button(to_button) unless user_operation.pressed_button?(to_button)
120
+ to_buttons[:to].each do |to_button|
121
+ user_operation.press_button(to_button) unless user_operation.pressed_button?(to_button)
122
+ end
121
123
  end
122
124
  end
123
125
 
@@ -1,12 +1,10 @@
1
1
  require_relative "io_monitor"
2
+ require_relative "uptime"
2
3
 
3
4
  class ProconBypassMan::Runner
4
5
  class InterruptForRestart < StandardError; end
5
6
 
6
- def initialize(gadget: , procon: )
7
- @gadget = gadget
8
- @procon = procon
9
-
7
+ def initialize
10
8
  $will_interval_0_0_0_5 = 0
11
9
  $will_interval_1_6 = 0
12
10
  end
@@ -31,7 +29,7 @@ class ProconBypassMan::Runner
31
29
  main_loop_pid = fork { main_loop }
32
30
 
33
31
  begin
34
- while readable_io = IO.select([self_read])
32
+ while(readable_io = IO.select([self_read]))
35
33
  signal = readable_io.first[0].gets.strip
36
34
  handle_signal(signal)
37
35
  end
@@ -54,6 +52,7 @@ class ProconBypassMan::Runner
54
52
  @gadget&.close
55
53
  @procon&.close
56
54
  FileUtils.rm_rf(ProconBypassMan.pid_path)
55
+ FileUtils.rm_rf(ProconBypassMan.digest_path)
57
56
  exit 1
58
57
  end
59
58
  end
@@ -98,8 +97,11 @@ class ProconBypassMan::Runner
98
97
  loop do
99
98
  break if $will_terminate_token
100
99
  bypass.send_procon_to_gadget!
100
+ rescue EOFError => e
101
+ ProconBypassMan.logger.error "Proconと通信ができませんでした.終了処理を開始します"
102
+ Process.kill "TERM", Process.ppid
101
103
  rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
102
- ProconBypassMan.logger.error "Proconが切断されました.終了処理を開始します"
104
+ ProconBypassMan.logger.error "Proconが切断されました。終了処理を開始します"
103
105
  Process.kill "TERM", Process.ppid
104
106
  end
105
107
  ProconBypassMan.logger.info "Thread2を終了します"
@@ -119,7 +121,7 @@ class ProconBypassMan::Runner
119
121
 
120
122
  ProconBypassMan.logger.info "子プロセスでgraceful shutdownの準備ができました"
121
123
  begin
122
- while readable_io = IO.select([self_read])
124
+ while(readable_io = IO.select([self_read]))
123
125
  signal = readable_io.first[0].gets.strip
124
126
  handle_signal(signal)
125
127
  end
@@ -133,38 +135,12 @@ class ProconBypassMan::Runner
133
135
  end
134
136
 
135
137
  def first_negotiation
136
- loop do
137
- begin
138
- input = @gadget.read_nonblock(128)
139
- ProconBypassMan.logger.debug { ">>> #{input.unpack("H*")}" }
140
- @procon.write_nonblock(input)
141
- if input[0] == "\x80".b && input[1] == "\x01".b
142
- ProconBypassMan.logger.info("first negotiation is over")
143
- break
144
- end
145
- break if $will_terminate_token
146
- rescue IO::EAGAINWaitReadable
147
- end
148
- end
149
-
150
- # ...
151
- # switch) 8001
152
- # procon) 8101
153
- # switch) 8002
154
- # が返ってくるプロトコルがあって、これができていないならやり直す
155
- loop do
156
- begin
157
- data = @procon.read_nonblock(128)
158
- if data[0] == "\x81".b && data[1] == "\x01".b
159
- ProconBypassMan.logger.debug { "接続を確認しました" }
160
- @gadget.write_nonblock(data)
161
- break
162
- else
163
- raise ::ProconBypassMan::FirstConnectionError
164
- end
165
- rescue IO::EAGAINWaitReadable
166
- end
167
- end
138
+ @gadget, @procon = ProconBypassMan::DeviceConnector.connect
139
+ rescue ProconBypassMan::Timer::Timeout
140
+ ::ProconBypassMan.logger.error "デバイスとの通信でタイムアウトが起きて接続ができませんでした。"
141
+ @gadget&.close
142
+ @procon&.close
143
+ raise ::ProconBypassMan::EternalConnectionError
168
144
  end
169
145
 
170
146
  def handle_signal(sig)
@@ -187,6 +163,7 @@ class ProconBypassMan::Runner
187
163
  root: #{ProconBypassMan.root}
188
164
  pid_path: #{ProconBypassMan.pid_path}
189
165
  setting_path: #{ProconBypassMan::Configuration.instance.setting_path}
166
+ uptime from boot: #{ProconBypassMan::Uptime.from_boot} sec
190
167
  ----
191
168
  EOF
192
169
  ProconBypassMan.logger.info(booted_message)
@@ -0,0 +1,14 @@
1
+ module ProconBypassMan
2
+ class Timer
3
+ class Timeout < StandardError; end
4
+
5
+ # 5秒後がタイムアウト
6
+ def initialize(timeout: Time.now + 5)
7
+ @timeout = timeout
8
+ end
9
+
10
+ def throw_if_timeout!
11
+ raise Timeout if @timeout < Time.now
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ require "time"
2
+
3
+ module ProconBypassMan
4
+ class Uptime
5
+ def self.from_boot
6
+ boot_time = Time.parse(`uptime -s`.chomp).to_i
7
+ return Time.now.to_i - boot_time.to_i
8
+ rescue => e
9
+ ProconBypassMan.logger.error(e)
10
+ return "error!"
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProconBypassMan
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.8"
5
5
  end
@@ -3,21 +3,27 @@ require 'yaml'
3
3
  require "fileutils"
4
4
 
5
5
  require_relative "procon_bypass_man/version"
6
- require_relative "procon_bypass_man/device_registry"
6
+ require_relative "procon_bypass_man/timer"
7
7
  require_relative "procon_bypass_man/bypass"
8
+ require_relative "procon_bypass_man/device_connector"
8
9
  require_relative "procon_bypass_man/runner"
9
10
  require_relative "procon_bypass_man/processor"
10
- require_relative "procon_bypass_man/procon/data"
11
11
  require_relative "procon_bypass_man/configuration"
12
12
  require_relative "procon_bypass_man/procon"
13
13
 
14
14
  STDOUT.sync = true
15
15
  Thread.abort_on_exception = true
16
16
 
17
+ # new feature from ruby3.0's
18
+ if GC.respond_to?(:auto_compact)
19
+ GC.auto_compact = true
20
+ end
21
+
17
22
  module ProconBypassMan
18
23
  class ProConRejected < StandardError; end
19
24
  class CouldNotLoadConfigError < StandardError; end
20
25
  class FirstConnectionError < StandardError; end
26
+ class EternalConnectionError < StandardError; end
21
27
 
22
28
  def self.configure(setting_path: nil, &block)
23
29
  unless setting_path
@@ -34,13 +40,18 @@ module ProconBypassMan
34
40
  def self.run(setting_path: nil, &block)
35
41
  configure(setting_path: setting_path, &block)
36
42
  File.write(pid_path, $$)
37
- registry = ProconBypassMan::DeviceRegistry.new
38
- Runner.new(gadget: registry.gadget, procon: registry.procon).run
43
+ Runner.new.run
39
44
  rescue CouldNotLoadConfigError
40
45
  ProconBypassMan.logger.error "設定ファイルが不正です。設定ファイルの読み込みに失敗しました"
41
46
  puts "設定ファイルが不正です。設定ファイルの読み込みに失敗しました"
42
47
  FileUtils.rm_rf(ProconBypassMan.pid_path)
48
+ FileUtils.rm_rf(ProconBypassMan.digest_path)
43
49
  exit 1
50
+ rescue EternalConnectionError
51
+ ProconBypassMan.logger.error "接続の見込みがないのでsleepしまくります"
52
+ puts "接続の見込みがないのでsleepしまくります"
53
+ FileUtils.rm_rf(ProconBypassMan.pid_path)
54
+ sleep(999999999)
44
55
  rescue FirstConnectionError
45
56
  puts "接続を確立できませんでした。やりなおします。"
46
57
  retry
@@ -81,4 +92,8 @@ module ProconBypassMan
81
92
  def self.root=(path)
82
93
  @@root = path
83
94
  end
95
+
96
+ def self.digest_path
97
+ "#{root}/.setting_yaml_digest"
98
+ end
84
99
  end
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = "extension for Nintendo Switch Pro Controller"
12
12
  spec.description = spec.summary
13
- spec.homepage = "https://github.com/splaspla-hacker/procon_bypass_man"
13
+ spec.homepage = "https://github.com/splaplapla/procon_bypass_man"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
16
16
 
@@ -0,0 +1,17 @@
1
+ # Project Template
2
+ https://github.com/splaplapla/pbmenv で使っているファイルです
3
+
4
+ ## systemd
5
+ * sudo ln -s /usr/share/pbm/current/systemd_units/pbm.service /etc/systemd/system/pbm.service
6
+ * commands
7
+ * systemctl daemon-reload
8
+ * systemctl enable pbm.service
9
+ * systemctl disable pbm.service
10
+ * systemctl start pbm.service
11
+ * systemctl status pbm.service
12
+ * systemctl restart pbm.service
13
+ * systemctl list-unit-files --type=service
14
+
15
+ ### ログ
16
+ * journalctl -xe -f
17
+
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
8
+ gem 'procon_bypass_man', '0.1.8'
9
+ gem 'procon_bypass_man-splatoon2', github: 'splaplapla/procon_bypass_man-splatoon2', tag: "0.1.1"
10
+ end
11
+
12
+ ProconBypassMan.tap do |pbm|
13
+ pbm.root = File.expand_path(__dir__)
14
+ pbm.logger = Logger.new("#{ProconBypassMan.root}/app.log", 5, 1024 * 1024 * 10)
15
+ pbm.logger.level = :debug
16
+ end
17
+
18
+ ProconBypassMan.run(setting_path: "/usr/share/pbm/current/setting.yml")