procon_bypass_man 0.1.15 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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