Coder Social home page Coder Social logo

bindings: python about libgpiod HOT 39 CLOSED

brgl avatar brgl commented on August 25, 2024 2
bindings: python

from libgpiod.

Comments (39)

brgl avatar brgl commented on August 25, 2024 1

Hi @pdp7

Yes, I was recently contacted by @sgjava who showed me his automatically generated ctypes bindings.

You can find them here.

However I plan to write object oriented python 3 bindings (using C extensions) right after I finish the C++ bindings.

There were some issues raised on the linux-gpio mailing list about the safety of ctypes for public structures with different memory layout on 32 and 64 bit architectures.

Please note that I just released v1.0 of libgpiod with an improved API which shall remain stable from now on.

from libgpiod.

nullr0ute avatar nullr0ute commented on August 25, 2024 1

Perfect timing on this query, I have similar ideas as @pdp7 around the RPi.GPIO stuff and was thinking (only an idea ATM) something around this as a GSOC [1] project.

Good news on v1, will updated Fedora packages :)

[1] https://docs.fedoraproject.org/mentored-projects/gsoc/2018/ideas.html#improve-gpio-support-in-fedora-in-general-and-particularly-on-the-raspberry-pi

from libgpiod.

brgl avatar brgl commented on August 25, 2024

Seems like ctypes is the way to go and it should be quite easy to implement.

from libgpiod.

pdp7 avatar pdp7 commented on August 25, 2024

@brgl do you know if anyone has thus far utilized libgpiod from Python?

I maintain the Adafruit BeagleBone library (Adafruit_BBIO) and I am exploring how to support the new GPIO character device interface.

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

@pdp7 @nullr0ute I've started a new project that covers user space GPIO, SPI, I2C, MMIO and Serial interfaces with libgpiod + c-periphery https://github.com/sgjava/userspaceio This will generate Python and Java bindings that work on 32 and 64 bit architectures. Also, I'm targeting Python 2.7, but 3.x generation should work as well (ctypesgen is used on the target platform, so I didn't experience the issus @brgl described above). This shouldn't overlap with @brgl 's work. The scripts currently support Armbian (but should work with other Ubuntu/Debian distros work as well). If you want to support other distros submit a PR and I'll add the scripts.

The idea is to have a cross SBC platform / cross language support by generating the bindings over user space APIs. A RPi.GPIO clone should be easy to generate from my Python bindings over libgpiod. See https://github.com/rm-hull/OPi.GPIO for an example using old sysfs interface.

from libgpiod.

nullr0ute avatar nullr0ute commented on August 25, 2024

I feel with py2 being EOL in ~ 2 years, and hence being in maintenance mode, that py3 should be a reasonable priority for new projects like this :)

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

@nullr0ute it shouldn't be a big deal. I'll look at making that the default. This is the beauty of code generation. OK, looks like CFFI is the way to go. This is a good post https://www.paypal-engineering.com/2016/09/22/python-by-the-c-side I've already kind of gone down this road. I started with SWIG, then ctypes, now CFFI. At least I only spent a few weeks going over the whole life cycle of code generators :)

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

OK @nullr0ute , using compile in CFFI failed because it cannot handle include directives (i.e. ffi.compile()). I was able to get CFFI working with ABI inline. This is pretty slick and code will work with Python 2/3:

Name: gpiochip1, label: 1f02c00.pinctrl, lines: 32
Press button within 5 seconds
Falling edge timestamp 02/10/2018 19:28:15

import sys, time
from argparse import *
from cffi import FFI

parser = ArgumentParser()
parser.add_argument("--chip", help="GPIO chip number (default 1 '/dev/gpiochip1')", type=int, default=1)
parser.add_argument("--line", help="GPIO line number (default 3 button on NanoPi Duo)", type=int, default=3)
args = parser.parse_args()
ffi = FFI()
# Specify each C function, struct and constant you want a Python binding for
# Copy-n-paste with minor edits
ffi.cdef("""
enum {
    GPIOD_LINE_EVENT_RISING_EDGE,
    GPIOD_LINE_EVENT_FALLING_EDGE,
};

struct timespec {
    long tv_sec;
    long tv_nsec;
};

struct gpiod_line {
    unsigned int offset;
    int direction;
    int active_state;
    bool used;
    bool open_source;
    bool open_drain;
    int state;
    bool up_to_date;
    struct gpiod_chip *chip;
    int fd;
    char name[32];
    char consumer[32];
};

struct gpiod_chip {
    struct gpiod_line **lines;
    unsigned int num_lines;
    int fd;
    char name[32];
    char label[32];
};

struct gpiod_line_event {
    struct timespec ts;
    int event_type;
};

const char *gpiod_version_string(void);
struct gpiod_chip *gpiod_chip_open_by_number(unsigned int num);
struct gpiod_line *gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset);
int gpiod_line_request_falling_edge_events(struct gpiod_line *line, const char *consumer);
int gpiod_line_event_wait(struct gpiod_line *line, const struct timespec *timeout);
int gpiod_line_event_read(struct gpiod_line *line, struct gpiod_line_event *event);
void gpiod_line_release(struct gpiod_line *line);
void gpiod_chip_close(struct gpiod_chip *chip);
""")
lib = ffi.dlopen("libgpiod.so")
print "libgpiod version %s" % ffi.string(lib.gpiod_version_string())
gpiod_chip = lib.gpiod_chip_open_by_number(args.chip)
# Make sure GPIO chip opened
if gpiod_chip != ffi.NULL:
    print("Name: %s, label: %s, lines: %d" % (ffi.string(gpiod_chip.name), ffi.string(gpiod_chip.label), gpiod_chip.num_lines))
    gpiod_line = lib.gpiod_chip_get_line(gpiod_chip, args.line)
    if gpiod_line != ffi.NULL:
        consumer = sys.argv[0][:-3]
        if lib.gpiod_line_request_falling_edge_events(gpiod_line, consumer) == 0:
            timespec = ffi.new("struct timespec*")
            timespec.tv_sec = 5
            print("Press button within 5 seconds")
            rc = lib.gpiod_line_event_wait(gpiod_line, timespec)
            if rc == 0:
                print("Timed out")
            elif rc == 1:
                event = ffi.new("struct gpiod_line_event*")
                # Read event off queue
                lib.gpiod_line_event_read(gpiod_line, event)
                if event.event_type == lib.GPIOD_LINE_EVENT_RISING_EDGE:
                    print("Rising edge timestamp %s" % time.strftime('%m/%d/%Y %H:%M:%S', time.localtime(event.ts.tv_sec)))
                else:
                    print("Falling edge timestamp %s" % time.strftime('%m/%d/%Y %H:%M:%S', time.localtime(event.ts.tv_sec)))
            else:
                print("Unable request falling edge for line %d" % args.line)            
        lib.gpiod_line_release(gpiod_line)
    else:
        print("Unable to get line %d" % args.line)
    lib.gpiod_chip_close(gpiod_chip)    
else:
    print("Unable to open chip %d" % args.chip)

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

@pdp7 @nullr0ute https://github.com/sgjava/userspaceio is Python 3 bindings using CFFI!

from libgpiod.

pdp7 avatar pdp7 commented on August 25, 2024

@sgjava thanks, that looks very interesting!

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

I'm working on a RPi.GPIO clone, so you can use Luma.OLED stuff on multiple SBCs.

from libgpiod.

nullr0ute avatar nullr0ute commented on August 25, 2024

A clone of RPi.GPIO isn't really of much use TBH, it needs to be accepted upstream into it. The reason is because it needs to be able to work with all the 100s of existing howtos, educational instructions, blogs etc around the internet. Without that all the non Raspbian distributions still end up with 100s of support queries of "X doesn't work with your distro" and redirecting people to some other resource doesn't work well. Raspbian themselves also won't adopt the new way of doing things because of support issues too. Unfortunately the support just needs to be upstream and seamless to the end user.

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

No, I'm talking about something like https://github.com/rm-hull/OPi.GPIO in order to use Luma.OLED. I'm actually not interested in RPi.GPIO for any reason other than to extend it to non-Pi platforms that requires RPi.GPIO. OPi.GPIO is based on sysfs, so it can miss events, etc. I'm not interested in reinventing the RPi.GPIO wheel since libgpiod provides a better API in my opinion.

from libgpiod.

brgl avatar brgl commented on August 25, 2024

Hey,

@sgjava @pdp7 @nullr0ute @smurfix

you guys may be interested in the latest commit in libgpiod's master branch. I pushed the first version of native Python 3 bindings for the library. I still need to figure out how to cross-compile it using autotools (I have an issue with AX_PYTHON_DEVEL macro described here.

It would be great if you could give it a try and help me test it. It'll be released as part of v1.1 release together with C++ bindings.

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

This is in master?

from libgpiod.

brgl avatar brgl commented on August 25, 2024

Yes, commit 96c524c

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

Just tried to build on Armbian and I get:

./autogen.sh --enable-tools=yes --prefix=/usr/local CFLAGS="-I/usr/src/linux-headers-$(uname -r)/include/uapi -I$HOME/include"

checking for sys/signalfd.h... yes
./configure: line 17561: syntax error near unexpected token `ext,'
./configure: line 17561: `	AX_CXX_COMPILE_STDCXX_11(ext, mandatory)'

from libgpiod.

brgl avatar brgl commented on August 25, 2024

@sgjava You need the autoconf-archive package to build now. If you don't have it, this macro (AX_CXX_COMPILE_STDCXX_11) doesn't get expanded. You also need to specify the --enable-bindings-python option in configure. If your autoconf-archive macros are in some strange place, you need to run autoreconf with -I.

EDIT: depending on your environment you may also need to pass PYTHON_VERSION=3 to configure.

from libgpiod.

brgl avatar brgl commented on August 25, 2024

@sgjava FYI autoreconf will now complain about unexpanded m4 macros with a clear error message.

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

OK, will try again tonight when I get home.

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

@brgl I installed autoconf-archive and python3-dev and used PYTHON_VERSION=3. It worked with:

./autogen.sh --enable-tools=yes --enable-bindings-python --prefix=/usr/local CFLAGS="-I/usr/src/linux-headers-$(uname -r)/include/uapi -I$HOME/include"

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

@brgl trying to run python example (do you install as a pip3 module?):

gpiod.a gpiod.la gpiod.so are in /usr/local/lib/python3.5/site-packages

alias python=python3
cd ~/libgpiod/bindings/python/examples
python gpiodetect.py
Traceback (most recent call last):
  File "gpiodetect.py", line 12, in <module>
    import gpiod
ImportError: No module named gpiod

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

@brgl I fixed it with export PYTHONPATH=/usr/local/lib/python3.5/site-packages. I assume because sys.path has the default 2.7 stuff in Ubuntu.

python3 gpiodetect.py 
gpiochip0 [1c20800.pinctrl] (224 lines)
gpiochip1 [1f02c00.pinctrl] (32 lines)

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

@pdp7 @nullr0ute @smurfix https://github.com/sgjava/userspaceio now builds libgpiod master. I removed my CFFI bindings and will use @brgl bindings instead. I need to refactor my example Python code. I also need to test the JNA Java bindings against this build. :)

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

I built a simple example that reads the built in button and optionally will turn an LED on and off based on the button state. https://github.com/sgjava/userspaceio/blob/master/libgpiod/python/src/buttonpress.py

The Python bindings are easier than using CFFI wrapper I wrote for libgpiod 1.0. I'll continue to update my Python examples.

from libgpiod.

brgl avatar brgl commented on August 25, 2024

Python bindings can now be correctly cross-compiled. An example buildroot recipe is available in my github repo.

from libgpiod.

nullr0ute avatar nullr0ute commented on August 25, 2024

So testing 1.1 it all builds fine for me on Fedora except on 64 bit arches the python bindings are being installed to /usr/lib/ rather than /usr/lib64. not had time to work out the fix as yet.

from libgpiod.

nullr0ute avatar nullr0ute commented on August 25, 2024

My issue was a cut/paste error, all built for Fedora for 28+ will ask people to test and provide feedback

from libgpiod.

brgl avatar brgl commented on August 25, 2024

Cool, thanks. I was on vacation and didn't have time to look at it in the last three weeks.

from libgpiod.

quintusfelix avatar quintusfelix commented on August 25, 2024

Another example for cross compiling libgpiod with python bindings is available in PTXdist git repo now.

from libgpiod.

brgl avatar brgl commented on August 25, 2024

Native bindings implemented.

from libgpiod.

Careknight avatar Careknight commented on August 25, 2024

@brgl trying to run python example (do you install as a pip3 module?):

gpiod.a gpiod.la gpiod.so are in /usr/local/lib/python3.5/site-packages

alias python=python3
cd ~/libgpiod/bindings/python/examples
python gpiodetect.py
Traceback (most recent call last):
  File "gpiodetect.py", line 12, in <module>
    import gpiod
ImportError: No module named gpiod

I'm getting stuck with import gpiod.
I've installed libgpiod from apt and am unable to find gpiod package on pip.

I'd rather not write a OOP wrapper to the command line functions if there are already bindings available.

from libgpiod.

brgl avatar brgl commented on August 25, 2024

@Careknight I have never packaged libgpiod python bindings for pip. I have no need for it as I either use the package in yocto/buildroot or build it from sources. I guess this isn't available yet.

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

alias python=python3
export PYTHONPATH=/usr/local/lib/python3.5/site-packages

Check and make sure packages are in /usr/local/lib/python3.5/site-packages. In Ubuntu 18.04 they are in /usr/local/lib/python3.6/site-packages

from libgpiod.

Careknight avatar Careknight commented on August 25, 2024

@sgjava
I've managed to get away with not pip installing anything so far and therefore have no "site-packages", and subsequently don't have anything in /usr/local/lib/python3.6/site-packages. I'll make sure that my python content is up to date. I do have a "dist-packages" folder, (see screenshot)
Is the python gpiod module an artifact of the ;
''' "./autogen.sh --enable-tools=yes --enable-bindings-python --prefix=/usr/local CFLAGS="-I/usr/src/linux-headers-$(uname -r)/include/uapi -I$HOME/include"
'''
Being run?

So ultimately I understand that I'm missing the dependency, I'm trying to understand how I get it :)

image

@brgl I appreciate that, Is there a view that this could be done in the future?
As currently getting hold of libgpiod does not require building . (i.e. greatly deskilled access to the components.) but being able to use the components as part of python program would require the build environment /knowledge.

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

Take a look at my script https://github.com/sgjava/userspaceio/blob/master/libgpiod/install.sh It works fine and deposits the libgpiod python artifacts in dir I described above. I'll check later tonight and give you a list of artifacts in the site-packages dir.

Also, some distros are including libgpiod, but I don't think any of them are mainstream (i.e. Fedora).

from libgpiod.

nullr0ute avatar nullr0ute commented on August 25, 2024

@sgjava Fedora has libgpid 1.1.1 inc the c++ and python bindings enabled, I'm the maintainer. Any feedback/fixes/suggestions welcome too.

from libgpiod.

brgl avatar brgl commented on August 25, 2024

@Careknight I don't know much about pip packages so I will probably not do it anytime soon. I only keep the meta-openembedded and buildroot packages up to date. Everything else is packaged by others (really appreciated BTW).

from libgpiod.

sgjava avatar sgjava commented on August 25, 2024

@brgl Making pip wrappers shouldn't be too hard. Maybe when I have some time I'll add it to https://github.com/sgjava/userspaceio For pip package you just need a setup.py and sudo -H pip install -e .

from libgpiod.

Related Issues (20)

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.