0

I'm writing an app that allows an Arduino plugged in via USB to send serial data to the app to graph it in realtime. It can scan available ports for the Arduino and attempt to connect to it, but I'm running into permissions issues whether I use pyserial or QtSerialPort. I have added my user to the groups tty, uucp, and dialout. (When listing ports I see that they belong to uucp.) This doesn't seem to do anything. I can chmod a+rw the port every time the Arduino is plugged in but this is not practical because less technical users (i.e. my kids) need to be able to plug it in and use it via a GUI that I'm writing. I've seen suggestions to run the whole script with sudo but this seems less safe than it needs to be, and also requires typing in the command line.

Is there a way to read from the serial port without resetting permissions every time I plug the USB cable in? Or if not, is there an accepted way to do this from the GUI to make sure the permissions are right before the attempt to connect, without running the whole program as sudo? I'm building this on Linux (Arch) btw.

  • Does this answer your question? [Read/Write to a Serial Port Without Root?](https://unix.stackexchange.com/questions/14354/read-write-to-a-serial-port-without-root) – musicamante Nov 25 '20 at 12:57
  • @musicamante No, not really, unless there's something more to it that I'm not understanding. I already tried looking at `ls -l /dev/ttyACM*` seeing that they belong to group `uucp` I added my user to this group, as well as to `tty` and `dialout` to be safe. No luck. – the_pie_in_the_sky_is_a_lie Nov 25 '20 at 13:13
  • There seems to be an *old* bug (which seems to have been solved since Qt 5.6) related to the permissions, and it's related to the fact that you should ensure that the QSerialPort object is properly closed before exiting, otherwise there could be problems as the lock file won't be released: see https://stackoverflow.com/a/37402197 – musicamante Nov 25 '20 at 13:21
  • @musicamante I'll look into that. In this instance, I had this problem with permissions also before I imported PyQt5 and encountered it when only using PySerial. – the_pie_in_the_sky_is_a_lie Nov 25 '20 at 13:24
  • @musicamante I also reinstalled PyQt5 brand new today, so I don't think it's using a 3.5 year old version of Qt5, although it's not clear to me how to check what version of Qt5 is being used with PyQt5 installed from pip. – the_pie_in_the_sky_is_a_lie Nov 25 '20 at 13:32
  • You can check it using `from PyQt5 import QtCore; print(QtCore.QT_VERSION_STR)`, but if you installed it today from pip it should be at least 5.12/5.14. Are you opening the port in read mode? Does the device have read/write permissions for the group? – musicamante Nov 25 '20 at 13:55
  • @musicamante PyQt5 is version 5.15.2. The linked question/answer specifies Qt5 version 5.6 and above, which made me confused bc the Qt5 version isn't the same as the PyQt5 version. I don't know what it means "does the device have read/write permissions for the group". – the_pie_in_the_sky_is_a_lie Nov 25 '20 at 14:16
  • The first column of `ls -l` shows the permissions in the format `xuuugggooo`: `x` is the type, `uuu` are the permission for the user, `ggg` for the group, `ooo` for others, those three letters are `rwx` meaning read/write/execute, if one of those letters doesn't appear (and it shows a dash instead) means that that role has not that permission; for example: `rw-rw----` means that the owner and the group have read/write permissions, while others have no access, with `rw-r--r--` the owner can read/write, everybody else can only read. You need to check if the group column has `r` at least. – musicamante Nov 25 '20 at 14:24
  • @musicamante Ah, ok I didn't understand the meaning of "device" here. The group has read and write permissions, and the user that's running the script is in the group, yes. – the_pie_in_the_sky_is_a_lie Nov 25 '20 at 14:54

1 Answers1

0

I solved this using udev rules. I created the rules file, which I called /etc/udev/rules.d/80-arduino.rules, and inside I put the following:

SUBSYSTEMS=="usb", ACTION=="add", DRIVERS=="usb", ATTRS{idProduct}=="0042", ATTRS{idVendor}=="2341", ATTRS{manufacturer}=="Arduino (www.arduino.cc)", ATTRS{serial}=="85734323231351404021", RUN+="/bin/arduino_added.sh", RUN+="/bin/device_added.sh", MODE="0660"

This selects for my specific device by serial number as well as manufacturer (ATTRS{serial}=="85734323231351404021"), runs a little script that writes something to a logfile it creates in /tmp (for debugging), and the MODE="0660" opens the port with permissions to let it be accessed.

I had to mess with it a bit to get it to work. Running sudo udevadm control --reload was enough to get the script to write to the logfile each time it was plugged in, but I had to reboot the computer to get it to work with the permissions for some reason.