5

Working on a project that uses a little keyboard and an E-ink display which will run on a raspberry pi Zero. I have tried a couple of keyboard packages for python (pynput, pyxhook) and have written/tested simple keystroke loggers that work fine on my desktop (ubuntu)

However I try to run them on the pi with no monitor both libraries die

DisplayConnectionError: Can't connect to display ":0": [Errno 111] Connection refused

I know at least pyxhook has the ability to capture mouse movement so that makes sense why it would "Need" access to the monitor. But all I want is a way to capture the keyboard input in a process running in the background but with no monitor attached

The libraries can also return the current window that has focus as part of the key event, and that may be the other reason the monitor is tied in so deep.I tried

$export DISPLAY=":0"

did not help.

here is simple code for pynput, works with monitor but not when running headless(running it from SSH)

#!/usr/bin/env python

from pynput import keyboard

def on_press(key):
    print('Key {} pressed.'.format(key))
    if str(key) == 'Key.esc':
        print('Exiting...')
        return False


with keyboard.Listener(on_press = on_press) as listener:
    listener.join()

Is there any way to get these to work, or possibly a different way of a approaching this.

full stack trace of above program failing

Traceback (most recent call last):
  File "./keylog.py", line 3, in <module>
    from pynput import keyboard
  File "/usr/local/lib/python2.7/dist-packages/pynput/__init__.py", line 23, in <module>
    from . import keyboard
  File "/usr/local/lib/python2.7/dist-packages/pynput/keyboard/__init__.py", line 49, in <module>
    from ._xorg import KeyCode, Key, Controller, Listener
  File "/usr/local/lib/python2.7/dist-packages/pynput/keyboard/_xorg.py", line 38, in <module>
    from pynput._util.xorg import (
  File "/usr/local/lib/python2.7/dist-packages/pynput/_util/xorg.py", line 38, in <module>
    _check()
  File "/usr/local/lib/python2.7/dist-packages/pynput/_util/xorg.py", line 36, in _check
    display = Xlib.display.Display()
  File "/usr/local/lib/python2.7/dist-packages/Xlib/display.py", line 89, in __init__
    self.display = _BaseDisplay(display)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/display.py", line 71, in __init__
    protocol_display.Display.__init__(self, *args, **keys)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/protocol/display.py", line 90, in __init__
    self.socket = connect.get_socket(name, protocol, host, displayno)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/support/connect.py", line 87, in get_socket
    return mod.get_socket(dname, protocol, host, dno)
  File "/usr/local/lib/python2.7/dist-packages/Xlib/support/unix_connect.py", line 113, in get_socket
    raise error.DisplayConnectionError(dname, str(val))
Xlib.error.DisplayConnectionError: Can't connect to display ":0": [Errno 111] Connection refused
1
  • You will not be able to do this unless you run the full X11 server on your board, even without a monitor attached (look for the xorg package for the server). An alternative is to read directly from the libinput interface. For python see python-evdev
    – meuh
    Mar 1, 2018 at 16:23

2 Answers 2

10

Ok, i figured it out, figured I would post the answer.

pythons keyboard module, docs and source here

as stated in the "Known Limitations" section, (even though I don't think this is a limitation!)

"To avoid depending on X, the Linux parts reads raw device files (/dev/input/input*) but this requires root."

So this does bring up security issues obviously since the program now needs root privileges, but for my case this is not an issue.

pip install keyboard

simple program

import keyboard
import time

def key_press(key):
    print(key.name)

keyboard.on_press(key_press)

while True:
    time.sleep(1)
1
0

I am currently working on a similar problem. I got an idea how to solve this. But did not try it yet. Not sure if I should put this into a new question.

  • set up a virtual console that automatically logs in a user
  • this console does not show an interactive shell (bash) but just a process that listens for key-presses and sends them to MPD

That's it. You still may switch to a standard console using Ctrl-Fx and then log-in normally without any side effects like unwanted control of the MPD.

There are still several problems unsolved:

  • does linux open up the virtual consoles at all if there is no monitor attached?

  • how to set up this console? /etc/login.defs?

  • what language and library to use for the listener process (I implemented everything in python until now)

  • how to pass the events to MPD. (through mpc command line client or python mpc client library?)

I marked this as community wiki. So anybody feel free to contribute to this answer.

Background: I implemented a headless audio-player using MPD on raspberry pi that currently is controlled via GPIO pins. Now I would like to be able to control it via keyboard as well.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .