procon_bypass_man 0.1.20.2 → 0.1.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +9 -5
  3. data/.github/workflows/ruby.yml +1 -1
  4. data/.gitignore +1 -0
  5. data/.rspec +1 -0
  6. data/CHANGELOG.md +30 -1
  7. data/Gemfile.lock +4 -4
  8. data/README.md +4 -1
  9. data/docs/getting_started.md +81 -11
  10. data/docs/setting/left-analogstick-cap.md +1 -1
  11. data/docs/setting/splatoon2_macro_dasei_cancel.md +77 -0
  12. data/docs/setting/splatoon2_macro_sokuwari_bubble.md +4 -0
  13. data/docs/setting/splatoon2_shake_tansan.md +47 -0
  14. data/lib/procon_bypass_man/background/jobs/post_completed_remote_macro_job.rb +17 -0
  15. data/lib/procon_bypass_man/background.rb +1 -0
  16. data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +155 -70
  17. data/lib/procon_bypass_man/buttons_setting_configuration/loader.rb +2 -0
  18. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/button.rb +28 -0
  19. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/button_list.rb +31 -0
  20. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/disable_macro_if_pressed.rb +28 -0
  21. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/flip_if_pressed.rb +31 -0
  22. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/force_neutral.rb +28 -0
  23. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/if_pressed.rb +26 -0
  24. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/if_pressed_allows_nil.rb +28 -0
  25. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer/open_macro_steps.rb +26 -0
  26. data/lib/procon_bypass_man/buttons_setting_configuration/param_normalizer.rb +17 -0
  27. data/lib/procon_bypass_man/buttons_setting_configuration.rb +6 -5
  28. data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +4 -0
  29. data/lib/procon_bypass_man/bypass.rb +45 -23
  30. data/lib/procon_bypass_man/commands/bypass_command.rb +30 -10
  31. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +1 -1
  32. data/lib/procon_bypass_man/configuration.rb +8 -1
  33. data/lib/procon_bypass_man/device_connector.rb +55 -174
  34. data/lib/procon_bypass_man/plugin/splatoon2/macro/charge_tansan_bomb.rb +21 -0
  35. data/lib/procon_bypass_man/plugin/splatoon2/macro/dasei_cancel.rb +21 -0
  36. data/lib/procon_bypass_man/plugin/splatoon2/version.rb +1 -1
  37. data/lib/procon_bypass_man/plugins.rb +2 -0
  38. data/lib/procon_bypass_man/procon/analog_stick_cap.rb +4 -23
  39. data/lib/procon_bypass_man/procon/analog_stick_manipulator.rb +36 -0
  40. data/lib/procon_bypass_man/procon/button_collection.rb +0 -8
  41. data/lib/procon_bypass_man/procon/layer_changer.rb +4 -1
  42. data/lib/procon_bypass_man/procon/macro.rb +53 -25
  43. data/lib/procon_bypass_man/procon/macro_builder.rb +43 -35
  44. data/lib/procon_bypass_man/procon/macro_plugin_map.rb +23 -0
  45. data/lib/procon_bypass_man/procon/macro_registry.rb +26 -10
  46. data/lib/procon_bypass_man/procon/suppress_rumble.rb +13 -0
  47. data/lib/procon_bypass_man/procon/user_operation.rb +30 -16
  48. data/lib/procon_bypass_man/procon/value_objects/analog_stick.rb +9 -5
  49. data/lib/procon_bypass_man/procon/value_objects/analog_stick_position.rb +18 -0
  50. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/base.rb +0 -0
  51. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/has_immutable_binary.rb +0 -0
  52. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/has_mutable_binary.rb +0 -0
  53. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/inbound_procon_binary.rb +5 -0
  54. data/lib/procon_bypass_man/{domains → procon/value_objects}/binary/processing_procon_binary.rb +7 -2
  55. data/lib/procon_bypass_man/procon/value_objects/binary.rb +11 -0
  56. data/lib/procon_bypass_man/{bypass → procon/value_objects}/bypass_mode.rb +0 -0
  57. data/lib/procon_bypass_man/procon/value_objects/rumble_binary.rb +18 -0
  58. data/lib/procon_bypass_man/procon.rb +59 -17
  59. data/lib/procon_bypass_man/remote_macro/queue_over_process.rb +62 -0
  60. data/lib/procon_bypass_man/remote_macro/remote_macro_object.rb +30 -0
  61. data/lib/procon_bypass_man/remote_macro/remote_macro_receiver.rb +37 -0
  62. data/lib/procon_bypass_man/remote_macro/remote_macro_sender.rb +8 -0
  63. data/lib/procon_bypass_man/remote_macro/task.rb +6 -0
  64. data/lib/procon_bypass_man/remote_macro/task_queue.rb +13 -0
  65. data/lib/procon_bypass_man/remote_macro.rb +14 -0
  66. data/lib/procon_bypass_man/remote_pbm_action/value_objects/remote_pbm_action_object.rb +1 -1
  67. data/lib/procon_bypass_man/remote_pbm_action.rb +1 -0
  68. data/lib/procon_bypass_man/runner.rb +11 -7
  69. data/lib/procon_bypass_man/support/analog_stick_hypotenuse_tilting_power_scaler.rb +59 -0
  70. data/lib/procon_bypass_man/support/cycle_sleep.rb +22 -0
  71. data/lib/procon_bypass_man/support/device_mouse_finder.rb +60 -0
  72. data/lib/procon_bypass_man/{device_procon_finder.rb → support/device_procon_finder.rb} +0 -2
  73. data/lib/procon_bypass_man/{never_exit_accidentally.rb → support/never_exit_accidentally.rb} +0 -0
  74. data/lib/procon_bypass_man/support/remote_macro_http_client.rb +9 -0
  75. data/lib/procon_bypass_man/support/safe_timeout.rb +7 -1
  76. data/lib/procon_bypass_man/{usb_device_controller.rb → support/usb_device_controller.rb} +7 -4
  77. data/lib/procon_bypass_man/version.rb +1 -1
  78. data/lib/procon_bypass_man/websocket/{pbm_job_client.rb → client.rb} +34 -12
  79. data/lib/procon_bypass_man/websocket/forever.rb +47 -0
  80. data/lib/procon_bypass_man/websocket/watchdog.rb +19 -0
  81. data/lib/procon_bypass_man.rb +25 -23
  82. data/procon_bypass_man.gemspec +1 -1
  83. data/project_template/app.rb +13 -4
  84. data/sig/main.rbs +21 -13
  85. metadata +46 -14
  86. data/lib/procon_bypass_man/domains.rb +0 -11
@@ -1,13 +1,12 @@
1
1
  require "procon_bypass_man/bypass/usb_hid_logger"
2
- require "procon_bypass_man/bypass/bypass_mode"
3
2
 
4
3
  class ProconBypassMan::Bypass
5
4
  include ProconBypassMan::Bypass::UsbHidLogger
6
5
 
7
- class BypassValue < Struct.new(:binary, :sent)
6
+ class BypassValue < Struct.new(:binary)
8
7
  def to_text
9
8
  return unless binary
10
- "#{binary.unpack.first} #{'x' unless sent}"
9
+ binary.unpack.first
11
10
  end
12
11
  end
13
12
 
@@ -22,23 +21,32 @@ class ProconBypassMan::Bypass
22
21
  # ゆっくりでいい
23
22
  def send_gadget_to_procon!
24
23
  monitor.record(:start_function)
25
- input = nil
26
- self.bypass_value = BypassValue.new(nil, sent = false)
24
+ self.bypass_value = BypassValue.new(nil)
27
25
 
28
26
  run_callbacks(:send_gadget_to_procon) do
27
+ break if $will_terminate_token
28
+
29
+ raw_input = nil
29
30
  begin
30
- break if $will_terminate_token
31
31
  # TODO blocking readにしたいが、接続時のフェーズによって長さが違うので厳しい
32
- input = self.gadget.read_nonblock(64)
33
- self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: input)
32
+ raw_input = self.gadget.read_nonblock(64)
33
+ self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_input)
34
34
  rescue IO::EAGAINWaitReadable
35
35
  monitor.record(:eagain_wait_readable_on_read)
36
36
  end
37
37
 
38
- if input
38
+ if self.bypass_value.binary
39
39
  begin
40
- self.procon.write_nonblock(input)
41
- self.bypass_value.sent = true
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)
42
50
  rescue IO::EAGAINWaitReadable
43
51
  monitor.record(:eagain_wait_readable_on_write)
44
52
  break
@@ -51,15 +59,15 @@ class ProconBypassMan::Bypass
51
59
 
52
60
  def send_procon_to_gadget!
53
61
  monitor.record(:start_function)
54
- output = nil
55
- self.bypass_value = BypassValue.new(nil, sent = false)
62
+ self.bypass_value = BypassValue.new(nil)
56
63
 
57
64
  run_callbacks(:send_procon_to_gadget) do
65
+ break if $will_terminate_token
66
+
58
67
  begin
59
- break if $will_terminate_token
60
68
  Timeout.timeout(1) do
61
- output = self.procon.read(64)
62
- self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: output)
69
+ raw_output = self.procon.read(64)
70
+ self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_output)
63
71
  end
64
72
  rescue Timeout::Error
65
73
  ProconBypassMan.logger.debug { "read timeout! do sleep. by send_procon_to_gadget!" }
@@ -74,16 +82,10 @@ class ProconBypassMan::Bypass
74
82
  retry
75
83
  end
76
84
 
77
- # blocking readをしているのでnilが入ることはないが、雑なテストでnilが通るので分岐を入れる。できれば消したい
78
- break if output.nil?
79
-
80
85
  begin
81
86
  self.gadget.write_nonblock(
82
- ProconBypassMan::Processor.new(
83
- ProconBypassMan::Domains::InboundProconBinary.new(binary: output)
84
- ).process
87
+ ProconBypassMan::Processor.new(bypass_value.binary).process
85
88
  )
86
- self.bypass_value.sent = true
87
89
  rescue IO::EAGAINWaitReadable
88
90
  monitor.record(:eagain_wait_readable_on_write)
89
91
  break
@@ -91,4 +93,24 @@ class ProconBypassMan::Bypass
91
93
  end
92
94
  monitor.record(:end_function)
93
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(["8005"].pack("H*"))
101
+ self.procon.write_nonblock(["8005"].pack("H*"))
102
+ self.procon.write_nonblock(["8005"].pack("H*"))
103
+ end
104
+
105
+ # @return [void] 入力してから取り出さないと接続しっぱなしになるっぽいのでこれが必要っぽい
106
+ def be_empty_procon
107
+ timer = ProconBypassMan::SafeTimeout.new(timeout: Time.now + 5)
108
+ loop do
109
+ break if timer.timeout?
110
+ output = self.procon.read_nonblock(64)
111
+ ProconBypassMan.logger.debug { "[ProconBypassMan::Bypass#be_empty_procon] #{output.unpack("H*").first}" }
112
+ rescue IO::EAGAINWaitReadable
113
+ # no-op
114
+ end
115
+ end
94
116
  end
@@ -1,6 +1,11 @@
1
1
  class ProconBypassMan::BypassCommand
2
2
  include ProconBypassMan::SignalHandler
3
3
 
4
+ module WILL_TERMINATE_TOKEN
5
+ TERMINATE = :terminate
6
+ RESTART = :restart
7
+ end
8
+
4
9
  def initialize(gadget:, procon:)
5
10
  @gadget = gadget
6
11
  @procon = procon
@@ -12,7 +17,7 @@ class ProconBypassMan::BypassCommand
12
17
 
13
18
  def execute
14
19
  self_read, self_write = IO.pipe
15
- %w(TERM INT).each do |sig|
20
+ %w(TERM INT USR2).each do |sig|
16
21
  begin
17
22
  trap sig do
18
23
  self_write.puts(sig)
@@ -28,17 +33,19 @@ class ProconBypassMan::BypassCommand
28
33
  monitor2 = ProconBypassMan::IOMonitor.new(label: "procon -> switch")
29
34
  ProconBypassMan.logger.info "Thread1を起動します"
30
35
 
31
- @send_interval = 0.005
36
+ cycle_sleep = ProconBypassMan::CycleSleep.new(cycle_interval: 0.005, execution_cycle: 0)
32
37
 
33
38
  t1 = Thread.new do
34
39
  timer = ProconBypassMan::SafeTimeout.new(timeout: Time.now + 10)
35
40
  @did_first_step = false
36
41
  loop do
37
- bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor1)
38
42
  break if $will_terminate_token
39
- !@did_first_step && timer.throw_if_timeout!
40
- bypass.send_gadget_to_procon!
41
- sleep(@send_interval)
43
+
44
+ cycle_sleep.sleep_or_execute do
45
+ bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor1)
46
+ !@did_first_step && timer.throw_if_timeout!
47
+ bypass.send_gadget_to_procon!
48
+ end
42
49
  rescue ProconBypassMan::SafeTimeout::Timeout
43
50
  case ProconBypassMan.config.bypass_mode.mode
44
51
  when ProconBypassMan::BypassMode::TYPE_AGGRESSIVE
@@ -47,7 +54,7 @@ class ProconBypassMan::BypassCommand
47
54
  break
48
55
  when ProconBypassMan::BypassMode::TYPE_NORMAL
49
56
  ProconBypassMan.logger.info "10秒経過したのでsend_intervalを長くします"
50
- @send_interval = ProconBypassMan.config.bypass_mode.gadget_to_procon_interval
57
+ cycle_sleep = ProconBypassMan::CycleSleep.new(cycle_interval: 1, execution_cycle: ProconBypassMan.config.bypass_mode.gadget_to_procon_interval)
51
58
  else
52
59
  raise "unknown type"
53
60
  end
@@ -69,7 +76,14 @@ class ProconBypassMan::BypassCommand
69
76
  t2 = Thread.new do
70
77
  bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor2)
71
78
  loop do
72
- break if $will_terminate_token
79
+ if $will_terminate_token
80
+ if $will_terminate_token == WILL_TERMINATE_TOKEN::TERMINATE
81
+ bypass.direct_connect_switch_via_bluetooth
82
+ bypass.be_empty_procon
83
+ end
84
+ break
85
+ end
86
+
73
87
  bypass.send_procon_to_gadget!
74
88
  rescue EOFError => e
75
89
  ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
@@ -87,12 +101,18 @@ class ProconBypassMan::BypassCommand
87
101
  signal = readable_io.first[0].gets.strip
88
102
  handle_signal(signal)
89
103
  end
104
+ rescue ProconBypassMan::Runner::InterruptForRestart
105
+ $will_terminate_token = WILL_TERMINATE_TOKEN::RESTART
106
+ [t1, t2].each(&:join)
107
+ @gadget&.close
108
+ @procon&.close
109
+ exit! 1 # child processなのでexitしていい
90
110
  rescue Interrupt
91
- $will_terminate_token = true
111
+ $will_terminate_token = WILL_TERMINATE_TOKEN::TERMINATE
92
112
  [t1, t2].each(&:join)
93
113
  @gadget&.close
94
114
  @procon&.close
95
- exit 1 # child processなのでexitしていい
115
+ exit! 1 # child processなのでexitしていい
96
116
  end
97
117
  end
98
118
  end
@@ -42,7 +42,7 @@ class ProconBypassMan::PrintBootMessageCommand
42
42
  uptime from boot: #{@table[:uptime_from_boot]} sec
43
43
  use_pbmenv: #{@table[:use_pbmenv]}
44
44
  session_id: #{ProconBypassMan.session_id}
45
- device_id: #{ProconBypassMan.device_id}
45
+ device_id: #{ProconBypassMan.device_id.gsub(/.{25}$/, "*"*25)}
46
46
  bypass_mode: #{ProconBypassMan.config.bypass_mode}
47
47
  ----
48
48
  EOF
@@ -156,7 +156,14 @@ class ProconBypassMan::Configuration
156
156
  end
157
157
 
158
158
  # @return [Boolean]
159
- def enable_ws?; !!current_server; end
159
+ def enable_ws?
160
+ !!current_server
161
+ end
162
+
163
+ # @return [Boolean]
164
+ def enable_remote_macro?
165
+ enable_ws?
166
+ end
160
167
 
161
168
  # @return [Array<String>]
162
169
  def api_servers
@@ -1,25 +1,27 @@
1
+ require "timeout"
2
+
1
3
  class ProconBypassMan::DeviceConnector
2
4
  class BytesMismatchError < StandardError; end
3
5
  class NotFoundProconError < StandardError; end
4
6
 
5
7
  class Value
6
- attr_accessor :read_from, :values
7
- def initialize(values: , read_from: )
8
+ attr_accessor :read_from, :values, :call_block_if_receive, :block
9
+
10
+ def initialize(values: , read_from: , call_block_if_receive: false, &block)
8
11
  @values = values
9
12
  @read_from = read_from
13
+ @call_block_if_receive = call_block_if_receive
14
+ @block = block
10
15
  end
11
16
  end
12
17
 
13
- PROCON_PATH = "/dev/hidraw0"
14
- PROCON2_PATH = "/dev/hidraw1"
15
-
16
18
  def self.connect
17
- s = new(throw_error_if_timeout: true, enable_at_exit: false)
19
+ s = new(throw_error_if_timeout: true)
18
20
  s.add([
19
21
  ["0000"],
20
22
  ["0000"],
21
23
  ["8005"],
22
- ["0010"],
24
+ ["0000"],
23
25
  ], read_from: :switch)
24
26
  # 1. Sends current connection status, and if the Joy-Con are connected,
25
27
  s.add([["8001"]], read_from: :switch)
@@ -29,23 +31,30 @@ class ProconBypassMan::DeviceConnector
29
31
  s.add([/^8102/], read_from: :procon)
30
32
  # 3
31
33
  s.add([/^0100/], read_from: :switch)
32
- s.add([/^21/], read_from: :procon)
34
+ s.add([/^21/], read_from: :procon, call_block_if_receive: /^8101/) do |this|
35
+ ProconBypassMan.logger.info "(start special route)"
36
+ this.blocking_read_with_timeout_from_procon # <<< 810100032dbd42e9b698000
37
+ this.write_to_procon("8002")
38
+ this.blocking_read_with_timeout_from_procon # <<< 8102
39
+ this.write_to_procon("01000000000000000000033000000000000000000000000000000000000000000000000000000000000000000000000000")
40
+ this.blocking_read_with_timeout_from_procon # <<< 21
41
+ end
42
+
33
43
  # 4. Forces the Joy-Con or Pro Controller to only talk over USB HID without any timeouts. This is required for the Pro Controller to not time out and revert to Bluetooth.
34
44
  s.add([["8004"]], read_from: :switch)
35
45
  s.drain_all
36
46
  return [s.switch, s.procon]
37
47
  end
38
48
 
39
- def initialize(throw_error_if_timeout: false, throw_error_if_mismatch: false , enable_at_exit: true)
40
- @stack = []
49
+ def initialize(throw_error_if_timeout: false, throw_error_if_mismatch: false)
50
+ @queue = []
41
51
  @initialized_devices = false
42
52
  @throw_error_if_timeout = throw_error_if_timeout
43
53
  @throw_error_if_mismatch = throw_error_if_mismatch
44
- @enable_at_exit = enable_at_exit
45
54
  end
46
55
 
47
- def add(values, read_from: )
48
- @stack << Value.new(values: values, read_from: read_from)
56
+ def add(values, read_from: , call_block_if_receive: false, &block)
57
+ @queue << Value.new(values: values, read_from: read_from, call_block_if_receive: call_block_if_receive, &block)
49
58
  end
50
59
 
51
60
  def drain_all
@@ -54,181 +63,47 @@ class ProconBypassMan::DeviceConnector
54
63
  init_devices
55
64
  end
56
65
 
57
- while(item = @stack.shift)
66
+ while(item = @queue.shift)
58
67
  item.values.each do |value|
59
- data = nil
68
+ raw_data = nil
60
69
  timer = ProconBypassMan::SafeTimeout.new
61
70
  begin
62
71
  timer.throw_if_timeout!
63
- data = from_device(item).read_nonblock(64)
64
- debug_log_buffer << "read_from(#{item.read_from}): #{data.unpack("H*")}"
72
+ raw_data = from_device(item).read_nonblock(64)
73
+ debug_log_buffer << "read_from(#{item.read_from}): #{raw_data.unpack("H*")}"
65
74
  rescue IO::EAGAINWaitReadable
66
75
  # debug_log_buffer << "read_from(#{item.read_from}): IO::EAGAINWaitReadable"
67
76
  retry
68
77
  end
69
78
 
79
+ if item.call_block_if_receive =~ raw_data.unpack("H*").first
80
+ raw_data = item.block.call(self)
81
+ end
82
+
70
83
  result =
71
84
  case value
72
85
  when String, Array
73
- value == data.unpack("H*")
86
+ value == raw_data.unpack("H*")
74
87
  when Regexp
75
- value =~ data.unpack("H*").first
88
+ value =~ raw_data.unpack("H*").first
76
89
  else
77
90
  raise "#{value}は知りません"
78
91
  end
79
92
  if result
80
- ProconBypassMan.logger.info "OK(expected: #{value}, got: #{data.unpack("H*")})"
81
- debug_log_buffer << "OK(expected: #{value}, got: #{data.unpack("H*")})"
93
+ ProconBypassMan.logger.info "OK(expected: #{value}, got: #{raw_data.unpack("H*")})"
94
+ debug_log_buffer << "OK(expected: #{value}, got: #{raw_data.unpack("H*")})"
82
95
  else
83
- ProconBypassMan.logger.info "NG(expected: #{value}, got: #{data.unpack("H*")})"
84
- debug_log_buffer << "NG(expected: #{value}, got: #{data.unpack("H*")})"
85
- raise BytesMismatchError if @throw_error_if_mismatch
96
+ ProconBypassMan.logger.info "NG(expected: #{value}, got: #{raw_data.unpack("H*")})"
97
+ debug_log_buffer << "NG(expected: #{value}, got: #{raw_data.unpack("H*")})"
98
+ raise BytesMismatchError.new(debug_log_buffer) if @throw_error_if_mismatch
86
99
  end
87
- to_device(item).write_nonblock(data)
100
+ to_device(item).write_nonblock(raw_data)
88
101
  end
89
102
  end
90
- rescue ProconBypassMan::SafeTimeout::Timeout
91
- ProconBypassMan.logger.error "timeoutになりました"
92
- copressed_buffer_text = ProconBypassMan::CompressArray.new(debug_log_buffer).compress.join("\n")
93
- ProconBypassMan::SendErrorCommand.execute(error: copressed_buffer_text)
94
- raise if @throw_error_if_timeout
95
- end
96
-
97
- # switchに任意の命令を入力して、switchから読み取る
98
- def write_switch(data, only_write: false)
99
- if data.encoding.name == "UTF-8"
100
- data = [data].pack("H*")
101
- end
102
- unless @initialized_devices
103
- init_devices
104
- end
105
-
106
- timer = ProconBypassMan::SafeTimeout.new
107
- data = nil
108
- begin
109
- timer.throw_if_timeout!
110
- switch.write_nonblock(data)
111
- rescue IO::EAGAINWaitReadable
112
- retry
113
- rescue ProconBypassMan::SafeTimeout::Timeout
114
- ProconBypassMan.logger.error "writeでtimeoutになりました"
115
- raise
116
- end
117
- return(data.unpack("H*")) if only_write
118
-
119
- timer = ProconBypassMan::SafeTimeout.new
120
- begin
121
- timer.throw_if_timeout!
122
- data = switch.read_nonblock(64)
123
- ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
124
- rescue IO::EAGAINWaitReadable
125
- retry
126
- rescue ProconBypassMan::SafeTimeout::Timeout
127
- ProconBypassMan.logger.error "readでtimeoutになりました"
128
- raise
129
- end
130
- rescue ProconBypassMan::SafeTimeout::Timeout
131
- raise if @throw_error_if_timeout
132
- end
133
-
134
- def write_procon(data, only_write: false)
135
- if data.encoding.name == "UTF-8"
136
- data = [data].pack("H*")
137
- end
138
- unless @initialized_devices
139
- init_devices
140
- end
141
-
142
- timer = ProconBypassMan::SafeTimeout.new
143
- begin
144
- timer.throw_if_timeout!
145
- procon.write_nonblock(data)
146
- rescue IO::EAGAINWaitReadable
147
- retry
148
- rescue ProconBypassMan::SafeTimeout::Timeout
149
- ProconBypassMan.logger.error "writeでtimeoutになりました"
150
- raise
151
- end
152
- return(data.unpack("H*")) if only_write
153
-
154
- timer = ProconBypassMan::SafeTimeout.new
155
- begin
156
- timer.throw_if_timeout!
157
- data = procon.read_nonblock(64)
158
- ProconBypassMan.logger.error " <<< #{data.unpack("H*")})"
159
- rescue IO::EAGAINWaitReadable
160
- retry
161
- rescue ProconBypassMan::SafeTimeout::Timeout
162
- ProconBypassMan.logger.error "readでtimeoutになりました"
163
- raise
164
- end
165
- rescue ProconBypassMan::SafeTimeout::Timeout
166
- raise if @throw_error_if_timeout
167
- end
168
-
169
- def read_procon(only_read: false)
170
- unless @initialized_devices
171
- init_devices
172
- end
173
-
174
- data = nil
175
- timer = ProconBypassMan::SafeTimeout.new
176
- begin
177
- timer.throw_if_timeout!
178
- data = procon.read_nonblock(64)
179
- ProconBypassMan.logger.debug { " <<< #{data.unpack("H*")})" }
180
- rescue IO::EAGAINWaitReadable
181
- retry
182
- rescue ProconBypassMan::SafeTimeout::Timeout
183
- ProconBypassMan.logger.error "readでtimeoutになりました"
184
- raise
185
- end
186
- return(data.unpack("H*")) if only_read
187
-
188
- timer = ProconBypassMan::SafeTimeout.new
189
- begin
190
- timer.throw_if_timeout!
191
- switch.write_nonblock(data)
192
- rescue IO::EAGAINWaitReadable
193
- retry
194
- rescue ProconBypassMan::SafeTimeout::Timeout
195
- ProconBypassMan.logger.error "writeでtimeoutになりました"
196
- raise
197
- end
198
- rescue ProconBypassMan::SafeTimeout::Timeout
199
- raise if @throw_error_if_timeout
200
- end
201
-
202
- def read_switch(only_read: false)
203
- unless @initialized_devices
204
- init_devices
205
- end
206
-
207
- data = nil
208
- timer = ProconBypassMan::SafeTimeout.new
209
- begin
210
- timer.throw_if_timeout!
211
- data = switch.read_nonblock(64)
212
- ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
213
- rescue IO::EAGAINWaitReadable
214
- retry
215
- rescue ProconBypassMan::SafeTimeout::Timeout
216
- ProconBypassMan.logger.error "readでtimeoutになりました"
217
- raise
218
- end
219
- return(data.unpack("H*")) if only_read
220
-
221
- timer = ProconBypassMan::SafeTimeout.new
222
- begin
223
- timer.throw_if_timeout!
224
- procon.write_nonblock(data)
225
- rescue IO::EAGAINWaitReadable
226
- retry
227
- rescue ProconBypassMan::SafeTimeout::Timeout
228
- ProconBypassMan.logger.error "writeでtimeoutになりました"
229
- raise
230
- end
231
- rescue ProconBypassMan::SafeTimeout::Timeout
103
+ rescue ProconBypassMan::SafeTimeout::Timeout, Timeout::Error => e
104
+ ProconBypassMan.logger.error "timeoutになりました(#{e.message})"
105
+ compressed_buffer_text = ProconBypassMan::CompressArray.new(debug_log_buffer).compress.join("\n")
106
+ ProconBypassMan::SendErrorCommand.execute(error: compressed_buffer_text)
232
107
  raise if @throw_error_if_timeout
233
108
  end
234
109
 
@@ -280,17 +155,23 @@ class ProconBypassMan::DeviceConnector
280
155
  ProconBypassMan::UsbDeviceController.reset
281
156
 
282
157
  @initialized_devices = true
283
-
284
- if @enable_at_exit
285
- at_exit do
286
- @procon&.close
287
- @gadget&.close
288
- end
289
- end
290
158
  rescue Errno::ENXIO => e
291
159
  # /dev/hidg0 をopenできないときがある
292
160
  ProconBypassMan::SendErrorCommand.execute(error: "Errno::ENXIO (No such device or address @ rb_sysopen - /dev/hidg0)が起きました。resetします.\n #{e.full_message}")
293
161
  ProconBypassMan::UsbDeviceController.reset
294
162
  retry
295
163
  end
164
+
165
+ def blocking_read_with_timeout_from_procon
166
+ Timeout.timeout(4) do
167
+ raw_data = procon.read(64)
168
+ ProconBypassMan.logger.info "<<< #{raw_data.unpack("H*").first}"
169
+ return raw_data
170
+ end
171
+ end
172
+
173
+ def write_to_procon(data)
174
+ ProconBypassMan.logger.info ">>> #{data}"
175
+ procon.write_nonblock([data].pack("H*"))
176
+ end
296
177
  end
@@ -0,0 +1,21 @@
1
+ module ProconBypassMan
2
+ module Plugin
3
+ module Splatoon2
4
+ module Macro
5
+ module ChargeTansanBomb
6
+ def self.display_name
7
+ :charge_tansan_bomb
8
+ end
9
+
10
+ def self.steps
11
+ [:shake_left_stick_and_toggle_b_for_0_1sec].freeze
12
+ end
13
+
14
+ def self.description
15
+ 'タンサンボムのチャージ'
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module ProconBypassMan
2
+ module Plugin
3
+ module Splatoon2
4
+ module Macro
5
+ module DaseiCancel
6
+ def self.display_name
7
+ :dasei_cancel
8
+ end
9
+
10
+ def self.steps
11
+ [:pressing_r_for_0_03sec, :pressing_r_and_pressing_zl_for_0_2sec].freeze
12
+ end
13
+
14
+ def self.description
15
+ '惰性キャンセル'
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -3,7 +3,7 @@
3
3
  module ProconBypassMan
4
4
  module Plugin
5
5
  module Splatoon2
6
- VERSION = "0.1.3"
6
+ VERSION = "0.1.5"
7
7
  end
8
8
  end
9
9
  end
@@ -4,6 +4,8 @@ require_relative "plugin/splatoon2/macro/jump_to_right_key"
4
4
  require_relative "plugin/splatoon2/macro/jump_to_up_key"
5
5
  require_relative "plugin/splatoon2/macro/jump_to_left_key"
6
6
  require_relative "plugin/splatoon2/macro/sokuwari_for_splash_bomb"
7
+ require_relative "plugin/splatoon2/macro/dasei_cancel"
8
+ require_relative "plugin/splatoon2/macro/charge_tansan_bomb"
7
9
  require_relative "plugin/splatoon2/mode/guruguru"
8
10
 
9
11
  module ProconBypassMan
@@ -1,36 +1,17 @@
1
1
  class ProconBypassMan::Procon::AnalogStickCap
2
- class Position
3
- attr_accessor :x, :y
4
-
5
- def initialize(x:, y:)
6
- @x = x.to_i
7
- @y = y.to_i
8
- end
9
-
10
- def to_binary
11
- analog_stick_data = [
12
- (@x & "0xff".to_i(16)),
13
- ((@y << 4) & "0xf0".to_i(16)) | ((@x >> 8) & "0x0f".to_i(16)),
14
- (@y >> 4) & "0xff".to_i(16),
15
- ]
16
- hex = analog_stick_data.map{ |x| x.to_s(16).rjust(2, "0") }.join
17
- [hex].pack("H*")
18
- end
19
- end
20
-
21
2
  def initialize(binary)
22
3
  @binary = binary
23
4
  @analog_stick = ProconBypassMan::Procon::AnalogStick.new(binary: binary)
24
5
  end
25
6
 
26
- # @return [ProconBypassMan::Procon::AnalogStickCap::Position]
7
+ # @return [ProconBypassMan::AnalogStickPosition]
27
8
  def capped_position(cap_hypotenuse: )
28
9
  if hypotenuse > cap_hypotenuse
29
10
  relative_capped_x = cap_hypotenuse * Math.cos(rad * Math::PI / 180).abs
30
11
  relative_capped_y = cap_hypotenuse * Math.sin(rad * Math::PI / 180).abs
31
12
  relative_capped_x = -(relative_capped_x.abs) if relative_x.negative?
32
13
  relative_capped_y = -(relative_capped_y.abs) if relative_y.negative?
33
- return Position.new(
14
+ return ProconBypassMan::AnalogStickPosition.new(
34
15
  x: relative_capped_x + @analog_stick.neutral_position.x,
35
16
  y: relative_capped_y + @analog_stick.neutral_position.y,
36
17
  )
@@ -39,9 +20,9 @@ class ProconBypassMan::Procon::AnalogStickCap
39
20
  end
40
21
  end
41
22
 
42
- # @return [ProconBypassMan::Procon::AnalogStickCap::Position]
23
+ # @return [ProconBypassMan::AnalogStickPosition]
43
24
  def position
44
- Position.new(x: abs_x, y: abs_y)
25
+ ProconBypassMan::AnalogStickPosition.new(x: abs_x, y: abs_y)
45
26
  end
46
27
 
47
28
  def abs_x; @analog_stick.abs_x; end # 0, 0からのx