简体   繁体   中英

How to create and keep serialport connection in Ruby on Rails, handle infinity loop to create model with new messages?

I want to listening SerialPort and when message occurs then get or create Log model with id received from my device.

How to load once automatically SerialPort and keep established connection and if key_detected? in listener deal with Log model?

This is my autoloaded module in lib:

module Serialport
  class Connection
    def initialize(port = "/dev/tty0")
      port_str = port
      baud_rate = 9600
      data_bits = 8
      stop_bits = 1
      parity = SerialPort::NONE
      @sp = SerialPort.new(port_str, baud_rate, data_bits, stop_bits, parity)
      @key_parts = []
      @key_limit = 16 # number of slots in the RFID card.
      while true do
        listener
      end
      @sp.close
    end

    def key_detected?
      @key_parts << @sp.getc
      if @key_parts.size >= @key_limit
        self.key = @key_parts.join()
        @key_parts = []
        true
      else
        false
      end
    end

    def listener
      if key_detected?
        puts self.key
        # log = Log.find(rfid: self.key).first_or_create(rfid: self.key)
      end
    end
  end
end

Model:

class Log < ActiveRecord::Base
end

I would have written this in a comment, but it's a bit long... But I wonder if you could clarify your question, and I will update my answer as we go:

  1. With all due respect to the Rails ability to "autoload", why not initialize a connection in an initialization file or while setting up the environment?

ie, within a file in you_app/config/initializers called serial_port.rb :

SERIAL_PORT_CONNECTION = Serialport::Connection.new
  1. Implementing an infinite loop within your Rails application will, in all probability, hang the Rails app and prevent it from being used as a web service.

    What are you trying to accomplish?

    If you just want to use active_record or active_support, why not just include these two gems in a separate script?

    Alternatively, consider creating a separate thread for the infinite loop (or better yet, use a reactor (They are not that difficult to write, but there are plenty pre-written in the wild, such as Iodine which I wrote for implementing web services)...

Here's an example for an updated listener method, using a separate thread so you call it only once:

def listener
   Thread.new do
     loop { self.key while key_detected? }
     # this will never be called - same as in your code.
     @sp.close
   end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM