procon_bypass_man 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +19 -6
  3. data/.github/workflows/gitleacks.yml +1 -1
  4. data/.rubocop.yml +4 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +15 -0
  7. data/Gemfile +6 -3
  8. data/Gemfile.lock +5 -3
  9. data/README.md +28 -41
  10. data/Steepfile +0 -1
  11. data/bin/generate_default_app +10 -0
  12. data/docs/getting_started.md +102 -28
  13. data/docs/setup_raspi_by_mitamae.md +43 -2
  14. data/lib/procon_bypass_man/background/job_performer.rb +1 -2
  15. data/lib/procon_bypass_man/background/job_queue.rb +50 -0
  16. data/lib/procon_bypass_man/background/jobs/base_job.rb +1 -1
  17. data/lib/procon_bypass_man/background/jobs/concerns/has_external_api_setting.rb +2 -2
  18. data/lib/procon_bypass_man/background/jobs/concerns/job_performable.rb +16 -0
  19. data/lib/procon_bypass_man/background/jobs/post_completed_remote_macro_job.rb +1 -1
  20. data/lib/procon_bypass_man/background/jobs/report_boot_job.rb +1 -1
  21. data/lib/procon_bypass_man/background/jobs/report_completed_upgrade_pbm_job.rb +1 -1
  22. data/lib/procon_bypass_man/background/jobs/report_error_job.rb +1 -1
  23. data/lib/procon_bypass_man/background/jobs/report_error_reload_config_job.rb +1 -1
  24. data/lib/procon_bypass_man/background/jobs/report_load_config_job.rb +1 -1
  25. data/lib/procon_bypass_man/background/jobs/report_procon_performance_measurements_job.rb +43 -0
  26. data/lib/procon_bypass_man/background/jobs/report_reload_config_job.rb +1 -1
  27. data/lib/procon_bypass_man/background/jobs/report_start_reboot_job.rb +1 -1
  28. data/lib/procon_bypass_man/background/jobs/sync_device_stats_job.rb +1 -1
  29. data/lib/procon_bypass_man/background.rb +3 -4
  30. data/lib/procon_bypass_man/bypass/bypass_command.rb +16 -20
  31. data/lib/procon_bypass_man/bypass/bypass_value.rb +6 -0
  32. data/lib/procon_bypass_man/bypass/procon_to_switch.rb +99 -0
  33. data/lib/procon_bypass_man/bypass/switch_to_procon.rb +66 -0
  34. data/lib/procon_bypass_man/bypass.rb +5 -109
  35. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +0 -2
  36. data/lib/procon_bypass_man/configuration.rb +18 -39
  37. data/lib/procon_bypass_man/device_connection/procon_setting_overrider.rb +12 -3
  38. data/lib/procon_bypass_man/procon/analog_stick_manipulator.rb +2 -0
  39. data/lib/procon_bypass_man/procon/layer_changer.rb +2 -0
  40. data/lib/procon_bypass_man/procon/macro.rb +3 -1
  41. data/lib/procon_bypass_man/procon/macro_builder.rb +2 -0
  42. data/lib/procon_bypass_man/procon/macro_registry.rb +2 -0
  43. data/lib/procon_bypass_man/procon/performance_measurement/last_bypass_at.rb +17 -0
  44. data/lib/procon_bypass_man/procon/performance_measurement/measurement_collection.rb +9 -0
  45. data/lib/procon_bypass_man/procon/performance_measurement/measurements_summarizer.rb +101 -0
  46. data/lib/procon_bypass_man/procon/performance_measurement/procon_performance_span_transfer_job.rb +8 -0
  47. data/lib/procon_bypass_man/procon/performance_measurement/queue_over_process.rb +38 -0
  48. data/lib/procon_bypass_man/procon/performance_measurement/span_queue.rb +42 -0
  49. data/lib/procon_bypass_man/procon/performance_measurement/span_transfer_buffer.rb +39 -0
  50. data/lib/procon_bypass_man/procon/performance_measurement.rb +110 -0
  51. data/lib/procon_bypass_man/procon/suppress_rumble.rb +2 -0
  52. data/lib/procon_bypass_man/procon/user_operation.rb +2 -0
  53. data/lib/procon_bypass_man/procon/value_objects/analog_stick.rb +2 -0
  54. data/lib/procon_bypass_man/procon/value_objects/binary/inbound_procon_binary.rb +2 -0
  55. data/lib/procon_bypass_man/procon/value_objects/binary/processing_procon_binary.rb +2 -0
  56. data/lib/procon_bypass_man/procon/value_objects/rumble_binary.rb +2 -0
  57. data/lib/procon_bypass_man/procon.rb +26 -7
  58. data/lib/procon_bypass_man/procon_display/bypass_hook.rb +12 -0
  59. data/lib/procon_bypass_man/procon_display.rb +1 -0
  60. data/lib/procon_bypass_man/remote_macro/queue_over_process.rb +26 -44
  61. data/lib/procon_bypass_man/remote_macro/remote_macro_object.rb +22 -24
  62. data/lib/procon_bypass_man/remote_macro/remote_macro_receiver.rb +1 -1
  63. data/lib/procon_bypass_man/remote_macro/remote_macro_sender.rb +1 -1
  64. data/lib/procon_bypass_man/remote_macro/task.rb +1 -5
  65. data/lib/procon_bypass_man/remote_macro/task_queue.rb +6 -10
  66. data/lib/procon_bypass_man/remote_macro.rb +2 -0
  67. data/lib/procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command.rb +1 -1
  68. data/lib/procon_bypass_man/remote_pbm_action.rb +2 -0
  69. data/lib/procon_bypass_man/runner.rb +4 -10
  70. data/lib/procon_bypass_man/scheduler.rb +15 -6
  71. data/lib/procon_bypass_man/support/callbacks.rb +79 -34
  72. data/lib/procon_bypass_man/support/can_over_process.rb +60 -0
  73. data/lib/procon_bypass_man/support/gc.rb +8 -0
  74. data/lib/procon_bypass_man/support/http_client.rb +12 -6
  75. data/lib/procon_bypass_man/support/load_agv.rb +20 -0
  76. data/lib/procon_bypass_man/support/procon_performance_http_client.rb +7 -0
  77. data/lib/procon_bypass_man/support/renice_command.rb +17 -0
  78. data/lib/procon_bypass_man/support/retryable.rb +16 -0
  79. data/lib/procon_bypass_man/support/signal_handler.rb +1 -1
  80. data/lib/procon_bypass_man/version.rb +1 -1
  81. data/lib/procon_bypass_man/websocket/client.rb +2 -2
  82. data/lib/procon_bypass_man/worker.rb +32 -0
  83. data/lib/procon_bypass_man.rb +53 -10
  84. data/procon_bypass_man.gemspec +4 -2
  85. data/project_template/README.md +0 -5
  86. data/project_template/app.rb +17 -11
  87. data/project_template/app.rb.erb +59 -0
  88. data/project_template/lib/app_generator.rb +31 -0
  89. data/project_template/web.rb +1 -1
  90. data/sig/main.rbs +10 -52
  91. data/tmp/.keep +0 -0
  92. metadata +43 -10
  93. data/lib/procon_bypass_man/background/job_runner.rb +0 -45
  94. data/lib/procon_bypass_man/background/jobs/concerns/has_internal_api_setting.rb +0 -5
  95. data/lib/procon_bypass_man/background/jobs/concerns/job_runnable.rb +0 -16
  96. data/lib/procon_bypass_man/background/jobs/report_pressed_buttons_job.rb +0 -15
  97. data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +0 -47
  98. data/lib/procon_bypass_man/io_monitor.rb +0 -108
  99. data/lib/procon_bypass_man/support/server_pool.rb +0 -46
@@ -0,0 +1,50 @@
1
+ class ProconBypassMan::Background::JobQueue
2
+ extend ProconBypassMan::CanOverProcess
3
+
4
+ include Singleton
5
+
6
+ attr_reader :distributed_queue
7
+
8
+ # @override
9
+ def self.enable?
10
+ true
11
+ end
12
+
13
+ # @override
14
+ def self.distributed_class
15
+ Queue
16
+ end
17
+
18
+ # @override
19
+ def self.socket_file_path
20
+ "/tmp/procon_bypass_man_background_job_queue_queue".freeze
21
+ end
22
+
23
+ def self.push(value)
24
+ return unless enable?
25
+
26
+ instance.distributed_queue.push(value)
27
+ end
28
+
29
+ def self.pop
30
+ return unless enable?
31
+
32
+ instance.distributed_queue.pop
33
+ end
34
+
35
+ def self.size
36
+ return unless enable?
37
+
38
+ instance.distributed_queue.size
39
+ end
40
+
41
+ def self.clear
42
+ return unless enable?
43
+
44
+ instance.distributed_queue.clear
45
+ end
46
+
47
+ def initialize
48
+ @distributed_queue = DRbObject.new_with_uri(self.class.socket_path)
49
+ end
50
+ end
@@ -1,5 +1,5 @@
1
1
  class ProconBypassMan::BaseJob
2
- extend ProconBypassMan::Background::JobRunnable
2
+ extend ProconBypassMan::Background::JobPerformable
3
3
 
4
4
  def self.servers
5
5
  raise NotImplementedError
@@ -1,5 +1,5 @@
1
1
  module ProconBypassMan::HasExternalApiSetting
2
- def server_pool
3
- ProconBypassMan.config.server_pool
2
+ def api_server
3
+ ProconBypassMan.config.api_server
4
4
  end
5
5
  end
@@ -0,0 +1,16 @@
1
+ module ProconBypassMan
2
+ module Background
3
+ module JobPerformable
4
+ def perform(*)
5
+ raise NotImplementedError, nil
6
+ end
7
+
8
+ def perform_async(*args)
9
+ ProconBypassMan::Background::JobQueue.push(
10
+ args: args,
11
+ job_class: self.name, # drb上のQueueに格納するので念の為文字列入れて、取り出すときにevalでクラス化する
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
@@ -5,7 +5,7 @@ class ProconBypassMan::PostCompletedRemoteMacroJob < ProconBypassMan::BaseJob
5
5
  def self.perform(job_id)
6
6
  ProconBypassMan::RemoteMacroHttpClient.new(
7
7
  path: path,
8
- server_pool: server_pool,
8
+ server: api_server,
9
9
  ).post(job_id: job_id)
10
10
  end
11
11
 
@@ -5,7 +5,7 @@ class ProconBypassMan::ReportBootJob < ProconBypassMan::ReportEventBaseJob
5
5
  def self.perform(body)
6
6
  ProconBypassMan::ReportHttpClient.new(
7
7
  path: path,
8
- server_pool: server_pool,
8
+ server: api_server,
9
9
  retry_on_connection_error: true,
10
10
  ).post(body: body, event_type: :boot)
11
11
  end
@@ -4,7 +4,7 @@ class ProconBypassMan::ReportCompletedUpgradePbmJob < ProconBypassMan::ReportEve
4
4
  def self.perform
5
5
  ProconBypassMan::ReportHttpClient.new(
6
6
  path: path,
7
- server_pool: server_pool,
7
+ server: api_server,
8
8
  ).post(body: nil, event_type: :completed_upgrade_pbm)
9
9
  end
10
10
  end
@@ -5,7 +5,7 @@ class ProconBypassMan::ReportErrorJob < ProconBypassMan::ReportEventBaseJob
5
5
  def self.perform(body)
6
6
  ProconBypassMan::ReportHttpClient.new(
7
7
  path: path,
8
- server_pool: server_pool,
8
+ server: api_server,
9
9
  ).post(body: body, event_type: :error)
10
10
  end
11
11
  end
@@ -5,7 +5,7 @@ class ProconBypassMan::ReportErrorReloadConfigJob < ProconBypassMan::ReportEvent
5
5
  def self.perform(body)
6
6
  ProconBypassMan::ReportHttpClient.new(
7
7
  path: path,
8
- server_pool: server_pool,
8
+ server: api_server,
9
9
  ).post(body: body, event_type: :error_reload_config)
10
10
  end
11
11
  end
@@ -5,7 +5,7 @@ class ProconBypassMan::ReportLoadConfigJob < ProconBypassMan::ReportEventBaseJob
5
5
  def self.perform(body)
6
6
  ProconBypassMan::ReportHttpClient.new(
7
7
  path: path,
8
- server_pool: server_pool,
8
+ server: api_server,
9
9
  ).post(body: body, event_type: :load_config)
10
10
  end
11
11
  end
@@ -0,0 +1,43 @@
1
+ class ProconBypassMan::ReportProconPerformanceMeasurementsJob < ProconBypassMan::BaseJob
2
+ extend ProconBypassMan::HasExternalApiSetting
3
+
4
+ # @param [ProconBypassMan::Procon::PerformanceMeasurement::MeasurementCollection] measurement_collection
5
+ def self.perform(measurement_collection)
6
+ return if measurement_collection.nil?
7
+
8
+ collected_spans_size = measurement_collection.spans.size
9
+ metric = ProconBypassMan::Procon::PerformanceMeasurement.summarize(
10
+ spans: measurement_collection.spans
11
+ )
12
+ body = {
13
+ timestamp: measurement_collection.timestamp_key,
14
+ interval_from_previous_succeed_max: metric.interval_from_previous_succeed_max,
15
+ interval_from_previous_succeed_p50: metric.interval_from_previous_succeed_p50,
16
+ write_time_max: metric.write_time_max,
17
+ write_time_p50: metric.write_time_p50,
18
+ read_time_max: metric.read_time_max,
19
+ read_time_p50: metric.read_time_p50,
20
+ time_taken_max: metric.time_taken_max,
21
+ time_taken_p50: metric.time_taken_p50,
22
+ time_taken_p95: metric.time_taken_p95,
23
+ time_taken_p99: metric.time_taken_p99,
24
+ read_error_count: metric.read_error_count,
25
+ write_error_count: metric.write_error_count,
26
+ gc_count: metric.gc_count,
27
+ gc_time: metric.gc_time,
28
+ succeed_rate: metric.succeed_rate,
29
+ load_agv: ProconBypassMan::LoadAgv.new.get,
30
+ collected_spans_size: collected_spans_size,
31
+ }
32
+ ProconBypassMan.logger.info(body)
33
+
34
+ ProconBypassMan::ProconPerformanceHttpClient.new(
35
+ path: path,
36
+ server: api_server,
37
+ ).post(body: body)
38
+ end
39
+
40
+ def self.path
41
+ "/api/devices/#{ProconBypassMan.device_id}/procon_performance_metrics"
42
+ end
43
+ end
@@ -5,7 +5,7 @@ class ProconBypassMan::ReportReloadConfigJob < ProconBypassMan::ReportEventBaseJ
5
5
  def self.perform(body)
6
6
  ProconBypassMan::ReportHttpClient.new(
7
7
  path: path,
8
- server_pool: server_pool,
8
+ server: api_server,
9
9
  ).post(body: body, event_type: :reload_config)
10
10
  end
11
11
  end
@@ -4,7 +4,7 @@ class ProconBypassMan::ReportStartRebootJob < ProconBypassMan::ReportEventBaseJo
4
4
  def self.perform
5
5
  ProconBypassMan::ReportHttpClient.new(
6
6
  path: path,
7
- server_pool: server_pool,
7
+ server: api_server,
8
8
  ).post(body: nil, event_type: :start_reboot)
9
9
  end
10
10
  end
@@ -5,7 +5,7 @@ class ProconBypassMan::SyncDeviceStatsJob < ProconBypassMan::BaseJob
5
5
  def self.perform(status)
6
6
  ProconBypassMan::SendDeviceStatsHttpClient.new(
7
7
  path: path,
8
- server_pool: server_pool,
8
+ server: api_server,
9
9
  ).post(status: status, pbm_session_id: ProconBypassMan.session_id)
10
10
  end
11
11
 
@@ -1,7 +1,6 @@
1
- require "procon_bypass_man/background/jobs/concerns/has_internal_api_setting"
2
1
  require "procon_bypass_man/background/jobs/concerns/has_external_api_setting"
3
- require "procon_bypass_man/background/jobs/concerns/job_runnable"
4
- require "procon_bypass_man/background/job_runner"
2
+ require "procon_bypass_man/background/jobs/concerns/job_performable"
3
+ require "procon_bypass_man/background/job_queue"
5
4
  require "procon_bypass_man/background/job_performer"
6
5
  require "procon_bypass_man/background/jobs/base_job"
7
6
  require "procon_bypass_man/background/jobs/report_event_base_job"
@@ -11,7 +10,7 @@ require "procon_bypass_man/background/jobs/report_reload_config_job"
11
10
  require "procon_bypass_man/background/jobs/report_error_reload_config_job"
12
11
  require "procon_bypass_man/background/jobs/report_load_config_job"
13
12
  require "procon_bypass_man/background/jobs/report_error_job"
14
- require "procon_bypass_man/background/jobs/report_pressed_buttons_job"
15
13
  require "procon_bypass_man/background/jobs/report_completed_upgrade_pbm_job"
14
+ require "procon_bypass_man/background/jobs/report_procon_performance_measurements_job"
16
15
  require "procon_bypass_man/background/jobs/sync_device_stats_job"
17
16
  require "procon_bypass_man/background/jobs/post_completed_remote_macro_job"
@@ -6,13 +6,9 @@ class ProconBypassMan::BypassCommand
6
6
  RESTART = :restart
7
7
  end
8
8
 
9
- def initialize(gadget:, procon:)
9
+ def initialize(gadget: , procon: )
10
10
  @gadget = gadget
11
11
  @procon = procon
12
-
13
- ProconBypassMan::IOMonitor.start! if ProconBypassMan.io_monitor_logging
14
- ProconBypassMan::Background::JobRunner.queue.clear # forkしたときに残留物も移ってしまうため
15
- ProconBypassMan::Background::JobRunner.start!
16
12
  end
17
13
 
18
14
  def execute
@@ -29,25 +25,17 @@ class ProconBypassMan::BypassCommand
29
25
 
30
26
  # gadget => procon
31
27
  # 遅くていい
32
- monitor1 = ProconBypassMan::IOMonitor.new(label: "switch -> procon")
33
- monitor2 = ProconBypassMan::IOMonitor.new(label: "procon -> switch")
34
28
  ProconBypassMan.logger.info "Thread1を起動します"
35
29
 
36
30
  cycle_sleep = ProconBypassMan::CycleSleep.new(cycle_interval: 1, execution_cycle: ProconBypassMan.config.bypass_mode.gadget_to_procon_interval)
37
31
 
38
32
  t1 = Thread.new do
39
- if ProconBypassMan.config.bypass_mode.mode == ProconBypassMan::BypassMode::TYPE_AGGRESSIVE
40
- ProconBypassMan.logger.info "TYPE_AGGRESSIVEなのでThread1を終了します"
41
- monitor1.shutdown
42
- next
43
- end
44
-
33
+ bypass = ProconBypassMan::Bypass::SwitchToProcon.new(gadget: @gadget, procon: @procon)
45
34
  loop do
46
35
  break if $will_terminate_token
47
36
 
48
37
  cycle_sleep.sleep_or_execute do
49
- bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor1)
50
- bypass.send_gadget_to_procon!
38
+ bypass.run
51
39
  end
52
40
  rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN => e
53
41
  ProconBypassMan::SendErrorCommand.execute(error: "Switchとの切断されました.終了処理を開始します. #{e.full_message}")
@@ -63,28 +51,36 @@ class ProconBypassMan::BypassCommand
63
51
 
64
52
  # procon => gadget
65
53
  # シビア
66
- ProconBypassMan.logger.info "Thread2を起動します"
67
54
  t2 = Thread.new do
68
- bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor2)
55
+ bypass = ProconBypassMan::Bypass::ProconToSwitch.new(gadget: @gadget, procon: @procon)
56
+ process = BlueGreenProcess.new(worker_instance: bypass, max_work: 200)
69
57
  loop do
70
58
  if $will_terminate_token
71
59
  if $will_terminate_token == WILL_TERMINATE_TOKEN::TERMINATE
72
60
  bypass.direct_connect_switch_via_bluetooth
61
+ process.shutdown
73
62
  end
74
63
  break
75
64
  end
76
65
 
77
- bypass.send_procon_to_gadget!
66
+ process.work
67
+
68
+ process_switching_time_before_work = BlueGreenProcess.performance.process_switching_time_before_work
69
+ if process_switching_time_before_work > 0.1
70
+ ProconBypassMan.logger.info("slow process_switching_time_before_work: #{process_switching_time_before_work}")
71
+ end
72
+
78
73
  rescue EOFError => e
79
74
  ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
80
75
  Process.kill "TERM", Process.ppid
76
+ process.shutdown
81
77
  break
82
78
  rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN => e
83
79
  ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します2. #{e.full_message}")
84
80
  Process.kill "TERM", Process.ppid
81
+ process.shutdown
85
82
  break
86
83
  end
87
- ProconBypassMan.logger.info "Thread2を終了します"
88
84
  end
89
85
 
90
86
  ProconBypassMan.logger.info "子プロセスでgraceful shutdownの準備ができました"
@@ -93,7 +89,7 @@ class ProconBypassMan::BypassCommand
93
89
  signal = readable_io.first[0].gets.strip
94
90
  handle_signal(signal)
95
91
  end
96
- rescue ProconBypassMan::Runner::InterruptForRestart
92
+ rescue ProconBypassMan::InterruptForRestart
97
93
  $will_terminate_token = WILL_TERMINATE_TOKEN::RESTART
98
94
  [t1, t2].each(&:join)
99
95
  @gadget&.close
@@ -0,0 +1,6 @@
1
+ class ProconBypassMan::Bypass::BypassValue < Struct.new(:binary)
2
+ def to_text
3
+ return unless binary
4
+ binary.unpack.first
5
+ end
6
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "procon_bypass_man/bypass/bypass_command"
4
+
5
+ class ProconBypassMan::Bypass::ProconToSwitch
6
+ extend ProconBypassMan::CallbacksRegisterable
7
+ include ProconBypassMan::Callbacks
8
+
9
+ class CouldNotReadFromProconError < StandardError; end
10
+ class CouldNotWriteToSwitchError < StandardError; end
11
+
12
+ define_callbacks :work
13
+ set_callback :work, :after, :log_after_run
14
+
15
+ # マルチプロセス化したので一旦無効にする
16
+ # register_callback_module(ProconBypassMan::ProconDisplay::BypassHook)
17
+
18
+ attr_accessor :gadget, :procon, :bypass_value
19
+
20
+ def initialize(gadget: , procon: )
21
+ self.gadget = gadget
22
+ self.procon = procon
23
+ end
24
+
25
+ # @raise [Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT]
26
+ # @return [void]
27
+ def work(*)
28
+ ProconBypassMan::Procon::PerformanceMeasurement.measure do |measurement|
29
+ self.bypass_value = ProconBypassMan::Bypass::BypassValue.new(nil)
30
+
31
+ next(run_callbacks(:work) {
32
+ next(false) if $will_terminate_token
33
+
34
+ raw_output = nil
35
+ measurement.record_read_time do
36
+ begin
37
+ return(false) if $will_terminate_token
38
+ raw_output = self.procon.read_nonblock(64)
39
+ rescue IO::EAGAINWaitReadable
40
+ sleep(0.002)
41
+ retry
42
+ rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT => e
43
+ return(false) if $will_terminate_token
44
+ raise
45
+ end
46
+
47
+ self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_output)
48
+ end
49
+
50
+ result = measurement.record_write_time do
51
+ begin
52
+ ProconBypassMan::Retryable.retryable(tries: 5, on_no_retry: [Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT]) do
53
+ begin
54
+ # 終了処理を希望されているのでブロックを無視してメソッドを抜けてOK
55
+ return(false) if $will_terminate_token # rubocop:disable Lint/NoReturnInBeginEndBlocks
56
+ self.gadget.write_nonblock(
57
+ ProconBypassMan::Processor.new(bypass_value.binary).process
58
+ )
59
+ next(true)
60
+ rescue IO::EAGAINWaitReadable
61
+ return(false) if $will_terminate_token # rubocop:disable Lint/NoReturnInBeginEndBlocks
62
+ measurement.record_write_error
63
+ raise CouldNotWriteToSwitchError
64
+ rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT => e
65
+ return(false) if $will_terminate_token # rubocop:disable Lint/NoReturnInBeginEndBlocks
66
+ raise
67
+ end
68
+ end
69
+ rescue CouldNotWriteToSwitchError
70
+ next(false)
71
+ end
72
+ end
73
+
74
+ next(result)
75
+ })
76
+ end
77
+ end
78
+
79
+ # @return [void]
80
+ def direct_connect_switch_via_bluetooth
81
+ ProconBypassMan.logger.debug { "direct_connect_switch_via_bluetooth!" }
82
+ self.procon.write_nonblock(["010500000000000000003800"].pack("H*")) # home led off
83
+ self.procon.write_nonblock(["010600000000000000003800"].pack("H*")) # home led off
84
+ self.procon.write_nonblock(["010700000000000000003800"].pack("H*")) # home led off
85
+ self.procon.write_nonblock(["010800000000000000003800"].pack("H*")) # home led off
86
+ self.procon.write_nonblock(["8005"].pack("H*"))
87
+ self.procon.write_nonblock(["8005"].pack("H*"))
88
+ self.procon.write_nonblock(["8005"].pack("H*"))
89
+ end
90
+
91
+ private
92
+
93
+ def log_after_run
94
+ return unless ProconBypassMan.config.verbose_bypass_log
95
+ return unless bypass_value.to_text
96
+
97
+ ProconBypassMan.logger.debug { "<<< #{bypass_value.to_text}" }
98
+ end
99
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "procon_bypass_man/bypass/bypass_command"
4
+
5
+ class ProconBypassMan::Bypass::SwitchToProcon
6
+ include ProconBypassMan::Callbacks
7
+
8
+ define_callbacks :run
9
+ set_callback :run, :after, :log_after_run
10
+
11
+ attr_accessor :gadget, :procon, :bypass_value
12
+
13
+ def initialize(gadget: , procon: )
14
+ self.gadget = gadget
15
+ self.procon = procon
16
+ end
17
+
18
+ # ゆっくりでいい
19
+ def run
20
+ self.bypass_value = ProconBypassMan::Bypass::BypassValue.new(nil)
21
+
22
+ run_callbacks(:run) do
23
+ next if $will_terminate_token
24
+
25
+ raw_input = nil
26
+ begin
27
+ raw_input = self.gadget.read_nonblock(64)
28
+ self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_input)
29
+ rescue IO::EAGAINWaitReadable
30
+ next
31
+ end
32
+
33
+ if self.bypass_value.binary
34
+ begin
35
+ raw_data =
36
+ case
37
+ when self.bypass_value.binary.rumble_data? # TODO そもそも無効になっているので消していい
38
+ binary = ProconBypassMan::RumbleBinary.new(binary: self.bypass_value.binary.raw)
39
+ binary.noop!
40
+ binary.raw
41
+ else
42
+ self.bypass_value.binary.raw
43
+ end
44
+ # バイブレーションを無効にしているのでおそらく書き込む必要はない
45
+ # self.procon.write_nonblock(raw_data)
46
+ rescue IO::EAGAINWaitReadable
47
+ next
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ private
54
+
55
+ def log_after_run
56
+ return unless bypass_value.to_text
57
+
58
+ if ProconBypassMan.config.verbose_bypass_log
59
+ ProconBypassMan.logger.debug { ">>> #{bypass_value.to_text}" }
60
+ else
61
+ ProconBypassMan.cache.fetch key: 'bypass_log', expires_in: 1 do
62
+ ProconBypassMan.logger.debug { ">>> #{bypass_value.to_text}" }
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,110 +1,6 @@
1
- require "procon_bypass_man/bypass/usb_hid_logger"
2
- require "procon_bypass_man/bypass/bypass_command"
3
-
4
- class ProconBypassMan::Bypass
5
- include ProconBypassMan::Bypass::UsbHidLogger
6
- # TODO callbackモジュールを修正して複数のメソッドをチェインできるようにする
7
- # include ProconBypassMan::ProconDisplay::BypassCallback
8
-
9
- class BypassValue < Struct.new(:binary)
10
- def to_text
11
- return unless binary
12
- binary.unpack.first
13
- end
14
- end
15
-
16
- attr_accessor :gadget, :procon, :monitor, :bypass_value
17
-
18
- def initialize(gadget: , procon: , monitor: )
19
- self.gadget = gadget
20
- self.procon = procon
21
- self.monitor = monitor
22
- end
23
-
24
- # ゆっくりでいい
25
- def send_gadget_to_procon!
26
- monitor.record(:start_function)
27
- self.bypass_value = BypassValue.new(nil)
28
-
29
- run_callbacks(:send_gadget_to_procon) do
30
- break if $will_terminate_token
31
-
32
- raw_input = nil
33
- begin
34
- raw_input = self.gadget.read_nonblock(64)
35
- self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_input)
36
- rescue IO::EAGAINWaitReadable
37
- monitor.record(:eagain_wait_readable_on_read)
38
- end
1
+ module ProconBypassMan::Bypass; end
39
2
 
40
- if self.bypass_value.binary
41
- begin
42
- raw_data =
43
- case
44
- when self.bypass_value.binary.rumble_data?
45
- binary = ProconBypassMan::RumbleBinary.new(binary: self.bypass_value.binary.raw)
46
- binary.noop!
47
- binary.raw
48
- else
49
- self.bypass_value.binary.raw
50
- end
51
- self.procon.write_nonblock(raw_data)
52
- rescue IO::EAGAINWaitReadable
53
- monitor.record(:eagain_wait_readable_on_write)
54
- break
55
- end
56
- end
57
- end
58
-
59
- monitor.record(:end_function)
60
- end
61
-
62
- def send_procon_to_gadget!
63
- monitor.record(:start_function)
64
- self.bypass_value = BypassValue.new(nil)
65
-
66
- run_callbacks(:send_procon_to_gadget) do
67
- break if $will_terminate_token
68
-
69
- begin
70
- Timeout.timeout(1) do
71
- raw_output = self.procon.read(64)
72
- self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_output)
73
- end
74
- rescue Timeout::Error
75
- ProconBypassMan.logger.debug { "read timeout! do sleep. by send_procon_to_gadget!" }
76
- ProconBypassMan.error_logger.error { "read timeout! do sleep. by send_procon_to_gadget!" }
77
- ProconBypassMan::SendErrorCommand.execute(error: "read timeout! do sleep. by send_procon_to_gadget!")
78
- monitor.record(:eagain_wait_readable_on_read)
79
- retry
80
- rescue IO::EAGAINWaitReadable
81
- ProconBypassMan.logger.debug { "EAGAINWaitReadable" }
82
- monitor.record(:eagain_wait_readable_on_read)
83
- sleep(0.005)
84
- retry
85
- end
86
-
87
- begin
88
- self.gadget.write_nonblock(
89
- ProconBypassMan::Processor.new(bypass_value.binary).process
90
- )
91
- rescue IO::EAGAINWaitReadable
92
- monitor.record(:eagain_wait_readable_on_write)
93
- break
94
- end
95
- end
96
- monitor.record(:end_function)
97
- end
98
-
99
- # @return [void]
100
- def direct_connect_switch_via_bluetooth
101
- ProconBypassMan.logger.debug { "direct_connect_switch_via_bluetooth!" }
102
- self.procon.write_nonblock(["010500000000000000003800"].pack("H*")) # home led off
103
- self.procon.write_nonblock(["010600000000000000003800"].pack("H*")) # home led off
104
- self.procon.write_nonblock(["010700000000000000003800"].pack("H*")) # home led off
105
- self.procon.write_nonblock(["010800000000000000003800"].pack("H*")) # home led off
106
- self.procon.write_nonblock(["8005"].pack("H*"))
107
- self.procon.write_nonblock(["8005"].pack("H*"))
108
- self.procon.write_nonblock(["8005"].pack("H*"))
109
- end
110
- end
3
+ require "procon_bypass_man/bypass/bypass_command"
4
+ require "procon_bypass_man/bypass/bypass_value"
5
+ require "procon_bypass_man/bypass/procon_to_switch"
6
+ require "procon_bypass_man/bypass/switch_to_procon"
@@ -13,7 +13,6 @@ class ProconBypassMan::PrintBootMessageCommand
13
13
  @table[:use_pbmenv] = !(!!`which pbmenv`.empty?)
14
14
  @table[:session_id] = ProconBypassMan.session_id
15
15
  @table[:device_id] = ProconBypassMan.device_id
16
- @table[:bypass_mode] = ProconBypassMan.config.bypass_mode.to_s
17
16
  @table[:never_exit_accidentally] = ProconBypassMan.config.never_exit_accidentally
18
17
  @table[:uname] = `uname -a`.chomp
19
18
 
@@ -43,7 +42,6 @@ class ProconBypassMan::PrintBootMessageCommand
43
42
  use_pbmenv: #{@table[:use_pbmenv]}
44
43
  session_id: #{ProconBypassMan.session_id}
45
44
  device_id: #{ProconBypassMan.device_id.gsub(/.{25}$/, "*"*25)}
46
- bypass_mode: #{ProconBypassMan.config.bypass_mode}
47
45
  ----
48
46
  EOF
49
47
  end