procon_bypass_man 0.2.0 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +19 -6
  3. data/.github/workflows/gitleacks.yml +2 -1
  4. data/.github/workflows/release.yml +1 -0
  5. data/.github/workflows/ruby.yml +1 -1
  6. data/.rubocop.yml +4 -0
  7. data/.ruby-version +1 -1
  8. data/CHANGELOG.md +16 -1
  9. data/Gemfile +6 -3
  10. data/Gemfile.lock +3 -3
  11. data/README.md +17 -8
  12. data/Steepfile +0 -1
  13. data/bin/generate_default_app +10 -0
  14. data/docs/getting_started.md +98 -25
  15. data/docs/setup_raspi_by_mitamae.md +44 -2
  16. data/lib/procon_bypass_man/background/job_performer.rb +1 -2
  17. data/lib/procon_bypass_man/background/job_queue.rb +50 -0
  18. data/lib/procon_bypass_man/background/jobs/base_job.rb +1 -1
  19. data/lib/procon_bypass_man/background/jobs/concerns/has_external_api_setting.rb +2 -2
  20. data/lib/procon_bypass_man/background/jobs/concerns/job_performable.rb +16 -0
  21. data/lib/procon_bypass_man/background/jobs/post_completed_remote_macro_job.rb +1 -1
  22. data/lib/procon_bypass_man/background/jobs/report_boot_job.rb +1 -1
  23. data/lib/procon_bypass_man/background/jobs/report_completed_upgrade_pbm_job.rb +1 -1
  24. data/lib/procon_bypass_man/background/jobs/report_error_job.rb +1 -1
  25. data/lib/procon_bypass_man/background/jobs/report_error_reload_config_job.rb +1 -1
  26. data/lib/procon_bypass_man/background/jobs/report_load_config_job.rb +1 -1
  27. data/lib/procon_bypass_man/background/jobs/report_procon_performance_measurements_job.rb +43 -0
  28. data/lib/procon_bypass_man/background/jobs/report_reload_config_job.rb +1 -1
  29. data/lib/procon_bypass_man/background/jobs/report_start_reboot_job.rb +1 -1
  30. data/lib/procon_bypass_man/background/jobs/sync_device_stats_job.rb +1 -1
  31. data/lib/procon_bypass_man/background.rb +3 -4
  32. data/lib/procon_bypass_man/bypass/bypass_command.rb +6 -15
  33. data/lib/procon_bypass_man/bypass/bypass_value.rb +6 -0
  34. data/lib/procon_bypass_man/bypass/procon_to_switch.rb +107 -0
  35. data/lib/procon_bypass_man/bypass/switch_to_procon.rb +64 -0
  36. data/lib/procon_bypass_man/bypass.rb +5 -112
  37. data/lib/procon_bypass_man/configuration.rb +16 -40
  38. data/lib/procon_bypass_man/device_connection/output_report_sub_command_table.rb +1 -1
  39. data/lib/procon_bypass_man/device_connection/procon_setting_overrider.rb +12 -3
  40. data/lib/procon_bypass_man/procon/macro.rb +1 -1
  41. data/lib/procon_bypass_man/procon/performance_measurement/last_bypass_at.rb +17 -0
  42. data/lib/procon_bypass_man/procon/performance_measurement/measurement_collection.rb +9 -0
  43. data/lib/procon_bypass_man/procon/performance_measurement/measurements_summarizer.rb +84 -0
  44. data/lib/procon_bypass_man/procon/performance_measurement/procon_performance_span_transfer_job.rb +8 -0
  45. data/lib/procon_bypass_man/procon/performance_measurement/queue_over_process.rb +38 -0
  46. data/lib/procon_bypass_man/procon/performance_measurement/span_queue.rb +42 -0
  47. data/lib/procon_bypass_man/procon/performance_measurement/span_transfer_buffer.rb +39 -0
  48. data/lib/procon_bypass_man/procon/performance_measurement.rb +103 -0
  49. data/lib/procon_bypass_man/procon.rb +2 -1
  50. data/lib/procon_bypass_man/procon_display/bypass_hook.rb +12 -0
  51. data/lib/procon_bypass_man/procon_display/http_request.rb +31 -0
  52. data/lib/procon_bypass_man/procon_display/http_response.rb +23 -0
  53. data/lib/procon_bypass_man/procon_display/server.rb +33 -0
  54. data/lib/procon_bypass_man/procon_display/server_app.rb +17 -0
  55. data/lib/procon_bypass_man/procon_display/status.rb +20 -0
  56. data/lib/procon_bypass_man/procon_display.rb +11 -0
  57. data/lib/procon_bypass_man/remote_macro/queue_over_process.rb +26 -44
  58. data/lib/procon_bypass_man/remote_macro/remote_macro_object.rb +22 -24
  59. data/lib/procon_bypass_man/remote_macro/remote_macro_receiver.rb +1 -1
  60. data/lib/procon_bypass_man/remote_macro/remote_macro_sender.rb +1 -1
  61. data/lib/procon_bypass_man/remote_macro/task.rb +1 -5
  62. data/lib/procon_bypass_man/remote_macro/task_queue.rb +6 -10
  63. data/lib/procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command.rb +1 -1
  64. data/lib/procon_bypass_man/runner.rb +4 -9
  65. data/lib/procon_bypass_man/scheduler.rb +15 -6
  66. data/lib/procon_bypass_man/support/callbacks.rb +72 -34
  67. data/lib/procon_bypass_man/support/can_over_process.rb +60 -0
  68. data/lib/procon_bypass_man/support/gc.rb +8 -0
  69. data/lib/procon_bypass_man/support/http_client.rb +9 -6
  70. data/lib/procon_bypass_man/support/load_agv.rb +20 -0
  71. data/lib/procon_bypass_man/support/procon_performance_http_client.rb +7 -0
  72. data/lib/procon_bypass_man/support/retryable.rb +16 -0
  73. data/lib/procon_bypass_man/support/signal_handler.rb +1 -1
  74. data/lib/procon_bypass_man/version.rb +1 -1
  75. data/lib/procon_bypass_man/websocket/client.rb +2 -2
  76. data/lib/procon_bypass_man/worker.rb +32 -0
  77. data/lib/procon_bypass_man.rb +41 -10
  78. data/procon_bypass_man.gemspec +1 -1
  79. data/project_template/README.md +0 -5
  80. data/project_template/app.rb +21 -11
  81. data/project_template/app.rb.erb +62 -0
  82. data/project_template/lib/app_generator.rb +31 -0
  83. data/project_template/web.rb +1 -1
  84. data/sig/main.rbs +10 -52
  85. data/tmp/.keep +0 -0
  86. metadata +34 -10
  87. data/lib/procon_bypass_man/background/job_runner.rb +0 -45
  88. data/lib/procon_bypass_man/background/jobs/concerns/has_internal_api_setting.rb +0 -5
  89. data/lib/procon_bypass_man/background/jobs/concerns/job_runnable.rb +0 -16
  90. data/lib/procon_bypass_man/background/jobs/report_pressed_buttons_job.rb +0 -15
  91. data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +0 -44
  92. data/lib/procon_bypass_man/io_monitor.rb +0 -108
  93. data/lib/procon_bypass_man/support/server_pool.rb +0 -46
@@ -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,8 +25,6 @@ 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)
@@ -38,16 +32,15 @@ class ProconBypassMan::BypassCommand
38
32
  t1 = Thread.new do
39
33
  if ProconBypassMan.config.bypass_mode.mode == ProconBypassMan::BypassMode::TYPE_AGGRESSIVE
40
34
  ProconBypassMan.logger.info "TYPE_AGGRESSIVEなのでThread1を終了します"
41
- monitor1.shutdown
42
35
  next
43
36
  end
44
37
 
38
+ bypass = ProconBypassMan::Bypass::SwitchToProcon.new(gadget: @gadget, procon: @procon)
45
39
  loop do
46
40
  break if $will_terminate_token
47
41
 
48
42
  cycle_sleep.sleep_or_execute do
49
- bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor1)
50
- bypass.send_gadget_to_procon!
43
+ bypass.run
51
44
  end
52
45
  rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN => e
53
46
  ProconBypassMan::SendErrorCommand.execute(error: "Switchとの切断されました.終了処理を開始します. #{e.full_message}")
@@ -63,9 +56,8 @@ class ProconBypassMan::BypassCommand
63
56
 
64
57
  # procon => gadget
65
58
  # シビア
66
- ProconBypassMan.logger.info "Thread2を起動します"
67
59
  t2 = Thread.new do
68
- bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor2)
60
+ bypass = ProconBypassMan::Bypass::ProconToSwitch.new(gadget: @gadget, procon: @procon)
69
61
  loop do
70
62
  if $will_terminate_token
71
63
  if $will_terminate_token == WILL_TERMINATE_TOKEN::TERMINATE
@@ -74,7 +66,7 @@ class ProconBypassMan::BypassCommand
74
66
  break
75
67
  end
76
68
 
77
- bypass.send_procon_to_gadget!
69
+ bypass.run
78
70
  rescue EOFError => e
79
71
  ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
80
72
  Process.kill "TERM", Process.ppid
@@ -84,7 +76,6 @@ class ProconBypassMan::BypassCommand
84
76
  Process.kill "TERM", Process.ppid
85
77
  break
86
78
  end
87
- ProconBypassMan.logger.info "Thread2を終了します"
88
79
  end
89
80
 
90
81
  ProconBypassMan.logger.info "子プロセスでgraceful shutdownの準備ができました"
@@ -93,7 +84,7 @@ class ProconBypassMan::BypassCommand
93
84
  signal = readable_io.first[0].gets.strip
94
85
  handle_signal(signal)
95
86
  end
96
- rescue ProconBypassMan::Runner::InterruptForRestart
87
+ rescue ProconBypassMan::InterruptForRestart
97
88
  $will_terminate_token = WILL_TERMINATE_TOKEN::RESTART
98
89
  [t1, t2].each(&:join)
99
90
  @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,107 @@
1
+ require "procon_bypass_man/bypass/bypass_command"
2
+
3
+ class ProconBypassMan::Bypass::ProconToSwitch
4
+ extend ProconBypassMan::CallbacksRegisterable
5
+ include ProconBypassMan::Callbacks
6
+
7
+ class CouldNotReadFromProconError < StandardError; end
8
+ class CouldNotWriteToSwitchError < StandardError; end
9
+
10
+ define_callbacks :run
11
+ set_callback :run, :after, :log_after_run
12
+
13
+ register_callback_module(ProconBypassMan::ProconDisplay::BypassHook)
14
+
15
+ attr_accessor :gadget, :procon, :bypass_value, :procon_binary_queue
16
+
17
+ def initialize(gadget: , procon: )
18
+ self.gadget = gadget
19
+ self.procon = procon
20
+ end
21
+
22
+ # @raise [Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT]
23
+ # @return [void]
24
+ def run
25
+ ProconBypassMan::Procon::PerformanceMeasurement.measure do |measurement|
26
+ self.bypass_value = ProconBypassMan::Bypass::BypassValue.new(nil)
27
+
28
+ next(run_callbacks(:run) {
29
+ next(false) if $will_terminate_token
30
+
31
+ raw_output = nil
32
+ measurement.record_read_time do
33
+ begin
34
+ ProconBypassMan::GC.stop_gc_in do
35
+ return(false) if $will_terminate_token
36
+ raw_output = self.procon.read_nonblock(64)
37
+ end
38
+ rescue IO::EAGAINWaitReadable
39
+ sleep(0.002)
40
+ retry
41
+ rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT => e
42
+ return(false) if $will_terminate_token
43
+ raise
44
+ end
45
+ end
46
+
47
+ self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_output)
48
+
49
+ result = ProconBypassMan::GC.stop_gc_in do
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
+ end
76
+
77
+ next(result)
78
+ })
79
+ end
80
+ end
81
+
82
+ # @return [void]
83
+ def direct_connect_switch_via_bluetooth
84
+ ProconBypassMan.logger.debug { "direct_connect_switch_via_bluetooth!" }
85
+ self.procon.write_nonblock(["010500000000000000003800"].pack("H*")) # home led off
86
+ self.procon.write_nonblock(["010600000000000000003800"].pack("H*")) # home led off
87
+ self.procon.write_nonblock(["010700000000000000003800"].pack("H*")) # home led off
88
+ self.procon.write_nonblock(["010800000000000000003800"].pack("H*")) # home led off
89
+ self.procon.write_nonblock(["8005"].pack("H*"))
90
+ self.procon.write_nonblock(["8005"].pack("H*"))
91
+ self.procon.write_nonblock(["8005"].pack("H*"))
92
+ end
93
+
94
+ private
95
+
96
+ def log_after_run
97
+ return unless bypass_value.to_text
98
+
99
+ if ProconBypassMan.config.verbose_bypass_log
100
+ ProconBypassMan.logger.debug { "<<< #{bypass_value.to_text}" }
101
+ else
102
+ ProconBypassMan.cache.fetch key: 'bypass_log', expires_in: 1 do
103
+ ProconBypassMan.logger.debug { "<<< #{bypass_value.to_text}" }
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,64 @@
1
+ require "procon_bypass_man/bypass/bypass_command"
2
+
3
+ class ProconBypassMan::Bypass::SwitchToProcon
4
+ include ProconBypassMan::Callbacks
5
+
6
+ define_callbacks :run
7
+ set_callback :run, :after, :log_after_run
8
+
9
+ attr_accessor :gadget, :procon, :bypass_value
10
+
11
+ def initialize(gadget: , procon: )
12
+ self.gadget = gadget
13
+ self.procon = procon
14
+ end
15
+
16
+ # ゆっくりでいい
17
+ def run
18
+ self.bypass_value = ProconBypassMan::Bypass::BypassValue.new(nil)
19
+
20
+ run_callbacks(:run) do
21
+ next if $will_terminate_token
22
+
23
+ raw_input = nil
24
+ begin
25
+ raw_input = self.gadget.read_nonblock(64)
26
+ self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_input)
27
+ rescue IO::EAGAINWaitReadable
28
+ next
29
+ end
30
+
31
+ if self.bypass_value.binary
32
+ begin
33
+ raw_data =
34
+ case
35
+ when self.bypass_value.binary.rumble_data? # TODO そもそも無効になっているので消していい
36
+ binary = ProconBypassMan::RumbleBinary.new(binary: self.bypass_value.binary.raw)
37
+ binary.noop!
38
+ binary.raw
39
+ else
40
+ self.bypass_value.binary.raw
41
+ end
42
+ # バイブレーションを無効にしているのでおそらく書き込む必要はない
43
+ # self.procon.write_nonblock(raw_data)
44
+ rescue IO::EAGAINWaitReadable
45
+ next
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def log_after_run
54
+ return unless bypass_value.to_text
55
+
56
+ if ProconBypassMan.config.verbose_bypass_log
57
+ ProconBypassMan.logger.debug { ">>> #{bypass_value.to_text}" }
58
+ else
59
+ ProconBypassMan.cache.fetch key: 'bypass_log', expires_in: 1 do
60
+ ProconBypassMan.logger.debug { ">>> #{bypass_value.to_text}" }
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,113 +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
-
7
- class BypassValue < Struct.new(:binary)
8
- def to_text
9
- return unless binary
10
- binary.unpack.first
11
- end
12
- end
13
-
14
- attr_accessor :gadget, :procon, :monitor, :bypass_value
15
-
16
- def initialize(gadget: , procon: , monitor: )
17
- self.gadget = gadget
18
- self.procon = procon
19
- self.monitor = monitor
20
- end
21
-
22
- # ゆっくりでいい
23
- def send_gadget_to_procon!
24
- monitor.record(:start_function)
25
- self.bypass_value = BypassValue.new(nil)
26
-
27
- run_callbacks(:send_gadget_to_procon) do
28
- break if $will_terminate_token
29
-
30
- raw_input = nil
31
- begin
32
- raw_input = self.gadget.read_nonblock(64)
33
- self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_input)
34
- rescue IO::EAGAINWaitReadable
35
- monitor.record(:eagain_wait_readable_on_read)
36
- end
1
+ module ProconBypassMan::Bypass; end
37
2
 
38
- if self.bypass_value.binary
39
- begin
40
- raw_data =
41
- case
42
- when self.bypass_value.binary.rumble_data?
43
- binary = ProconBypassMan::RumbleBinary.new(binary: self.bypass_value.binary.raw)
44
- binary.noop!
45
- binary.raw
46
- else
47
- self.bypass_value.binary.raw
48
- end
49
- self.procon.write_nonblock(raw_data)
50
- rescue IO::EAGAINWaitReadable
51
- monitor.record(:eagain_wait_readable_on_write)
52
- break
53
- end
54
- end
55
- end
56
-
57
- monitor.record(:end_function)
58
- end
59
-
60
- def send_procon_to_gadget!
61
- monitor.record(:start_function)
62
- self.bypass_value = BypassValue.new(nil)
63
-
64
- run_callbacks(:send_procon_to_gadget) do
65
- break if $will_terminate_token
66
-
67
- begin
68
- Timeout.timeout(1) do
69
- raw_output = self.procon.read(64)
70
- self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_output)
71
- end
72
- rescue Timeout::Error
73
- ProconBypassMan.logger.debug { "read timeout! do sleep. by send_procon_to_gadget!" }
74
- ProconBypassMan.error_logger.error { "read timeout! do sleep. by send_procon_to_gadget!" }
75
- ProconBypassMan::SendErrorCommand.execute(error: "read timeout! do sleep. by send_procon_to_gadget!")
76
- monitor.record(:eagain_wait_readable_on_read)
77
- retry
78
- rescue IO::EAGAINWaitReadable
79
- ProconBypassMan.logger.debug { "EAGAINWaitReadable" }
80
- monitor.record(:eagain_wait_readable_on_read)
81
- sleep(0.005)
82
- retry
83
- end
84
-
85
- begin
86
- self.gadget.write_nonblock(
87
- ProconBypassMan::Processor.new(bypass_value.binary).process
88
- )
89
- rescue IO::EAGAINWaitReadable
90
- monitor.record(:eagain_wait_readable_on_write)
91
- break
92
- end
93
- end
94
- monitor.record(:end_function)
95
- end
96
-
97
- # @return [void]
98
- def direct_connect_switch_via_bluetooth
99
- ProconBypassMan.logger.debug { "direct_connect_switch_via_bluetooth!" }
100
- self.procon.write_nonblock(["010500000000000000003800"].pack("H*")) # home led off
101
- self.procon.write_nonblock(["010600000000000000003800"].pack("H*")) # home led off
102
- self.procon.write_nonblock(["010700000000000000003800"].pack("H*")) # home led off
103
- self.procon.write_nonblock(["010800000000000000003800"].pack("H*")) # home led off
104
- self.procon.write_nonblock(["8005"].pack("H*"))
105
- self.procon.write_nonblock(["8005"].pack("H*"))
106
- self.procon.write_nonblock(["8005"].pack("H*"))
107
- end
108
-
109
- # @return [void] 入力してから取り出さないと接続しっぱなしになるっぽいのでこれが必要っぽい
110
- def be_empty_procon
111
- # タイムアウトまでブロッキングされるので、プロセスに逃す
112
- end
113
- 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"
@@ -47,14 +47,15 @@ class ProconBypassMan::Configuration
47
47
  def fallback_setting_path
48
48
  "/tmp/procon_bypass_man_fallback_setting.yaml"
49
49
  end
50
-
51
- def io_monitor_logging
52
- config.io_monitor_logging
53
- end
54
50
  end
55
51
 
56
52
  attr_accessor :enable_critical_error_logging
57
- attr_writer :verbose_bypass_log, :raw_setting, :enable_reporting_pressed_buttons, :never_exit_accidentally, :io_monitor_logging, :enable_home_led_on_connect
53
+ attr_writer :verbose_bypass_log, :raw_setting, :never_exit_accidentally, :enable_home_led_on_connect
54
+ # 削除予定
55
+ attr_writer :enable_reporting_pressed_buttons
56
+
57
+ # NOTE 非推奨. 削除したいが設定ファイルに残っているときにエラーにしたくないので互換性維持のため残す
58
+ attr_writer :io_monitor_logging
58
59
 
59
60
  def root=(path)
60
61
  @root = path
@@ -104,7 +105,7 @@ class ProconBypassMan::Configuration
104
105
 
105
106
  def error_logger
106
107
  if enable_critical_error_logging
107
- @error_logger ||= Logger.new("#{ProconBypassMan.root}/error.log", 5, 1024 * 1024 * 10)
108
+ @error_logger ||= Logger.new("#{ProconBypassMan.root}/error.log", 1, 1024 * 1024 * 1)
108
109
  else
109
110
  Logger.new(File.open("/dev/null"))
110
111
  end
@@ -114,35 +115,14 @@ class ProconBypassMan::Configuration
114
115
  "#{root}/.setting_yaml_digest"
115
116
  end
116
117
 
117
- # @return [String] pbm-webの接続先
118
- def internal_api_servers
119
- if !!ENV["INTERNAL_API_SERVER"]
120
- [ENV["INTERNAL_API_SERVER"]]
121
- else
122
- [ 'http://localhost:9090',
123
- 'http://localhost:8080',
124
- ].compact
125
- end
126
- end
127
-
128
- # @return [Array<ProconBypassMan::ServerPool>]
129
- def internal_server_pool
130
- @internal_server_pool ||= ProconBypassMan::ServerPool.new(servers: internal_api_servers)
131
- end
132
-
133
- # @return [Array<ProconBypassMan::ServerPool>]
134
- def server_pool
135
- @server_pool ||= ProconBypassMan::ServerPool.new(servers: api_servers)
136
- end
137
-
138
118
  # @return [String, NilClass]
139
- def current_server
140
- server_pool.server
119
+ def api_server
120
+ api_servers&.first
141
121
  end
142
122
 
143
123
  # @return [String, NilClass]
144
124
  def current_ws_server
145
- if (uri = URI.parse(server_pool.server))
125
+ if (uri = URI.parse(api_server))
146
126
  if uri.port == 443
147
127
  return "ws://#{uri.host}"
148
128
  else
@@ -161,7 +141,7 @@ class ProconBypassMan::Configuration
161
141
 
162
142
  # @return [Boolean]
163
143
  def enable_ws?
164
- !!current_server
144
+ !!api_server
165
145
  end
166
146
 
167
147
  # @return [Boolean]
@@ -178,8 +158,9 @@ class ProconBypassMan::Configuration
178
158
  end
179
159
  end
180
160
 
161
+ # @return [Boolean]
181
162
  def has_api_server?
182
- not api_servers.length.zero?
163
+ !!api_server
183
164
  end
184
165
 
185
166
  def verbose_bypass_log
@@ -190,19 +171,14 @@ class ProconBypassMan::Configuration
190
171
  @raw_setting ||= {}
191
172
  end
192
173
 
193
- # @return [Boolean] default false
194
- def enable_reporting_pressed_buttons
195
- @enable_reporting_pressed_buttons ||= false
196
- end
197
-
198
174
  # @return [Boolean] default false
199
175
  def never_exit_accidentally
200
176
  @never_exit_accidentally || false
201
177
  end
202
178
 
203
- # @return [Boolean] default false
204
- def io_monitor_logging
205
- @io_monitor_logging ||= false
179
+ # @return [Boolean] プロコンから「入力にかかっている時間」と「1秒間あたり何回入力できているか」をサーバに送信する
180
+ def enable_procon_performance_measurement?
181
+ has_api_server?
206
182
  end
207
183
 
208
184
  # @return [Boolean] default true
@@ -24,6 +24,7 @@ class ProconBypassMan::DeviceConnection::OutputReportSubCommandTable
24
24
  IGNORE_SUB_COMMANDS = {
25
25
  "48-01" => true,
26
26
  "04-00" => true,
27
+ "10-28" => true, # 返ってこないことがあった
27
28
  }
28
29
  # レスポンスに引数が含まれない
29
30
  SPECIAL_SUB_COMMANDS = [
@@ -46,7 +47,6 @@ class ProconBypassMan::DeviceConnection::OutputReportSubCommandTable
46
47
  "10-80",
47
48
  "10-98",
48
49
  "10-10",
49
- "10-28",
50
50
  "30-",
51
51
  "40-",
52
52
  "48-", # Enable vibration