procon_bypass_man 0.1.8 → 0.1.12
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +3 -2
- data/.github/workflows/ruby.yml +5 -4
- data/.gitignore +5 -0
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +18 -1
- data/Gemfile +4 -0
- data/Gemfile.lock +53 -2
- data/README.md +14 -8
- data/Steepfile +39 -0
- data/bin/console +4 -0
- data/bin/dev_api_server.rb +18 -0
- data/docs/setup_raspi.mitamae.rb +12 -0
- data/lib/procon_bypass_man/background/has_server_pool.rb +54 -0
- data/lib/procon_bypass_man/background/http_client.rb +70 -0
- data/lib/procon_bypass_man/background/job_performer.rb +16 -0
- data/lib/procon_bypass_man/background/job_runnable.rb +16 -0
- data/lib/procon_bypass_man/background/job_runner.rb +44 -0
- data/lib/procon_bypass_man/background/jobs/base_job.rb +12 -0
- data/lib/procon_bypass_man/background/jobs/report_boot_job.rb +10 -0
- data/lib/procon_bypass_man/background/jobs/report_error_job.rb +10 -0
- data/lib/procon_bypass_man/background/jobs/report_heartbeat_job.rb +10 -0
- data/lib/procon_bypass_man/background/jobs/report_pressed_buttons_job.rb +18 -0
- data/lib/procon_bypass_man/background/jobs/report_reload_config_job.rb +10 -0
- data/lib/procon_bypass_man/background.rb +10 -0
- data/lib/procon_bypass_man/boot_message.rb +42 -0
- data/lib/procon_bypass_man/{configuration → buttons_setting_configuration}/layer.rb +50 -4
- data/lib/procon_bypass_man/{configuration → buttons_setting_configuration}/loader.rb +12 -11
- data/lib/procon_bypass_man/{configuration → buttons_setting_configuration}/validator.rb +1 -1
- data/lib/procon_bypass_man/buttons_setting_configuration.rb +101 -0
- data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +36 -0
- data/lib/procon_bypass_man/bypass.rb +61 -29
- data/lib/procon_bypass_man/callbacks.rb +70 -0
- data/lib/procon_bypass_man/commands/connect_device_command.rb +11 -0
- data/lib/procon_bypass_man/commands/print_boot_message_command.rb +9 -0
- data/lib/procon_bypass_man/commands/send_error_command.rb +18 -0
- data/lib/procon_bypass_man/commands/send_reload_config_event_command.rb +10 -0
- data/lib/procon_bypass_man/commands/write_device_id_command.rb +11 -0
- data/lib/procon_bypass_man/commands/write_session_id_command.rb +13 -0
- data/lib/procon_bypass_man/commands.rb +6 -0
- data/lib/procon_bypass_man/configuration.rb +92 -67
- data/lib/procon_bypass_man/device_connector.rb +11 -29
- data/lib/procon_bypass_man/io_monitor.rb +16 -8
- data/lib/procon_bypass_man/on_memory_cache.rb +34 -0
- data/lib/procon_bypass_man/procon/analog_stick.rb +31 -0
- data/lib/procon_bypass_man/procon/analog_stick_cap.rb +65 -0
- data/lib/procon_bypass_man/procon/button_collection.rb +15 -6
- data/lib/procon_bypass_man/procon/{data.rb → consts.rb} +1 -1
- data/lib/procon_bypass_man/procon/layer_changer.rb +40 -0
- data/lib/procon_bypass_man/procon/macro_registry.rb +2 -2
- data/lib/procon_bypass_man/procon/mode_registry.rb +4 -4
- data/lib/procon_bypass_man/procon/press_button_aware.rb +13 -0
- data/lib/procon_bypass_man/procon/user_operation.rb +21 -16
- data/lib/procon_bypass_man/procon.rb +23 -9
- data/lib/procon_bypass_man/procon_reader.rb +31 -0
- data/lib/procon_bypass_man/runner.rb +43 -64
- data/lib/procon_bypass_man/uptime.rb +14 -2
- data/lib/procon_bypass_man/version.rb +1 -1
- data/lib/procon_bypass_man.rb +38 -43
- data/project_template/README.md +1 -1
- data/project_template/app.rb +7 -5
- data/project_template/systemd_units/pbm_web.service +11 -0
- data/project_template/web.rb +16 -0
- data/sig/README.rb +4 -0
- data/sig/main.rbs +505 -0
- metadata +42 -11
- data/examples/practical/app.rb +0 -21
- data/examples/practical/setting.yml +0 -24
- data/lib/procon_bypass_man/procon/layer_changeable.rb +0 -28
- data/lib/procon_bypass_man/procon/pressed_button_helper.rb +0 -25
@@ -1,86 +1,111 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
module ProconBypassMan
|
6
|
-
class Configuration
|
7
|
-
|
8
|
-
attr_accessor :layers,
|
9
|
-
:setting_path,
|
10
|
-
:mode_plugins,
|
11
|
-
:macro_plugins,
|
12
|
-
:context,
|
13
|
-
:current_context_key
|
14
|
-
|
15
|
-
def self.instance
|
16
|
-
@@current_context_key ||= :main
|
17
|
-
@@context ||= {}
|
18
|
-
@@context[@@current_context_key] ||= new
|
1
|
+
class ProconBypassMan::Configuration
|
2
|
+
module ClassMethods
|
3
|
+
def root
|
4
|
+
config.root
|
19
5
|
end
|
20
6
|
|
21
|
-
def
|
22
|
-
|
23
|
-
previous_key = @@current_context_key
|
24
|
-
if block_given?
|
25
|
-
@@current_context_key = key
|
26
|
-
value = yield(@@context[key])
|
27
|
-
@@current_context_key = previous_key
|
28
|
-
return value
|
29
|
-
else
|
30
|
-
@@current_context_key = key
|
31
|
-
end
|
7
|
+
def logger
|
8
|
+
config.logger
|
32
9
|
end
|
33
10
|
|
34
|
-
def
|
35
|
-
|
11
|
+
def error_logger
|
12
|
+
config.error_logger
|
36
13
|
end
|
37
14
|
|
38
|
-
|
39
|
-
|
40
|
-
if mode.respond_to?(:name)
|
41
|
-
mode_name = mode.name.to_sym
|
42
|
-
else
|
43
|
-
mode_name = mode
|
44
|
-
end
|
45
|
-
unless (MODES + ProconBypassMan::Procon::ModeRegistry.plugins.keys).include?(mode_name)
|
46
|
-
raise("#{mode_name} mode is unknown")
|
47
|
-
end
|
48
|
-
|
49
|
-
layer = Layer.new(mode: mode_name)
|
50
|
-
layer.instance_eval(&block) if block_given?
|
51
|
-
self.layers[direction] = layer
|
52
|
-
self
|
15
|
+
def pid_path
|
16
|
+
@@pid_path ||= File.expand_path("#{root}/pbm_pid", __dir__).freeze
|
53
17
|
end
|
54
18
|
|
55
|
-
def
|
56
|
-
|
57
|
-
self
|
19
|
+
def digest_path
|
20
|
+
config.digest_path
|
58
21
|
end
|
59
22
|
|
60
|
-
def
|
61
|
-
ProconBypassMan::
|
62
|
-
self
|
23
|
+
def cache
|
24
|
+
@@cache_table ||= ProconBypassMan::OnMemoryCache.new
|
63
25
|
end
|
64
26
|
|
65
|
-
|
66
|
-
|
67
|
-
|
27
|
+
# @return [String]
|
28
|
+
def session_id
|
29
|
+
ProconBypassMan::WriteSessionIdCommand.execute
|
68
30
|
end
|
69
31
|
|
70
|
-
|
71
|
-
|
32
|
+
# @return [String]
|
33
|
+
def device_id
|
34
|
+
ProconBypassMan::WriteDeviceIdCommand.execute
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
attr_accessor :enable_critical_error_logging, :raw_setting
|
39
|
+
attr_writer :verbose_bypass_log
|
40
|
+
|
41
|
+
def root=(path)
|
42
|
+
@root = path
|
43
|
+
return self
|
44
|
+
end
|
45
|
+
|
46
|
+
def root
|
47
|
+
if defined?(@root)
|
48
|
+
@root
|
49
|
+
else
|
50
|
+
File.expand_path('..', __dir__ || ".").freeze
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def api_servers=(api_servers)
|
55
|
+
@api_servers = api_servers
|
56
|
+
return self
|
57
|
+
end
|
58
|
+
|
59
|
+
def logger=(logger)
|
60
|
+
@logger = logger
|
61
|
+
return self
|
62
|
+
end
|
63
|
+
|
64
|
+
def logger
|
65
|
+
if ENV["PBM_ENV"] == 'test'
|
66
|
+
return Logger.new($stdout)
|
72
67
|
end
|
73
68
|
|
74
|
-
|
75
|
-
@
|
76
|
-
|
77
|
-
|
78
|
-
self.layers = {
|
79
|
-
up: Layer.new,
|
80
|
-
down: Layer.new,
|
81
|
-
left: Layer.new,
|
82
|
-
right: Layer.new,
|
83
|
-
}
|
69
|
+
if defined?(@logger) && @logger.is_a?(Logger)
|
70
|
+
@logger
|
71
|
+
else
|
72
|
+
Logger.new(File.open("/dev/null"))
|
84
73
|
end
|
85
74
|
end
|
75
|
+
|
76
|
+
def error_logger
|
77
|
+
if enable_critical_error_logging
|
78
|
+
@@error_logger ||= Logger.new("#{ProconBypassMan.root}/error.log", 5, 1024 * 1024 * 10)
|
79
|
+
else
|
80
|
+
Logger.new(File.open("/dev/null"))
|
81
|
+
end
|
82
|
+
self
|
83
|
+
end
|
84
|
+
|
85
|
+
def digest_path
|
86
|
+
"#{root}/.setting_yaml_digest"
|
87
|
+
end
|
88
|
+
|
89
|
+
# @return [String] pbm-webの接続先
|
90
|
+
def internal_api_servers
|
91
|
+
if !!ENV["INTERNAL_API_SERVER"]
|
92
|
+
[ENV["INTERNAL_API_SERVER"]]
|
93
|
+
else
|
94
|
+
[ 'http://localhost:9090',
|
95
|
+
'http://localhost:8080',
|
96
|
+
].compact
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def api_servers
|
101
|
+
if !!ENV["API_SERVER"]
|
102
|
+
[ENV["API_SERVER"]].reject(&:nil?)
|
103
|
+
else
|
104
|
+
[@api_servers].flatten.reject(&:nil?)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def verbose_bypass_log
|
109
|
+
@verbose_bypass_log || !!ENV["VERBOSE_BYPASS_LOG"]
|
110
|
+
end
|
86
111
|
end
|
@@ -12,23 +12,6 @@ class ProconBypassMan::DeviceConnector
|
|
12
12
|
PROCON_PATH = "/dev/hidraw0"
|
13
13
|
PROCON2_PATH = "/dev/hidraw1"
|
14
14
|
|
15
|
-
# 画面で再接続ができたが状況は変わらない
|
16
|
-
def self.reset_connection!
|
17
|
-
s = new
|
18
|
-
s.add([
|
19
|
-
["0000"],
|
20
|
-
["0000"],
|
21
|
-
["8005"],
|
22
|
-
["0000"],
|
23
|
-
["8001"],
|
24
|
-
], read_from: :switch)
|
25
|
-
s.drain_all
|
26
|
-
s.read_procon
|
27
|
-
s.write_switch("213c910080005db7723d48720a800300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
|
28
|
-
sleep(10) # いらないかも
|
29
|
-
s
|
30
|
-
end
|
31
|
-
|
32
15
|
def self.connect
|
33
16
|
s = new(throw_error_if_timeout: true, enable_at_exit: false)
|
34
17
|
s.add([
|
@@ -75,7 +58,7 @@ class ProconBypassMan::DeviceConnector
|
|
75
58
|
timer = ProconBypassMan::Timer.new
|
76
59
|
begin
|
77
60
|
timer.throw_if_timeout!
|
78
|
-
data = from_device(item).read_nonblock(
|
61
|
+
data = from_device(item).read_nonblock(64)
|
79
62
|
rescue IO::EAGAINWaitReadable
|
80
63
|
retry
|
81
64
|
end
|
@@ -128,7 +111,7 @@ class ProconBypassMan::DeviceConnector
|
|
128
111
|
timer = ProconBypassMan::Timer.new
|
129
112
|
begin
|
130
113
|
timer.throw_if_timeout!
|
131
|
-
data = switch.read_nonblock(
|
114
|
+
data = switch.read_nonblock(64)
|
132
115
|
ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
|
133
116
|
rescue IO::EAGAINWaitReadable
|
134
117
|
retry
|
@@ -163,7 +146,7 @@ class ProconBypassMan::DeviceConnector
|
|
163
146
|
timer = ProconBypassMan::Timer.new
|
164
147
|
begin
|
165
148
|
timer.throw_if_timeout!
|
166
|
-
data = procon.read_nonblock(
|
149
|
+
data = procon.read_nonblock(64)
|
167
150
|
ProconBypassMan.logger.error " <<< #{data.unpack("H*")})"
|
168
151
|
rescue IO::EAGAINWaitReadable
|
169
152
|
retry
|
@@ -184,7 +167,7 @@ class ProconBypassMan::DeviceConnector
|
|
184
167
|
timer = ProconBypassMan::Timer.new
|
185
168
|
begin
|
186
169
|
timer.throw_if_timeout!
|
187
|
-
data = procon.read_nonblock(
|
170
|
+
data = procon.read_nonblock(64)
|
188
171
|
ProconBypassMan.logger.debug { " <<< #{data.unpack("H*")})" }
|
189
172
|
rescue IO::EAGAINWaitReadable
|
190
173
|
retry
|
@@ -217,7 +200,7 @@ class ProconBypassMan::DeviceConnector
|
|
217
200
|
timer = ProconBypassMan::Timer.new
|
218
201
|
begin
|
219
202
|
timer.throw_if_timeout!
|
220
|
-
data = switch.read_nonblock(
|
203
|
+
data = switch.read_nonblock(64)
|
221
204
|
ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
|
222
205
|
rescue IO::EAGAINWaitReadable
|
223
206
|
retry
|
@@ -281,7 +264,7 @@ class ProconBypassMan::DeviceConnector
|
|
281
264
|
|
282
265
|
file = File.open(path, "w+")
|
283
266
|
begin
|
284
|
-
file.read_nonblock(
|
267
|
+
file.read_nonblock(64)
|
285
268
|
rescue EOFError
|
286
269
|
file.close
|
287
270
|
return false
|
@@ -303,12 +286,12 @@ class ProconBypassMan::DeviceConnector
|
|
303
286
|
case
|
304
287
|
when is_available_device?(PROCON_PATH)
|
305
288
|
ProconBypassMan.logger.info "proconのデバイスファイルは#{PROCON_PATH}を使います"
|
306
|
-
@procon = File.open(PROCON_PATH, "w+")
|
307
|
-
@gadget = File.open('/dev/hidg0', "w+")
|
289
|
+
@procon = File.open(PROCON_PATH, "w+b")
|
290
|
+
@gadget = File.open('/dev/hidg0', "w+b")
|
308
291
|
when is_available_device?(PROCON2_PATH)
|
309
292
|
ProconBypassMan.logger.info "proconのデバイスファイルは#{PROCON2_PATH}を使います"
|
310
|
-
@procon = File.open(PROCON2_PATH, "w+")
|
311
|
-
@gadget = File.open('/dev/hidg0', "w+")
|
293
|
+
@procon = File.open(PROCON2_PATH, "w+b")
|
294
|
+
@gadget = File.open('/dev/hidg0', "w+b")
|
312
295
|
else
|
313
296
|
raise "/dev/hidraw0, /dev/hidraw1の両方見つかりませんでした"
|
314
297
|
end
|
@@ -326,8 +309,7 @@ class ProconBypassMan::DeviceConnector
|
|
326
309
|
end
|
327
310
|
rescue Errno::ENXIO => e
|
328
311
|
# /dev/hidg0 をopenできないときがある
|
329
|
-
ProconBypassMan.
|
330
|
-
ProconBypassMan.logger.error e
|
312
|
+
ProconBypassMan::SendErrorCommand.execute(error: "Errno::ENXIO (No such device or address @ rb_sysopen - /dev/hidg0)が起きました。resetします. #{e.full_message}")
|
331
313
|
system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
|
332
314
|
system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')
|
333
315
|
sleep 2
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module ProconBypassMan
|
2
2
|
class Counter
|
3
|
-
attr_accessor :label, :table, :previous_table
|
3
|
+
attr_accessor :label, :table, :previous_table, :active
|
4
4
|
|
5
5
|
def initialize(label: )
|
6
6
|
self.label = label
|
7
7
|
self.table = {}
|
8
8
|
self.previous_table = {}
|
9
|
+
self.active = true
|
9
10
|
end
|
10
11
|
|
11
12
|
# アクティブなバケットは1つだけ
|
@@ -24,7 +25,7 @@ module ProconBypassMan
|
|
24
25
|
self
|
25
26
|
end
|
26
27
|
|
27
|
-
def
|
28
|
+
def formatted_previous_table
|
28
29
|
t = previous_table.dup
|
29
30
|
start_function = t[:start_function] || 0
|
30
31
|
end_function = t[:end_function] || 0
|
@@ -32,6 +33,10 @@ module ProconBypassMan
|
|
32
33
|
eagain_wait_readable_on_write = t[:eagain_wait_readable_on_write] || 0
|
33
34
|
"(#{(end_function / start_function.to_f * 100).floor(1)}%(#{end_function}/#{start_function}), loss: #{eagain_wait_readable_on_read}, #{eagain_wait_readable_on_write})"
|
34
35
|
end
|
36
|
+
|
37
|
+
def shutdown
|
38
|
+
self.active = false
|
39
|
+
end
|
35
40
|
end
|
36
41
|
|
37
42
|
module IOMonitor
|
@@ -51,21 +56,24 @@ module ProconBypassMan
|
|
51
56
|
Thread.start do
|
52
57
|
max_output_length = 0
|
53
58
|
loop do
|
54
|
-
list = @@list.dup
|
59
|
+
list = @@list.select(&:active).dup
|
55
60
|
unless list.all? { |x| x&.previous_table.is_a?(Hash) }
|
56
61
|
sleep 0.5
|
57
62
|
next
|
58
63
|
end
|
59
64
|
|
60
65
|
line = list.map { |counter|
|
61
|
-
"#{counter.label}(#{counter.
|
66
|
+
"#{counter.label}(#{counter.formatted_previous_table})"
|
62
67
|
}.join(", ")
|
63
68
|
max_output_length = line.length
|
64
69
|
sleep 0.7
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
70
|
+
|
71
|
+
if ENV["PBM_FOREGROUND"]
|
72
|
+
print "\r"
|
73
|
+
print " " * max_output_length
|
74
|
+
print "\r"
|
75
|
+
print line
|
76
|
+
end
|
69
77
|
ProconBypassMan.logger.debug { line }
|
70
78
|
break if $will_terminate_token
|
71
79
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class ProconBypassMan::OnMemoryCache
|
2
|
+
class CacheValue
|
3
|
+
attr_accessor :expired_at, :value
|
4
|
+
|
5
|
+
def initialize(expired_at: , value: )
|
6
|
+
self.expired_at = expired_at
|
7
|
+
self.value = value
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@table = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [Integer] expires_in 秒数
|
16
|
+
# @param [String] key
|
17
|
+
def fetch(key: , expires_in: , &block)
|
18
|
+
now = Time.now
|
19
|
+
if @table[key].nil?
|
20
|
+
value = block.call
|
21
|
+
value_object = CacheValue.new(expired_at: now + expires_in, value: value)
|
22
|
+
@table[key] = value_object
|
23
|
+
return value
|
24
|
+
end
|
25
|
+
|
26
|
+
if @table[key].expired_at < now
|
27
|
+
value = block.call
|
28
|
+
@table[key] = CacheValue.new(expired_at: now + expires_in, value: value)
|
29
|
+
return value
|
30
|
+
else
|
31
|
+
return @table[key].value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class ProconBypassMan::Procon::AnalogStick
|
2
|
+
attr_accessor :neutral_position
|
3
|
+
attr_accessor :bin_x, :bin_y
|
4
|
+
|
5
|
+
def initialize(binary: )
|
6
|
+
@neutral_position = ProconBypassMan::ButtonsSettingConfiguration.instance.neutral_position
|
7
|
+
|
8
|
+
byte6 = binary[6].unpack("H*").first.to_i(16).to_s(2).rjust(8, "0")
|
9
|
+
byte7 = binary[7].unpack("H*").first.to_i(16).to_s(2).rjust(8, "0")
|
10
|
+
byte8 = binary[8].unpack("H*").first.to_i(16).to_s(2).rjust(8, "0")
|
11
|
+
|
12
|
+
self.bin_x = "#{byte7[4..7]}#{byte6}"
|
13
|
+
self.bin_y = "#{byte8}#{byte7[0..3]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def abs_x
|
17
|
+
bin_x.to_i(2)
|
18
|
+
end
|
19
|
+
|
20
|
+
def abs_y
|
21
|
+
bin_y.to_i(2)
|
22
|
+
end
|
23
|
+
|
24
|
+
def relative_x
|
25
|
+
bin_x.to_i(2) - neutral_position.x
|
26
|
+
end
|
27
|
+
|
28
|
+
def relative_y
|
29
|
+
bin_y.to_i(2) - neutral_position.y
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,65 @@
|
|
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
|
+
def initialize(binary)
|
22
|
+
@binary = binary
|
23
|
+
@analog_stick = ProconBypassMan::Procon::AnalogStick.new(binary: binary)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [ProconBypassMan::Procon::AnalogStickCap::Position]
|
27
|
+
def capped_position(cap_hypotenuse: )
|
28
|
+
if hypotenuse > cap_hypotenuse
|
29
|
+
relative_capped_x = cap_hypotenuse * Math.cos(rad * Math::PI / 180).abs
|
30
|
+
relative_capped_y = cap_hypotenuse * Math.sin(rad * Math::PI / 180).abs
|
31
|
+
relative_capped_x = -(relative_capped_x.abs) if relative_x.negative?
|
32
|
+
relative_capped_y = -(relative_capped_y.abs) if relative_y.negative?
|
33
|
+
return Position.new(
|
34
|
+
x: relative_capped_x + @analog_stick.neutral_position.x,
|
35
|
+
y: relative_capped_y + @analog_stick.neutral_position.y,
|
36
|
+
)
|
37
|
+
else
|
38
|
+
return position
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [ProconBypassMan::Procon::AnalogStickCap::Position]
|
43
|
+
def position
|
44
|
+
Position.new(x: abs_x, y: abs_y)
|
45
|
+
end
|
46
|
+
|
47
|
+
def abs_x; @analog_stick.abs_x; end # 0, 0からのx
|
48
|
+
def abs_y; @analog_stick.abs_y; end # 0, 0からのy
|
49
|
+
def relative_x; @analog_stick.relative_x; end
|
50
|
+
def relative_y; @analog_stick.relative_y; end
|
51
|
+
|
52
|
+
# @deprecated
|
53
|
+
def x; relative_x; end
|
54
|
+
def y; relative_y; end
|
55
|
+
|
56
|
+
def rad
|
57
|
+
(
|
58
|
+
Math.atan(relative_y / relative_x.to_f) * 180 / Math::PI
|
59
|
+
).floor(6)
|
60
|
+
end
|
61
|
+
|
62
|
+
def hypotenuse
|
63
|
+
Math.sqrt(relative_x**2 + relative_y**2).floor(6)
|
64
|
+
end
|
65
|
+
end
|
@@ -8,15 +8,20 @@ class ProconBypassMan::Procon::ButtonCollection
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
# https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/ac8093c84194b3232acb675ac1accce9bcb456a3/bluetooth_hid_notes.md
|
12
|
+
#0) Input report ID
|
13
|
+
#1) Timer. Increments very fast. Can be used to estimate excess Bluetooth latency.
|
14
|
+
#2 high nibble) Battery level. 8=full, 6=medium, 4=low, 2=critical, 0=empty. LSB=Charging.
|
15
|
+
#2 low nibble) Connection info. (con_info >> 1) & 3 - 3=JC, 0=Pro/ChrGrip. con_info & 1 - 1=Switch/USB powered.
|
11
16
|
#3) ZR R SR(right) SL(right) A B X Y
|
12
17
|
#4) Grip (none) Cap Home ThumbL ThumbR + -
|
13
18
|
#5) ZL L SL(left) SR(left) Left Right Up Down
|
14
|
-
#6) analog[0]
|
15
|
-
#7) analog[1]
|
16
|
-
#8) analog[2]
|
17
|
-
#9) analog[3]
|
18
|
-
#a) analog[4]
|
19
|
-
#b) analog[5]
|
19
|
+
#6) analog[0] Left analog stick data
|
20
|
+
#7) analog[1] Left analog stick data
|
21
|
+
#8) analog[2] Left analog stick data
|
22
|
+
#9) analog[3] Right analog stick data
|
23
|
+
#a) analog[4] Right analog stick data
|
24
|
+
#b) analog[5] Right analog stick data
|
20
25
|
BYTES_MAP = {
|
21
26
|
0 => nil,
|
22
27
|
1 => nil,
|
@@ -24,11 +29,15 @@ class ProconBypassMan::Procon::ButtonCollection
|
|
24
29
|
3 => [:zr, :r, :sr, :sl, :a, :b, :x, :y],
|
25
30
|
4 => [:grip, :_undefined_key, :cap, :home, :thumbl, :thumbr, :plus, :minus],
|
26
31
|
5 => [:zl, :l, :sl, :sr, :left, :right, :up, :down],
|
32
|
+
6 => [],
|
33
|
+
7 => [],
|
34
|
+
8 => [],
|
27
35
|
}.freeze
|
28
36
|
|
29
37
|
BUTTONS_MAP = BYTES_MAP.reduce({}) { |acc, value|
|
30
38
|
next acc if value[1].nil?
|
31
39
|
value[1].reverse.each.with_index do |button, index|
|
40
|
+
next(acc) if button == :grip || button == :_undefined_key
|
32
41
|
acc[button] = { byte_position: value[0], bit_position: index }
|
33
42
|
end
|
34
43
|
acc
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class ProconBypassMan::Procon::LayerChanger
|
2
|
+
def initialize(binary: )
|
3
|
+
@procon_reader = ProconBypassMan::ProconReader.new(binary: binary)
|
4
|
+
end
|
5
|
+
|
6
|
+
# @return [Symbol]
|
7
|
+
def next_layer_key
|
8
|
+
case
|
9
|
+
when pressed?(button: :up)
|
10
|
+
:up
|
11
|
+
when pressed?(button: :right)
|
12
|
+
:right
|
13
|
+
when pressed?(button: :left)
|
14
|
+
:left
|
15
|
+
when pressed?(button: :down)
|
16
|
+
:down
|
17
|
+
else
|
18
|
+
ProconBypassMan.logger.warn("next_layer_key is unknown")
|
19
|
+
:up
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Boolean]
|
24
|
+
def change_layer?
|
25
|
+
if ProconBypassMan::ButtonsSettingConfiguration.instance.prefix_keys.empty?
|
26
|
+
raise "prefix_keysが未設定です"
|
27
|
+
end
|
28
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.prefix_keys.map { |b| pressed?(button: b) }.all?
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Boolean]
|
32
|
+
def pressed_next_layer?
|
33
|
+
change_layer? && (pressed?(button: :up) || pressed?(button: :right) || pressed?(button: :left) || pressed?(button: :down))
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [Boolean]
|
37
|
+
def pressed?(button: )
|
38
|
+
@procon_reader.pressed.include?(button)
|
39
|
+
end
|
40
|
+
end
|
@@ -37,11 +37,11 @@ class ProconBypassMan::Procon::MacroRegistry
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.reset!
|
40
|
-
ProconBypassMan::
|
40
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins = {}
|
41
41
|
end
|
42
42
|
|
43
43
|
def self.plugins
|
44
|
-
ProconBypassMan::
|
44
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.macro_plugins
|
45
45
|
end
|
46
46
|
|
47
47
|
reset!
|
@@ -23,10 +23,10 @@ class ProconBypassMan::Procon::ModeRegistry
|
|
23
23
|
}
|
24
24
|
|
25
25
|
def self.install_plugin(klass)
|
26
|
-
if plugins[klass.name]
|
26
|
+
if plugins[klass.name.to_sym]
|
27
27
|
raise "すでに登録済みです"
|
28
28
|
end
|
29
|
-
plugins[klass.name] = klass.binaries
|
29
|
+
plugins[klass.name.to_sym] = klass.binaries
|
30
30
|
end
|
31
31
|
|
32
32
|
def self.load(name)
|
@@ -35,11 +35,11 @@ class ProconBypassMan::Procon::ModeRegistry
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.reset!
|
38
|
-
ProconBypassMan::
|
38
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.mode_plugins = {}
|
39
39
|
end
|
40
40
|
|
41
41
|
def self.plugins
|
42
|
-
ProconBypassMan::
|
42
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.mode_plugins
|
43
43
|
end
|
44
44
|
|
45
45
|
reset!
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ProconBypassMan::PpressButtonAware
|
2
|
+
def initialize(binary)
|
3
|
+
@binary = binary
|
4
|
+
end
|
5
|
+
|
6
|
+
def pressed_button?(button)
|
7
|
+
@binary[
|
8
|
+
::ProconBypassMan::Procon::ButtonCollection.load(button).byte_position
|
9
|
+
].unpack("H*").first.to_i(16).to_s(2).reverse[
|
10
|
+
::ProconBypassMan::Procon::ButtonCollection.load(button).bit_position
|
11
|
+
] == '1'
|
12
|
+
end
|
13
|
+
end
|