procon_bypass_man 0.1.23 → 0.2.0

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 (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