读取串行输入,直到控制字符指示消息结束

opt*_*fel 3 serial-port arduino elixir

我正在使用带有Elixir的knowter/erlang-serial并尝试读取JSON-String(例如{"temperature":20.40,"humidity":30.10},在收到控制信号后通过串行输入从Arduino进入:

defmodule MyApp.SerialInput do
  require Logger


  def start_link do
    serial_pid = :serial.start [{:open, "/dev/cu.usbmodem1431"}, {:speed, 115200}]

    control_signal = "1"
    :timer.send_interval 5000, serial_pid, {:send, control_signal}

    wait_for_new_values serial_pid
  end


  defp wait_for_new_values(serial_pid) do
    receive do
      {:data, jsonString} when is_binary(jsonString) ->
        Logger.debug "received :data #{inspect jsonString}"

    wait_for_new_values serial_pid
  end
end
Run Code Online (Sandbox Code Playgroud)

我现在的问题是,我将串行输入分开(有时它会立即通过):

[debug] received :data "{\"t"
[debug] received :data "emperature\":19.00,\"humidity\":42.00}\r\n"

[debug] received :data "{\"temperature\":19.60,\"humidity\":41"
[debug] received :data ".00}\r\n"

[debug] received :data "{\"temperature\":19.50,\"humidity\":40.90}\r\n"

[debug] received :data "{\"temperature\":19.50,\"humi"
[debug] received :data "dity\":40.90}\r\n"

[debug] received :data "{\"temperat"
[debug] received :data "ure\":19.50,\"humidity\":41.30}\r\n"
Run Code Online (Sandbox Code Playgroud)

有没有办法告诉接收块等待,直到\r\n字符串的结束或字符的固定金额或类似的东西出现?如果没有,什么是持有境外状态的最佳方式wait_for_new_values,直到\r\n出现那么Concat的这些?

Pat*_*ity 5

receive块是一个非常低级别的功能,所以它不能做这样的专门的事情.

Elixir中的State是显式的,可以通过可选参数(累加器)实现(acc在本例中).您可以稍后将累计值传递给递归调用,并仅在结束时打印它"\r\n".

defp wait_for_new_values(serial_pid, acc \\ "") do
  receive do
    {:data, chunk} when is_binary(chunk) ->
      acc = acc + chunk
  end

  if String.ends_with? acc, "\r\n"
    Logger.debug "received :data #{inspect acc}"
    acc = ""
  end

  wait_for_new_values serial_pid, acc
end
Run Code Online (Sandbox Code Playgroud)