procon_bypass_man 0.1.15 → 0.1.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/Gemfile.lock +24 -6
  4. data/README.md +8 -0
  5. data/lib/ext/em_pure_ruby.rb +25 -0
  6. data/lib/procon_bypass_man/background.rb +0 -1
  7. data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +2 -6
  8. data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +1 -1
  9. data/lib/procon_bypass_man/bypass.rb +13 -6
  10. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +50 -1
  11. data/lib/procon_bypass_man/commands/print_message_command.rb +8 -0
  12. data/lib/procon_bypass_man/commands/run_remote_pbm_action_dispatch_command.rb +1 -1
  13. data/lib/procon_bypass_man/commands/send_reload_config_event_command.rb +1 -2
  14. data/lib/procon_bypass_man/commands.rb +1 -0
  15. data/lib/procon_bypass_man/configuration.rb +27 -0
  16. data/lib/procon_bypass_man/domains/binary/base.rb +11 -0
  17. data/lib/procon_bypass_man/domains/binary/has_immutable_binary.rb +5 -0
  18. data/lib/procon_bypass_man/domains/binary/has_mutable_binary.rb +5 -0
  19. data/lib/procon_bypass_man/domains/binary/inbound_procon_binary.rb +23 -0
  20. data/lib/procon_bypass_man/domains/binary/processing_procon_binary.rb +80 -0
  21. data/lib/procon_bypass_man/domains.rb +11 -0
  22. data/lib/procon_bypass_man/{plugin.rb → plugins.rb} +0 -0
  23. data/lib/procon_bypass_man/processor.rb +4 -5
  24. data/lib/procon_bypass_man/procon/button.rb +11 -0
  25. data/lib/procon_bypass_man/procon/button_collection.rb +2 -12
  26. data/lib/procon_bypass_man/procon/layer_changer.rb +3 -2
  27. data/lib/procon_bypass_man/procon/press_button_aware.rb +5 -4
  28. data/lib/procon_bypass_man/procon/user_operation.rb +46 -63
  29. data/lib/procon_bypass_man/procon/{analog_stick.rb → value_objects/analog_stick.rb} +3 -4
  30. data/lib/procon_bypass_man/procon/value_objects/procon_reader.rb +34 -0
  31. data/lib/procon_bypass_man/procon.rb +16 -14
  32. data/lib/procon_bypass_man/remote_pbm_action/{lib → commands}/update_remote_pbm_action_status_command.rb +0 -0
  33. data/lib/procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb +1 -1
  34. data/lib/procon_bypass_man/{value_objects → remote_pbm_action/value_objects}/remote_pbm_action_object.rb +0 -0
  35. data/lib/procon_bypass_man/remote_pbm_action.rb +1 -1
  36. data/lib/procon_bypass_man/runner.rb +3 -3
  37. data/lib/procon_bypass_man/scheduler.rb +0 -7
  38. data/lib/procon_bypass_man/version.rb +1 -1
  39. data/lib/procon_bypass_man/websocket/pbm_job_client.rb +79 -0
  40. data/lib/procon_bypass_man.rb +12 -6
  41. data/procon_bypass_man.gemspec +2 -0
  42. data/project_template/app.rb +1 -1
  43. data/sig/main.rbs +15 -1
  44. metadata +45 -10
  45. data/lib/procon_bypass_man/background/jobs/fetch_and_run_remote_pbm_action_job.rb +0 -29
  46. data/lib/procon_bypass_man/boot_message.rb +0 -48
  47. data/lib/procon_bypass_man/commands/run_local_shell_command.rb +0 -6
  48. data/lib/procon_bypass_man/procon_reader.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7820b087d86ac7338128dbfdebba48f8e3100d4a2163894962296e6526ea6b6e
4
- data.tar.gz: 43d3bd4d0b3d18a61edc2df29320ad345f6d9313de79b6bb732a2bf526a18e5a
3
+ metadata.gz: ece30577af00d56afa2e2e0be7e09d8328c9d7f8cc96c2e49d207a2bb423b867
4
+ data.tar.gz: faf86731651a110fd63ce977f65b76f46c31fe6215a2512d4c3a1ba545fd4f81
5
5
  SHA512:
6
- metadata.gz: 78f98474a1a3d6bf7a6a6420c36c51bc4c9ba835d35361b5bcd45623b3c9c5e3b8ef173d341bd026d324f78787bc020b6536e6deff658c8f073767d3ff0f664e
7
- data.tar.gz: 341d4645b6650594533dcf23b32e24a8e5acd8413fea428d21fa2d2a2b4af1636d312a1ebc3472d5dbcbce193157a4da459eb1314619c27342b93dd30b8a96b3
6
+ metadata.gz: 313d36b543a7c539effaabb6fca121a5112b4076a196ad52386924f3e043ad25e52c5c880a710c1d8aafc66d4a647b3387cebe0b82391eb4ccffa10dd1f4af65
7
+ data.tar.gz: 55e7a87c35f972e8537654b86a1f5e1815ed22144a4097e1993ad986666f1111972ce8ce1a744e56196c16957a56c328ba510b6b19af4ff8961ac989d216af20
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ ## [0.1.16] - 202
2
+ - websocket経由で外部サーバからの命令を受け取れるようになりました
3
+
1
4
  ## [0.1.15] - 2021-12-08
2
5
  - 外部サーバから設定ファイルのリストアができるようになりました
3
6
  - splatoon2 pluginのネームスペースを変更しました
data/Gemfile.lock CHANGED
@@ -1,12 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- procon_bypass_man (0.1.15)
4
+ procon_bypass_man (0.1.16)
5
+ action_cable_client
5
6
  pbmenv
7
+ sorted_set
6
8
 
7
9
  GEM
8
10
  remote: https://rubygems.org/
9
11
  specs:
12
+ action_cable_client (3.1.0)
13
+ websocket-eventmachine-client (>= 1.2.0)
10
14
  activesupport (6.1.4.1)
11
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
12
16
  i18n (>= 1.6, < 2)
@@ -17,6 +21,7 @@ GEM
17
21
  coderay (1.1.3)
18
22
  concurrent-ruby (1.1.9)
19
23
  diff-lcs (1.4.4)
24
+ eventmachine (1.2.7)
20
25
  ffi (1.15.4)
21
26
  i18n (1.8.11)
22
27
  concurrent-ruby (~> 1.0)
@@ -29,7 +34,7 @@ GEM
29
34
  mustermann (1.1.1)
30
35
  ruby2_keywords (~> 0.0.1)
31
36
  parallel (1.21.0)
32
- parser (3.0.2.0)
37
+ parser (3.0.3.2)
33
38
  ast (~> 2.4.1)
34
39
  pbmenv (0.1.6)
35
40
  pry (0.14.1)
@@ -44,7 +49,8 @@ GEM
44
49
  rb-inotify (0.10.1)
45
50
  ffi (~> 1.0)
46
51
  rbs (1.7.1)
47
- regexp_parser (2.1.1)
52
+ rbtree (0.4.4)
53
+ regexp_parser (2.2.0)
48
54
  rexml (3.2.5)
49
55
  rspec (3.10.0)
50
56
  rspec-core (~> 3.10.0)
@@ -68,23 +74,27 @@ GEM
68
74
  rubocop-ast (>= 1.12.0, < 2.0)
69
75
  ruby-progressbar (~> 1.7)
70
76
  unicode-display_width (>= 1.4.0, < 3.0)
71
- rubocop-ast (1.13.0)
77
+ rubocop-ast (1.14.0)
72
78
  parser (>= 3.0.1.1)
73
79
  ruby-progressbar (1.11.0)
74
80
  ruby2_keywords (0.0.5)
81
+ set (1.0.2)
75
82
  sinatra (2.1.0)
76
83
  mustermann (~> 1.0)
77
84
  rack (~> 2.2)
78
85
  rack-protection (= 2.1.0)
79
86
  tilt (~> 2.0)
80
- steep (0.46.0)
87
+ sorted_set (1.0.3)
88
+ rbtree
89
+ set (~> 1.0)
90
+ steep (0.47.0)
81
91
  activesupport (>= 5.1)
82
92
  language_server-protocol (>= 3.15, < 4.0)
83
93
  listen (~> 3.0)
84
94
  parallel (>= 1.0.0)
85
95
  parser (>= 3.0)
86
96
  rainbow (>= 2.2.2, < 4.0)
87
- rbs (>= 1.2.0)
97
+ rbs (~> 1.7.0)
88
98
  terminal-table (>= 2, < 4)
89
99
  terminal-table (3.0.2)
90
100
  unicode-display_width (>= 1.1.1, < 3)
@@ -94,6 +104,14 @@ GEM
94
104
  concurrent-ruby (~> 1.0)
95
105
  unicode-display_width (2.1.0)
96
106
  webrick (1.7.0)
107
+ websocket (1.2.9)
108
+ websocket-eventmachine-base (1.2.0)
109
+ eventmachine (~> 1.0)
110
+ websocket (~> 1.0)
111
+ websocket-native (~> 1.0)
112
+ websocket-eventmachine-client (1.3.0)
113
+ websocket-eventmachine-base (~> 1.0)
114
+ websocket-native (1.0.0)
97
115
  zeitwerk (2.5.1)
98
116
 
99
117
  PLATFORMS
data/README.md CHANGED
@@ -34,6 +34,14 @@ Switch <-- (PBM): ZR連打
34
34
  ## Plugins
35
35
  * https://github.com/splaplapla/procon_bypass_man-splatoon2
36
36
 
37
+ ## 関連ソフトウェア
38
+ * サーバソフトウェア(WIP)
39
+ * https://github.com/splaplapla/procon_bypass_man_cloud
40
+ * このサーバからOS自体の再起動、設定ファイルの変更、PBMのバージョンアップができます
41
+ * 自分でホストティングしてください
42
+ * pbmenv
43
+ * バージョンマネージャー
44
+
37
45
  ## FAQ
38
46
  * どうやって動かすの?
39
47
  * このツールはRaspberry Pi4をUSBガジェットモードで起動して有線でプロコンとSwitchに接続して使います
@@ -0,0 +1,25 @@
1
+ # https://github.com/eventmachine/eventmachine/pull/929 is not released yet.
2
+ # i will delete this patch if released.
3
+ module EventMachine
4
+ # @private
5
+ class Reactor
6
+ def run_timers
7
+ timers_to_delete = []
8
+ @timers.each {|t|
9
+ if t.first <= @current_loop_time
10
+ #@timers.delete t
11
+ timers_to_delete << t
12
+ EventMachine::event_callback "", TimerFired, t.last
13
+ else
14
+ break
15
+ end
16
+ }
17
+ timers_to_delete.map{|c| @timers.delete c}
18
+ timers_to_delete = nil
19
+ #while @timers.length > 0 and @timers.first.first <= now
20
+ # t = @timers.shift
21
+ # EventMachine::event_callback "", TimerFired, t.last
22
+ #end
23
+ end
24
+ end
25
+ end
@@ -10,5 +10,4 @@ require "procon_bypass_man/background/jobs/report_reload_config_job"
10
10
  require "procon_bypass_man/background/jobs/report_load_config_job"
11
11
  require "procon_bypass_man/background/jobs/report_error_job"
12
12
  require "procon_bypass_man/background/jobs/report_pressed_buttons_job"
13
- require "procon_bypass_man/background/jobs/fetch_and_run_remote_pbm_action_job"
14
13
  require "procon_bypass_man/background/jobs/sync_device_stats_job"
@@ -10,7 +10,6 @@ module ProconBypassMan
10
10
  self.remaps = {}
11
11
  self.left_analog_stick_caps = {}
12
12
  self.disables = []
13
- instance_eval(&block) if block_given?
14
13
  end
15
14
 
16
15
  # @param [Symbol] button
@@ -50,11 +49,8 @@ module ProconBypassMan
50
49
  end
51
50
  hash[:flip_interval] = interval
52
51
  end
53
- if self.flips[button]
54
- raise "#{button}への設定をすでに割り当て済みです"
55
- else
56
- self.flips[button] = hash
57
- end
52
+
53
+ self.flips[button] = hash
58
54
  end
59
55
 
60
56
  def macro(name, if_pressed: )
@@ -30,7 +30,7 @@ class ProconBypassMan::Bypass
30
30
 
31
31
  ProconBypassMan.cache.fetch key: 'pressed_buttons_reporter', expires_in: 5 do
32
32
  ProconBypassMan::ReportPressedButtonsJob.perform_async(
33
- ProconBypassMan::ProconReader.new(binary: bypass_value.binary).to_hash
33
+ bypass_value.binary.to_procon_reader.to_hash
34
34
  )
35
35
  end
36
36
  end
@@ -5,7 +5,7 @@ class ProconBypassMan::Bypass
5
5
 
6
6
  class BypassValue < Struct.new(:binary, :sent)
7
7
  def to_text
8
- "#{binary.unpack("H*").first} #{'x' unless sent}"
8
+ "#{binary.unpack.first} #{'x' unless sent}"
9
9
  end
10
10
  end
11
11
 
@@ -21,14 +21,14 @@ class ProconBypassMan::Bypass
21
21
  def send_gadget_to_procon!
22
22
  monitor.record(:start_function)
23
23
  input = nil
24
- self.bypass_value = BypassValue.new(input, sent = false)
24
+ self.bypass_value = BypassValue.new(nil, sent = false)
25
25
 
26
26
  run_callbacks(:send_gadget_to_procon) do
27
27
  begin
28
28
  break if $will_terminate_token
29
29
  # TODO blocking readにしたいが、接続時のフェーズによって長さが違うので厳しい
30
30
  input = self.gadget.read_nonblock(64)
31
- self.bypass_value.binary = input
31
+ self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: input)
32
32
  rescue IO::EAGAINWaitReadable
33
33
  monitor.record(:eagain_wait_readable_on_read)
34
34
  sleep(0.001)
@@ -50,14 +50,14 @@ class ProconBypassMan::Bypass
50
50
  def send_procon_to_gadget!
51
51
  monitor.record(:start_function)
52
52
  output = nil
53
- self.bypass_value = BypassValue.new(output, sent = false)
53
+ self.bypass_value = BypassValue.new(nil, sent = false)
54
54
 
55
55
  run_callbacks(:send_procon_to_gadget) do
56
56
  begin
57
57
  break if $will_terminate_token
58
58
  Timeout.timeout(1) do
59
59
  output = self.procon.read(64)
60
- self.bypass_value.binary = output
60
+ self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: output)
61
61
  end
62
62
  rescue Timeout::Error
63
63
  ProconBypassMan.logger.debug { "read timeout! do sleep. by send_procon_to_gadget!" }
@@ -72,8 +72,15 @@ class ProconBypassMan::Bypass
72
72
  retry
73
73
  end
74
74
 
75
+ # blocking readをしているのでnilが入ることはないが、雑なテストでnilが通るので分岐を入れる。できれば消したい
76
+ break if output.nil?
77
+
75
78
  begin
76
- self.gadget.write_nonblock(ProconBypassMan::Processor.new(output).process)
79
+ self.gadget.write_nonblock(
80
+ ProconBypassMan::Processor.new(
81
+ ProconBypassMan::Domains::InboundProconBinary.new(binary: output)
82
+ ).process
83
+ )
77
84
  self.bypass_value.sent = true
78
85
  rescue IO::EAGAINWaitReadable
79
86
  monitor.record(:eagain_wait_readable_on_write)
@@ -1,7 +1,56 @@
1
1
  class ProconBypassMan::PrintBootMessageCommand
2
+ class BootMessage
3
+ def initialize
4
+ @table = {}
5
+ @table[:ruby_version] = RUBY_VERSION
6
+ @table[:pbm_version] = ProconBypassMan::VERSION
7
+ @table[:pid] = $$
8
+ @table[:root_path] = ProconBypassMan.root
9
+ @table[:pid_path] = ProconBypassMan.pid_path
10
+ @table[:setting_path] = ProconBypassMan::ButtonsSettingConfiguration.instance.setting_path
11
+ @table[:uptime_from_boot] = ProconBypassMan::Uptime.from_boot
12
+ @table[:use_pbmenv] = !(!!`which pbmenv`.empty?)
13
+ @table[:session_id] = ProconBypassMan.session_id
14
+ @table[:device_id] = ProconBypassMan.device_id
15
+
16
+ # 開発中のHEADを取りたかったけど、Gem::Specification経由から取得する必要がありそう
17
+ # build_version = `git rev-parse --short HEAD`.chomp
18
+ # if build_version.empty?
19
+ # @table[:build_version] = 'release version'
20
+ # else
21
+ # @table[:build_version] = build_version
22
+ # end
23
+
24
+ # build version: #{@table[:build_version]}
25
+ end
26
+
27
+ # @return [String]
28
+ def to_s
29
+ booted_message = <<~EOF
30
+ ----
31
+ RUBY_VERSION: #{@table[:ruby_version]}
32
+ ProconBypassMan::VERSION: #{@table[:pbm_version]}
33
+ pid: #{@table[:pid]}
34
+ root: #{@table[:root_path]}
35
+ pid_path: #{@table[:pid_path]}
36
+ setting_path: #{@table[:setting_path]}
37
+ uptime from boot: #{@table[:uptime_from_boot]} sec
38
+ use_pbmenv: #{@table[:use_pbmenv]}
39
+ session_id: #{ProconBypassMan.session_id}
40
+ device_id: #{ProconBypassMan.device_id}
41
+ ----
42
+ EOF
43
+ end
44
+
45
+ # @return [Hash]
46
+ def to_hash
47
+ @table
48
+ end
49
+ end
50
+
2
51
  # @return [void]
3
52
  def self.execute
4
- message = ProconBypassMan::BootMessage.new
53
+ message = BootMessage.new
5
54
  ProconBypassMan::ReportBootJob.perform_async(message.to_hash)
6
55
  ProconBypassMan::ReportLoadConfigJob.perform_async(ProconBypassMan.config.raw_setting)
7
56
  puts message.to_s
@@ -0,0 +1,8 @@
1
+ class ProconBypassMan::PrintMessageCommand
2
+ # @return [void]
3
+ # @param [String] text
4
+ def self.execute(text: )
5
+ ProconBypassMan.logger.info text
6
+ puts text
7
+ end
8
+ end
@@ -13,7 +13,7 @@ class ProconBypassMan::RunRemotePbmActionDispatchCommand
13
13
  when ProconBypassMan::RemotePbmAction::ACTION_RESTORE_SETTING
14
14
  ProconBypassMan::RemotePbmAction::RestorePbmSettingAction.new(pbm_job_uuid: uuid).run!(job_args: job_args)
15
15
  else
16
- ProconBypassMan::SendErrorCommand.execute(error: "#{action}は対応していないアクションです")
16
+ raise "#{action}は対応していないアクションです"
17
17
  end
18
18
  rescue ProconBypassMan::RemotePbmAction::ActionUnexpectedError => e
19
19
  ProconBypassMan::SendErrorCommand.execute(error: e)
@@ -1,8 +1,7 @@
1
1
  class ProconBypassMan::SendReloadConfigEventCommand
2
2
  # @return [void]
3
3
  def self.execute
4
- puts "設定ファイルの再読み込みができました"
5
- ProconBypassMan.logger.info "設定ファイルの再読み込みができました"
4
+ ProconBypassMan::PrintMessageCommand.execute(text: "設定ファイルの再読み込みができました")
6
5
  ProconBypassMan::ReportReloadConfigJob.perform_async(
7
6
  ProconBypassMan.config.raw_setting
8
7
  )
@@ -1,4 +1,5 @@
1
1
  require "procon_bypass_man/commands/print_boot_message_command"
2
+ require "procon_bypass_man/commands/print_message_command"
2
3
  require "procon_bypass_man/commands/write_session_id_command"
3
4
  require "procon_bypass_man/commands/write_device_id_command"
4
5
  require "procon_bypass_man/commands/send_reload_config_event_command"
@@ -111,6 +111,33 @@ class ProconBypassMan::Configuration
111
111
  @server_pool ||= ProconBypassMan::ServerPool.new(servers: api_servers)
112
112
  end
113
113
 
114
+ # @return [String, NilClass]
115
+ def current_server
116
+ server_pool.server
117
+ end
118
+
119
+ # @return [String, NilClass]
120
+ def current_ws_server
121
+ if (uri = URI.parse(server_pool.server))
122
+ if uri.port == 443
123
+ return "ws://#{uri.host}"
124
+ else
125
+ return "ws://#{uri.host}:#{uri.port}"
126
+ end
127
+ end
128
+ rescue URI::InvalidURIError
129
+ nil
130
+ end
131
+
132
+ # @return [String, NilClass]
133
+ def current_ws_server_url
134
+ return unless current_ws_server
135
+ "#{current_ws_server}/websocket/"
136
+ end
137
+
138
+ # @return [Boolean]
139
+ def enable_ws?; !!current_server; end
140
+
114
141
  # @return [Array<String>]
115
142
  def api_servers
116
143
  if !!ENV["API_SERVER"]
@@ -0,0 +1,11 @@
1
+ class ProconBypassMan::Domains::Binary::Base
2
+ # @param [String] binary
3
+ def initialize(binary: )
4
+ @binary = binary
5
+ end
6
+
7
+ # @return [String] バイナリ
8
+ def binary
9
+ raise NotImplementedError
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module ProconBypassMan::Domains::HasImmutableBinary
2
+ def binary
3
+ @binary.freeze
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module ProconBypassMan::Domains::HasMutableBinary
2
+ def binary
3
+ @binary
4
+ end
5
+ end
@@ -0,0 +1,23 @@
1
+ # proconから取得したばかりのバイナリ
2
+ class ProconBypassMan::Domains::InboundProconBinary < ProconBypassMan::Domains::Binary::Base
3
+ include ProconBypassMan::Domains::HasImmutableBinary
4
+
5
+ # @return [String]
6
+ def raw
7
+ binary.dup
8
+ end
9
+
10
+ def unpack
11
+ binary.unpack("H*")
12
+ end
13
+
14
+ # @return [ProconBypassMan::ProconReader]
15
+ def to_procon_reader
16
+ ProconBypassMan::ProconReader.new(binary: binary)
17
+ end
18
+
19
+ # @return [Boolean]
20
+ def user_operation_data?
21
+ binary[0] == "\x30".b
22
+ end
23
+ end
@@ -0,0 +1,80 @@
1
+ # バイナリの書き換えのみをする
2
+ class ProconBypassMan::Domains::ProcessingProconBinary < ProconBypassMan::Domains::Binary::Base
3
+ include ProconBypassMan::Domains::HasMutableBinary
4
+
5
+ ALL_ZERO_BIT = ["0"].pack("H*").freeze
6
+
7
+ # @return [String]
8
+ def raw
9
+ binary
10
+ end
11
+
12
+ def unpack
13
+ binary.unpack("H*")
14
+ end
15
+
16
+ def set_no_action!
17
+ binary[3] = ALL_ZERO_BIT
18
+ binary[4] = ALL_ZERO_BIT
19
+ binary[5] = ALL_ZERO_BIT
20
+ end
21
+
22
+ # @param [ProconBypassMan::Domains::ProcessingProconBinary]
23
+ # @return [ProconBypassMan::Domains::ProcessingProconBinary]
24
+ # アナログスティックは上書きし、ボタンだけマージする
25
+ def write_as_merge!(target_binary)
26
+ current_buttons = ProconBypassMan::ProconReader.new(binary: binary).pressing
27
+ target_buttons = ProconBypassMan::ProconReader.new(binary: target_binary.raw).pressing
28
+
29
+ set_no_action!
30
+ (current_buttons + target_buttons).uniq.each do |button|
31
+ write_as_press_button(button)
32
+ end
33
+
34
+ # override analog stick
35
+ tb = [target_binary.raw].pack("H*")
36
+ binary[6] = tb[6]
37
+ binary[7] = tb[7]
38
+ binary[8] = tb[8]
39
+ binary[9] = tb[9]
40
+ binary[10] = tb[10]
41
+ binary[11] = tb[11]
42
+
43
+ self
44
+ end
45
+
46
+ # @param [Symbol] button
47
+ def write_as_press_button(button)
48
+ raise "already pressing button(#{button})" if ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
49
+
50
+ button_obj = ProconBypassMan::Procon::Button.new(button)
51
+ value = binary[button_obj.byte_position].unpack("H*").first.to_i(16) + (2**button_obj.bit_position)
52
+ binary[button_obj.byte_position] = ["%02X" % value.to_s].pack("H*")
53
+ end
54
+
55
+ # @param [Symbol] button
56
+ def write_as_unpress_button(button)
57
+ raise "not press button(#{button}) yet" if not ProconBypassMan::PressButtonAware.new(binary).pressing_button?(button)
58
+
59
+ button_obj = ProconBypassMan::Procon::Button.new(button)
60
+ value = binary[button_obj.byte_position].unpack("H*").first.to_i(16) - (2**button_obj.bit_position)
61
+ binary[button_obj.byte_position] = ["%02X" % value.to_s].pack("H*")
62
+ end
63
+
64
+ # @param [Symbol] button
65
+ def write_as_press_button_only(button)
66
+ set_no_action!
67
+ write_as_press_button(button)
68
+ end
69
+
70
+ # @param [Integer] cap
71
+ def write_as_apply_left_analog_stick_cap(cap: )
72
+ analog_stick_cap = ProconBypassMan::Procon::AnalogStickCap.new(binary)
73
+ binary[6..8] = analog_stick_cap.capped_position(cap_hypotenuse: cap).to_binary
74
+ end
75
+
76
+ # @return [ProconBypassMan::ProconReader]
77
+ def to_procon_reader
78
+ ProconBypassMan::ProconReader.new(binary: binary)
79
+ end
80
+ end
@@ -0,0 +1,11 @@
1
+ module ProconBypassMan
2
+ module Domains
3
+ module Binary; end
4
+ end
5
+ end
6
+
7
+ require_relative "domains/binary/base"
8
+ require_relative "domains/binary/has_mutable_binary"
9
+ require_relative "domains/binary/has_immutable_binary"
10
+ require_relative "domains/binary/inbound_procon_binary"
11
+ require_relative "domains/binary/processing_procon_binary"
File without changes
@@ -1,16 +1,15 @@
1
1
  class ProconBypassMan::Processor
2
- # @return [String] binary
2
+
3
+ # @param [ProconBypassMan::Domains::InboundProconBinary] binary
3
4
  def initialize(binary)
4
5
  @binary = binary
5
6
  end
6
7
 
7
8
  # @return [String] 加工後の入力データ
8
9
  def process
9
- unless @binary[0] == "\x30".b
10
- return @binary
11
- end
10
+ return @binary.raw unless @binary.user_operation_data?
12
11
 
13
- procon = ProconBypassMan::Procon.new(@binary)
12
+ procon = ProconBypassMan::Procon.new(@binary.raw)
14
13
  procon.apply!
15
14
  procon.to_binary
16
15
  end
@@ -0,0 +1,11 @@
1
+ class ProconBypassMan::Procon::Button
2
+ class UnknownButtonFoundError < StandardError; end
3
+
4
+ attr_accessor :byte_position, :bit_position
5
+
6
+ def initialize(key)
7
+ b = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[key] or raise(UnknownButtonFoundError, '定義にないボタンです')
8
+ self.byte_position = b[:byte_position]
9
+ self.bit_position = b[:bit_position]
10
+ end
11
+ end
@@ -1,13 +1,4 @@
1
1
  class ProconBypassMan::Procon::ButtonCollection
2
- class Button
3
- attr_accessor :byte_position, :bit_position
4
- def initialize(key)
5
- b = BUTTONS_MAP[key] or raise("undefined button")
6
- self.byte_position = b[:byte_position]
7
- self.bit_position = b[:bit_position]
8
- end
9
- end
10
-
11
2
  # https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/ac8093c84194b3232acb675ac1accce9bcb456a3/bluetooth_hid_notes.md
12
3
  #0) Input report ID
13
4
  #1) Timer. Increments very fast. Can be used to estimate excess Bluetooth latency.
@@ -42,9 +33,8 @@ class ProconBypassMan::Procon::ButtonCollection
42
33
  end
43
34
  acc
44
35
  }.freeze
36
+
45
37
  BUTTONS = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP.keys.freeze
46
38
 
47
- def self.load(button_key)
48
- Button.new(button_key)
49
- end
39
+ LEFT_ANALOG_STICK = { byte_position: 6..8 }
50
40
  end
@@ -1,6 +1,7 @@
1
1
  class ProconBypassMan::Procon::LayerChanger
2
+ # @param [ProconBypassMan::Domains::ProcessingProconBinary] binary
2
3
  def initialize(binary: )
3
- @procon_reader = ProconBypassMan::ProconReader.new(binary: binary).freeze
4
+ @procon_reader = binary.to_procon_reader
4
5
  end
5
6
 
6
7
  # @return [Symbol]
@@ -35,6 +36,6 @@ class ProconBypassMan::Procon::LayerChanger
35
36
 
36
37
  # @return [Boolean]
37
38
  def pressed?(button: )
38
- @procon_reader.pressed.include?(button)
39
+ @procon_reader.pressing.include?(button)
39
40
  end
40
41
  end
@@ -1,13 +1,14 @@
1
- class ProconBypassMan::PpressButtonAware
1
+ class ProconBypassMan::PressButtonAware
2
2
  def initialize(binary)
3
3
  @binary = binary
4
4
  end
5
5
 
6
- def pressed_button?(button)
6
+ def pressing_button?(button)
7
+ button_obj = ProconBypassMan::Procon::Button.new(button)
7
8
  @binary[
8
- ::ProconBypassMan::Procon::ButtonCollection.load(button).byte_position
9
+ button_obj.byte_position
9
10
  ].unpack("H*").first.to_i(16).to_s(2).reverse[
10
- ::ProconBypassMan::Procon::ButtonCollection.load(button).bit_position
11
+ button_obj.bit_position
11
12
  ] == '1'
12
13
  end
13
14
  end