Coder Social home page Coder Social logo

elixir_serial's People

Contributors

bitgamma avatar kfatehi avatar stefan991 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

elixir_serial's Issues

Port process does not exit

I'm running into an issue where the port process isn't exiting after Elixir terminates. Unless I kill the offending process, my computer will crash if I unplug the usb connection.

I'm using the Sparkfun WRL-08687.

$ ps aux | grep serial
rockwood         5061   0.0  0.0  2445080    788 s004  S+    3:18PM   0:00.00 grep serial

I can then run the following:

{:ok, serial} = Serial.start_link

Serial.open(serial, "/dev/tty.usbserial-AM01VFAJ")
Serial.set_speed(serial, 9600)
Serial.connect(serial)
Serial.send_data(serial, "+++")

Serial.close(serial)
Serial.disconnect(serial)

And the process remains after elixir has exited.

$ ps aux | grep serial
rockwood         5110   0.0  0.0  2434840    752 s004  S+    3:21PM   0:00.00 grep serial
rockwood         5098   0.0  0.0  2434824    632   ??  Ss    3:21PM   0:00.00 /Users/rockwood/devel/exbee/_build/dev/lib/serial/priv/serial -erlang

I've tried modifying serial.ex to manually Port.close(port) on exit, but the process still remains.

Any ideas?

handle_info message per character

I'm wondering if there's any settings I can apply to the serial process to have it look for a line break before sending over a message to the elixir process. right now, calling flush() gives me this output.

One message per character.

{:elixir_serial, #PID<0.160.0>, "M"} {:elixir_serial, #PID<0.160.0>, "O"} {:elixir_serial, #PID<0.160.0>, "V"} {:elixir_serial, #PID<0.160.0>, "I"} {:elixir_serial, #PID<0.160.0>, "E"} {:elixir_serial, #PID<0.160.0>, "v"} {:elixir_serial, #PID<0.160.0>, "e"} {:elixir_serial, #PID<0.160.0>, "n"} {:elixir_serial, #PID<0.160.0>, "t"} {:elixir_serial, #PID<0.160.0>, "["} {:elixir_serial, #PID<0.160.0>, "1"} {:elixir_serial, #PID<0.160.0>, "5"} {:elixir_serial, #PID<0.160.0>, "0"} {:elixir_serial, #PID<0.160.0>, "]"} {:elixir_serial, #PID<0.160.0>, ":"} {:elixir_serial, #PID<0.160.0>, " "} {:elixir_serial, #PID<0.160.0>, "S"} {:elixir_serial, #PID<0.160.0>, "P"} {:elixir_serial, #PID<0.160.0>, "E"} {:elixir_serial, #PID<0.160.0>, "A"} {:elixir_serial, #PID<0.160.0>, "K"} {:elixir_serial, #PID<0.160.0>, "I"} {:elixir_serial, #PID<0.160.0>, "N"} {:elixir_serial, #PID<0.160.0>, "G"} {:elixir_serial, #PID<0.160.0>, "\r"} {:elixir_serial, #PID<0.160.0>, "\n"} {:elixir_serial, #PID<0.160.0>, "M"} {:elixir_serial, #PID<0.160.0>, "O"} {:elixir_serial, #PID<0.160.0>, "V"} {:elixir_serial, #PID<0.160.0>, "I"} {:elixir_serial, #PID<0.160.0>, "E"} {:elixir_serial, #PID<0.160.0>, "v"} {:elixir_serial, #PID<0.160.0>, "e"} {:elixir_serial, #PID<0.160.0>, "n"} {:elixir_serial, #PID<0.160.0>, "t"} {:elixir_serial, #PID<0.160.0>, "["} {:elixir_serial, #PID<0.160.0>, "1"} {:elixir_serial, #PID<0.160.0>, "5"} {:elixir_serial, #PID<0.160.0>, "1"} {:elixir_serial, #PID<0.160.0>, "]"} {:elixir_serial, #PID<0.160.0>, ":"} {:elixir_serial, #PID<0.160.0>, " "} {:elixir_serial, #PID<0.160.0>, "E"} {:elixir_serial, #PID<0.160.0>, "N"} {:elixir_serial, #PID<0.160.0>, "D"} {:elixir_serial, #PID<0.160.0>, " "} {:elixir_serial, #PID<0.160.0>, "S"} {:elixir_serial, #PID<0.160.0>, "P"} {:elixir_serial, #PID<0.160.0>, "E"} {:elixir_serial, #PID<0.160.0>, "A"} {:elixir_serial, #PID<0.160.0>, "K"} {:elixir_serial, #PID<0.160.0>, "I"} {:elixir_serial, #PID<0.160.0>, "N"} {:elixir_serial, #PID<0.160.0>, "G"} {:elixir_serial, #PID<0.160.0>, "\r"} {:elixir_serial, #PID<0.160.0>, "\n"}

I'm not sure if I can add an accumulator for the handle_info call to build up the message myself.

handle_info() not always receives a message entirely

I'm trying to handle RFID SEN-09963 ids via serialport and I've encountered difficulty that handle_info() receives id not entirely. It may be associated with Serial setting?
In documentation I've read that device has none parity, data bits is 8 and stop bits is 1.
How to workaround this?

setup:

    {:ok, serial} = Serial.start_link
    Serial.open(serial, "/dev/cu.usbserial-A5026NYN")
    Serial.set_speed(serial, 9600)
    Serial.connect(serial)

handle_info():

  def handle_info({:elixir_serial, serial, data}, state) do
    Logger.debug "received :data #{data}"
    {:noreply, state}
  end

log:

[debug] received :data
[debug] received :data 7A005AFA518B

[debug] received :data
[debug] received :data 7
[debug] received :data A005AFA518B

[debug] received :data
[debug] received :data 7A005AFA518B

[debug] received :data
[debug] received :data 7A005AFA518
[debug] received :data B

I've tryed to figure out why I get multiple messages, this is not related with bits, I set manually in set_tty_speed() and result is the same:

  ttymodes.c_cflag |= CS8;         /* enable eight bit chars */
  ttymodes.c_cflag &= ~PARENB;     /* disable input parity check */
  ttymodes.c_cflag &= ~CSTOPB;     /* enable 1 stop bit */

I've compiled serial.c, and it seems that it isn't waiting for whole message, it cut ids as in handle_info()

./compiledserial
7AB
AFA518BA518B
5AFA518B
8B
7A005AF

In BeagleBoneBlack it throws an argument error.

Hi.

Thanks for this package I've been using it successfully on my Mac for working with an Arduino.

On the Beaglebone, however, with /dev/ttyACM0 as the Arduino connected via USB, I get this error and crash when trying to call Serial.open/2.

Maybe you have an idea?

Thanks

iex(branch@nerves)3> {:ok, serial} = Serial.start_link
{:ok, #PID<0.115.0>}
iex(branch@nerves)4>
nil
iex(branch@nerves)5> Serial.open(serial, "/dev/ttyACM0")
** (EXIT from #PID<0.110.0>) an exception was raised:
    ** (ArgumentError) argument error
        :erlang.port_command(#Port<0.1278>, [3, "/dev/ttyACM0"])
        (serial) lib/serial.ex:99: Serial.handle_call/3
        (stdlib) gen_server.erl:629: :gen_server.try_handle_call/4
        (stdlib) gen_server.erl:661: :gen_server.handle_msg/5
        (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

Interactive Elixir (1.1.1) - press Ctrl+C to exit (type h() ENTER for help)

00:03:37.171 [error] GenServer #PID<0.115.0> terminating
** (ArgumentError) argument error
    :erlang.port_command(#Port<0.1278>, [3, "/dev/ttyACM0"])
    (serial) lib/serial.ex:99: Serial.handle_call/3
    (stdlib) gen_server.erl:629: :gen_server.try_handle_call/4
    (stdlib) gen_server.erl:661: :gen_server.handle_msg/5
    (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Last message: {:open, "/dev/ttyACM0"}
State: {#PID<0.110.0>, #Port<0.1278>}

=CRASH REPORT==== 1-Jan-1970::00:03:37 ===
  crasher:
    initial call: Elixir.Serial:init/1
    pid: <0.115.0>
    registered_name: []
    exception exit: {badarg,
                        [{erlang,port_command,
                             [#Port<0.1278>,[3,<<"/dev/ttyACM0">>]],
                             []},
                         {'Elixir.Serial',handle_call,3,
                             [{file,"lib/serial.ex"},{line,99}]},
                         {gen_server,try_handle_call,4,
                             [{file,"gen_server.erl"},{line,629}]},
                         {gen_server,handle_msg,5,
                             [{file,"gen_server.erl"},{line,661}]},
                         {proc_lib,init_p_do_apply,3,
                             [{file,"proc_lib.erl"},{line,240}]}]}
      in function  gen_server:terminate/7 (gen_server.erl, line 826)
    ancestors: [<0.110.0>]
    messages: []
    links: [<0.110.0>]
    dictionary: []
    trap_exit: false
    status: running
    heap_size: 610
    stack_size: 27
    reductions: 141
  neighbours:
    neighbour: [{pid,<0.110.0>},
                  {registered_name,[]},
                  {initial_call,{erlang,apply,2}},
                  {current_function,{gen,do_call,4}},
                  {ancestors,[]},
                  {messages,[]},
                  {links,[<0.115.0>]},
                  {dictionary,
                      [{iex_history,
                           #{'__struct__' => 'Elixir.IEx.History.State',
                             queue => {[{4,"\n",nil},
                               {3,"{:ok, serial} = Serial.start_link\n",
                                {ok,<0.115.0>}},
                               {2,"\n",nil}],
                              [{1,"\n",nil}]},
                             size => 4,
                             start => 1}}]},
                  {trap_exit,false},
                  {status,waiting},
                  {heap_size,4185},
                  {stack_size,50},
                  {reductions,6273}]
iex(branch@nerves)1>

Return error or crash on failure to connect

Currently if I call Serial.connect and there is a problem there is no way of knowing from the calling process. I see a message in iex but the Serial.connect call always return :ok and a failed command does not crash the Serial GenServer.

To reproduce just try to open a resource that does not exist.

Ideally one of three things would happen:

# Option 1
Serial.open("/dev/myport")
Serial.set_speed(9600)

case Serial.connect(pid) do
  :ok -> Logger.info("Yay! we have a serial port")
  {:error, _reason} -> Logger.warn(":( no serial port")
end
#Option 2
:ok = Serial.connect(pid) 
# Serial GenServer crashes on failure to open 
# this is what erlang-serial does
#Option 3
try do
  :ok = Serial.connect(pid)
  Logger.info("Yay!! serial port")
rescue
  RuntimeError -> Logger.warn(":'( no serial port")

Personally I like options 1 or 3. Option 2 relies on running both Serial and the calling server under the same Sup, or monitoring the Serial GenServer from your calling server. Which is still workable though.

Serial has to be compiled twice with `mix deps.compile`

This is a strange problem, but very reproducible for me. When I first run the app on a new system, I have to run mix deps.compile twice. If I run it only once, the deps compile without warning or error, but when I start the app, it fails with this message:

{failed_to_start_child,'Elixir.Gatekeeper.DoorInterface',{enoent,[{erlang,open_port,[{spawn_executable,\"/var/www/gatekeeper/_build/prod/lib/serial/priv/serial\"}

Simply running mix deps.compile again "fixes" the issue. Here's the abbreviated output

$ mix deps.compile
# ... snip
==> serial
-- The C compiler identification is GNU 4.9.2
-- The CXX compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /var/www/gatekeeper/deps/serial

Scanning dependencies of target serial
[100%] Building C object CMakeFiles/serial.dir/src/serial.c.o
Linking C executable priv/serial
[100%] Built target serial

Compiled lib/serial.ex
Generated serial app
# ... snip
$ mix phoenix.server
21:25:36.360 [info] Running Gatekeeper.Endpoint with Cowboy on http://localhost:4000
{"Kernel pid terminated",application_controller,"{application_start_failure,gatekeeper,{{shutdown,{failed_to_start_child,'Elixir.Gatekeeper.DoorInterface',{enoent,[{erlang,open_port,[{spawn_executable,\"/var/www/gatekeeper/_build/prod/lib/serial/priv/serial\"},[{args,[\"-erlang\"]},binary,{packet,2}]],[]},{'Elixir.Serial',init,1,[{file,\"lib/serial.ex\"},{line,94}]},{gen_server,init_it,6,[{file,\"gen_server.erl\"},{line,328}]},{proc_lib,init_p_do_apply,3,[{file,\"proc_lib.erl\"},{line,240}]}]}}},{'Elixir.Gatekeeper',start,[normal,[]]}}}"}

Crash dump is being written to: erl_crash.dump...done
Kernel pid terminated (application_controller) ({application_start_failure,gatekeeper,{{shutdown,{failed_to_start_child,'Elixir.Gatekeeper.DoorInterface',{enoent,[{erlang,open_port,[{spawn_executabl
$ mix deps.compile
# ... snip
==> serial
-- Configuring done
-- Generating done
-- Build files have been written to: /var/www/gatekeeper/deps/serial

[100%] Built target serial

$ mix phoenix.server
21:27:01.147 [info] Running Gatekeeper.Endpoint with Cowboy on http://localhost:4000
21:27:01.380 [info] RFID listener process started for reader /dev/ttyUSB0

Full logs: https://gist.github.com/bklang/c1435f247d73fc81a37c

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.