procon_bypass_man 0.1.23 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/gitleacks.yml +11 -0
  3. data/CHANGELOG.md +10 -0
  4. data/Gemfile.lock +1 -1
  5. data/docs/setup_raspi.md +0 -1
  6. data/lib/procon_bypass_man/buttons_setting_configuration/loader.rb +1 -1
  7. data/lib/procon_bypass_man/{commands → bypass}/bypass_command.rb +11 -19
  8. data/lib/procon_bypass_man/bypass.rb +6 -9
  9. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +1 -2
  10. data/lib/procon_bypass_man/commands/send_error_command.rb +2 -2
  11. data/lib/procon_bypass_man/commands.rb +0 -3
  12. data/lib/procon_bypass_man/configuration.rb +21 -2
  13. data/lib/procon_bypass_man/device_connection/command.rb +28 -0
  14. data/lib/procon_bypass_man/{device_connector.rb → device_connection/executor.rb} +51 -38
  15. data/lib/procon_bypass_man/device_connection/output_report_generator.rb +42 -0
  16. data/lib/procon_bypass_man/device_connection/output_report_markerable.rb +28 -0
  17. data/lib/procon_bypass_man/device_connection/output_report_sub_command_table.rb +133 -0
  18. data/lib/procon_bypass_man/device_connection/output_report_watcher.rb +41 -0
  19. data/lib/procon_bypass_man/device_connection/pre_bypass.rb +67 -0
  20. data/lib/procon_bypass_man/device_connection/procon_setting_overrider.rb +78 -0
  21. data/lib/procon_bypass_man/device_connection/spoofing_output_report_watcher.rb +39 -0
  22. data/lib/procon_bypass_man/device_connection.rb +16 -0
  23. data/lib/procon_bypass_man/device_model.rb +17 -0
  24. data/lib/procon_bypass_man/io_monitor.rb +20 -1
  25. data/lib/procon_bypass_man/procon/macro_builder.rb +5 -3
  26. data/lib/procon_bypass_man/{commands → remote_pbm_action/commands}/run_remote_pbm_action_dispatch_command.rb +0 -0
  27. data/lib/procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb +7 -1
  28. data/lib/procon_bypass_man/remote_pbm_action.rb +1 -0
  29. data/lib/procon_bypass_man/runner.rb +3 -7
  30. data/lib/procon_bypass_man/support/never_exit_accidentally.rb +3 -3
  31. data/lib/procon_bypass_man/support/usb_device_controller.rb +2 -2
  32. data/lib/procon_bypass_man/support/yaml_loader.rb +12 -0
  33. data/lib/procon_bypass_man/version.rb +1 -1
  34. data/lib/procon_bypass_man/websocket/client.rb +1 -4
  35. data/lib/procon_bypass_man.rb +65 -41
  36. data/project_template/app.rb +7 -1
  37. data/sig/main.rbs +3 -3
  38. metadata +17 -6
  39. data/lib/procon_bypass_man/commands/connect_device_command.rb +0 -18
@@ -0,0 +1,41 @@
1
+ class ProconBypassMan::DeviceConnection::OutputReportWatcher
2
+ include ProconBypassMan::DeviceConnection::OutputReportMarkerable
3
+
4
+ def initialize
5
+ @hid_sub_command_request_table = ProconBypassMan::DeviceConnection::OutputReportSubCommandTable.new
6
+ @timer = ProconBypassMan::SafeTimeout.new
7
+ end
8
+
9
+ # @param [String] sub_command
10
+ # @param [String] sub_command_arg
11
+ # @return [Boolean]
12
+ def sent?(sub_command: , sub_command_arg: )
13
+ @hid_sub_command_request_table.has_key?(sub_command: sub_command, sub_command_arg: sub_command_arg)
14
+ end
15
+
16
+ # @param [String] sub_command
17
+ # @param [String] sub_command_arg
18
+ # @return [Boolean]
19
+ def received?(sub_command: , sub_command_arg: )
20
+ @hid_sub_command_request_table.has_value?(sub_command: sub_command, sub_command_arg: sub_command_arg)
21
+ end
22
+
23
+ # @return [Boolean]
24
+ def completed?
25
+ @hid_sub_command_request_table.completed?
26
+ end
27
+
28
+ # @return [Boolean]
29
+ # @raise [Timeout::Error]
30
+ def timeout_or_completed?
31
+ if @timer.timeout?
32
+ ProconBypassMan::SendErrorCommand.execute(error: "[pre_bypass] pre_bypassフェーズがタイムアウトしました")
33
+ return true
34
+ end
35
+
36
+ if completed?
37
+ ProconBypassMan.logger.info "[pre_bypass] pre_bypassフェーズが想定通り終了しました"
38
+ return true
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,67 @@
1
+ class ProconBypassMan::DeviceConnection::PreBypass
2
+ attr_accessor :gadget, :procon, :output_report_watcher
3
+
4
+ def initialize(gadget: , procon: )
5
+ self.gadget = ProconBypassMan::DeviceModel.new(gadget)
6
+ self.procon = ProconBypassMan::DeviceModel.new(procon)
7
+ self.output_report_watcher = ProconBypassMan::DeviceConnection::OutputReportWatcher.new
8
+ end
9
+
10
+ # @return [void]
11
+ def execute!
12
+ loop do
13
+ run_once
14
+
15
+ if output_report_watcher.timeout_or_completed?
16
+ break
17
+ end
18
+ end
19
+ end
20
+
21
+ # @return [void]
22
+ def run_once
23
+ begin
24
+ raw_data = non_blocking_read_switch
25
+ output_report_watcher.mark_as_send(raw_data)
26
+ ProconBypassMan.logger.info "[pre_bypass] >>> #{raw_data.unpack("H*").first}"
27
+ send_procon(raw_data)
28
+ rescue IO::EAGAINWaitReadable
29
+ # no-op
30
+ end
31
+
32
+ 3.times do
33
+ begin
34
+ raw_data = non_blocking_read_procon
35
+ output_report_watcher.mark_as_receive(raw_data)
36
+ ProconBypassMan.logger.info "[pre_bypass] <<< #{raw_data.unpack("H*").first}"
37
+ send_switch(raw_data)
38
+ rescue IO::EAGAINWaitReadable
39
+ # no-op
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ # @raise [IO::EAGAINWaitReadable]
47
+ # @return [String]
48
+ def non_blocking_read_switch
49
+ gadget.non_blocking_read
50
+ end
51
+
52
+ # @raise [IO::EAGAINWaitReadable]
53
+ # @return [String]
54
+ def non_blocking_read_procon
55
+ procon.non_blocking_read
56
+ end
57
+
58
+ # @return [void]
59
+ def send_procon(raw_data)
60
+ procon.send(raw_data)
61
+ end
62
+
63
+ # @return [void]
64
+ def send_switch(raw_data)
65
+ gadget.send(raw_data)
66
+ end
67
+ end
@@ -0,0 +1,78 @@
1
+ class ProconBypassMan::DeviceConnection::ProconSettingOverrider
2
+ attr_accessor :procon, :output_report_watcher, :output_report_generator
3
+
4
+ SUB_COMMAND_HOME_LED_ON = "38"
5
+ SUB_COMMAND_ARG_HOME_LED_ON = "1FF0FF"
6
+ SPECIAL_SUB_COMMAND_ARGS = {
7
+ SUB_COMMAND_HOME_LED_ON => SUB_COMMAND_ARG_HOME_LED_ON,
8
+ }
9
+ SETTING_HOME_LED_ON = { home_led_on: [SUB_COMMAND_HOME_LED_ON, SUB_COMMAND_ARG_HOME_LED_ON] }
10
+ ALL_SETTINGS = SETTING_HOME_LED_ON
11
+
12
+ def initialize(procon: )
13
+ use_steps = {}
14
+ if ProconBypassMan.config.enable_home_led_on_connect
15
+ use_steps.merge!(SETTING_HOME_LED_ON)
16
+ end
17
+
18
+ @setting_steps = use_steps.keys
19
+ self.procon = ProconBypassMan::DeviceModel.new(procon)
20
+ self.output_report_watcher = ProconBypassMan::DeviceConnection::SpoofingOutputReportWatcher.new(expected_sub_commands: use_steps.values)
21
+ self.output_report_generator = ProconBypassMan::DeviceConnection::OutputReportGenerator.new
22
+ end
23
+
24
+ def execute!
25
+ loop do
26
+ run_once
27
+
28
+ if output_report_watcher.timeout_or_completed?
29
+ break
30
+ end
31
+ end
32
+ end
33
+
34
+ def run_once
35
+ begin
36
+ raw_data = non_blocking_read_procon
37
+ rescue IO::EAGAINWaitReadable
38
+ return
39
+ end
40
+
41
+ ProconBypassMan.logger.info "[procon_setting_overrider] <<< #{raw_data.unpack("H*").first}"
42
+ output_report_watcher.mark_as_receive(raw_data)
43
+ if output_report_watcher.has_unreceived_command?
44
+ re_override_setting_by_cmd(output_report_watcher.unreceived_sub_command_with_arg)
45
+ else
46
+ if(setting_step = @setting_steps.shift)
47
+ override_setting_by_step(setting_step)
48
+ else
49
+ return
50
+ end
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ # @return [void]
57
+ def override_setting_by_step(setting_step)
58
+ raw_data = output_report_generator.generate_by_step(setting_step)
59
+ ProconBypassMan.logger.info "[procon_setting_overrider] >>> #{raw_data.unpack("H*").first}"
60
+ output_report_watcher.mark_as_send(raw_data)
61
+ send_procon(raw_data)
62
+ end
63
+
64
+ # @return [void]
65
+ def re_override_setting_by_cmd(sub_command_with_arg)
66
+ raw_data = output_report_generator.generate_by_sub_command_with_arg(sub_command_with_arg)
67
+ ProconBypassMan.logger.info "[procon_setting_overrider] >>> #{raw_data.unpack("H*").first}"
68
+ send_procon(raw_data)
69
+ end
70
+
71
+ def non_blocking_read_procon
72
+ procon.non_blocking_read
73
+ end
74
+
75
+ def send_procon(raw_data)
76
+ procon.send(raw_data)
77
+ end
78
+ end
@@ -0,0 +1,39 @@
1
+ class ProconBypassMan::DeviceConnection::SpoofingOutputReportWatcher
2
+ include ProconBypassMan::DeviceConnection::OutputReportMarkerable
3
+
4
+ def initialize(expected_sub_commands: )
5
+ @timer = ProconBypassMan::SafeTimeout.new
6
+ @hid_sub_command_request_table = ProconBypassMan::DeviceConnection::OutputReportSubCommandTable.new
7
+ @expected_sub_commands = expected_sub_commands
8
+ end
9
+
10
+ # @return [Boolean]
11
+ def has_unreceived_command?
12
+ @hid_sub_command_request_table.has_unreceived_command?
13
+ end
14
+
15
+ # @return [String, NilClass]
16
+ def unreceived_sub_command_with_arg
17
+ @hid_sub_command_request_table.unreceived_sub_command_with_arg
18
+ end
19
+
20
+ # @return [Boolean]
21
+ def completed?
22
+ @expected_sub_commands.all? do |sub_command, sub_command_arg|
23
+ @hid_sub_command_request_table.has_value?(sub_command: sub_command, sub_command_arg: sub_command_arg)
24
+ end
25
+ end
26
+
27
+ # @return [Boolean]
28
+ def timeout_or_completed?
29
+ if @timer.timeout?
30
+ ProconBypassMan.logger.info "[procon setting override] プロコンの設定上書き処理がタイムアウトしました"
31
+ return true
32
+ end
33
+
34
+ if completed?
35
+ ProconBypassMan.logger.info "[procon setting override] プロコンの設定上書き処理が想定通り終了しました"
36
+ return true
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,16 @@
1
+ module ProconBypassMan::DeviceConnection
2
+ class BytesMismatchError < StandardError; end
3
+ class NotFoundProconError < StandardError; end
4
+ class TimeoutErrorInConditionalRoute < StandardError; end
5
+ class TimeoutError < StandardError; end
6
+ end
7
+
8
+ require_relative "device_connection/executor"
9
+ require_relative "device_connection/pre_bypass"
10
+ require_relative "device_connection/command"
11
+ require_relative "device_connection/output_report_markerable"
12
+ require_relative "device_connection/procon_setting_overrider"
13
+ require_relative "device_connection/output_report_generator"
14
+ require_relative "device_connection/output_report_sub_command_table"
15
+ require_relative "device_connection/spoofing_output_report_watcher"
16
+ require_relative "device_connection/output_report_watcher"
@@ -0,0 +1,17 @@
1
+ class ProconBypassMan::DeviceModel
2
+ # @param [File] device
3
+ def initialize(device)
4
+ @device = device
5
+ end
6
+
7
+ # @param [String] raw_data
8
+ def send(raw_data)
9
+ @device.write_nonblock(raw_data)
10
+ end
11
+
12
+ # @raise [IO::EAGAINWaitReadable]
13
+ # @return [String]
14
+ def non_blocking_read
15
+ @device.read_nonblock(64)
16
+ end
17
+ end
@@ -1,4 +1,15 @@
1
1
  module ProconBypassMan
2
+ class NullCounter
3
+ def initialize(label: )
4
+ end
5
+
6
+ def record(_)
7
+ end
8
+
9
+ def shutdown
10
+ end
11
+ end
12
+
2
13
  class Counter
3
14
  attr_accessor :label, :table, :previous_table, :active
4
15
 
@@ -40,7 +51,11 @@ module ProconBypassMan
40
51
  end
41
52
 
42
53
  module IOMonitor
54
+ @@thread = nil
55
+
43
56
  def self.new(label: )
57
+ return NullCounter.new(label: label) if not started?
58
+
44
59
  counter = Counter.new(label: label)
45
60
  @@list << counter
46
61
  counter
@@ -51,9 +66,13 @@ module ProconBypassMan
51
66
  @@list
52
67
  end
53
68
 
69
+ def self.started?
70
+ !!@@thread
71
+ end
72
+
54
73
  # ここで集計する
55
74
  def self.start!
56
- Thread.start do
75
+ @@thread = Thread.start do
57
76
  max_output_length = 0
58
77
  loop do
59
78
  list = @@list.select(&:active).dup
@@ -5,9 +5,11 @@ class ProconBypassMan::Procon::MacroBuilder
5
5
  return subjects.first.to_steps
6
6
  end
7
7
 
8
- base = subjects.first
9
- remain = subjects[1..-1]
10
- remain.map { |x| base.to_steps.zip(x.to_steps) }.first
8
+ subjects.inject([[], []]) do |acc, item|
9
+ acc[0] << item.to_steps[0]
10
+ acc[1] << item.to_steps[1]
11
+ acc
12
+ end
11
13
  end
12
14
  end
13
15
 
@@ -17,7 +17,8 @@ module ProconBypassMan
17
17
  path: ProconBypassMan::ButtonsSettingConfiguration.instance.setting_path,
18
18
  content: setting,
19
19
  )
20
- ProconBypassMan.hot_reload!
20
+
21
+ hot_reload!
21
22
  end
22
23
 
23
24
  private
@@ -29,6 +30,11 @@ module ProconBypassMan
29
30
  def after_action_callback
30
31
  be_processed
31
32
  end
33
+
34
+ # @return [void]
35
+ def hot_reload!
36
+ Process.kill(:USR2, ProconBypassMan.pid)
37
+ end
32
38
  end
33
39
  end
34
40
  end
@@ -6,6 +6,7 @@ module ProconBypassMan
6
6
  require "procon_bypass_man/remote_pbm_action/stop_pbm_action"
7
7
  require "procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb"
8
8
  require "procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command"
9
+ require "procon_bypass_man/remote_pbm_action/commands/run_remote_pbm_action_dispatch_command"
9
10
  require "procon_bypass_man/remote_pbm_action/value_objects/remote_pbm_action_object"
10
11
 
11
12
  ACTION_CHANGE_PBM_VERSION = "change_pbm_version"
@@ -8,8 +8,6 @@ class ProconBypassMan::Runner
8
8
  def initialize(gadget: , procon: )
9
9
  @gadget = gadget
10
10
  @procon = procon
11
-
12
- ProconBypassMan::PrintBootMessageCommand.execute
13
11
  end
14
12
 
15
13
  def run
@@ -41,9 +39,9 @@ class ProconBypassMan::Runner
41
39
  handle_signal(signal)
42
40
  end
43
41
  rescue InterruptForRestart
42
+ ProconBypassMan::PrintMessageCommand.execute(text: "設定ファイルの再読み込みを開始します")
44
43
  Process.kill("USR2", child_pid)
45
44
  Process.wait
46
- ProconBypassMan::PrintMessageCommand.execute(text: "Reloading config file")
47
45
  begin
48
46
  ProconBypassMan::ButtonsSettingConfiguration::Loader.reload_setting
49
47
  ProconBypassMan::SendReloadConfigEventCommand.execute
@@ -53,12 +51,10 @@ class ProconBypassMan::Runner
53
51
  end
54
52
  ProconBypassMan::PrintMessageCommand.execute(text: "バイパス処理を再開します")
55
53
  rescue Interrupt
54
+ puts
55
+ ProconBypassMan::PrintMessageCommand.execute(text: "処理を終了します")
56
56
  Process.kill("TERM", child_pid)
57
57
  Process.wait
58
- ProconBypassMan::PrintMessageCommand.execute(text: "処理を終了します")
59
- ProconBypassMan::UsbDeviceController.reset
60
- @gadget&.close
61
- @procon&.close
62
58
  break
63
59
  end
64
60
  end
@@ -1,11 +1,11 @@
1
1
  module ProconBypassMan
2
2
  module NeverExitAccidentally
3
- def exit_if_allow(status)
3
+ def self.exit_if_allow_at_config
4
4
  if ProconBypassMan.never_exit_accidentally
5
- eternal_sleep
5
+ ProconBypassMan.eternal_sleep
6
6
  else
7
7
  yield if block_given?
8
- exit(status)
8
+ exit 1
9
9
  end
10
10
  end
11
11
  end
@@ -1,13 +1,13 @@
1
1
  class ProconBypassMan::UsbDeviceController
2
2
  class << self
3
- def reset
3
+ def reset(cooldown: 0.5)
4
4
  [ "echo > /sys/kernel/config/usb_gadget/procon/UDC",
5
5
  "ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC",
6
6
  ].each do |shell|
7
7
  system shell
8
8
  ProconBypassMan.logger.debug { "[SHELL] #{shell}" }
9
9
  end
10
- sleep 0.5
10
+ sleep cooldown
11
11
  end
12
12
 
13
13
  def init
@@ -0,0 +1,12 @@
1
+ class ProconBypassMan::YamlLoader
2
+ # @param [String] path
3
+ # @return [Hash]
4
+ def self.load(path: )
5
+ YAML.load_file(path).tap do |y|
6
+ # 行末に空白があるとto_yamlしたときに改行コードがエスケープされてしまうのでstrip
7
+ y.transform_values do |v|
8
+ v.strip! if v.is_a?(String)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProconBypassMan
4
- VERSION = "0.1.23"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -23,8 +23,7 @@ module ProconBypassMan
23
23
  ProconBypassMan.logger.info('websocket client: successfully connected in ProconBypassMan::Websocket::Client')
24
24
  }
25
25
  client.subscribed { |msg|
26
- ProconBypassMan.logger.info('websocket client: subscribed')
27
- puts({ event: :subscribed, msg: msg })
26
+ ProconBypassMan.logger.info("websocket client: subscribed(#{msg})")
28
27
  ProconBypassMan::SyncDeviceStatsJob.perform(ProconBypassMan::DeviceStatus.current)
29
28
  }
30
29
 
@@ -39,13 +38,11 @@ module ProconBypassMan
39
38
 
40
39
  client.disconnected {
41
40
  ProconBypassMan.logger.info('websocket client: disconnected!!')
42
- puts :disconnected
43
41
  client.reconnect!
44
42
  sleep 2
45
43
  }
46
44
  client.errored { |msg|
47
45
  ProconBypassMan.logger.error("websocket client: errored!!, #{msg}")
48
- puts :errored
49
46
  client.reconnect!
50
47
  sleep 2
51
48
  }
@@ -14,11 +14,14 @@ require "pbmenv"
14
14
  require_relative "procon_bypass_man/version"
15
15
  require_relative "procon_bypass_man/remote_pbm_action"
16
16
  require_relative "procon_bypass_man/remote_macro"
17
+
18
+ require_relative "procon_bypass_man/device_connection"
17
19
  require_relative "procon_bypass_man/support/usb_device_controller"
18
20
  require_relative "procon_bypass_man/support/device_procon_finder"
19
21
  require_relative "procon_bypass_man/support/device_mouse_finder"
20
22
  require_relative "procon_bypass_man/support/signal_handler"
21
23
  require_relative "procon_bypass_man/support/callbacks"
24
+ require_relative "procon_bypass_man/support/yaml_loader"
22
25
  require_relative "procon_bypass_man/support/yaml_writer"
23
26
  require_relative "procon_bypass_man/support/safe_timeout"
24
27
  require_relative "procon_bypass_man/support/compress_array"
@@ -36,13 +39,13 @@ require_relative "procon_bypass_man/support/cycle_sleep"
36
39
  require_relative "procon_bypass_man/background"
37
40
  require_relative "procon_bypass_man/commands"
38
41
  require_relative "procon_bypass_man/bypass"
39
- require_relative "procon_bypass_man/device_connector"
40
42
  require_relative "procon_bypass_man/device_status"
41
43
  require_relative "procon_bypass_man/runner"
42
44
  require_relative "procon_bypass_man/processor"
43
45
  require_relative "procon_bypass_man/configuration"
44
46
  require_relative "procon_bypass_man/buttons_setting_configuration"
45
47
  require_relative "procon_bypass_man/procon"
48
+ require_relative "procon_bypass_man/device_model"
46
49
  require_relative "procon_bypass_man/procon/button"
47
50
  require_relative "procon_bypass_man/procon/analog_stick_cap"
48
51
  require_relative "procon_bypass_man/procon/analog_stick_manipulator"
@@ -61,52 +64,59 @@ module ProconBypassMan
61
64
  extend ProconBypassMan::NeverExitAccidentally
62
65
 
63
66
  class CouldNotLoadConfigError < StandardError; end
64
- class EternalConnectionError < StandardError; end
67
+ class NotFoundProconError < StandardError; end
65
68
 
66
69
  # @return [void]
67
70
  def self.run(setting_path: nil)
68
- ProconBypassMan::Scheduler.start!
69
- ProconBypassMan::Background::JobRunner.start!
70
- ProconBypassMan::Websocket::Client.start!
71
- ProconBypassMan::QueueOverProcess.start!
72
-
73
71
  ProconBypassMan::PrintMessageCommand.execute(text: "PBMを起動しています")
74
72
  initialize_pbm
75
- ProconBypassMan::ButtonsSettingConfiguration::Loader.load(setting_path: setting_path)
76
- gadget, procon = ProconBypassMan::ConnectDeviceCommand.execute!
77
- Runner.new(gadget: gadget, procon: procon).run # ここでblockingする
78
- FileUtils.rm_rf(ProconBypassMan.pid_path)
79
- FileUtils.rm_rf(ProconBypassMan.digest_path)
80
- ProconBypassMan::QueueOverProcess.shutdown
81
- rescue ProconBypassMan::CouldNotLoadConfigError
82
- ProconBypassMan::SendErrorCommand.execute(error: "設定ファイルが不正です。設定ファイルの読み込みに失敗しました")
83
- ProconBypassMan::DeviceStatus.change_to_setting_syntax_error_and_shutdown!
84
- # TODO シグナルトラップをしていないのでUSR2を送ったときにプロセスが停止している. 明示的にハンドリングするべき.
85
- ProconBypassMan.exit_if_allow(1) do
86
- FileUtils.rm_rf(ProconBypassMan.pid_path)
87
- FileUtils.rm_rf(ProconBypassMan.digest_path)
88
- ProconBypassMan::QueueOverProcess.shutdown
73
+
74
+ begin
75
+ ProconBypassMan::ButtonsSettingConfiguration::Loader.load(setting_path: setting_path)
76
+ rescue ProconBypassMan::CouldNotLoadConfigError
77
+ ProconBypassMan::SendErrorCommand.execute(error: "設定ファイルが不正です。設定ファイルの読み込みに失敗しました")
78
+ ProconBypassMan::DeviceStatus.change_to_setting_syntax_error_and_shutdown!
79
+ # TODO シグナルトラップをしていないのでUSR2を送ったときにプロセスが停止している. 明示的にハンドリングするべき.
80
+ ProconBypassMan::NeverExitAccidentally.exit_if_allow_at_config do
81
+ terminate_pbm
82
+ end
83
+ return
89
84
  end
90
- rescue ProconBypassMan::ConnectDeviceCommand::NotFoundProconError
91
- ProconBypassMan::SendErrorCommand.execute(error: "プロコンが見つかりませんでした。")
92
- ProconBypassMan::DeviceStatus.change_to_procon_not_found_error!
93
- # TODO シグナルトラップをしていないのでUSR2を送ったときにプロセスが停止している. 明示的にハンドリングするべき.
94
- ProconBypassMan.exit_if_allow(1) do
95
- FileUtils.rm_rf(ProconBypassMan.pid_path)
96
- FileUtils.rm_rf(ProconBypassMan.digest_path)
97
- ProconBypassMan::QueueOverProcess.shutdown
85
+
86
+ begin
87
+ gadget, procon = ProconBypassMan::DeviceConnection::Command.execute!
88
+ rescue ProconBypassMan::DeviceConnection::NotFoundProconError
89
+ ProconBypassMan::SendErrorCommand.execute(error: "プロコンが見つかりませんでした。")
90
+ ProconBypassMan::DeviceStatus.change_to_procon_not_found_error!
91
+ # TODO シグナルトラップをしていないので以下の状態に、USR2を送ったときにプロセスが停止してしまう
92
+ ProconBypassMan::NeverExitAccidentally.exit_if_allow_at_config do
93
+ terminate_pbm
94
+ end
95
+ return
96
+ rescue ProconBypassMan::DeviceConnection::TimeoutError
97
+ ProconBypassMan::SendErrorCommand.execute(error: "接続の見込みがないのでsleepしまくります")
98
+ ProconBypassMan::DeviceStatus.change_to_connected_but_sleeping!
99
+ %w(TERM INT).each do |sig|
100
+ Kernel.trap(sig) { exit 0 }
101
+ end
102
+ Kernel.trap :USR2 do
103
+ exit 0 # TODO retryする
104
+ end
105
+ eternal_sleep
106
+ return
98
107
  end
99
- rescue ProconBypassMan::EternalConnectionError
100
- ProconBypassMan::SendErrorCommand.execute(error: "接続の見込みがないのでsleepしまくります")
101
- ProconBypassMan::DeviceStatus.change_to_connected_but_sleeping!
102
- FileUtils.rm_rf(ProconBypassMan.pid_path)
103
- eternal_sleep
108
+
109
+ ready_pbm
110
+ Runner.new(gadget: gadget, procon: procon).run # ここでblockingする
111
+ terminate_pbm
104
112
  end
105
113
 
114
+ # 実行ファイル(app.rb)から呼び出している
115
+ # @return [void]
106
116
  def self.configure(&block)
107
117
  @@configuration = ProconBypassMan::Configuration.new
108
118
  @@configuration.instance_eval(&block)
109
- @@configuration
119
+ nil
110
120
  end
111
121
 
112
122
  # @return [ProconBypassMan::Configuration]
@@ -123,20 +133,34 @@ module ProconBypassMan
123
133
  ProconBypassMan::IOMonitor.reset!
124
134
  end
125
135
 
136
+ # @return [void]
126
137
  def self.initialize_pbm
138
+ ProconBypassMan::Scheduler.start!
139
+ ProconBypassMan::Background::JobRunner.start!
140
+ ProconBypassMan::Websocket::Client.start!
141
+ ProconBypassMan::QueueOverProcess.start!
142
+
127
143
  ProconBypassMan::WriteDeviceIdCommand.execute
128
144
  ProconBypassMan::WriteSessionIdCommand.execute
129
- system("renice -n -20 -p #{$$}")
145
+ `renice -n -20 -p #{$$}`
130
146
  File.write(pid_path, $$)
131
147
  ProconBypassMan::DeviceStatus.change_to_running!
132
148
  end
133
149
 
134
- def self.eternal_sleep
135
- sleep(999999999)
150
+ def self.ready_pbm
151
+ ProconBypassMan::PrintBootMessageCommand.execute
152
+ ProconBypassMan::ReportLoadConfigJob.perform_async(ProconBypassMan.config.raw_setting)
153
+ end
154
+
155
+ # @return [void]
156
+ def self.terminate_pbm
157
+ FileUtils.rm_rf(ProconBypassMan.pid_path)
158
+ FileUtils.rm_rf(ProconBypassMan.digest_path)
159
+ ProconBypassMan::QueueOverProcess.shutdown
136
160
  end
137
161
 
138
- # @return [Void]
139
- def self.hot_reload!
140
- Process.kill(:USR2, pid)
162
+ # @return [void]
163
+ def self.eternal_sleep
164
+ sleep(999999999)
141
165
  end
142
166
  end
@@ -6,7 +6,7 @@ begin
6
6
  gemfile do
7
7
  source 'https://rubygems.org'
8
8
  git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
9
- gem 'procon_bypass_man', '0.1.23'
9
+ gem 'procon_bypass_man', '0.2.0'
10
10
  end
11
11
  rescue Bundler::Source::Git::GitCommandError => e
12
12
  # install中に強制終了するとgitの管理ファイルが不正状態になり、次のエラーが起きるので発生したらcache directoryを削除する
@@ -34,6 +34,12 @@ ProconBypassMan.configure do |config|
34
34
  # pbm-cloudで使う場合はnever_exitにtrueをセットしてください. trueがセットされている場合、不慮の事故が発生してもプロセスが終了しなくなります
35
35
  config.never_exit_accidentally = true
36
36
 
37
+ # 毎秒行ったIOをログに出力するか
38
+ config.io_monitor_logging = false
39
+
40
+ # 接続に成功したらコントローラーのHOME LEDを光らせるか
41
+ config.enable_home_led_on_connect = true
42
+
37
43
  # 操作が高頻度で固まるときは、 gadget_to_procon_interval の数値は大きくしてください
38
44
  config.bypass_mode = { mode: :normal, gadget_to_procon_interval: 5 }
39
45
  end