Read serial input until char control shows end of message

I am using knewter / erlang-serial with Elixir and am trying to read JSON-String (for example {"temperature":20.40,"humidity":30.10}

, coming into Arduino via serial input after receiving control signal:

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

      

Now my problem is that I am getting serial input this way (sometimes it goes right through):

[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"

      

Is there a way to tell the receive block to wait until \r\n

it appears at the end of the line or for a fixed number of characters or something? If not, what's the best way to keep the state out wait_for_new_values

until \r\n

it appears, and then compare these?

+3


source to share


1 answer


A block receive

is a pretty low-level function, so it cannot do such a specialized thing.

State in Elixir is explicit and can be implemented with an optional argument, accumulator ( acc

in this case). You can later pass the accumulated value to the recursive call and only print it out when it ends with "\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

      

+5


source







All Articles