我正在尝试使用RoR设置Web应用程序,以便能够使用Web界面控制Arduino。我的方法可能是这里出了问题,因为在发送命令时,我很难读取arduino在串行上所说的内容。我的主要目标和未来目标是将串行端口列出(流式传输)到我的Web界面,并在服务器端进行响应(如果在串行端口上给出了一些特定命令)。
我已经尝试了什么?我虽然使用Threads是个好主意,但是我遇到了一些问题。首先,我通过创建一个新的Thred并使用.join尝试了最简单的方法。由于serial.gets正常运行了一段时间却无法解决,所以我的服务器一直挂在那里。
即使最终没有满足我的需求,我也会通过运行10次来限制我真正的出路(如代码所示)。
我的arduino代码(有效):
char receivedChar;
boolean newData = false;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println("<Arduino is ready>");
}
void loop() {
recvOneChar();
}
void recvOneChar() {
if (Serial.available() > 0) {
receivedChar = Serial.read();
if (receivedChar == '1') {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("LED IS ON");
}else if (receivedChar == '2' ){
digitalWrite(LED_BUILTIN, LOW);
Serial.println("LED IS OFF");
}
}
}
RoR上的控制器:
def blink_led
puts "blink_led action called"
t1 = Thread.new do
Setting.blink_led
end
Setting.read_board
t1.join
end
RoR模型:
@port_str = "/dev/tty.usbmodem14201"
@baud_rate = 9600
@data_bits = 8
@stop_bits = 1
@parity = SerialPort::NONE
def self.read_board
puts "INSIDE READ METHOD"
sp = SerialPort.new(@port_str, @baud_rate, @data_bits, @stop_bits, @parity)
i = 0
while i < 10 do
message = sp.gets
if message
message.chomp!
puts message
end
i += 1
end
end
def self.blink_led
puts "INSIDE BLINK METHOD"
sp = SerialPort.new(@port_str, @baud_rate, @data_bits, @stop_bits, @parity)
#just read forever
i = 0
while i < 5
sp.write('1');
sleep(1)
sp.write('2');
sleep(1)
i += 1
end
sp.close
end
根据我的幼稚经验,我希望一旦我使用一个按钮调用控制器方法,就能看到LED闪烁(它闪烁),同时又能在服务器上看到PUTS上说LED亮/关(期望一切正常运行) 嗯,那并没有发生,我得到了一些奇怪的结果:
在我的服务器上运行1次正常(我第一次按下按钮)时,在我的计数器上添加i之前,这之后很奇怪。 第一次运行:
blink_led action called
INSIDE READ METHOD
INSIDE BLINK METHOD
Completed 200 OK in 6015ms (ActiveRecord: 0.0ms)
IS D ISIS OLS ONLED IS OFF
LED IS ON
LED IS OFF
LED IS ON
LED IS OFF
它只是挂在那里。
现在,在while循环上使用get计数器,它确实不执行我想要的操作,我希望它一直运行(如果发生某些情况),我还将数据从另一个源发送到串行(一个小的ruby脚本),并希望我的服务器能够对其进行检查/反应。
blink_led action called
INSIDE READ METHOD
INSIDE BLINK METHOD
LED IS LED IS OFF
Completed 200 OK in 6013ms (ActiveRecord: 0.0ms)
LED IS ON
LED IS OFF
LED IS ON
LED IS OFF
LED IS ON
LED IS OFF
LED IS ON
LED IS OFF
消息至少正确显示,但是我的服务器仍然挂起。
我在这里走的路都错吗?什么是实现我想要实现的最佳方法?最后,我希望我的服务器能够一直运行串行读取命令,同时对从串行端口读取的内容做出反应,并对接口上的输入做出反应,例如按下按钮。完成此操作后,我希望能够将串行端口“流式传输”(不知道这是否是正确的词)。
EDIT1:更正了一些拼写错误,并学习了如何在每次挂起时终止服务器进程
Edit2:明确我的问题。我正在寻找一种2路通信,一种是从接口/服务器到arduino的通信,另一种是从arduino到我的服务器的通信。我正在寻找一种可以将命令发送到arduino并从中读取答案的东西。到目前为止,我有一个动作/方法,该命令向arduino发送闪烁命令,发送“ 1”或“ 2”,arduino“ LED亮”对它进行响应,“ LED灭”。但这(到目前为止)仅在我的服务器知道它将得到答案时才可行。
我有一个小的ruby脚本,它发送相同的命令来打开和关闭LED,而我所缺少的是我的服务器能够注意到在Serialport上写了一些东西(在这种情况下,来自当此事件是由另一个来源触发时,arduino说“ LED亮” /“ LED灭”。
答案 0 :(得分:0)
您可以将read_board
方法更改为无休止的后台线程。当收到消息时,它可以调用其他方法,并使用websockets / action cable更新前端。
# app/models/setting.rb
def self.read_board
sp = SerialPort.new(@port_str, @baud_rate, @data_bits, @stop_bits, @parity)
Thread.new do
loop do
message = sp.gets # This will probably wait for input
if message
message.chomp!
message_received(message)
end
end
end
end
def self.message_received(message)
# Alert clients of message using websockets / actioncable.
end
从某个地方调用此方法(只需调用一次)
# config/initializers/read_board.rb
Setting.read_board
您需要填写message_received
方法。如果您不想弄乱动作电缆/ websocket,可以创建一个存储新消息的数组,并从前端弹出的循环中发送查询,该循环从列表中弹出。但是,使用websockets是更好的选择。不幸的是,要解释此答案中的设置有点太复杂了,但是如果您四处搜寻,就会发现很好的教程。
我会说尝试为websockets / actioncable制作一个演示项目(只是一个简单的聊天室,有大量的教程),然后再尝试为arduino项目改编代码。