procon_bypass_man 0.1.12 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +33 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +35 -15
- data/README.md +19 -8
- data/lib/ext/em_pure_ruby.rb +25 -0
- data/lib/procon_bypass_man/background/job_runner.rb +6 -5
- data/lib/procon_bypass_man/background/jobs/base_job.rb +1 -6
- data/lib/procon_bypass_man/background/jobs/concerns/has_external_api_setting.rb +5 -0
- data/lib/procon_bypass_man/background/jobs/concerns/has_internal_api_setting.rb +5 -0
- data/lib/procon_bypass_man/background/{job_runnable.rb → jobs/concerns/job_runnable.rb} +0 -0
- data/lib/procon_bypass_man/background/jobs/report_boot_job.rb +5 -3
- data/lib/procon_bypass_man/background/jobs/report_error_job.rb +6 -5
- data/lib/procon_bypass_man/background/jobs/report_event_base_job.rb +5 -0
- data/lib/procon_bypass_man/background/jobs/report_load_config_job.rb +11 -0
- data/lib/procon_bypass_man/background/jobs/report_pressed_buttons_job.rb +7 -10
- data/lib/procon_bypass_man/background/jobs/report_reload_config_job.rb +5 -4
- data/lib/procon_bypass_man/background/jobs/sync_device_stats_job.rb +16 -0
- data/lib/procon_bypass_man/background.rb +7 -4
- data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +36 -35
- data/lib/procon_bypass_man/buttons_setting_configuration.rb +2 -2
- data/lib/procon_bypass_man/bypass/usb_hid_logger.rb +8 -6
- data/lib/procon_bypass_man/bypass.rb +13 -6
- data/lib/procon_bypass_man/commands/bypass_command.rb +86 -0
- data/lib/procon_bypass_man/commands/connect_device_command.rb +7 -2
- data/lib/procon_bypass_man/commands/print_boot_message_command.rb +51 -2
- data/lib/procon_bypass_man/commands/print_message_command.rb +8 -0
- data/lib/procon_bypass_man/commands/run_remote_pbm_action_dispatch_command.rb +21 -0
- data/lib/procon_bypass_man/commands/send_error_command.rb +2 -1
- data/lib/procon_bypass_man/commands/send_reload_config_event_command.rb +2 -2
- data/lib/procon_bypass_man/commands/write_device_id_command.rb +1 -0
- data/lib/procon_bypass_man/commands/write_session_id_command.rb +1 -7
- data/lib/procon_bypass_man/commands.rb +3 -0
- data/lib/procon_bypass_man/configuration.rb +51 -5
- data/lib/procon_bypass_man/device_connector.rb +32 -24
- data/lib/procon_bypass_man/device_status.rb +44 -0
- data/lib/procon_bypass_man/domains/binary/base.rb +11 -0
- data/lib/procon_bypass_man/domains/binary/has_immutable_binary.rb +5 -0
- data/lib/procon_bypass_man/domains/binary/has_mutable_binary.rb +5 -0
- data/lib/procon_bypass_man/domains/binary/inbound_procon_binary.rb +23 -0
- data/lib/procon_bypass_man/domains/binary/processing_procon_binary.rb +80 -0
- data/lib/procon_bypass_man/domains.rb +11 -0
- data/lib/procon_bypass_man/plugin/splatoon2/macro/fast_return.rb +17 -0
- data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_left_key.rb +17 -0
- data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_right_key.rb +17 -0
- data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_up_key.rb +17 -0
- data/lib/procon_bypass_man/plugin/splatoon2/mode/guruguru.rb +59 -0
- data/lib/procon_bypass_man/plugin/splatoon2/version.rb +9 -0
- data/lib/procon_bypass_man/plugins.rb +11 -0
- data/lib/procon_bypass_man/processor.rb +4 -5
- data/lib/procon_bypass_man/procon/analog_stick_cap.rb +1 -1
- data/lib/procon_bypass_man/procon/button.rb +11 -0
- data/lib/procon_bypass_man/procon/button_collection.rb +2 -12
- data/lib/procon_bypass_man/procon/layer_changer.rb +3 -2
- data/lib/procon_bypass_man/procon/press_button_aware.rb +5 -4
- data/lib/procon_bypass_man/procon/user_operation.rb +46 -63
- data/lib/procon_bypass_man/procon/{analog_stick.rb → value_objects/analog_stick.rb} +3 -4
- data/lib/procon_bypass_man/procon/value_objects/procon_reader.rb +34 -0
- data/lib/procon_bypass_man/procon.rb +16 -14
- data/lib/procon_bypass_man/remote_pbm_action/base_action.rb +53 -0
- data/lib/procon_bypass_man/remote_pbm_action/change_pbm_version_action.rb +25 -0
- data/lib/procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command.rb +24 -0
- data/lib/procon_bypass_man/remote_pbm_action/reboot_os_action.rb +21 -0
- data/lib/procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb +28 -0
- data/lib/procon_bypass_man/remote_pbm_action/stop_pbm_action.rb +21 -0
- data/lib/procon_bypass_man/remote_pbm_action/value_objects/remote_pbm_action_object.rb +38 -0
- data/lib/procon_bypass_man/remote_pbm_action.rb +32 -0
- data/lib/procon_bypass_man/runner.rb +8 -97
- data/lib/procon_bypass_man/scheduler.rb +85 -0
- data/lib/procon_bypass_man/{callbacks.rb → support/callbacks.rb} +0 -0
- data/lib/procon_bypass_man/support/compress_array.rb +56 -0
- data/lib/procon_bypass_man/support/http_client.rb +102 -0
- data/lib/procon_bypass_man/{on_memory_cache.rb → support/on_memory_cache.rb} +0 -0
- data/lib/procon_bypass_man/support/report_http_client.rb +19 -0
- data/lib/procon_bypass_man/{timer.rb → support/safe_timeout.rb} +1 -1
- data/lib/procon_bypass_man/support/send_device_stats_http_client.rb +9 -0
- data/lib/procon_bypass_man/{background/has_server_pool.rb → support/server_pool.rb} +3 -15
- data/lib/procon_bypass_man/support/signal_handler.rb +11 -0
- data/lib/procon_bypass_man/support/update_remote_pbm_action_status_http_client.rb +9 -0
- data/lib/procon_bypass_man/{uptime.rb → support/uptime.rb} +0 -0
- data/lib/procon_bypass_man/version.rb +1 -1
- data/lib/procon_bypass_man/websocket/pbm_job_client.rb +79 -0
- data/lib/procon_bypass_man.rb +68 -34
- data/procon_bypass_man.gemspec +5 -3
- data/project_template/README.md +18 -11
- data/project_template/app.rb +1 -2
- data/project_template/setting.yml +8 -8
- data/sig/{README.rb → README.md} +0 -0
- data/sig/main.rbs +16 -1
- metadata +102 -21
- data/lib/procon_bypass_man/background/http_client.rb +0 -70
- data/lib/procon_bypass_man/background/jobs/report_heartbeat_job.rb +0 -10
- data/lib/procon_bypass_man/boot_message.rb +0 -42
- data/lib/procon_bypass_man/procon_reader.rb +0 -31
@@ -20,8 +20,11 @@ class ProconBypassMan::Procon
|
|
20
20
|
end
|
21
21
|
reset!
|
22
22
|
|
23
|
+
# @param [string] binary
|
23
24
|
def initialize(binary)
|
24
|
-
self.user_operation = ProconBypassMan::Procon::UserOperation.new(
|
25
|
+
self.user_operation = ProconBypassMan::Procon::UserOperation.new(
|
26
|
+
binary.dup
|
27
|
+
)
|
25
28
|
end
|
26
29
|
|
27
30
|
def status; @@status[:buttons]; end
|
@@ -43,7 +46,7 @@ class ProconBypassMan::Procon
|
|
43
46
|
|
44
47
|
if ongoing_macro.finished?
|
45
48
|
current_layer.macros.each do |macro_name, options|
|
46
|
-
if options[:if_pressed]
|
49
|
+
if user_operation.pressing_all_buttons?(options[:if_pressed])
|
47
50
|
@@status[:ongoing_macro] = MacroRegistry.load(macro_name)
|
48
51
|
end
|
49
52
|
end
|
@@ -60,7 +63,7 @@ class ProconBypassMan::Procon
|
|
60
63
|
next
|
61
64
|
end
|
62
65
|
|
63
|
-
if options[:if_pressed] && options[:if_pressed]
|
66
|
+
if options[:if_pressed] && user_operation.pressing_all_buttons?(options[:if_pressed])
|
64
67
|
FlipCache.fetch(key: button, expires_in: options[:flip_interval]) do
|
65
68
|
status[button] = !status[button]
|
66
69
|
end
|
@@ -75,7 +78,7 @@ class ProconBypassMan::Procon
|
|
75
78
|
@@status[:ongoing_mode] = ProconBypassMan::Procon::ModeRegistry.load(current_layer.mode)
|
76
79
|
end
|
77
80
|
if(binary = ongoing_mode.next_binary)
|
78
|
-
self.user_operation.merge(
|
81
|
+
self.user_operation.merge([binary].pack("H*"))
|
79
82
|
end
|
80
83
|
return
|
81
84
|
end
|
@@ -83,24 +86,24 @@ class ProconBypassMan::Procon
|
|
83
86
|
status
|
84
87
|
end
|
85
88
|
|
86
|
-
# @return [
|
89
|
+
# @return [ProconBypassMan::Domains::ProcessingProconBinary]
|
87
90
|
def to_binary
|
88
91
|
if ongoing_mode.name != :manual
|
89
|
-
return user_operation.binary
|
92
|
+
return user_operation.binary.raw
|
90
93
|
end
|
91
94
|
|
92
95
|
if ongoing_macro.ongoing?
|
93
|
-
step = ongoing_macro.next_step or return(user_operation.binary)
|
96
|
+
step = ongoing_macro.next_step or return(user_operation.binary.raw)
|
94
97
|
user_operation.press_button_only(step)
|
95
|
-
return user_operation.binary
|
98
|
+
return user_operation.binary.raw
|
96
99
|
end
|
97
100
|
|
98
101
|
current_layer.disables.each do |button|
|
99
102
|
user_operation.unpress_button(button)
|
100
103
|
end
|
101
104
|
|
102
|
-
current_layer.left_analog_stick_caps.each do |
|
103
|
-
if
|
105
|
+
current_layer.left_analog_stick_caps.each do |buttons, options|
|
106
|
+
if buttons.nil? || user_operation.pressing_all_buttons?(buttons)
|
104
107
|
options[:force_neutral]&.each do |force_neutral_button|
|
105
108
|
user_operation.unpress_button(force_neutral_button)
|
106
109
|
end
|
@@ -116,7 +119,7 @@ class ProconBypassMan::Procon
|
|
116
119
|
end
|
117
120
|
|
118
121
|
# 押している時だけ連打
|
119
|
-
if options[:if_pressed] && options[:if_pressed]
|
122
|
+
if options[:if_pressed] && user_operation.pressing_all_buttons?(options[:if_pressed])
|
120
123
|
if !status[button]
|
121
124
|
user_operation.unpress_button(button)
|
122
125
|
end
|
@@ -128,16 +131,15 @@ class ProconBypassMan::Procon
|
|
128
131
|
end
|
129
132
|
|
130
133
|
current_layer.remaps.each do |from_button, to_buttons|
|
131
|
-
if user_operation.
|
134
|
+
if user_operation.pressing_button?(from_button)
|
132
135
|
user_operation.unpress_button(from_button)
|
133
|
-
# TODO 2重でpressしないようにしたい
|
134
136
|
to_buttons[:to].each do |to_button|
|
135
137
|
user_operation.press_button(to_button)
|
136
138
|
end
|
137
139
|
end
|
138
140
|
end
|
139
141
|
|
140
|
-
user_operation.binary
|
142
|
+
user_operation.binary.raw
|
141
143
|
end
|
142
144
|
|
143
145
|
private
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
module RemotePbmAction
|
3
|
+
class ActionUnexpectedError < StandardError; end
|
4
|
+
class NeedPbmVersionError < ActionUnexpectedError; end
|
5
|
+
|
6
|
+
class BaseAction
|
7
|
+
attr_accessor :pbm_job_uuid
|
8
|
+
|
9
|
+
# @param [String] pbm_job_uuid
|
10
|
+
def initialize(pbm_job_uuid: )
|
11
|
+
self.pbm_job_uuid = pbm_job_uuid
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [void]
|
15
|
+
def action_content(_args)
|
16
|
+
raise NotImplementedError, nil
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param [Hash] args
|
20
|
+
# @return [void]
|
21
|
+
def run!(job_args: )
|
22
|
+
before_action_callback
|
23
|
+
action_content(args: job_args)
|
24
|
+
after_action_callback
|
25
|
+
rescue => e
|
26
|
+
be_failed
|
27
|
+
ProconBypassMan::SendErrorCommand.execute(error: e)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
# @return [void]
|
33
|
+
def before_action_callback; end
|
34
|
+
# @return [void]
|
35
|
+
def after_action_callback; end
|
36
|
+
|
37
|
+
# @return [void]
|
38
|
+
def be_failed
|
39
|
+
ProconBypassMan::UpdateRemotePbmActionStatusCommand.new(pbm_job_uuid: pbm_job_uuid).execute(to_status: :failed)
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [void]
|
43
|
+
def be_in_progress
|
44
|
+
ProconBypassMan::UpdateRemotePbmActionStatusCommand.new(pbm_job_uuid: pbm_job_uuid).execute(to_status: :in_progress)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [void]
|
48
|
+
def be_processed
|
49
|
+
ProconBypassMan::UpdateRemotePbmActionStatusCommand.new(pbm_job_uuid: pbm_job_uuid).execute(to_status: :processed)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
module RemotePbmAction
|
3
|
+
class ChangePbmVersionAction < BaseAction
|
4
|
+
|
5
|
+
def action_content(args: )
|
6
|
+
require "pbmenv"
|
7
|
+
ProconBypassMan.logger.info "execute ChangePbmVersionAction!"
|
8
|
+
pbm_version = args["pbm_version"] or raise(ProconBypassMan::RemotePbmAction::NeedPbmVersionError, "pbm_versionが必要です, #{args.inspect}")
|
9
|
+
Pbmenv.install(pbm_version)
|
10
|
+
Pbmenv.use(pbm_version)
|
11
|
+
`reboot` # symlinkの参照先が変わるのでrebootする必要がある
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def before_action_callback
|
17
|
+
be_processed
|
18
|
+
end
|
19
|
+
|
20
|
+
def after_action_callback
|
21
|
+
# no-op
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
class UpdateRemotePbmActionStatusCommand
|
3
|
+
# @param [String] pbm_job_uuid
|
4
|
+
def initialize(pbm_job_uuid: )
|
5
|
+
@pbm_job_uuid = pbm_job_uuid
|
6
|
+
end
|
7
|
+
|
8
|
+
# @param [String] to_status
|
9
|
+
# @return [void]
|
10
|
+
def execute(to_status: )
|
11
|
+
ProconBypassMan::UpdateRemotePbmActionStatusHttpClient.new(
|
12
|
+
path: path,
|
13
|
+
server_pool: ProconBypassMan.config.server_pool,
|
14
|
+
).put(to_status: to_status)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
# @return [String]
|
20
|
+
def path
|
21
|
+
"/api/devices/#{ProconBypassMan.device_id}/pbm_jobs/#{@pbm_job_uuid}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
module RemotePbmAction
|
3
|
+
class RebootOsAction < BaseAction
|
4
|
+
|
5
|
+
def action_content(_args)
|
6
|
+
ProconBypassMan.logger.info "execute RebootOsAction!"
|
7
|
+
`reboot`
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def before_action_callback
|
13
|
+
be_processed
|
14
|
+
end
|
15
|
+
|
16
|
+
def after_action_callback
|
17
|
+
# no-op
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
module RemotePbmAction
|
3
|
+
class RestorePbmSettingAction < BaseAction
|
4
|
+
|
5
|
+
def action_content(args: )
|
6
|
+
require "pbmenv"
|
7
|
+
ProconBypassMan.logger.info "execute RestorePbmSettingAction!"
|
8
|
+
setting = args.dig("setting") or raise(ProconBypassMan::RemotePbmAction::NeedPbmVersionError, "settingが必要です, #{args.inspect}")
|
9
|
+
File.write(
|
10
|
+
ProconBypassMan::ButtonsSettingConfiguration.instance.setting_path,
|
11
|
+
setting.to_yaml,
|
12
|
+
)
|
13
|
+
ProconBypassMan.hot_reload!
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def before_action_callback
|
19
|
+
be_in_progress
|
20
|
+
end
|
21
|
+
|
22
|
+
def after_action_callback
|
23
|
+
be_processed
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
module RemotePbmAction
|
3
|
+
class StopPbmAction < BaseAction
|
4
|
+
|
5
|
+
def action_content(_args)
|
6
|
+
ProconBypassMan.logger.info "execute StopPbmAction!"
|
7
|
+
Process.kill("TERM", ProconBypassMan.pid)
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def before_action_callback
|
13
|
+
be_processed
|
14
|
+
end
|
15
|
+
|
16
|
+
def after_action_callback
|
17
|
+
# no-op
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
class RemotePbmActionObject
|
3
|
+
# valueobjectがvalidatorの責務も持っている. 今度分離する
|
4
|
+
class ValidationError < StandardError; end
|
5
|
+
class MustBeNotNilError < ValidationError; end
|
6
|
+
class NonSupportAction < ValidationError; end
|
7
|
+
|
8
|
+
attr_accessor :action, :status, :uuid, :created_at, :job_args
|
9
|
+
|
10
|
+
# @param [String] action
|
11
|
+
# @param [String] status
|
12
|
+
# @param [String] #uuid
|
13
|
+
# @param [Time] created_at
|
14
|
+
# @return [Hash] job_args
|
15
|
+
def initialize(action: , status:, uuid:, created_at:, job_args: )
|
16
|
+
self.action = action
|
17
|
+
self.status = status
|
18
|
+
self.uuid = uuid
|
19
|
+
self.created_at = created_at
|
20
|
+
self.job_args = job_args
|
21
|
+
|
22
|
+
freeze
|
23
|
+
end
|
24
|
+
|
25
|
+
# @raise [MustBeNotNilError]
|
26
|
+
# @raise [NonSupportAction]
|
27
|
+
# @return [void]
|
28
|
+
def validate!
|
29
|
+
self.action or raise MustBeNotNilError, "actionは値が必須です"
|
30
|
+
self.status or raise MustBeNotNilError, "statusは値が必須です"
|
31
|
+
self.uuid or raise MustBeNotNilError, "uuidは値が必須です"
|
32
|
+
|
33
|
+
unless ProconBypassMan::RemotePbmAction::ACTIONS.include?(action)
|
34
|
+
raise NonSupportAction, "知らないアクションです"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
module RemotePbmAction
|
3
|
+
require "procon_bypass_man/remote_pbm_action/base_action"
|
4
|
+
require "procon_bypass_man/remote_pbm_action/change_pbm_version_action"
|
5
|
+
require "procon_bypass_man/remote_pbm_action/reboot_os_action"
|
6
|
+
require "procon_bypass_man/remote_pbm_action/stop_pbm_action"
|
7
|
+
require "procon_bypass_man/remote_pbm_action/restore_pbm_setting.rb"
|
8
|
+
require "procon_bypass_man/remote_pbm_action/commands/update_remote_pbm_action_status_command"
|
9
|
+
|
10
|
+
ACTION_CHANGE_PBM_VERSION = "change_pbm_version"
|
11
|
+
ACTION_REBOOT_OS = "reboot_os"
|
12
|
+
ACTION_STOP_PBM = "stop_pbm"
|
13
|
+
ACTION_RESTORE_SETTING = "restore_pbm_setting"
|
14
|
+
|
15
|
+
ACTIONS = [
|
16
|
+
ACTION_CHANGE_PBM_VERSION,
|
17
|
+
ACTION_REBOOT_OS,
|
18
|
+
ACTION_STOP_PBM,
|
19
|
+
ACTION_RESTORE_SETTING,
|
20
|
+
]
|
21
|
+
|
22
|
+
STATUS_FAILED = :failed
|
23
|
+
STATUS_IN_PROGRESS = :in_progress
|
24
|
+
STATUS_PROCESSED = :processed
|
25
|
+
|
26
|
+
ACTION_STATUSES = [
|
27
|
+
STATUS_FAILED,
|
28
|
+
STATUS_IN_PROGRESS,
|
29
|
+
STATUS_PROCESSED,
|
30
|
+
]
|
31
|
+
end
|
32
|
+
end
|
@@ -1,17 +1,15 @@
|
|
1
1
|
require_relative "io_monitor"
|
2
|
-
require_relative "uptime"
|
3
|
-
require_relative "boot_message"
|
4
|
-
require_relative "background/job_runner"
|
5
2
|
|
6
3
|
class ProconBypassMan::Runner
|
7
4
|
class InterruptForRestart < StandardError; end
|
8
5
|
|
6
|
+
include ProconBypassMan::SignalHandler
|
7
|
+
|
9
8
|
def initialize(gadget: , procon: )
|
10
9
|
@gadget = gadget
|
11
10
|
@procon = procon
|
12
11
|
|
13
12
|
ProconBypassMan::PrintBootMessageCommand.execute
|
14
|
-
ProconBypassMan::Background::JobRunner.start!
|
15
13
|
end
|
16
14
|
|
17
15
|
def run
|
@@ -28,9 +26,11 @@ class ProconBypassMan::Runner
|
|
28
26
|
|
29
27
|
loop do
|
30
28
|
$will_terminate_token = false
|
31
|
-
|
29
|
+
# NOTE メインプロセスではThreadをいくつか起動しているので念のためパフォーマンスを優先するためにforkしていく
|
30
|
+
main_loop_pid = Kernel.fork { ProconBypassMan::BypassCommand.new(gadget: @gadget, procon: @procon).execute }
|
32
31
|
|
33
32
|
begin
|
33
|
+
# TODO 小プロセスが消滅した時に、メインプロセスは生き続けてしまい、何もできなくなる問題がある
|
34
34
|
while(readable_io = IO.select([self_read]))
|
35
35
|
signal = readable_io.first[0].gets.strip
|
36
36
|
handle_signal(signal)
|
@@ -39,14 +39,14 @@ class ProconBypassMan::Runner
|
|
39
39
|
$will_terminate_token = true
|
40
40
|
Process.kill("TERM", main_loop_pid)
|
41
41
|
Process.wait
|
42
|
-
ProconBypassMan.
|
42
|
+
ProconBypassMan::PrintMessageCommand.execute(text: "Reloading config file")
|
43
43
|
begin
|
44
44
|
ProconBypassMan::ButtonsSettingConfiguration::Loader.reload_setting
|
45
|
+
ProconBypassMan::SendReloadConfigEventCommand.execute
|
45
46
|
rescue ProconBypassMan::CouldNotLoadConfigError
|
46
47
|
ProconBypassMan::SendErrorCommand.execute(error: "設定ファイルが不正です。再読み込みができませんでした")
|
47
48
|
end
|
48
|
-
ProconBypassMan::
|
49
|
-
ProconBypassMan.logger.info("バイパス処理を再開します")
|
49
|
+
ProconBypassMan::PrintMessageCommand.execute(text: "バイパス処理を再開します")
|
50
50
|
rescue Interrupt
|
51
51
|
$will_terminate_token = true
|
52
52
|
Process.kill("TERM", main_loop_pid)
|
@@ -59,93 +59,4 @@ class ProconBypassMan::Runner
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def main_loop
|
66
|
-
ProconBypassMan::IOMonitor.start!
|
67
|
-
ProconBypassMan::Background::JobRunner.start!
|
68
|
-
|
69
|
-
# gadget => procon
|
70
|
-
# 遅くていい
|
71
|
-
monitor1 = ProconBypassMan::IOMonitor.new(label: "switch -> procon")
|
72
|
-
monitor2 = ProconBypassMan::IOMonitor.new(label: "procon -> switch")
|
73
|
-
ProconBypassMan.logger.info "Thread1を起動します"
|
74
|
-
t1 = Thread.new do
|
75
|
-
timer = ProconBypassMan::Timer.new(timeout: Time.now + 10)
|
76
|
-
bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor1)
|
77
|
-
loop do
|
78
|
-
break if $will_terminate_token
|
79
|
-
timer.throw_if_timeout!
|
80
|
-
bypass.send_gadget_to_procon!
|
81
|
-
sleep(0.005)
|
82
|
-
rescue ProconBypassMan::Timer::Timeout
|
83
|
-
ProconBypassMan.logger.info "10秒経過したのでThread1を終了します"
|
84
|
-
monitor1.shutdown
|
85
|
-
puts "10秒経過したのでThread1を終了します"
|
86
|
-
break
|
87
|
-
rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
|
88
|
-
ProconBypassMan::SendErrorCommand.execute(error: "Switchとの切断されました.終了処理を開始します. #{e.full_message}")
|
89
|
-
Process.kill "TERM", Process.ppid
|
90
|
-
rescue Errno::ETIMEDOUT => e
|
91
|
-
# TODO まれにこれが発生する. 再接続したい
|
92
|
-
ProconBypassMan::SendErrorCommand.execute(error: "Switchと意図せず切断されました.終了処理を開始します. #{e.full_message}")
|
93
|
-
Process.kill "TERM", Process.ppid
|
94
|
-
end
|
95
|
-
ProconBypassMan.logger.info "Thread1を終了します"
|
96
|
-
end
|
97
|
-
|
98
|
-
# procon => gadget
|
99
|
-
# シビア
|
100
|
-
ProconBypassMan.logger.info "Thread2を起動します"
|
101
|
-
t2 = Thread.new do
|
102
|
-
bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor2)
|
103
|
-
loop do
|
104
|
-
break if $will_terminate_token
|
105
|
-
bypass.send_procon_to_gadget!
|
106
|
-
rescue EOFError => e
|
107
|
-
ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
|
108
|
-
Process.kill "TERM", Process.ppid
|
109
|
-
rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
|
110
|
-
ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します2. #{e.full_message}")
|
111
|
-
Process.kill "TERM", Process.ppid
|
112
|
-
end
|
113
|
-
ProconBypassMan.logger.info "Thread2を終了します"
|
114
|
-
end
|
115
|
-
|
116
|
-
self_read, self_write = IO.pipe
|
117
|
-
%w(TERM INT).each do |sig|
|
118
|
-
begin
|
119
|
-
trap sig do
|
120
|
-
self_write.puts(sig)
|
121
|
-
end
|
122
|
-
rescue ArgumentError
|
123
|
-
puts "プロセスでSignal #{sig} not supported"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
ProconBypassMan.logger.info "子プロセスでgraceful shutdownの準備ができました"
|
128
|
-
begin
|
129
|
-
while(readable_io = IO.select([self_read]))
|
130
|
-
signal = readable_io.first[0].gets.strip
|
131
|
-
handle_signal(signal)
|
132
|
-
end
|
133
|
-
rescue Interrupt
|
134
|
-
$will_terminate_token = true
|
135
|
-
[t1, t2].each(&:join)
|
136
|
-
@gadget&.close
|
137
|
-
@procon&.close
|
138
|
-
exit 1
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def handle_signal(sig)
|
143
|
-
ProconBypassMan.logger.info "#{$$}で#{sig}を受け取りました"
|
144
|
-
case sig
|
145
|
-
when 'USR2'
|
146
|
-
raise InterruptForRestart
|
147
|
-
when 'INT', 'TERM'
|
148
|
-
raise Interrupt
|
149
|
-
end
|
150
|
-
end
|
151
62
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
class Scheduler
|
3
|
+
class Schedule
|
4
|
+
attr_accessor :klass, :args, :interval, :next_enqueue_at
|
5
|
+
|
6
|
+
# @param [any] klass
|
7
|
+
# @param [Array] args
|
8
|
+
# @param [Integer] interval
|
9
|
+
def initialize(klass: , args: , interval: )
|
10
|
+
self.klass = klass
|
11
|
+
self.args = args
|
12
|
+
self.interval = interval
|
13
|
+
self.next_enqueue_at = Time.now
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [void]
|
17
|
+
def enqueue
|
18
|
+
klass.perform_async(*unwrap_args(args))
|
19
|
+
set_next_enqueue_at!
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [boolean]
|
23
|
+
def past_interval?
|
24
|
+
next_enqueue_at < Time.now
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# @return [void]
|
30
|
+
def set_next_enqueue_at!
|
31
|
+
self.next_enqueue_at = Time.now + interval
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param [Array] args
|
35
|
+
# @return [void]
|
36
|
+
def unwrap_args(args)
|
37
|
+
args.map do |arg|
|
38
|
+
case arg
|
39
|
+
when Proc
|
40
|
+
arg.call
|
41
|
+
else
|
42
|
+
arg
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Hash]
|
49
|
+
def self.schedules
|
50
|
+
@@schedules
|
51
|
+
end
|
52
|
+
|
53
|
+
@@schedules = {}
|
54
|
+
|
55
|
+
def self.start!
|
56
|
+
register_schedules
|
57
|
+
|
58
|
+
@@thread = Thread.start do
|
59
|
+
loop do
|
60
|
+
schedules.each do |_key, schedule|
|
61
|
+
if schedule.past_interval?
|
62
|
+
schedule.enqueue
|
63
|
+
end
|
64
|
+
end
|
65
|
+
sleep 10
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.register_schedules
|
71
|
+
register(
|
72
|
+
schedule: Schedule.new(
|
73
|
+
klass: ProconBypassMan::SyncDeviceStatsJob,
|
74
|
+
args: [->{ ProconBypassMan::DeviceStatus.current }],
|
75
|
+
interval: 60,
|
76
|
+
)
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
# @param [Schedule] schedule
|
81
|
+
def self.register(schedule: )
|
82
|
+
schedules[schedule.klass] = schedule
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
File without changes
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ProconBypassMan
|
2
|
+
class CompressArray
|
3
|
+
class CompressibleValue
|
4
|
+
# @params [String] prev
|
5
|
+
# @params [String] current
|
6
|
+
def initialize(prev, current)
|
7
|
+
@prev = prev
|
8
|
+
@current = current
|
9
|
+
end
|
10
|
+
|
11
|
+
# @return [Boolean]
|
12
|
+
def compress?
|
13
|
+
@prev.include?(@current)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [String]
|
17
|
+
def to_s_with_mark
|
18
|
+
if /^(.+) \* (\d+)/ =~ @prev
|
19
|
+
value = $1
|
20
|
+
count = $2
|
21
|
+
return "#{value} * #{count.to_i + 1}"
|
22
|
+
end
|
23
|
+
if /^(.+)/ =~ @prev
|
24
|
+
value = $1
|
25
|
+
return "#{value} * 1"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(array)
|
31
|
+
@array = array
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Array<String>]
|
35
|
+
def compress
|
36
|
+
previous_value = nil
|
37
|
+
@array.reduce([]) do |acc, item|
|
38
|
+
if previous_value.nil?
|
39
|
+
acc << item
|
40
|
+
previous_value = item
|
41
|
+
next acc
|
42
|
+
end
|
43
|
+
|
44
|
+
if CompressibleValue.new(previous_value, item).compress?
|
45
|
+
registered_value = acc.pop
|
46
|
+
acc << CompressibleValue.new(registered_value, item).to_s_with_mark
|
47
|
+
else
|
48
|
+
acc << item
|
49
|
+
end
|
50
|
+
|
51
|
+
previous_value = item
|
52
|
+
next acc
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|