Reputation: 1653
I'm exploring connecting to a serial device with Elixir. The only library I've found is this one. I'm still trying to wrap my head around Genservers and before I start writing out a program/application I want to just do some simple experimenting in iex
, but I don't know how to get started.
I've started a new mix project, added the elixir_serial
package as a dependency and started up iex with sudo iex -S mix
. (I'm on ubuntu, and currently if I don't use sudo I get an error about read/write permissions when trying to connect, but that's a separate issue afaik).
I seem to be able to connect ok:
iex(3)> {:ok, serial} = Serial.start_link
{:ok, #PID<0.124.0>}
iex(4)> Serial.open(serial, "/dev/ttyUSB0")
:ok
iex(5)> Serial.set_speed(serial, 9600)
:ok
iex(6)> Serial.connect(serial)
:ok
iex(7)> Serial.send_data(serial, <<0x01, 0x02, 0x03>>)
:ok
But I don't know how to receive data back. I've tried putting in the code suggested in the elixir_serial
README:
def handle_info({:elixir_serial, serial, data}, state) do
# do something with the data
end
both in iex (wrapped in a defmodule MySerial do end block) and in the mix project main file, just sticking in an IO.puts(data)
in the function.
I'm obviously missing something here, does the Serial connection need the iex pid to send data back to? I don't understand whether I need to set up a GenServer app to read data, or if I can use the elixir_serial
api to read data back from the serial port.
As I say I'm wrapping my head around GenServer, I understand the generalities, but I'd like to know how to start using this package to just test sending and receiving data before I start building an application around it.
Upvotes: 3
Views: 1797
Reputation: 3612
Here are the docs in elixir_serial
for Serial.start_link:
Starts a serial port. The process invoking this function will receive messages in the form of
{:elixir_serial, pid, data}
.
So, you don't actually need a GenServer
to handle the response. Simply add a receive block in the code with this sort of format:
receive do
{:elixir_serial, serial_pid, data} ->
IO.puts "Received data"
Serial.send_data(serial_pid, "ACK: Received Message")
end
Essentially, the library receives the call from its C counterpart and then sends a message to the process who started the Serial
link.
send(pid, {:elixir_serial, self(), data})
See https://github.com/bitgamma/elixir_serial/blob/master/lib/serial.ex#L129
Upvotes: 1