procon_bypass_man 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +4 -2
- data/README.md +11 -33
- data/docs/getting_started.md +8 -0
- data/docs/setup_raspi_by_mitamae.md +0 -1
- data/lib/procon_bypass_man/bypass/bypass_command.rb +11 -6
- data/lib/procon_bypass_man/bypass/procon_to_switch.rb +34 -42
- data/lib/procon_bypass_man/bypass/switch_to_procon.rb +2 -0
- data/lib/procon_bypass_man/commands/print_boot_message_command.rb +0 -2
- data/lib/procon_bypass_man/configuration.rb +3 -0
- data/lib/procon_bypass_man/procon/analog_stick_manipulator.rb +2 -0
- data/lib/procon_bypass_man/procon/layer_changer.rb +2 -0
- data/lib/procon_bypass_man/procon/macro.rb +2 -0
- data/lib/procon_bypass_man/procon/macro_builder.rb +2 -0
- data/lib/procon_bypass_man/procon/macro_registry.rb +2 -0
- data/lib/procon_bypass_man/procon/performance_measurement/measurements_summarizer.rb +41 -24
- data/lib/procon_bypass_man/procon/performance_measurement/span_transfer_buffer.rb +1 -1
- data/lib/procon_bypass_man/procon/performance_measurement.rb +12 -5
- data/lib/procon_bypass_man/procon/suppress_rumble.rb +2 -0
- data/lib/procon_bypass_man/procon/user_operation.rb +2 -0
- data/lib/procon_bypass_man/procon/value_objects/analog_stick.rb +2 -0
- data/lib/procon_bypass_man/procon/value_objects/binary/inbound_procon_binary.rb +2 -0
- data/lib/procon_bypass_man/procon/value_objects/binary/processing_procon_binary.rb +2 -0
- data/lib/procon_bypass_man/procon/value_objects/rumble_binary.rb +2 -0
- data/lib/procon_bypass_man/procon.rb +24 -6
- data/lib/procon_bypass_man/remote_macro.rb +2 -0
- data/lib/procon_bypass_man/remote_pbm_action.rb +2 -0
- data/lib/procon_bypass_man/support/callbacks.rb +10 -3
- data/lib/procon_bypass_man/support/http_client.rb +3 -0
- data/lib/procon_bypass_man/support/renice_command.rb +17 -0
- data/lib/procon_bypass_man/version.rb +1 -1
- data/lib/procon_bypass_man.rb +18 -5
- data/procon_bypass_man.gemspec +3 -1
- data/project_template/app.rb +1 -4
- data/project_template/app.rb.erb +1 -4
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 556a827cf03895e4212aa4c524963ca7efd24499c2ea14edff2d692bc3e1e63f
|
4
|
+
data.tar.gz: bf7cf5a735fffa13e1ff99c259a329a4c6981be755440477884ece0246188f21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bdfd9d2c5bee033c8f6a1f87acebcf3374e353c0ea4d373c76f86ee33b87b248665b087276998f20dee9f0d1258ab2c7c49906cc55b94b51a5e35d84712da5c
|
7
|
+
data.tar.gz: 176ac515a48935df2953c36fb747e09be71c31f7850b09397e338bc0685b5da25bcd7ff81795d235287f2a5870fcdec3fec5aa9334e12ba90ca26662fe8807e7
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
procon_bypass_man (0.
|
4
|
+
procon_bypass_man (0.3.0)
|
5
5
|
action_cable_client
|
6
|
+
blue_green_process
|
6
7
|
pbmenv (>= 0.1.9)
|
7
8
|
sorted_set
|
8
9
|
|
@@ -18,6 +19,7 @@ GEM
|
|
18
19
|
tzinfo (~> 2.0)
|
19
20
|
zeitwerk (~> 2.3)
|
20
21
|
ast (2.4.2)
|
22
|
+
blue_green_process (0.1.3)
|
21
23
|
coderay (1.1.3)
|
22
24
|
concurrent-ruby (1.1.9)
|
23
25
|
diff-lcs (1.4.4)
|
@@ -78,7 +80,7 @@ GEM
|
|
78
80
|
parser (>= 3.0.1.1)
|
79
81
|
ruby-progressbar (1.11.0)
|
80
82
|
ruby2_keywords (0.0.5)
|
81
|
-
set (1.0.
|
83
|
+
set (1.0.3)
|
82
84
|
sinatra (2.2.0)
|
83
85
|
mustermann (~> 1.0)
|
84
86
|
rack (~> 2.2)
|
data/README.md
CHANGED
@@ -3,9 +3,7 @@
|
|
3
3
|
|
4
4
|
[![Ruby](https://github.com/splaplapla/procon_bypass_man/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/splaplapla/procon_bypass_man/actions/workflows/ruby.yml)
|
5
5
|
|
6
|
-
* Switch
|
7
|
-
* 設定ファイルはrubyスクリプトで記述します
|
8
|
-
* 特定のタイトルに特化した振る舞いにしたい時は各プラグインを使ってください
|
6
|
+
* Nintendo Switch Proコントローラーを連射機などにするRaspberry Pi上で動かすコンバータです
|
9
7
|
* ドキュメントは [getting_started.md](docs/getting_started.md) にまとめています
|
10
8
|
* https://pbm-cloud.herokuapp.com を使うと、webだけで運用が可能です
|
11
9
|
|
@@ -14,44 +12,17 @@
|
|
14
12
|
|
15
13
|
https://user-images.githubusercontent.com/1664497/171327108-f12f56a5-fc36-48da-95a5-65e976553a20.mov
|
16
14
|
|
17
|
-
<!--
|
18
|
-
![image](https://user-images.githubusercontent.com/1664497/123414210-942f6980-d5ee-11eb-8192-955bd9e37e0b.png)
|
19
|
-
```
|
20
|
-
@startuml
|
21
|
-
ProController \-\-> (PBM): ZR押しっぱなし
|
22
|
-
Switch <-- (PBM): ZR連打
|
23
|
-
@enduml
|
24
|
-
```
|
25
|
-
-->
|
26
|
-
|
27
15
|
## 使うハードウェア
|
28
|
-
*
|
16
|
+
* Nintendo Switch Proコントローラー
|
29
17
|
* Switch本体とドック
|
30
|
-
* Raspberry Pi4
|
18
|
+
* Raspberry Pi4 (Raspberry Pi OS)
|
31
19
|
* 他のシリーズは未確認です
|
32
|
-
* zeroは非対応
|
33
20
|
* データ通信が可能なUSBケーブル
|
34
21
|
|
35
22
|
## 使うソフトウェア
|
36
23
|
* ruby 2.5 以上
|
37
24
|
|
38
|
-
##
|
39
|
-
* USBガジェットモードで起動するRaspberry Pi4を用意する
|
40
|
-
* https://github.com/splaplapla/procon_bypass_man/blob/master/docs/setup_raspi.md
|
41
|
-
* Raspberry Pi4 でprocon_bypass_manを実行するための準備
|
42
|
-
* rubyのインストール
|
43
|
-
* sudo apt-get install rbenv
|
44
|
-
* git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
|
45
|
-
* rbenv install 3.0.1
|
46
|
-
* gem install pbmenv
|
47
|
-
* sudo [pbmenv](https://github.com/splaplapla/pbmenv) install latest
|
48
|
-
* Raspberry Pi4 でprocon_bypass_manを実行する
|
49
|
-
* cd /usr/share/pbm/current
|
50
|
-
* sudo /home/pi/.rbenv/versions/3.0.1/bin/ruby app.rb
|
51
|
-
* 動いたのを確認したらserviceとして登録にするなどしてください
|
52
|
-
* [serviceとして登録する方法](https://github.com/splaplapla/procon_bypass_man/tree/master/project_template#systemd%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E3%81%AB%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)
|
53
|
-
|
54
|
-
## Plugins
|
25
|
+
## プラグイン
|
55
26
|
* https://github.com/splaplapla/procon_bypass_man-splatoon2
|
56
27
|
|
57
28
|
## FAQ
|
@@ -109,6 +80,13 @@ sudo kill -USR2 `cat ./pbm_pid`
|
|
109
80
|
* githubのreleaseを作成する
|
110
81
|
-->
|
111
82
|
|
83
|
+
## Raspberry Pi4のセットアップを代行します
|
84
|
+
* Raspberry Pi4を開発者である私の家に配送してくれれば、セットアップを代行します。セットアップが終わり次第送り返します
|
85
|
+
* 使い方に関しては、https://pbm-cloud.herokuapp.com ですべて完結するので、Linuxの知識は不要です
|
86
|
+
* 何か問題が起きた時はリモートログインでサポート可能です
|
87
|
+
* 希望者はDiscordの `kawagu#7684` にDMを送ってください
|
88
|
+
* お金はかかりません
|
89
|
+
|
112
90
|
## 開発を支援してくれる人を募集しています
|
113
91
|
* https://jiikko.fanbox.cc/
|
114
92
|
* procon_bypassの運営・開発・サーバー費用に充てさせていただきます。また、問い合わせに優先して対応します。
|
data/docs/getting_started.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
* [はじめに](#はじめに)
|
4
4
|
* [procon_bypass_manで解決したいこと](#procon_bypass_manで解決したいこと)
|
5
5
|
* [procon_bypass_manでできること](#procon_bypass_manでできること)
|
6
|
+
* [セットアップを代行できます](#セットアップを代行できます)
|
6
7
|
* [セットアップ](#セットアップ)
|
7
8
|
* [ラズベリーパイのセットアップ](#ラズベリーパイのセットアップ)
|
8
9
|
* [procon_bypass_manのインストール](#procon_bypass_manのインストール)
|
@@ -45,6 +46,13 @@
|
|
45
46
|
* 入力表示
|
46
47
|
* https://github.com/splaplapla/switch-procon-input-viewer
|
47
48
|
|
49
|
+
## セットアップを代行できます
|
50
|
+
* Raspberry Pi4を開発者である私の家に配送してくれれば、セットアップを代行します。セットアップが終わり次第送り返します
|
51
|
+
* 使い方に関しては、https://pbm-cloud.herokuapp.com ですべて完結するので、Linuxの知識は不要です
|
52
|
+
* 何か問題が起きた時はリモートログインでサポート可能です
|
53
|
+
* 希望者はDiscordの `kawagu#7684` にDMを送ってください
|
54
|
+
* お金はかかりません
|
55
|
+
|
48
56
|
## セットアップ
|
49
57
|
### ラズベリーパイのセットアップ
|
50
58
|
|
@@ -30,11 +30,6 @@ class ProconBypassMan::BypassCommand
|
|
30
30
|
cycle_sleep = ProconBypassMan::CycleSleep.new(cycle_interval: 1, execution_cycle: ProconBypassMan.config.bypass_mode.gadget_to_procon_interval)
|
31
31
|
|
32
32
|
t1 = Thread.new do
|
33
|
-
if ProconBypassMan.config.bypass_mode.mode == ProconBypassMan::BypassMode::TYPE_AGGRESSIVE
|
34
|
-
ProconBypassMan.logger.info "TYPE_AGGRESSIVEなのでThread1を終了します"
|
35
|
-
next
|
36
|
-
end
|
37
|
-
|
38
33
|
bypass = ProconBypassMan::Bypass::SwitchToProcon.new(gadget: @gadget, procon: @procon)
|
39
34
|
loop do
|
40
35
|
break if $will_terminate_token
|
@@ -58,22 +53,32 @@ class ProconBypassMan::BypassCommand
|
|
58
53
|
# シビア
|
59
54
|
t2 = Thread.new do
|
60
55
|
bypass = ProconBypassMan::Bypass::ProconToSwitch.new(gadget: @gadget, procon: @procon)
|
56
|
+
process = BlueGreenProcess.new(worker_instance: bypass, max_work: 200)
|
61
57
|
loop do
|
62
58
|
if $will_terminate_token
|
63
59
|
if $will_terminate_token == WILL_TERMINATE_TOKEN::TERMINATE
|
64
60
|
bypass.direct_connect_switch_via_bluetooth
|
61
|
+
process.shutdown
|
65
62
|
end
|
66
63
|
break
|
67
64
|
end
|
68
65
|
|
69
|
-
|
66
|
+
process.work
|
67
|
+
|
68
|
+
process_switching_time_before_work = BlueGreenProcess.performance.process_switching_time_before_work
|
69
|
+
if process_switching_time_before_work > 0.1
|
70
|
+
ProconBypassMan.logger.info("slow process_switching_time_before_work: #{process_switching_time_before_work}")
|
71
|
+
end
|
72
|
+
|
70
73
|
rescue EOFError => e
|
71
74
|
ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
|
72
75
|
Process.kill "TERM", Process.ppid
|
76
|
+
process.shutdown
|
73
77
|
break
|
74
78
|
rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN => e
|
75
79
|
ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します2. #{e.full_message}")
|
76
80
|
Process.kill "TERM", Process.ppid
|
81
|
+
process.shutdown
|
77
82
|
break
|
78
83
|
end
|
79
84
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "procon_bypass_man/bypass/bypass_command"
|
2
4
|
|
3
5
|
class ProconBypassMan::Bypass::ProconToSwitch
|
@@ -7,12 +9,13 @@ class ProconBypassMan::Bypass::ProconToSwitch
|
|
7
9
|
class CouldNotReadFromProconError < StandardError; end
|
8
10
|
class CouldNotWriteToSwitchError < StandardError; end
|
9
11
|
|
10
|
-
define_callbacks :
|
11
|
-
set_callback :
|
12
|
+
define_callbacks :work
|
13
|
+
set_callback :work, :after, :log_after_run
|
12
14
|
|
13
|
-
|
15
|
+
# マルチプロセス化したので一旦無効にする
|
16
|
+
# register_callback_module(ProconBypassMan::ProconDisplay::BypassHook)
|
14
17
|
|
15
|
-
attr_accessor :gadget, :procon, :bypass_value
|
18
|
+
attr_accessor :gadget, :procon, :bypass_value
|
16
19
|
|
17
20
|
def initialize(gadget: , procon: )
|
18
21
|
self.gadget = gadget
|
@@ -21,20 +24,18 @@ class ProconBypassMan::Bypass::ProconToSwitch
|
|
21
24
|
|
22
25
|
# @raise [Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT]
|
23
26
|
# @return [void]
|
24
|
-
def
|
27
|
+
def work(*)
|
25
28
|
ProconBypassMan::Procon::PerformanceMeasurement.measure do |measurement|
|
26
29
|
self.bypass_value = ProconBypassMan::Bypass::BypassValue.new(nil)
|
27
30
|
|
28
|
-
next(run_callbacks(:
|
31
|
+
next(run_callbacks(:work) {
|
29
32
|
next(false) if $will_terminate_token
|
30
33
|
|
31
34
|
raw_output = nil
|
32
35
|
measurement.record_read_time do
|
33
36
|
begin
|
34
|
-
|
35
|
-
|
36
|
-
raw_output = self.procon.read_nonblock(64)
|
37
|
-
end
|
37
|
+
return(false) if $will_terminate_token
|
38
|
+
raw_output = self.procon.read_nonblock(64)
|
38
39
|
rescue IO::EAGAINWaitReadable
|
39
40
|
sleep(0.002)
|
40
41
|
retry
|
@@ -42,36 +43,32 @@ class ProconBypassMan::Bypass::ProconToSwitch
|
|
42
43
|
return(false) if $will_terminate_token
|
43
44
|
raise
|
44
45
|
end
|
46
|
+
|
47
|
+
self.bypass_value.binary = ProconBypassMan::Domains::InboundProconBinary.new(binary: raw_output)
|
45
48
|
end
|
46
49
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT => e
|
65
|
-
return(false) if $will_terminate_token # rubocop:disable Lint/NoReturnInBeginEndBlocks
|
66
|
-
raise
|
67
|
-
end
|
50
|
+
result = measurement.record_write_time do
|
51
|
+
begin
|
52
|
+
ProconBypassMan::Retryable.retryable(tries: 5, on_no_retry: [Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT]) do
|
53
|
+
begin
|
54
|
+
# 終了処理を希望されているのでブロックを無視してメソッドを抜けてOK
|
55
|
+
return(false) if $will_terminate_token # rubocop:disable Lint/NoReturnInBeginEndBlocks
|
56
|
+
self.gadget.write_nonblock(
|
57
|
+
ProconBypassMan::Processor.new(bypass_value.binary).process
|
58
|
+
)
|
59
|
+
next(true)
|
60
|
+
rescue IO::EAGAINWaitReadable
|
61
|
+
return(false) if $will_terminate_token # rubocop:disable Lint/NoReturnInBeginEndBlocks
|
62
|
+
measurement.record_write_error
|
63
|
+
raise CouldNotWriteToSwitchError
|
64
|
+
rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError, Errno::ESHUTDOWN, Errno::ETIMEDOUT => e
|
65
|
+
return(false) if $will_terminate_token # rubocop:disable Lint/NoReturnInBeginEndBlocks
|
66
|
+
raise
|
68
67
|
end
|
69
|
-
rescue CouldNotWriteToSwitchError
|
70
|
-
next(false)
|
71
68
|
end
|
69
|
+
rescue CouldNotWriteToSwitchError
|
70
|
+
next(false)
|
72
71
|
end
|
73
|
-
|
74
|
-
next(result)
|
75
72
|
end
|
76
73
|
|
77
74
|
next(result)
|
@@ -94,14 +91,9 @@ class ProconBypassMan::Bypass::ProconToSwitch
|
|
94
91
|
private
|
95
92
|
|
96
93
|
def log_after_run
|
94
|
+
return unless ProconBypassMan.config.verbose_bypass_log
|
97
95
|
return unless bypass_value.to_text
|
98
96
|
|
99
|
-
|
100
|
-
ProconBypassMan.logger.debug { "<<< #{bypass_value.to_text}" }
|
101
|
-
else
|
102
|
-
ProconBypassMan.cache.fetch key: 'bypass_log', expires_in: 1 do
|
103
|
-
ProconBypassMan.logger.debug { "<<< #{bypass_value.to_text}" }
|
104
|
-
end
|
105
|
-
end
|
97
|
+
ProconBypassMan.logger.debug { "<<< #{bypass_value.to_text}" }
|
106
98
|
end
|
107
99
|
end
|
@@ -13,7 +13,6 @@ class ProconBypassMan::PrintBootMessageCommand
|
|
13
13
|
@table[:use_pbmenv] = !(!!`which pbmenv`.empty?)
|
14
14
|
@table[:session_id] = ProconBypassMan.session_id
|
15
15
|
@table[:device_id] = ProconBypassMan.device_id
|
16
|
-
@table[:bypass_mode] = ProconBypassMan.config.bypass_mode.to_s
|
17
16
|
@table[:never_exit_accidentally] = ProconBypassMan.config.never_exit_accidentally
|
18
17
|
@table[:uname] = `uname -a`.chomp
|
19
18
|
|
@@ -43,7 +42,6 @@ class ProconBypassMan::PrintBootMessageCommand
|
|
43
42
|
use_pbmenv: #{@table[:use_pbmenv]}
|
44
43
|
session_id: #{ProconBypassMan.session_id}
|
45
44
|
device_id: #{ProconBypassMan.device_id.gsub(/.{25}$/, "*"*25)}
|
46
|
-
bypass_mode: #{ProconBypassMan.config.bypass_mode}
|
47
45
|
----
|
48
46
|
EOF
|
49
47
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class ProconBypassMan::Configuration
|
2
4
|
module ClassMethods
|
3
5
|
def root
|
@@ -70,6 +72,7 @@ class ProconBypassMan::Configuration
|
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
75
|
+
# NOTE 不具合の原因は修正済みなので可変である必要は無くなった。削除したいが各端末内の設定ファイルに存在している場合があるのでしばらく残す
|
73
76
|
def bypass_mode=(value)
|
74
77
|
@bypass_mode = ProconBypassMan::BypassMode.new(
|
75
78
|
mode: value[:mode],
|
@@ -20,37 +20,54 @@ class ProconBypassMan::Procon::PerformanceMeasurement::MeasurementsSummarizer
|
|
20
20
|
end
|
21
21
|
|
22
22
|
# @return [PerformanceMetric]
|
23
|
+
# NOTE 中央値の表示価値が低いのでコメントアウト
|
23
24
|
def summarize
|
24
|
-
sorted_write_time = @spans.map(&:write_time).sort
|
25
|
-
sorted_read_time = @spans.map(&:read_time).sort
|
26
|
-
gc_count = @spans.map(&:gc_count).sum
|
27
|
-
gc_time = @spans.map(&:gc_time).sum
|
28
25
|
|
29
|
-
|
30
|
-
|
26
|
+
write_time_max = 0
|
27
|
+
read_time_max = 0
|
28
|
+
time_taken_max = 0
|
29
|
+
interval_from_previous_succeed_max = 0
|
30
|
+
@spans.each do |span|
|
31
|
+
# NOTE @spans.map(&:write_time).sort.last と同じことだけど、処理コストを軽くするためにループを共通化する
|
32
|
+
write_time_max = span.write_time if write_time_max < span.write_time
|
33
|
+
read_time_max = span.read_time if write_time_max < span.read_time
|
34
|
+
time_taken_max = span.time_taken if span.succeed && time_taken_max < span.time_taken
|
35
|
+
interval_from_previous_succeed_max = span.interval_from_previous_succeed if span.succeed && interval_from_previous_succeed_max < span.interval_from_previous_succeed
|
36
|
+
end
|
31
37
|
|
32
|
-
|
33
|
-
|
38
|
+
# NOTE 今はGCを無効にしており、集計するまでもないのでコメントアウトにする. 今後GCを有効にしたバイパスをするかもしれないので残しておく
|
39
|
+
gc_count = 0 # @spans.map(&:gc_count).sum
|
40
|
+
gc_time = 0 # @spans.map(&:gc_time).sum
|
34
41
|
|
35
|
-
|
36
|
-
|
42
|
+
# sorted_interval_from_previous_succeed = @spans.select(&:succeed).map(&:interval_from_previous_succeed).sort
|
43
|
+
# interval_from_previous_succeed_max = sorted_interval_from_previous_succeed.last || 0
|
44
|
+
interval_from_previous_succeed_p50 = 0 # percentile(sorted_list: sorted_interval_from_previous_succeed , percentile: 0.50)
|
37
45
|
|
38
|
-
|
39
|
-
read_time_p50 = percentile(sorted_list: sorted_read_time , percentile: 0.50)
|
46
|
+
# sorted_read_time = @spans.map(&:read_time).sort
|
47
|
+
read_time_p50 = 0 # percentile(sorted_list: sorted_read_time , percentile: 0.50)
|
48
|
+
# read_time_max = sorted_read_time.last || 0
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
time_taken_max = sorted_time_taken.last || 0
|
50
|
+
# sorted_write_time = @spans.map(&:write_time).sort
|
51
|
+
write_time_p50 = 0 # percentile(sorted_list: sorted_write_time , percentile: 0.50)
|
52
|
+
# write_time_max = sorted_write_time.last || 0
|
45
53
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
+
# sorted_time_taken = @spans.select(&:succeed).map(&:time_taken).sort
|
55
|
+
time_taken_p50 = 0 # percentile(sorted_list: sorted_time_taken, percentile: 0.50)
|
56
|
+
time_taken_p95 = 0 # percentile(sorted_list: sorted_time_taken, percentile: 0.95)
|
57
|
+
time_taken_p99 = 0 # percentile(sorted_list: sorted_time_taken, percentile: 0.99)
|
58
|
+
# time_taken_max = sorted_time_taken.last || 0
|
59
|
+
|
60
|
+
# NOTE webに表示していないのでコメントアウト. デバッグ時に見ることがあるので残しておく
|
61
|
+
total_read_error_count = 0 # @spans.map(&:read_error_count).sum
|
62
|
+
total_write_error_count = 0 # @spans.map(&:write_error_count).sum
|
63
|
+
|
64
|
+
# succeed_rate =
|
65
|
+
# if @spans.length.zero?
|
66
|
+
# 0
|
67
|
+
# else
|
68
|
+
# succeed_rate = (sorted_time_taken.length / @spans.length.to_f).floor(3)
|
69
|
+
# end
|
70
|
+
succeed_rate = 1 # Switchへの書き込みに失敗した時にretryしているので100%になるようになってる. succeedの個数をカウントコストを減らすためにハードコード
|
54
71
|
|
55
72
|
PerformanceMetric.new(interval_from_previous_succeed_max,
|
56
73
|
interval_from_previous_succeed_p50,
|
@@ -45,6 +45,13 @@ module ProconBypassMan::Procon::PerformanceMeasurement
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
# 全部送ると負荷になるので適当にまびく
|
49
|
+
def self.is_not_measure_with_random_or_if_fast(span: )
|
50
|
+
return false if span.time_taken > 0.1
|
51
|
+
return true if rand(20) != 0 # 19/20は捨てる
|
52
|
+
return false
|
53
|
+
end
|
54
|
+
|
48
55
|
# measureをして、measureの結果をためる
|
49
56
|
# @return [Boolean] 成功したか. テスト時に戻り値を使いたい
|
50
57
|
def self.measure(&bypass_process_block)
|
@@ -63,6 +70,8 @@ module ProconBypassMan::Procon::PerformanceMeasurement
|
|
63
70
|
span.succeed = bypass_process_block.call(span)
|
64
71
|
}.floor(3)
|
65
72
|
|
73
|
+
return if is_not_measure_with_random_or_if_fast(span: span)
|
74
|
+
|
66
75
|
if span.succeed
|
67
76
|
ProconBypassMan::Procon::PerformanceMeasurement::LastBypassAt.touch do |interval_from_previous_succeed|
|
68
77
|
span.interval_from_previous_succeed = interval_from_previous_succeed.floor(3)
|
@@ -79,11 +88,9 @@ module ProconBypassMan::Procon::PerformanceMeasurement
|
|
79
88
|
end
|
80
89
|
end
|
81
90
|
|
82
|
-
|
83
|
-
|
84
|
-
ProconBypassMan::
|
85
|
-
ProconBypassMan::ProconPerformanceSpanTransferJob.perform_async(spans.dup)
|
86
|
-
end
|
91
|
+
# measureするたびにperform_asyncしているとjob queueが詰まるのでbufferingしている
|
92
|
+
ProconBypassMan::Procon::PerformanceMeasurement::SpanTransferBuffer.instance.push_and_run_block_if_buffer_over(span) do |spans|
|
93
|
+
ProconBypassMan::ProconPerformanceSpanTransferJob.perform_async(spans)
|
87
94
|
end
|
88
95
|
return span.succeed
|
89
96
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "procon_bypass_man/procon/macro_plugin_map"
|
2
4
|
|
3
5
|
class ProconBypassMan::Procon
|
@@ -25,11 +27,11 @@ class ProconBypassMan::Procon
|
|
25
27
|
|
26
28
|
def self.reset!
|
27
29
|
@@status = {
|
28
|
-
buttons: {},
|
29
|
-
current_layer_key: :up,
|
30
30
|
ongoing_macro: MacroRegistry.load(:null),
|
31
|
-
ongoing_mode: ModeRegistry.load(:manual),
|
31
|
+
ongoing_mode: ModeRegistry.load(:manual), # 削除予定
|
32
32
|
}
|
33
|
+
BlueGreenProcess::SharedVariable.instance.data["buttons"] = {}
|
34
|
+
BlueGreenProcess::SharedVariable.instance.data["current_layer_key"] = :up
|
33
35
|
@@left_stick_tilting_power_scaler = ProconBypassMan::AnalogStickTiltingPowerScaler.new
|
34
36
|
end
|
35
37
|
reset!
|
@@ -41,10 +43,20 @@ class ProconBypassMan::Procon
|
|
41
43
|
)
|
42
44
|
end
|
43
45
|
|
44
|
-
def status
|
46
|
+
def status
|
47
|
+
BlueGreenProcess::SharedVariable.instance.data["buttons"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def current_layer_key
|
51
|
+
BlueGreenProcess::SharedVariable.instance.data["current_layer_key"].to_sym
|
52
|
+
end
|
53
|
+
|
54
|
+
def current_layer_key=(layer)
|
55
|
+
BlueGreenProcess::SharedVariable.instance.data["current_layer_key"] = layer
|
56
|
+
end
|
57
|
+
|
45
58
|
def ongoing_macro; @@status[:ongoing_macro]; end
|
46
59
|
def ongoing_mode; @@status[:ongoing_mode]; end
|
47
|
-
def current_layer_key; @@status[:current_layer_key]; end
|
48
60
|
|
49
61
|
def current_layer
|
50
62
|
ProconBypassMan::ButtonsSettingConfiguration.instance.layers[current_layer_key]
|
@@ -54,7 +66,7 @@ class ProconBypassMan::Procon
|
|
54
66
|
def apply!
|
55
67
|
layer_changer = ProconBypassMan::Procon::LayerChanger.new(binary: user_operation.binary)
|
56
68
|
if layer_changer.change_layer?
|
57
|
-
|
69
|
+
self.current_layer_key = layer_changer.next_layer_key if layer_changer.pressed_next_layer?
|
58
70
|
user_operation.set_no_action!
|
59
71
|
return
|
60
72
|
end
|
@@ -97,10 +109,14 @@ class ProconBypassMan::Procon
|
|
97
109
|
|
98
110
|
# remote macro
|
99
111
|
if task = ProconBypassMan::RemoteMacro::TaskQueueInProcess.non_blocking_shift
|
112
|
+
no_op_step = :wait_for_0_3 # マクロの最後に固まって最後の入力をし続けるので、無の状態を最後に注入する
|
113
|
+
BlueGreenProcess::SharedVariable.extend_run_on_this_process = true
|
100
114
|
ProconBypassMan::Procon::MacroRegistry.cleanup_remote_macros!
|
101
115
|
macro_name = task.name || "RemoteMacro-#{task.steps.join}".to_sym
|
116
|
+
task.steps << no_op_step
|
102
117
|
ProconBypassMan::Procon::MacroRegistry.install_plugin(macro_name, steps: task.steps, macro_type: :remote)
|
103
118
|
@@status[:ongoing_macro] = MacroRegistry.load(macro_name, macro_type: :remote) do
|
119
|
+
GC.start # NOTE: extend_run_on_this_process = true するとGCされなくなるので手動で呼び出す
|
104
120
|
ProconBypassMan::PostCompletedRemoteMacroJob.perform_async(task.uuid)
|
105
121
|
end
|
106
122
|
end
|
@@ -110,6 +126,7 @@ class ProconBypassMan::Procon
|
|
110
126
|
@@status[:ongoing_mode] = ModeRegistry.load(:manual)
|
111
127
|
current_layer.flip_buttons.each do |button, options|
|
112
128
|
if !options[:if_pressed]
|
129
|
+
# FIXME マルチプロセス化したので、クラス変数に状態を保持するFlipCacheは意図した挙動にならない. BlueGreenProcess.shared_variables を使って状態をプロセス間で共有すれば動く
|
113
130
|
FlipCache.fetch(key: button, expires_in: options[:flip_interval]) do
|
114
131
|
status[button] = !status[button]
|
115
132
|
end
|
@@ -146,6 +163,7 @@ class ProconBypassMan::Procon
|
|
146
163
|
end
|
147
164
|
|
148
165
|
if ongoing_macro.ongoing? && (step = ongoing_macro.next_step)
|
166
|
+
BlueGreenProcess::SharedVariable.extend_run_on_this_process = true
|
149
167
|
ongoing_macro.force_neutral_buttons&.each do |force_neutral_button|
|
150
168
|
user_operation.unpress_button(force_neutral_button)
|
151
169
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ProconBypassMan
|
2
4
|
module CallbacksRegisterable
|
3
5
|
attr_accessor :callbacks
|
@@ -93,9 +95,14 @@ module ProconBypassMan
|
|
93
95
|
return self.class.__callbacks[kind.to_sym]
|
94
96
|
end
|
95
97
|
|
96
|
-
list =
|
97
|
-
|
98
|
-
|
98
|
+
list =
|
99
|
+
if self.class.callbacks.nil?
|
100
|
+
[]
|
101
|
+
else
|
102
|
+
self.class.callbacks.flat_map { |callback_mod|
|
103
|
+
callback_mod.__callbacks && callback_mod.__callbacks[kind.to_sym]
|
104
|
+
}.compact
|
105
|
+
end
|
99
106
|
if(self.class.respond_to?(:__callbacks) && chain = self.class.__callbacks[kind.to_sym])
|
100
107
|
list << chain
|
101
108
|
end
|
@@ -34,6 +34,7 @@ module ProconBypassMan
|
|
34
34
|
|
35
35
|
def get
|
36
36
|
handle_request do
|
37
|
+
ProconBypassMan.logger.info "[HTTP] GET #{@uri}"
|
37
38
|
response = HttpRequest::Get.request!(
|
38
39
|
uri: @uri,
|
39
40
|
)
|
@@ -44,6 +45,7 @@ module ProconBypassMan
|
|
44
45
|
def post(request_body: )
|
45
46
|
handle_request do
|
46
47
|
body = {}.merge!(request_body)
|
48
|
+
ProconBypassMan.logger.info "[HTTP] POST #{@uri}"
|
47
49
|
response = HttpRequest::Post.request!(
|
48
50
|
uri: @uri,
|
49
51
|
request_body: body,
|
@@ -57,6 +59,7 @@ module ProconBypassMan
|
|
57
59
|
body = {
|
58
60
|
hostname: `hostname`.chomp,
|
59
61
|
}.merge!(request_body)
|
62
|
+
ProconBypassMan.logger.info "[HTTP] PUT #{@uri}"
|
60
63
|
response = HttpRequest::Put.request!(
|
61
64
|
uri: @uri,
|
62
65
|
request_body: body,
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
class ReniceCommand
|
3
|
+
def self.change_priority(to: , pid: )
|
4
|
+
cmd =
|
5
|
+
case to
|
6
|
+
when :high
|
7
|
+
"renice -n -20 -p #{pid}"
|
8
|
+
when :low
|
9
|
+
"renice -n 20 -p #{pid}"
|
10
|
+
else
|
11
|
+
raise "unknown priority"
|
12
|
+
end
|
13
|
+
ProconBypassMan.logger.debug { "[SHELL] #{cmd}" }
|
14
|
+
`#{cmd}`
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/procon_bypass_man.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "logger"
|
2
4
|
require 'yaml'
|
3
5
|
require "json"
|
@@ -10,6 +12,7 @@ require "ext/em_pure_ruby"
|
|
10
12
|
require "ext/module"
|
11
13
|
require "resolv-replace"
|
12
14
|
require "pbmenv"
|
15
|
+
require "blue_green_process"
|
13
16
|
|
14
17
|
require_relative "procon_bypass_man/version"
|
15
18
|
|
@@ -38,6 +41,7 @@ require_relative "procon_bypass_man/support/cycle_sleep"
|
|
38
41
|
require_relative "procon_bypass_man/support/can_over_process"
|
39
42
|
require_relative "procon_bypass_man/support/gc"
|
40
43
|
require_relative "procon_bypass_man/support/retryable"
|
44
|
+
require_relative "procon_bypass_man/support/renice_command"
|
41
45
|
require_relative "procon_bypass_man/procon_display"
|
42
46
|
require_relative "procon_bypass_man/background"
|
43
47
|
require_relative "procon_bypass_man/commands"
|
@@ -149,7 +153,7 @@ module ProconBypassMan
|
|
149
153
|
|
150
154
|
# @return [void]
|
151
155
|
def self.initialize_pbm
|
152
|
-
|
156
|
+
ProconBypassMan::ReniceCommand.change_priority(to: :low, pid: $$)
|
153
157
|
ProconBypassMan::Background::JobQueue.start!
|
154
158
|
ProconBypassMan::Websocket::Client.start!
|
155
159
|
# TODO ProconBypassMan::DrbObjects.start_all! みたいな感じで書きたい
|
@@ -173,18 +177,27 @@ module ProconBypassMan
|
|
173
177
|
|
174
178
|
# @return [void]
|
175
179
|
def self.after_fork_on_bypass_process
|
176
|
-
|
180
|
+
ProconBypassMan::ReniceCommand.change_priority(to: :high, pid: $$)
|
177
181
|
::GC.start
|
178
182
|
DRb.start_service if defined?(DRb)
|
179
|
-
|
180
|
-
ProconBypassMan::ProconDisplay::Server.start!
|
183
|
+
# GC対策することによって一時的に削除した機能
|
184
|
+
# ProconBypassMan::ProconDisplay::Server.start!
|
185
|
+
|
186
|
+
DRb.start_service if defined?(DRb)
|
187
|
+
BlueGreenProcess.configure do |config|
|
188
|
+
config.after_fork = -> {
|
189
|
+
DRb.start_service if defined?(DRb)
|
190
|
+
ProconBypassMan::RemoteMacroReceiver.start!
|
191
|
+
BlueGreenProcess.config.logger = ProconBypassMan.logger
|
192
|
+
}
|
193
|
+
config.shared_variables = [:buttons, :current_layer_key]
|
194
|
+
end
|
181
195
|
end
|
182
196
|
|
183
197
|
# @return [void]
|
184
198
|
def self.terminate_pbm
|
185
199
|
FileUtils.rm_rf(ProconBypassMan.pid_path)
|
186
200
|
FileUtils.rm_rf(ProconBypassMan.digest_path)
|
187
|
-
ProconBypassMan::Background::JobQueue.shutdown
|
188
201
|
ProconBypassMan::RemoteMacro::QueueOverProcess.shutdown
|
189
202
|
ProconBypassMan::Procon::PerformanceMeasurement::QueueOverProcess.shutdown
|
190
203
|
self.worker&.shutdown
|
data/procon_bypass_man.gemspec
CHANGED
@@ -28,9 +28,11 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
30
|
# Uncomment to register a new dependency of your gem
|
31
|
-
spec.add_dependency "pbmenv", ">= 0.1.9" # Pbmenv.install
|
31
|
+
spec.add_dependency "pbmenv", ">= 0.1.9" # enable_pbm_cloud連携機能でPbmenv.installを使っている.
|
32
32
|
spec.add_dependency "action_cable_client"
|
33
33
|
spec.add_dependency "sorted_set"
|
34
|
+
spec.add_dependency "blue_green_process"
|
35
|
+
# spec.add_dependency "blue_green_process"
|
34
36
|
|
35
37
|
# For more information and examples about making a new gem, checkout our
|
36
38
|
# guide at: https://bundler.io/guides/creating_gem.html
|
data/project_template/app.rb
CHANGED
@@ -12,7 +12,7 @@ begin
|
|
12
12
|
gemfile do
|
13
13
|
source 'https://rubygems.org'
|
14
14
|
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
15
|
-
gem 'procon_bypass_man', '0.
|
15
|
+
gem 'procon_bypass_man', '0.3.0'
|
16
16
|
end
|
17
17
|
rescue Bundler::Source::Git::GitCommandError => e
|
18
18
|
retry_count_on_git_command_error = retry_count_on_git_command_error + 1
|
@@ -49,9 +49,6 @@ ProconBypassMan.configure do |config|
|
|
49
49
|
|
50
50
|
# 接続に成功したらコントローラーのHOME LEDを光らせるか
|
51
51
|
config.enable_home_led_on_connect = true
|
52
|
-
|
53
|
-
# 操作が高頻度で固まるときは、 gadget_to_procon_interval の数値を大きくしてください
|
54
|
-
config.bypass_mode = { mode: :normal, gadget_to_procon_interval: 10 }
|
55
52
|
end
|
56
53
|
|
57
54
|
ProconBypassMan.run(setting_path: "/usr/share/pbm/current/setting.yml")
|
data/project_template/app.rb.erb
CHANGED
@@ -12,7 +12,7 @@ begin
|
|
12
12
|
gemfile do
|
13
13
|
source 'https://rubygems.org'
|
14
14
|
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
15
|
-
gem 'procon_bypass_man', '0.
|
15
|
+
gem 'procon_bypass_man', '0.3.0'
|
16
16
|
end
|
17
17
|
rescue Bundler::Source::Git::GitCommandError => e
|
18
18
|
retry_count_on_git_command_error = retry_count_on_git_command_error + 1
|
@@ -54,9 +54,6 @@ ProconBypassMan.configure do |config|
|
|
54
54
|
|
55
55
|
# 接続に成功したらコントローラーのHOME LEDを光らせるか
|
56
56
|
config.enable_home_led_on_connect = true
|
57
|
-
|
58
|
-
# 操作が高頻度で固まるときは、 gadget_to_procon_interval の数値を大きくしてください
|
59
|
-
config.bypass_mode = { mode: :normal, gadget_to_procon_interval: 10 }
|
60
57
|
end
|
61
58
|
|
62
59
|
ProconBypassMan.run(setting_path: "/usr/share/pbm/current/setting.yml")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: procon_bypass_man
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jiikko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-08
|
11
|
+
date: 2022-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pbmenv
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: blue_green_process
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
description: A programmable converter for Nintendo Switch Pro Controller
|
56
70
|
email:
|
57
71
|
- n905i.1214@gmail.com
|
@@ -232,6 +246,7 @@ files:
|
|
232
246
|
- lib/procon_bypass_man/support/on_memory_cache.rb
|
233
247
|
- lib/procon_bypass_man/support/procon_performance_http_client.rb
|
234
248
|
- lib/procon_bypass_man/support/remote_macro_http_client.rb
|
249
|
+
- lib/procon_bypass_man/support/renice_command.rb
|
235
250
|
- lib/procon_bypass_man/support/report_http_client.rb
|
236
251
|
- lib/procon_bypass_man/support/retryable.rb
|
237
252
|
- lib/procon_bypass_man/support/safe_timeout.rb
|