procon_bypass_man 0.3.6 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +4 -0
  3. data/.github/workflows/gitleacks.yml +1 -1
  4. data/.github/workflows/release.yml +1 -1
  5. data/.github/workflows/ruby.yml +2 -2
  6. data/CHANGELOG.md +10 -0
  7. data/Gemfile +1 -0
  8. data/Gemfile.lock +4 -2
  9. data/README.md +2 -2
  10. data/bin/validate_external_input +19 -0
  11. data/docs/getting_started.md +28 -0
  12. data/docs/setting/integration_external_input_serial_port.md +56 -0
  13. data/docs/setting/integration_external_input_serial_port_format.md +36 -0
  14. data/lib/procon_bypass_man/background/jobs/report_procon_performance_measurements_job.rb +1 -0
  15. data/lib/procon_bypass_man/bypass/procon_to_switch.rb +16 -1
  16. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +4 -1
  17. data/lib/procon_bypass_man/configuration.rb +31 -14
  18. data/lib/procon_bypass_man/external_input/boot_message.rb +21 -0
  19. data/lib/procon_bypass_man/external_input/channels/base.rb +22 -0
  20. data/lib/procon_bypass_man/external_input/channels/serial_port_channel.rb +56 -0
  21. data/lib/procon_bypass_man/external_input/channels/tcpip_channel.rb +131 -0
  22. data/lib/procon_bypass_man/external_input/channels.rb +12 -0
  23. data/lib/procon_bypass_man/external_input/external_data.rb +79 -0
  24. data/lib/procon_bypass_man/external_input.rb +31 -0
  25. data/lib/procon_bypass_man/processor.rb +3 -2
  26. data/lib/procon_bypass_man/procon/button_collection.rb +5 -0
  27. data/lib/procon_bypass_man/procon/performance_measurement/measurements_summarizer.rb +4 -0
  28. data/lib/procon_bypass_man/procon/performance_measurement.rb +7 -1
  29. data/lib/procon_bypass_man/procon.rb +17 -2
  30. data/lib/procon_bypass_man/procon_display/status.rb +0 -2
  31. data/lib/procon_bypass_man/support/forever.rb +51 -0
  32. data/lib/procon_bypass_man/support/proccess_cheacker.rb +14 -0
  33. data/lib/procon_bypass_man/support/retryable.rb +5 -2
  34. data/lib/procon_bypass_man/support/simple_tcp_server.rb +63 -0
  35. data/lib/procon_bypass_man/support/watchdog.rb +23 -0
  36. data/lib/procon_bypass_man/support/web_connectivity_checker.rb +41 -0
  37. data/lib/procon_bypass_man/version.rb +1 -1
  38. data/lib/procon_bypass_man/websocket/client.rb +11 -9
  39. data/lib/procon_bypass_man.rb +16 -3
  40. data/project_template/app.rb +11 -1
  41. data/project_template/app.rb.erb +11 -1
  42. data/sig/main.rbs +2 -2
  43. metadata +17 -4
  44. data/lib/procon_bypass_man/websocket/forever.rb +0 -47
  45. data/lib/procon_bypass_man/websocket/watchdog.rb +0 -19
@@ -0,0 +1,131 @@
1
+ module ProconBypassMan
2
+ module ExternalInput
3
+ module Channels
4
+ class TCPIPChannel < Base
5
+ class ShutdownSignal < StandardError; end
6
+
7
+ class AppServer < SimpleTCPServer
8
+ @command_queue = Queue.new
9
+
10
+ class << self
11
+ attr_accessor :command_queue
12
+ end
13
+
14
+ def post_init
15
+ ProconBypassMan.logger.info { "[ExternalInput][TCPIPChannel] A client has connected" }
16
+ end
17
+
18
+ def unbind
19
+ ProconBypassMan.logger.info { "[ExternalInput][TCPIPChannel] A client has disconnected" }
20
+ end
21
+
22
+ # @return [String]
23
+ def receive_data(client, data)
24
+ case data
25
+ when /^{/
26
+ self.class.command_queue.push(data)
27
+ client.write("OK\n")
28
+ return
29
+ when /^\n/
30
+ if self.class.command_queue.empty?
31
+ client.write("EMPTY\n")
32
+ return
33
+ end
34
+
35
+ data = self.class.command_queue.pop
36
+ client.write("#{data}\n")
37
+ return
38
+ else
39
+ client.write("Unknown command\n")
40
+ return
41
+ end
42
+ end
43
+ end
44
+
45
+ def initialize(port: )
46
+ @port = port
47
+ super()
48
+
49
+ begin
50
+ @server = AppServer.new('0.0.0.0', @port)
51
+ rescue Errno::EADDRINUSE # NOTE: Address already in use - bind(2) for "0.0.0.0" port XXXX
52
+ ProconBypassMan::SendErrorCommand.execute(error: "[ExternalInput][TCPIPChannel] 起動に失敗しました。#{e.message}")
53
+ @server_thread = Thread.start {}
54
+ return
55
+ end
56
+
57
+ # NOTE: masterプロセスで起動する
58
+ @server_thread = Thread.start do
59
+ begin
60
+ loop do
61
+ @server.start_server
62
+ @server.run
63
+ end
64
+ rescue Errno::EPIPE, EOFError, Errno::ECONNRESET => e
65
+ ProconBypassMan::SendErrorCommand.execute(error: "[ExternalInput][TCPIPChannel] #{e.message}(#{e})")
66
+ sleep(5)
67
+
68
+ @server.shutdown
69
+ retry
70
+ rescue ShutdownSignal => e
71
+ ProconBypassMan::SendErrorCommand.execute(error: "[ExternalInput][TCPIPChannel] ShutdownSignalを受け取りました。終了します。")
72
+ @server.shutdown
73
+ rescue => e
74
+ ProconBypassMan::SendErrorCommand.execute(error: "[ExternalInput][TCPIPChannel] #{e.message}(#{e})")
75
+ end
76
+ end
77
+ end
78
+
79
+ # NOTE: bypassプロセスから呼ばれ、masterプロセスへ繋ぐ
80
+ # @return [String, NilClass]
81
+ def read
82
+ @socket ||= TCPSocket.new('0.0.0.0', @port)
83
+ read_command = "\n"
84
+ @socket.write(read_command)
85
+ response = @socket.gets&.strip
86
+ # ProconBypassMan.logger.debug { "Received: #{response}" }
87
+
88
+ case response
89
+ when /^{/
90
+ return response
91
+ when /^EMPTY/, ''
92
+ return nil
93
+ else
94
+ ProconBypassMan.logger.warn { "[ExternalInput][TCPIPChannel] Unknown response(#{response}, codepoints: #{response.codepoints})" }
95
+ return nil
96
+ end
97
+ rescue Errno::EPIPE, EOFError => e
98
+ @socket = nil
99
+ sleep(10)
100
+ ProconBypassMan.logger.error { "[ExternalInput][TCPIPChannel] #{e.message}!!!!!!!(#{e})" }
101
+ retry
102
+ rescue => e
103
+ @socket = nil
104
+ ProconBypassMan.logger.error { "[ExternalInput][TCPIPChannel] #{e.message} が起きました(#{e})" }
105
+ return nil
106
+ end
107
+
108
+ def shutdown
109
+ ProconBypassMan.logger.info { "[ExternalInput][TCPIPChannel] shutdown" }
110
+ @server_thread.raise(ShutdownSignal)
111
+ end
112
+
113
+ def alive_server?
114
+ return false if not @server_thread.alive?
115
+
116
+ begin
117
+ TCPSocket.new('0.0.0.0', @port).close
118
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET
119
+ return false
120
+ end
121
+
122
+ true
123
+ end
124
+
125
+ def display_name_for_boot_message
126
+ "TCPIP(port: #{@port})"
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ProconBypassMan
4
+ module ExternalInput
5
+ module Channels
6
+ end
7
+ end
8
+ end
9
+
10
+ require "procon_bypass_man/external_input/channels/base"
11
+ require "procon_bypass_man/external_input/channels/serial_port_channel"
12
+ require "procon_bypass_man/external_input/channels/tcpip_channel"
@@ -0,0 +1,79 @@
1
+ module ProconBypassMan
2
+ module ExternalInput
3
+ class ExternalData
4
+ UNPRESS_BUTTONS = Set.new(ProconBypassMan::Procon::ButtonCollection.available.map { |x| "un#{x}".to_sym })
5
+
6
+ # @return [String, NilClass] 16進数表現のデータ
7
+ attr_reader :hex
8
+
9
+ # @return [String, NilClass] ログに表示する用
10
+ attr_reader :raw_data
11
+
12
+ # @raise [ParseError]
13
+ # @return [ExternalData] JSON か カンマ区切りのbuttons
14
+ def self.parse!(raw_data)
15
+ raise ParseError unless raw_data.ascii_only?
16
+
17
+ if is_json(raw_data)
18
+ begin
19
+ json = JSON.parse(raw_data)
20
+ return new(hex: json['hex'], buttons: json['buttons'])
21
+ rescue JSON::ParserError
22
+ raise ParseError
23
+ end
24
+ end
25
+
26
+ return new(hex: nil, buttons: raw_data.scan(/:\w+:/).map { |x| x.gsub(':', '') }, raw_data: raw_data)
27
+ end
28
+
29
+ # @param [String] raw_data
30
+ # @return [Boolean]
31
+ def self.is_json(raw_data)
32
+ raw_data.start_with?('{')
33
+ end
34
+
35
+ # @param [String, NilClass] hex
36
+ # @param [Array<String>, NilClass] buttons
37
+ # @param [String, NilClass] raw_data
38
+ def initialize(hex: , buttons: , raw_data: nil)
39
+ @hex = hex
40
+ @buttons = buttons || []
41
+ @raw_data = raw_data
42
+ end
43
+
44
+ # @return [String, NilClass]
45
+ def to_binary
46
+ return nil if @hex.nil?
47
+ [@hex].pack('H*')
48
+ end
49
+
50
+ # @return [Array<Symbol>]
51
+ def press_buttons
52
+ buttons.select do |button|
53
+ ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[button]
54
+ end
55
+ end
56
+
57
+ # @return [Array<Symbol>]
58
+ def unpress_buttons
59
+ buttons.select { |button|
60
+ UNPRESS_BUTTONS.include?(button)
61
+ }.map { |b| to_button(b.to_s).to_sym }
62
+ end
63
+
64
+ # NOTE: ログに表示する用
65
+ # @return [Array<Symbol>]
66
+ def buttons
67
+ @buttons.map(&:to_sym)
68
+ end
69
+
70
+ private
71
+
72
+ # @return [String]
73
+ # NOTE: un#{button} って名前をbuttonに変換する
74
+ def to_button(button)
75
+ button.sub(/^un/, '')
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ProconBypassMan
4
+ module ExternalInput
5
+ class ParseError < StandardError; end
6
+
7
+ # @return [Array<ProconBypassMan::ExternalInput::Channels::Base>]
8
+ def self.channels
9
+ @@channels ||= ProconBypassMan.config.external_input_channels
10
+ end
11
+
12
+ def self.shutdown
13
+ channels.each(&:shutdown)
14
+ end
15
+
16
+ # @return [NilClass, String]
17
+ # NOTE: 外部入力からのreadがボトルネックになるなら、Concurrent::Futureを使ってプロコンからの読み出しと並列化することを検討する
18
+ def self.read
19
+ value = nil
20
+ channels.each do |channel|
21
+ value = channel.read
22
+ break if value
23
+ end
24
+ value
25
+ end
26
+ end
27
+ end
28
+
29
+ require "procon_bypass_man/external_input/external_data"
30
+ require "procon_bypass_man/external_input/channels.rb"
31
+ require "procon_bypass_man/external_input/boot_message"
@@ -5,12 +5,13 @@ class ProconBypassMan::Processor
5
5
  @binary = binary
6
6
  end
7
7
 
8
+ # @param [ProconBypassMan::ExternalInput::ExternalData, NilClass] external_input_data
8
9
  # @return [String] 加工後の入力データ
9
- def process
10
+ def process(external_input_data: nil)
10
11
  return @binary.raw unless @binary.user_operation_data?
11
12
 
12
13
  procon = ProconBypassMan::Procon.new(@binary.raw)
13
14
  procon.apply!
14
- procon.to_binary
15
+ procon.to_binary(external_input_data: external_input_data)
15
16
  end
16
17
  end
@@ -37,4 +37,9 @@ class ProconBypassMan::Procon::ButtonCollection
37
37
  BUTTONS = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP.keys.freeze
38
38
 
39
39
  LEFT_ANALOG_STICK = { byte_position: 6..8 }
40
+
41
+ # @return [Array<Symbol>]
42
+ def self.available
43
+ BUTTONS
44
+ end
40
45
  end
@@ -9,6 +9,7 @@ class ProconBypassMan::Procon::PerformanceMeasurement::MeasurementsSummarizer
9
9
  :time_taken_p95,
10
10
  :time_taken_p99,
11
11
  :time_taken_max,
12
+ :external_input_time_max,
12
13
  :read_error_count,
13
14
  :write_error_count,
14
15
  :gc_count,
@@ -26,6 +27,7 @@ class ProconBypassMan::Procon::PerformanceMeasurement::MeasurementsSummarizer
26
27
  write_time_max = 0
27
28
  read_time_max = 0
28
29
  time_taken_max = 0
30
+ external_input_time_max = 0
29
31
  interval_from_previous_succeed_max = 0
30
32
  @spans.each do |span|
31
33
  # NOTE @spans.map(&:write_time).sort.last と同じことだけど、処理コストを軽くするためにループを共通化する
@@ -33,6 +35,7 @@ class ProconBypassMan::Procon::PerformanceMeasurement::MeasurementsSummarizer
33
35
  read_time_max = span.read_time if write_time_max < span.read_time
34
36
  time_taken_max = span.time_taken if span.succeed && time_taken_max < span.time_taken
35
37
  interval_from_previous_succeed_max = span.interval_from_previous_succeed if span.succeed && interval_from_previous_succeed_max < span.interval_from_previous_succeed
38
+ external_input_time_max = span.external_input_time if span.succeed && external_input_time_max < span.external_input_time
36
39
  end
37
40
 
38
41
  # NOTE 今はGCを無効にしており、集計するまでもないのでコメントアウトにする. 今後GCを有効にしたバイパスをするかもしれないので残しておく
@@ -79,6 +82,7 @@ class ProconBypassMan::Procon::PerformanceMeasurement::MeasurementsSummarizer
79
82
  time_taken_p95,
80
83
  time_taken_p99,
81
84
  time_taken_max,
85
+ external_input_time_max,
82
86
  total_read_error_count,
83
87
  total_write_error_count,
84
88
  gc_count,
@@ -12,7 +12,7 @@ require 'procon_bypass_man/procon/performance_measurement/last_bypass_at'
12
12
  module ProconBypassMan::Procon::PerformanceMeasurement
13
13
  class PerformanceSpan
14
14
  attr_accessor :time_taken, :succeed, :interval_from_previous_succeed, :gc_count, :gc_time
15
- attr_reader :write_error_count, :read_error_count, :write_time, :read_time
15
+ attr_reader :write_error_count, :read_error_count, :write_time, :read_time, :external_input_time
16
16
 
17
17
  def initialize
18
18
  @write_error_count = 0
@@ -40,9 +40,15 @@ module ProconBypassMan::Procon::PerformanceMeasurement
40
40
  return result
41
41
  end
42
42
 
43
+ # @return [void]
43
44
  def record_read_time(&block)
44
45
  @read_time = Benchmark.realtime { block.call }
45
46
  end
47
+
48
+ # @return [void]
49
+ def record_external_input_time(&block)
50
+ @external_input_time = Benchmark.realtime { block.call }
51
+ end
46
52
  end
47
53
 
48
54
  # 全部送ると負荷になるので適当にまびく
@@ -128,7 +128,7 @@ class ProconBypassMan::Procon
128
128
  end
129
129
 
130
130
  # remote macro or pbm action
131
- if task = ProconBypassMan::RemoteAction::TaskQueueInProcess.non_blocking_shift
131
+ if(task = ProconBypassMan::RemoteAction::TaskQueueInProcess.non_blocking_shift)
132
132
  case task.type
133
133
  when ProconBypassMan::RemoteAction::Task::TYPE_MACRO
134
134
  no_op_step = :wait_for_0_3 # マクロの最後に固まって最後の入力をし続けるので、無の状態を最後に注入する
@@ -187,12 +187,27 @@ class ProconBypassMan::Procon
187
187
  status
188
188
  end
189
189
 
190
+ # @param [ProconBypassMan::ExternalInput::ExternalData, NilClass] external_input_data
190
191
  # @return [String]
191
- def to_binary
192
+ def to_binary(external_input_data: nil)
192
193
  if ongoing_mode.name != :manual
193
194
  return user_operation.binary.raw
194
195
  end
195
196
 
197
+ if external_input_data
198
+ if(external_input_data_raw_binary = external_input_data.to_binary)
199
+ self.user_operation.merge(external_input_data_raw_binary)
200
+ else
201
+ external_input_data.press_buttons.each do |button|
202
+ self.user_operation.press_button(button)
203
+ end
204
+ external_input_data.unpress_buttons.each do |button|
205
+ self.user_operation.unpress_button(button)
206
+ end
207
+ end
208
+ return self.user_operation.binary.raw
209
+ end
210
+
196
211
  if ongoing_macro.ongoing? && (step = ongoing_macro.next_step)
197
212
  BlueGreenProcess::SharedVariable.extend_run_on_this_process = true
198
213
  ongoing_macro.force_neutral_buttons&.each do |force_neutral_button|
@@ -1,5 +1,3 @@
1
- require 'singleton'
2
-
3
1
  class ProconBypassMan::ProconDisplay::Status
4
2
  include Singleton
5
3
 
@@ -0,0 +1,51 @@
1
+ module ProconBypassMan
2
+ class Forever
3
+ # 動作確認方法
4
+ # - 10秒ごとにrefreshするのでタイムアウトは起きない
5
+ # - ProconBypassMan::Forever.run { |watchdog| loop { puts(:hi); sleep(10); watchdog.active! } }
6
+ # - タイムアウトが起きること
7
+ # - ProconBypassMan::Forever.run { |watchdog| loop { puts(:hi); sleep(10); } }
8
+ def self.run(&block)
9
+ loop do
10
+ new.run(&block)
11
+ end
12
+ end
13
+
14
+ # @return [void]
15
+ def run(&block)
16
+ raise(ArgumentError, "need a block") unless block_given?
17
+
18
+ thread, watchdog = work_one(callable: block)
19
+ wait_and_kill_if_outdated(thread, watchdog)
20
+ end
21
+
22
+ # @param [Proc] callable
23
+ # @return [Array<Thread, ProconBypassMan::Watchdog>]
24
+ def work_one(callable: )
25
+ watchdog = ProconBypassMan::Watchdog.new
26
+ thread = Thread.start do
27
+ callable.call(watchdog)
28
+ rescue => e
29
+ ProconBypassMan.logger.error("[Forever] #{e.full_message}")
30
+ end
31
+
32
+ return [thread, watchdog]
33
+ end
34
+
35
+ # @param [ProconBypassMan::Watchdog] watchdog
36
+ # @param [Thread] thread
37
+ # @return [void]
38
+ def wait_and_kill_if_outdated(thread, watchdog)
39
+ loop do
40
+ if watchdog.outdated?
41
+ watchdog.active!
42
+ ProconBypassMan.logger.error("watchdog timeout!!")
43
+ thread.kill
44
+ return
45
+ end
46
+
47
+ sleep(10)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,14 @@
1
+ class ProconBypassMan::ProcessChecker
2
+ # @param [integer] pid
3
+ # @return [Boolean]
4
+ def self.running?(pid)
5
+ begin
6
+ Process.kill(0, pid)
7
+ true
8
+ rescue Errno::ESRCH
9
+ false
10
+ rescue Errno::EPERM
11
+ true
12
+ end
13
+ end
14
+ end
@@ -1,14 +1,17 @@
1
1
  module ProconBypassMan
2
2
  class Retryable
3
- def self.retryable(tries: , retried: 0, on_no_retry: [])
3
+ def self.retryable(tries: , retried: 0, on_no_retry: [], log_label: nil, interval_on_retry: 0)
4
4
  return yield(retried)
5
5
  rescue *on_no_retry
6
6
  raise
7
- rescue
7
+ rescue => e
8
8
  if tries <= retried
9
9
  raise
10
10
  else
11
11
  retried = retried + 1
12
+ ProconBypassMan.logger.debug "[Retryable]#{log_label && "[#{log_label}]"} #{e}が起きました。retryします。#{retried} / #{tries}"
13
+
14
+ sleep(interval_on_retry)
12
15
  retry
13
16
  end
14
17
  end
@@ -0,0 +1,63 @@
1
+ require 'socket'
2
+
3
+ class SimpleTCPServer
4
+ def initialize(host, port)
5
+ @host = host
6
+ @port = port
7
+ end
8
+
9
+ def start_server
10
+ @connections = []
11
+ @server = TCPServer.new(@host, @port)
12
+ end
13
+
14
+ def run
15
+ loop do
16
+ timeout = 5 # 5秒のタイムアウト
17
+ readable, _ = IO.select(@connections + [@server], nil, nil, timeout)
18
+ next if readable.nil? # timeoutを迎えるとnilになる
19
+
20
+ readable.each do |socket|
21
+ if socket == @server
22
+ client = @server.accept
23
+ post_init
24
+ @connections << client
25
+ else
26
+ data = socket.gets
27
+ if data.nil?
28
+ @connections.delete(socket)
29
+ unbind
30
+ socket.close
31
+ else
32
+ receive_data(socket, data)
33
+ end
34
+ end
35
+ end
36
+ rescue Errno::EBADF, IOError => e
37
+ unbind
38
+ @connections = []
39
+ @server.close
40
+ end
41
+ end
42
+
43
+ def shutdown
44
+ @server.close
45
+ end
46
+
47
+ # @return [Integer]
48
+ def connections_size
49
+ @connections.size
50
+ end
51
+
52
+ def post_init
53
+ # Override this method
54
+ end
55
+
56
+ def receive_data(socket, data)
57
+ # Override this method
58
+ end
59
+
60
+ def unbind
61
+ # Override this method
62
+ end
63
+ end
@@ -0,0 +1,23 @@
1
+ module ProconBypassMan
2
+ class Watchdog
3
+ def initialize(timeout: 100)
4
+ @timeout = timeout
5
+ active!
6
+ end
7
+
8
+ # @return [Boolean]
9
+ def outdated?
10
+ @time < Time.now
11
+ end
12
+
13
+ # @return [Time]
14
+ def time
15
+ @time
16
+ end
17
+
18
+ # @return [void]
19
+ def active!
20
+ @time = Time.now + @timeout
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+ class ProconBypassMan::WebConnectivityChecker
2
+ # @param [String, NilClass] url
3
+ # @param [String, NilClass] ws_url
4
+ def initialize(url, ws_url)
5
+ @url = url
6
+ @ws_url = ws_url
7
+ end
8
+
9
+ # @return [String]
10
+ def to_s
11
+ if @url.nil?
12
+ return "DISABLE"
13
+ end
14
+
15
+ if alive?
16
+ return "ENABLE (#{@url}, #{@ws_url})"
17
+ else
18
+ return "UNREACHABLE (#{@url})"
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ # @return [Boolean]
25
+ def alive?
26
+ uri = URI.parse(@url)
27
+ response = nil
28
+
29
+ begin
30
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
31
+ request = Net::HTTP::Head.new(uri)
32
+ response = http.request(request)
33
+ end
34
+ rescue StandardError => e
35
+ ProconBypassMan.logger.error e
36
+ return false
37
+ end
38
+
39
+ response.is_a?(Net::HTTPSuccess) or response.is_a?(Net::HTTPMovedPermanently)
40
+ end
41
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProconBypassMan
4
- VERSION = "0.3.6"
4
+ VERSION = "0.3.8"
5
5
  end
@@ -7,11 +7,13 @@ module ProconBypassMan
7
7
  return unless ProconBypassMan.config.enable_ws?
8
8
 
9
9
  Thread.start do
10
- Forever.run { run }
10
+ ProconBypassMan::Forever.run do |watchdog|
11
+ run(watchdog: watchdog)
12
+ end
11
13
  end
12
14
  end
13
15
 
14
- def self.run
16
+ def self.run(watchdog: )
15
17
  EventMachine.run do
16
18
  client = ActionCableClient.new(
17
19
  ProconBypassMan.config.current_ws_server_url, {
@@ -20,15 +22,15 @@ module ProconBypassMan
20
22
  )
21
23
 
22
24
  client.connected {
23
- ProconBypassMan.logger.info('websocket client: successfully connected in ProconBypassMan::Websocket::Client')
25
+ ProconBypassMan.logger.info('[WebsocketClient] successfully connected in ProconBypassMan::Websocket::Client')
24
26
  }
25
27
  client.subscribed { |msg|
26
- ProconBypassMan.logger.info("websocket client: subscribed(#{msg})")
28
+ ProconBypassMan.logger.info("[WebsocketClient] subscribed(#{msg})")
27
29
  ProconBypassMan::SyncDeviceStatsJob.perform(ProconBypassMan::DeviceStatus.current)
28
30
  }
29
31
 
30
32
  client.received do |data|
31
- ProconBypassMan.logger.info('websocket client: received!!')
33
+ ProconBypassMan.logger.info('[WebsocketClient] received!!')
32
34
  ProconBypassMan.logger.info(data)
33
35
 
34
36
  dispatch(data: data, client: client)
@@ -37,20 +39,20 @@ module ProconBypassMan
37
39
  end
38
40
 
39
41
  client.disconnected {
40
- ProconBypassMan.logger.info('websocket client: disconnected!!')
42
+ ProconBypassMan.logger.info('[WebsocketClient] disconnected!!')
41
43
  client.reconnect!
42
44
  sleep 2
43
45
  }
44
46
  client.errored { |msg|
45
- ProconBypassMan.logger.error("websocket client: errored!!, #{msg}")
47
+ ProconBypassMan.logger.error("[WebsocketClient] errored!!, #{msg}")
46
48
  client.reconnect!
47
49
  sleep 2
48
50
  }
49
51
  client.pinged { |msg|
50
- Watchdog.active!
52
+ watchdog.active!
51
53
 
52
54
  ProconBypassMan.cache.fetch key: 'ws_pinged', expires_in: 10 do
53
- ProconBypassMan.logger.info('websocket client: pinged!!')
55
+ ProconBypassMan.logger.info('[WebsocketClient] pinged!!')
54
56
  ProconBypassMan.logger.info(msg)
55
57
  end
56
58
  }