Class: ProconBypassMan::ExternalInput::Channels::SerialPortChannel

Inherits:
Base
  • Object
show all
Defined in:
lib/procon_bypass_man/external_input/channels/serial_port_channel.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(device_path:, baud_rate: 9600) ⇒ SerialPortChannel

Returns a new instance of SerialPortChannel.

Parameters:

  • device_path (String)
  • baud_rate (Integer) (defaults to: 9600)


9
10
11
12
13
14
15
16
17
18
# File 'lib/procon_bypass_man/external_input/channels/serial_port_channel.rb', line 9

def initialize(device_path: , baud_rate: 9600)
  require 'serialport'

  super()
  # data_bitsあたりは必要があれば設定ができるようにしたいがよくわからないのでとりあえずnilを入れる
  data_bits = 8
  stop_bits = 1
  parity = SerialPort::NONE
  @serial_port = SerialPort.new(device_path, baud_rate, data_bits, stop_bits, parity)
end

Instance Attribute Details

#serial_portObject (readonly)

Returns the value of attribute serial_port.



5
6
7
# File 'lib/procon_bypass_man/external_input/channels/serial_port_channel.rb', line 5

def serial_port
  @serial_port
end

Instance Method Details

#display_name_for_boot_messageObject



50
51
52
# File 'lib/procon_bypass_man/external_input/channels/serial_port_channel.rb', line 50

def display_name_for_boot_message
  'SerialPort'
end

#readString, NilClass

NOTE: この実装では、::IO::EAGAINWaitReadableを実質的な終端として扱っているので、高速に書き込みがされると取りこぼす可能性がある. NOTE: read_nonblockでバッファから読み出すとき、バッファが空になるまでは::IO::EAGAINWaitReadableが起きない前提で実装している. NOTE: 取りこぼししないよう精度を上げるには、終端文字が来るまで1文字ずつ読む必要があるがパフォーマンスが犠牲になってしまう. この対策をするには、bypass処理の開始で非同期に1文字ずつ読み込むことをすると多少マシになるはず

Returns:

  • (String, NilClass)


24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/procon_bypass_man/external_input/channels/serial_port_channel.rb', line 24

def read
  buffer = ''
  loop do
    begin
      buffer += @serial_port.read_nonblock(1024) || ''
    rescue ::IO::EAGAINWaitReadable
      break
    end
  end

  return nil if buffer.empty?

  # NOTE: 高速に書き込まれた場合、複数のチャンクを含む可能性があるので、最初だけを切り取る
  chunks = buffer.split("\n")
  if(chunks.size > 1)
    ProconBypassMan::SendErrorCommand.execute(
      error: "[ExternalInput] シリアルポートから読み込んだchunkが複数あります. 高い書き込み頻度に耐えられていないので実装を見直してください。 (chunks.size: #{chunks.size})"
    )
  end
  chunks.first
end

#shutdownObject



46
47
48
# File 'lib/procon_bypass_man/external_input/channels/serial_port_channel.rb', line 46

def shutdown
  # no-op
end