Closed mattneel closed 8 years ago
FYI - I'm working on this feature the lines
branch. Hopefully I'll get it merged to master and make a release soon. The framing of packets is done via a behaviour, but there's a built-in one for lines. Just add the :framing
parameter to your Nerves.UART.open
or Nerves.UART.configure
calls.
Here's an example for passive mode, but active mode works similarly:
iex> {:ok, uart}= Nerves.UART.start_link
{:ok, #PID<0.186.0>}
iex> Nerves.UART.open(uart, "ttyUSB0", speed: 9600, active: false)
:ok
iex> Nerves.UART.read(uart)
{:ok,
"$PGTOP,11,2*6E\r\n$GPGGA,000209.800,,,,,0,0,,,M,,M,,*4B\r\n$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r\n$GPRMC,000209.800,V,,,,,0.00,0.00,060180,,,N*41\r\n$GPVTG,0.00,T,,M,0.00,N,0.00,K,N*32\r\n$PGTOP,11,2*6E\r\n$GPGGA,000210.800,,,,,0,0,,,M,,M,,*43\r\n$GPGSA,A,1,,,,,,,,,,,,,,,*1E\r\n$GPRMC,000210.800,V,,,,,0.00,0.00,060180,,,N*49\r\n"}
iex> Nerves.UART.configure(uart, framing: {Nerves.UART.Framing.Line, separator: "\r\n"})
:ok
iex> Nerves.UART.read(uart)
{:ok, "$GPGGA,000226.800,,,,,0,0,,,M,,M,,*46"}
iex> Nerves.UART.read(uart)
{:ok, "$GPRMC,000226.800,V,,,,,0.00,0.00,060180,,,N*4C"}
Since you're breaking on "\n" characters, you don't need to specify the separator. I.e. adding framing: Nerves.UART.Framing.Line
to your Nerves.UART.open
call is sufficient.
The v0.1.0 release has this feature now. Closing this issue. If there are limitations with what I added, then let's open new issues up so that they can be addressed.
@mattneel, thanks for bring this issue up! I think this will help many people.
In my project, data is sent over serial in the following format:
node-id;child-sensor-id;message-type;ack;sub-type;payload\n
In it's current implementation, Nerves.UART makes this a little hard to work with, so I was looking for some method of reading things line by line.
The implementation I've worked out (in active mode, anyways) was to pass a string buffer around in state (initially empty), and on each serial callback I check if the new data contains a
\n
, and if it does, I take the existing buffer, append the new data, split it in 2 parts at the\n
character, stick the remainder back in the buffer, and GenServer.call my own {:readline} event.It would make it easier for people to adopt the library if we could set a delimiter to split packets in the buffer by, and even if we could define a fixed packet size, and buffer until we get that many bytes, and then send a message when data is ready.