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
@@ -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
|
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(
|
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(
|
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(
|
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)
|
@@ -0,0 +1,86 @@
|
|
1
|
+
class ProconBypassMan::BypassCommand
|
2
|
+
include ProconBypassMan::SignalHandler
|
3
|
+
|
4
|
+
def initialize(gadget:, procon:)
|
5
|
+
@gadget = gadget
|
6
|
+
@procon = procon
|
7
|
+
|
8
|
+
ProconBypassMan::IOMonitor.start!
|
9
|
+
ProconBypassMan::Background::JobRunner.queue.clear # forkしたときに残留物も移ってしまうため
|
10
|
+
ProconBypassMan::Background::JobRunner.start!
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute
|
14
|
+
self_read, self_write = IO.pipe
|
15
|
+
%w(TERM INT).each do |sig|
|
16
|
+
begin
|
17
|
+
trap sig do
|
18
|
+
self_write.puts(sig)
|
19
|
+
end
|
20
|
+
rescue ArgumentError
|
21
|
+
puts "プロセスでSignal #{sig} not supported"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# gadget => procon
|
26
|
+
# 遅くていい
|
27
|
+
monitor1 = ProconBypassMan::IOMonitor.new(label: "switch -> procon")
|
28
|
+
monitor2 = ProconBypassMan::IOMonitor.new(label: "procon -> switch")
|
29
|
+
ProconBypassMan.logger.info "Thread1を起動します"
|
30
|
+
t1 = Thread.new do
|
31
|
+
timer = ProconBypassMan::SafeTimeout.new(timeout: Time.now + 10)
|
32
|
+
bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor1)
|
33
|
+
loop do
|
34
|
+
break if $will_terminate_token
|
35
|
+
timer.throw_if_timeout!
|
36
|
+
bypass.send_gadget_to_procon!
|
37
|
+
sleep(0.005)
|
38
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
39
|
+
ProconBypassMan.logger.info "10秒経過したのでThread1を終了します"
|
40
|
+
monitor1.shutdown
|
41
|
+
puts "10秒経過したのでThread1を終了します"
|
42
|
+
break
|
43
|
+
rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
|
44
|
+
ProconBypassMan::SendErrorCommand.execute(error: "Switchとの切断されました.終了処理を開始します. #{e.full_message}")
|
45
|
+
Process.kill "TERM", Process.ppid
|
46
|
+
rescue Errno::ETIMEDOUT => e
|
47
|
+
# TODO まれにこれが発生する. 再接続したい
|
48
|
+
ProconBypassMan::SendErrorCommand.execute(error: "Switchと意図せず切断されました.終了処理を開始します. #{e.full_message}")
|
49
|
+
Process.kill "TERM", Process.ppid
|
50
|
+
end
|
51
|
+
ProconBypassMan.logger.info "Thread1を終了します"
|
52
|
+
end
|
53
|
+
|
54
|
+
# procon => gadget
|
55
|
+
# シビア
|
56
|
+
ProconBypassMan.logger.info "Thread2を起動します"
|
57
|
+
t2 = Thread.new do
|
58
|
+
bypass = ProconBypassMan::Bypass.new(gadget: @gadget, procon: @procon, monitor: monitor2)
|
59
|
+
loop do
|
60
|
+
break if $will_terminate_token
|
61
|
+
bypass.send_procon_to_gadget!
|
62
|
+
rescue EOFError => e
|
63
|
+
ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します. #{e.full_message}")
|
64
|
+
Process.kill "TERM", Process.ppid
|
65
|
+
rescue Errno::EIO, Errno::ENODEV, Errno::EPROTO, IOError => e
|
66
|
+
ProconBypassMan::SendErrorCommand.execute(error: "Proconが切断されました。終了処理を開始します2. #{e.full_message}")
|
67
|
+
Process.kill "TERM", Process.ppid
|
68
|
+
end
|
69
|
+
ProconBypassMan.logger.info "Thread2を終了します"
|
70
|
+
end
|
71
|
+
|
72
|
+
ProconBypassMan.logger.info "子プロセスでgraceful shutdownの準備ができました"
|
73
|
+
begin
|
74
|
+
while(readable_io = IO.select([self_read]))
|
75
|
+
signal = readable_io.first[0].gets.strip
|
76
|
+
handle_signal(signal)
|
77
|
+
end
|
78
|
+
rescue Interrupt
|
79
|
+
$will_terminate_token = true
|
80
|
+
[t1, t2].each(&:join)
|
81
|
+
@gadget&.close
|
82
|
+
@procon&.close
|
83
|
+
exit 1
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -2,8 +2,13 @@ class ProconBypassMan::ConnectDeviceCommand
|
|
2
2
|
# @return [void]
|
3
3
|
def self.execute!
|
4
4
|
gadget, procon = ProconBypassMan::DeviceConnector.connect
|
5
|
-
rescue ProconBypassMan::
|
6
|
-
|
5
|
+
rescue ProconBypassMan::DeviceConnector::NotFoundProconError => e
|
6
|
+
ProconBypassMan.logger.error e
|
7
|
+
gadget&.close
|
8
|
+
procon&.close
|
9
|
+
raise ProconBypassMan::NotFoundProconError
|
10
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
11
|
+
ProconBypassMan.logger.error "デバイスとの通信でタイムアウトが起きて接続ができませんでした。"
|
7
12
|
gadget&.close
|
8
13
|
procon&.close
|
9
14
|
raise ::ProconBypassMan::EternalConnectionError
|
@@ -1,9 +1,58 @@
|
|
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 =
|
53
|
+
message = BootMessage.new
|
5
54
|
ProconBypassMan::ReportBootJob.perform_async(message.to_hash)
|
6
|
-
ProconBypassMan::
|
55
|
+
ProconBypassMan::ReportLoadConfigJob.perform_async(ProconBypassMan.config.raw_setting)
|
7
56
|
puts message.to_s
|
8
57
|
end
|
9
58
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class ProconBypassMan::RunRemotePbmActionDispatchCommand
|
2
|
+
# @param [String] action
|
3
|
+
# @param [String] uuid
|
4
|
+
# @return [void]
|
5
|
+
def self.execute(action: , uuid: , job_args: )
|
6
|
+
case action
|
7
|
+
when ProconBypassMan::RemotePbmAction::ACTION_CHANGE_PBM_VERSION
|
8
|
+
ProconBypassMan::RemotePbmAction::ChangePbmVersionAction.new(pbm_job_uuid: uuid).run!(job_args: job_args)
|
9
|
+
when ProconBypassMan::RemotePbmAction::ACTION_STOP_PBM
|
10
|
+
ProconBypassMan::RemotePbmAction::StopPbmAction.new(pbm_job_uuid: uuid).run!(job_args: {})
|
11
|
+
when ProconBypassMan::RemotePbmAction::ACTION_REBOOT_OS
|
12
|
+
ProconBypassMan::RemotePbmAction::RebootOsAction.new(pbm_job_uuid: uuid).run!(job_args: {})
|
13
|
+
when ProconBypassMan::RemotePbmAction::ACTION_RESTORE_SETTING
|
14
|
+
ProconBypassMan::RemotePbmAction::RestorePbmSettingAction.new(pbm_job_uuid: uuid).run!(job_args: job_args)
|
15
|
+
else
|
16
|
+
raise "#{action}は対応していないアクションです"
|
17
|
+
end
|
18
|
+
rescue ProconBypassMan::RemotePbmAction::ActionUnexpectedError => e
|
19
|
+
ProconBypassMan::SendErrorCommand.execute(error: e)
|
20
|
+
end
|
21
|
+
end
|
@@ -11,8 +11,9 @@ class ProconBypassMan::SendErrorCommand
|
|
11
11
|
end
|
12
12
|
|
13
13
|
ProconBypassMan.logger.error body
|
14
|
+
ProconBypassMan.error_logger.error body
|
14
15
|
puts body
|
15
16
|
|
16
|
-
ProconBypassMan::ReportErrorJob.
|
17
|
+
ProconBypassMan::ReportErrorJob.perform(error)
|
17
18
|
end
|
18
19
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class ProconBypassMan::SendReloadConfigEventCommand
|
2
|
+
# @return [void]
|
2
3
|
def self.execute
|
3
|
-
|
4
|
-
ProconBypassMan.logger.info "設定ファイルの再読み込みができました"
|
4
|
+
ProconBypassMan::PrintMessageCommand.execute(text: "設定ファイルの再読み込みができました")
|
5
5
|
ProconBypassMan::ReportReloadConfigJob.perform_async(
|
6
6
|
ProconBypassMan.config.raw_setting
|
7
7
|
)
|
@@ -2,12 +2,6 @@ class ProconBypassMan::WriteSessionIdCommand
|
|
2
2
|
# @return [String] session_id ラズパイが起動してからshutdownするまで同じ文字列を返す
|
3
3
|
# 起動すると/tmp がなくなる前提の実装
|
4
4
|
def self.execute
|
5
|
-
|
6
|
-
if(sid = File.read(path))
|
7
|
-
return sid
|
8
|
-
end
|
9
|
-
rescue Errno::ENOENT
|
10
|
-
File.write(path, "s_#{SecureRandom.uuid}")
|
11
|
-
return SecureRandom.uuid
|
5
|
+
@@session_id ||= "s_#{SecureRandom.uuid}"
|
12
6
|
end
|
13
7
|
end
|
@@ -1,6 +1,9 @@
|
|
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"
|
5
6
|
require "procon_bypass_man/commands/send_error_command"
|
6
7
|
require "procon_bypass_man/commands/connect_device_command"
|
8
|
+
require "procon_bypass_man/commands/bypass_command"
|
9
|
+
require "procon_bypass_man/commands/run_remote_pbm_action_dispatch_command"
|
@@ -16,6 +16,11 @@ class ProconBypassMan::Configuration
|
|
16
16
|
@@pid_path ||= File.expand_path("#{root}/pbm_pid", __dir__).freeze
|
17
17
|
end
|
18
18
|
|
19
|
+
# @return [Integer]
|
20
|
+
def pid
|
21
|
+
File.read(pid_path).to_i
|
22
|
+
end
|
23
|
+
|
19
24
|
def digest_path
|
20
25
|
config.digest_path
|
21
26
|
end
|
@@ -31,12 +36,12 @@ class ProconBypassMan::Configuration
|
|
31
36
|
|
32
37
|
# @return [String]
|
33
38
|
def device_id
|
34
|
-
ProconBypassMan::WriteDeviceIdCommand.execute
|
39
|
+
ENV["DEBUG_DEVICE_ID"] || ProconBypassMan::WriteDeviceIdCommand.execute
|
35
40
|
end
|
36
41
|
end
|
37
42
|
|
38
|
-
attr_accessor :enable_critical_error_logging
|
39
|
-
attr_writer :verbose_bypass_log
|
43
|
+
attr_accessor :enable_critical_error_logging
|
44
|
+
attr_writer :verbose_bypass_log, :raw_setting
|
40
45
|
|
41
46
|
def root=(path)
|
42
47
|
@root = path
|
@@ -75,11 +80,10 @@ class ProconBypassMan::Configuration
|
|
75
80
|
|
76
81
|
def error_logger
|
77
82
|
if enable_critical_error_logging
|
78
|
-
|
83
|
+
@error_logger ||= Logger.new("#{ProconBypassMan.root}/error.log", 5, 1024 * 1024 * 10)
|
79
84
|
else
|
80
85
|
Logger.new(File.open("/dev/null"))
|
81
86
|
end
|
82
|
-
self
|
83
87
|
end
|
84
88
|
|
85
89
|
def digest_path
|
@@ -97,6 +101,44 @@ class ProconBypassMan::Configuration
|
|
97
101
|
end
|
98
102
|
end
|
99
103
|
|
104
|
+
# @return [Array<ProconBypassMan::ServerPool>]
|
105
|
+
def internal_server_pool
|
106
|
+
@internal_server_pool ||= ProconBypassMan::ServerPool.new(servers: internal_api_servers)
|
107
|
+
end
|
108
|
+
|
109
|
+
# @return [Array<ProconBypassMan::ServerPool>]
|
110
|
+
def server_pool
|
111
|
+
@server_pool ||= ProconBypassMan::ServerPool.new(servers: api_servers)
|
112
|
+
end
|
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
|
+
|
141
|
+
# @return [Array<String>]
|
100
142
|
def api_servers
|
101
143
|
if !!ENV["API_SERVER"]
|
102
144
|
[ENV["API_SERVER"]].reject(&:nil?)
|
@@ -108,4 +150,8 @@ class ProconBypassMan::Configuration
|
|
108
150
|
def verbose_bypass_log
|
109
151
|
@verbose_bypass_log || !!ENV["VERBOSE_BYPASS_LOG"]
|
110
152
|
end
|
153
|
+
|
154
|
+
def raw_setting
|
155
|
+
@raw_setting ||= {}
|
156
|
+
end
|
111
157
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
class ProconBypassMan::DeviceConnector
|
2
2
|
class BytesMismatchError < StandardError; end
|
3
|
+
class NotFoundProconError < StandardError; end
|
3
4
|
|
4
5
|
class Value
|
5
6
|
attr_accessor :read_from, :values
|
@@ -48,6 +49,7 @@ class ProconBypassMan::DeviceConnector
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def drain_all
|
52
|
+
debug_log_buffer = []
|
51
53
|
unless @initialized_devices
|
52
54
|
init_devices
|
53
55
|
end
|
@@ -55,11 +57,13 @@ class ProconBypassMan::DeviceConnector
|
|
55
57
|
while(item = @stack.shift)
|
56
58
|
item.values.each do |value|
|
57
59
|
data = nil
|
58
|
-
timer = ProconBypassMan::
|
60
|
+
timer = ProconBypassMan::SafeTimeout.new
|
59
61
|
begin
|
60
62
|
timer.throw_if_timeout!
|
61
63
|
data = from_device(item).read_nonblock(64)
|
64
|
+
debug_log_buffer << "read_from(#{item.read_from}): #{data}"
|
62
65
|
rescue IO::EAGAINWaitReadable
|
66
|
+
debug_log_buffer << "read_from(#{item.read_from}): IO::EAGAINWaitReadable"
|
63
67
|
retry
|
64
68
|
end
|
65
69
|
|
@@ -74,15 +78,19 @@ class ProconBypassMan::DeviceConnector
|
|
74
78
|
end
|
75
79
|
if result
|
76
80
|
ProconBypassMan.logger.info "OK(expected: #{value}, got: #{data.unpack("H*")})"
|
81
|
+
debug_log_buffer << "OK(expected: #{value}, got: #{data.unpack("H*")})"
|
77
82
|
else
|
78
83
|
ProconBypassMan.logger.info "NG(expected: #{value}, got: #{data.unpack("H*")})"
|
84
|
+
debug_log_buffer << "NG(expected: #{value}, got: #{data.unpack("H*")})"
|
79
85
|
raise BytesMismatchError if @throw_error_if_mismatch
|
80
86
|
end
|
81
87
|
to_device(item).write_nonblock(data)
|
82
88
|
end
|
83
89
|
end
|
84
|
-
rescue ProconBypassMan::
|
90
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
85
91
|
ProconBypassMan.logger.error "timeoutになりました"
|
92
|
+
copressed_buffer_text = ProconBypassMan::CompressArray.new(debug_log_buffer).compress.join("\n")
|
93
|
+
ProconBypassMan::SendErrorCommand.execute(error: copressed_buffer_text)
|
86
94
|
raise if @throw_error_if_timeout
|
87
95
|
end
|
88
96
|
|
@@ -95,31 +103,31 @@ class ProconBypassMan::DeviceConnector
|
|
95
103
|
init_devices
|
96
104
|
end
|
97
105
|
|
98
|
-
timer = ProconBypassMan::
|
106
|
+
timer = ProconBypassMan::SafeTimeout.new
|
99
107
|
data = nil
|
100
108
|
begin
|
101
109
|
timer.throw_if_timeout!
|
102
110
|
switch.write_nonblock(data)
|
103
111
|
rescue IO::EAGAINWaitReadable
|
104
112
|
retry
|
105
|
-
rescue ProconBypassMan::
|
113
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
106
114
|
ProconBypassMan.logger.error "writeでtimeoutになりました"
|
107
115
|
raise
|
108
116
|
end
|
109
117
|
return(data.unpack("H*")) if only_write
|
110
118
|
|
111
|
-
timer = ProconBypassMan::
|
119
|
+
timer = ProconBypassMan::SafeTimeout.new
|
112
120
|
begin
|
113
121
|
timer.throw_if_timeout!
|
114
122
|
data = switch.read_nonblock(64)
|
115
123
|
ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
|
116
124
|
rescue IO::EAGAINWaitReadable
|
117
125
|
retry
|
118
|
-
rescue ProconBypassMan::
|
126
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
119
127
|
ProconBypassMan.logger.error "readでtimeoutになりました"
|
120
128
|
raise
|
121
129
|
end
|
122
|
-
rescue ProconBypassMan::
|
130
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
123
131
|
raise if @throw_error_if_timeout
|
124
132
|
end
|
125
133
|
|
@@ -131,30 +139,30 @@ class ProconBypassMan::DeviceConnector
|
|
131
139
|
init_devices
|
132
140
|
end
|
133
141
|
|
134
|
-
timer = ProconBypassMan::
|
142
|
+
timer = ProconBypassMan::SafeTimeout.new
|
135
143
|
begin
|
136
144
|
timer.throw_if_timeout!
|
137
145
|
procon.write_nonblock(data)
|
138
146
|
rescue IO::EAGAINWaitReadable
|
139
147
|
retry
|
140
|
-
rescue ProconBypassMan::
|
148
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
141
149
|
ProconBypassMan.logger.error "writeでtimeoutになりました"
|
142
150
|
raise
|
143
151
|
end
|
144
152
|
return(data.unpack("H*")) if only_write
|
145
153
|
|
146
|
-
timer = ProconBypassMan::
|
154
|
+
timer = ProconBypassMan::SafeTimeout.new
|
147
155
|
begin
|
148
156
|
timer.throw_if_timeout!
|
149
157
|
data = procon.read_nonblock(64)
|
150
158
|
ProconBypassMan.logger.error " <<< #{data.unpack("H*")})"
|
151
159
|
rescue IO::EAGAINWaitReadable
|
152
160
|
retry
|
153
|
-
rescue ProconBypassMan::
|
161
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
154
162
|
ProconBypassMan.logger.error "readでtimeoutになりました"
|
155
163
|
raise
|
156
164
|
end
|
157
|
-
rescue ProconBypassMan::
|
165
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
158
166
|
raise if @throw_error_if_timeout
|
159
167
|
end
|
160
168
|
|
@@ -164,30 +172,30 @@ class ProconBypassMan::DeviceConnector
|
|
164
172
|
end
|
165
173
|
|
166
174
|
data = nil
|
167
|
-
timer = ProconBypassMan::
|
175
|
+
timer = ProconBypassMan::SafeTimeout.new
|
168
176
|
begin
|
169
177
|
timer.throw_if_timeout!
|
170
178
|
data = procon.read_nonblock(64)
|
171
179
|
ProconBypassMan.logger.debug { " <<< #{data.unpack("H*")})" }
|
172
180
|
rescue IO::EAGAINWaitReadable
|
173
181
|
retry
|
174
|
-
rescue ProconBypassMan::
|
182
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
175
183
|
ProconBypassMan.logger.error "readでtimeoutになりました"
|
176
184
|
raise
|
177
185
|
end
|
178
186
|
return(data.unpack("H*")) if only_read
|
179
187
|
|
180
|
-
timer = ProconBypassMan::
|
188
|
+
timer = ProconBypassMan::SafeTimeout.new
|
181
189
|
begin
|
182
190
|
timer.throw_if_timeout!
|
183
191
|
switch.write_nonblock(data)
|
184
192
|
rescue IO::EAGAINWaitReadable
|
185
193
|
retry
|
186
|
-
rescue ProconBypassMan::
|
194
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
187
195
|
ProconBypassMan.logger.error "writeでtimeoutになりました"
|
188
196
|
raise
|
189
197
|
end
|
190
|
-
rescue ProconBypassMan::
|
198
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
191
199
|
raise if @throw_error_if_timeout
|
192
200
|
end
|
193
201
|
|
@@ -197,30 +205,30 @@ class ProconBypassMan::DeviceConnector
|
|
197
205
|
end
|
198
206
|
|
199
207
|
data = nil
|
200
|
-
timer = ProconBypassMan::
|
208
|
+
timer = ProconBypassMan::SafeTimeout.new
|
201
209
|
begin
|
202
210
|
timer.throw_if_timeout!
|
203
211
|
data = switch.read_nonblock(64)
|
204
212
|
ProconBypassMan.logger.debug { " >>> #{data.unpack("H*")})" }
|
205
213
|
rescue IO::EAGAINWaitReadable
|
206
214
|
retry
|
207
|
-
rescue ProconBypassMan::
|
215
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
208
216
|
ProconBypassMan.logger.error "readでtimeoutになりました"
|
209
217
|
raise
|
210
218
|
end
|
211
219
|
return(data.unpack("H*")) if only_read
|
212
220
|
|
213
|
-
timer = ProconBypassMan::
|
221
|
+
timer = ProconBypassMan::SafeTimeout.new
|
214
222
|
begin
|
215
223
|
timer.throw_if_timeout!
|
216
224
|
procon.write_nonblock(data)
|
217
225
|
rescue IO::EAGAINWaitReadable
|
218
226
|
retry
|
219
|
-
rescue ProconBypassMan::
|
227
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
220
228
|
ProconBypassMan.logger.error "writeでtimeoutになりました"
|
221
229
|
raise
|
222
230
|
end
|
223
|
-
rescue ProconBypassMan::
|
231
|
+
rescue ProconBypassMan::SafeTimeout::Timeout
|
224
232
|
raise if @throw_error_if_timeout
|
225
233
|
end
|
226
234
|
|
@@ -293,7 +301,7 @@ class ProconBypassMan::DeviceConnector
|
|
293
301
|
@procon = File.open(PROCON2_PATH, "w+b")
|
294
302
|
@gadget = File.open('/dev/hidg0', "w+b")
|
295
303
|
else
|
296
|
-
raise "/dev/hidraw0, /dev/hidraw1の両方見つかりませんでした"
|
304
|
+
raise NotFoundProconError, "/dev/hidraw0, /dev/hidraw1の両方見つかりませんでした"
|
297
305
|
end
|
298
306
|
system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
|
299
307
|
system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')
|
@@ -312,7 +320,7 @@ class ProconBypassMan::DeviceConnector
|
|
312
320
|
ProconBypassMan::SendErrorCommand.execute(error: "Errno::ENXIO (No such device or address @ rb_sysopen - /dev/hidg0)が起きました。resetします. #{e.full_message}")
|
313
321
|
system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
|
314
322
|
system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')
|
315
|
-
sleep
|
323
|
+
sleep 0.5
|
316
324
|
retry
|
317
325
|
end
|
318
326
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class ProconBypassMan::DeviceStatus
|
2
|
+
INITIALIZED = :initialized
|
3
|
+
RUNNING = :running
|
4
|
+
CONNECTED_BUT_SLEEPING = :connected_but_sleeping # コードはつながっているが、switchがsleepしているとき
|
5
|
+
PROCON_NOT_FOUND_ERROR = :procon_not_found_error # 繋がっていないとか、デバイスが使えない時
|
6
|
+
CONNECTED_BUT_ERROR = :connected_but_error # 実行時エラーあたり
|
7
|
+
SETTING_SYNTAX_ERROR_AND_SHUTDOWN = :setting_syntax_error_and_shutdown
|
8
|
+
|
9
|
+
@@status = nil
|
10
|
+
|
11
|
+
def self.current
|
12
|
+
@@status || INITIALIZED
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.change_to_running!
|
16
|
+
@@status = RUNNING
|
17
|
+
ProconBypassMan::SyncDeviceStatsJob.perform_async(ProconBypassMan::DeviceStatus.current)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.change_to_connected_but_sleeping!
|
21
|
+
@@status = CONNECTED_BUT_SLEEPING
|
22
|
+
ProconBypassMan::SyncDeviceStatsJob.perform_async(ProconBypassMan::DeviceStatus.current)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.change_to_procon_not_found_error!
|
26
|
+
@@status = PROCON_NOT_FOUND_ERROR
|
27
|
+
ProconBypassMan::SyncDeviceStatsJob.perform_async(ProconBypassMan::DeviceStatus.current)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.change_to_device_error!
|
31
|
+
@@status = DEVICE_ERROR
|
32
|
+
ProconBypassMan::SyncDeviceStatsJob.perform_async(ProconBypassMan::DeviceStatus.current)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.change_to_connected_but_error!
|
36
|
+
@@status = CONNECTED_BUT_ERROR
|
37
|
+
ProconBypassMan::SyncDeviceStatsJob.perform_async(ProconBypassMan::DeviceStatus.current)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.change_to_setting_syntax_error_and_shutdown!
|
41
|
+
@@status = SETTING_SYNTAX_ERROR_AND_SHUTDOWN
|
42
|
+
ProconBypassMan::SyncDeviceStatsJob.perform_async(ProconBypassMan::DeviceStatus.current)
|
43
|
+
end
|
44
|
+
end
|