bnjmnp / pysoem

Cython wrapper for the Simple Open EtherCAT Master Library
MIT License
95 stars 36 forks source link

ConnectionError: could not open interface on Ubuntu #133

Open asmorgan24 opened 5 months ago

asmorgan24 commented 5 months ago

I am curious as to if it is at all possible to open a connection to an adapter on Ubuntu without having to run things as root. For instance, I would like to just run master.open(<portname>) without having to first run the python script as sudo python name_of_script.py.

Is there any way to open this adapter up so that we don't need to be the super user to access it? It is pretty straight forward-ish to do this in windows, but I cannot be installing all of my pip packages as sudo on my system (doing so would complicate everything within dockers and such). Hoping there is an easy way to sidestep this issue without jumping through too many hoops.

Current code:

import pysoem
master = pysoem.Master()
master.open('enx207bd26016ea')

Error message:

Traceback (most recent call last):
  File "ethercat.py", line 13, in <module>
    master.open('enx207bd26016ea')
  File "pysoem/pysoem.pyx", line 227, in pysoem.pysoem.CdefMaster.open
ConnectionError: could not open interface enx207bd26016ea
bnjmnp commented 5 months ago

Hi, sorry I'm also no expert on Linux and don't know how to get around this. Maybe someone with enough knowledge reads this and can provide help. When searching on the web about this you could look for questions like this: https://raspberrypi.stackexchange.com/questions/40105/access-gpio-pins-without-root-no-access-to-dev-mem-try-running-as-root in the past on Raspbian one needed root access to access GPIO's from within a Python script. Maybe the solutions of this can be transferred to your system. I'd love to hear how you finally solved this.

asmorgan24 commented 5 months ago

Just wanted to follow up on this. After digging into this for a couple of days, and working with some embedded engineers, here is a single (1) solution to this problem. There may be others, but this is the most streamlined. I will be spending time figuring out how to make this work best in a docker container, but for the time being you can use this method for both your home (base) python environment or virtual ones. It should also work with C++ and other languages as well, just with some modification of what your "executable" is. Assuming we are using python:

ll `which python`

You will get a response that looks something like this: lrwxrwxrwx 1 amorgan amorgan 9 Apr 26  2023 **/home/amorgan/miniconda3/envs/play_env/bin/python** -> **python3.8***

Now that you know you are using python 3.8 (or whatever one you are using), then run:

ll `which python3.8`

You will get a reply that looks like: rwxrwxr-x 2 amorgan amorgan 14718232 Nov 6 2019 **/home/amorgan/miniconda3/envs/play_env/bin/python3.8**

Now, you know that when you call python in command line, python3.8 (or whatever it is for your system) is what is being called to run the executable. Finally, you can open up permissions to your python executable by running:

sudo setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip' ~/miniconda3/envs/play_env/bin/python3.8

Where the final argument is the location of your python executable (as determined in step 2). Hopefully this helps out anyone trying to work with opening ports/adapters for ethernet/ethercat on linux/ubuntu systems.

daironxuan commented 4 months ago
def request_root_permissions(m_path, m_pid):
    args = ["pkexec", "python3", m_path, str(m_pid)]
    process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    process.wait(60)
    if process.returncode == 1:
        return True
    else:
        return False

su_state = True
    if os.getuid() != 0:
        app_path = os.path.abspath(sys.argv[0])
        pid = os.getpid()
        su_state = request_root_permissions(app_path, pid)

# Do what you want.....