chill389cc
chill389cc

Reputation: 432

RPi - Python Curses program running at boot does not have keyboard focus

I am trying to write a program that will run when my raspberry pi starts up and will allow me to immediately begin typing things with my keyboard and have it be picked up by the program. I don't want to have to manually start the program when the pi starts. I need to use curses (or a similar unbuffered keyboard input library) because I display what I am typing on a 2x16 I2C LCD, but I also need everything that I am typing to be recorded to a text file.

Right now, I am auto-starting the program at boot by putting a line in rc.local. This works, and the I2C display is correctly showing program output, but it does not respond to keyboard input, and the keyboard input is instead displayed (when I connect the pie to a screen, the goal is to run headless) on an odd console layout that exits when I press enter and says -bash: 'whatever I just typed' command not found.

I have already tried:

  1. Setting a timer at the beginning of the program to wait until the pi has fully booted before initializing the curses window and keyboard capture

  2. Creating a seperate python program to wait until the pi has fully booted and then running the main script by importing it

Neither of these methods works though, I get the same problem with slight differences.

To be clear, the program works flawlessly if I run it manually from the command line. But there is no keyboard input to the program (or at least not where it is supposed to be inputted) when I autostart the script with rc.local.

My code:

 #!/usr/bin/python
import I2C_LCD_driver, datetime, sys
from time import *
from subprocess import call

mylcd = I2C_LCD_driver.lcd()

for x in range(30): #waits for raspberry pi to boot up
    mylcd.lcd_display_string("Booting Up: "+str(x), 1)
    sleep(1)

import curses
key = curses.initscr()
curses.cbreak()
curses.noecho()
key.keypad(1)
key.nodelay(1)

escape=0
while escape==0:
    #variable initialization

    while 1:
        k=key.getch()
        if k>-1: #runs when you hit any key. getch() returns -1 until a key is pressed
            if k==27: #exits the program when you hit Esc
                break
            elif k==269:
                # a couple other special Function key cases are here
            else:
                inpt=chr(k)
                mylcd.lcd_display_string(inpt,2,step) #writes the last character to the display
                #some more code that handles writing the text to the LCD, which works flawlessly when run manually.

    file.write("%s\r\n" % entry)
    file.close()
    mylcd.lcd_display_string("Saved           ",2)
    mylcd.lcd_display_string("F1 New F2 PwrOff",1)
    while 1:
        k=key.getch()
        if k>-1:
            if k==265: #do it again! with F1
                mylcd.lcd_clear()
                break
            elif k==266: #shut down with F2
                escape=1
                break
curses.nocbreak()
key.keypad(0)
curses.echo()
curses.endwin()
call("sudo shutdown -h now", shell=True)

The line that I have in /etc/rc.local is as follows if that is important:

sudo python3 journal.py &

and it is followed by the 'exit 0' line. Thanks for any help you can provide. I know this is a very specific problem and will be tedious to reproduce, but if anyone knows anything about autostarting functions I would be very appreciative of any tips.

Upvotes: 2

Views: 814

Answers (2)

chill389cc
chill389cc

Reputation: 432

Ok, literally all I had to do (which I did find after some more research on stackexchange, this is the thread that contained the answer I was looking for) was run my program from ~/.bashrc instead of /etc/rc.local. This method works perfectly, exactly what I wanted.

Upvotes: 1

Ondrej K.
Ondrej K.

Reputation: 9664

This should be because of how you called the program:

python3 journal.py &

You may want to check out JOB CONTROL of bash (or your shell) man page:

Only foreground processes are allowed to read from ... the terminal. Background processes which attempt to read from ... the terminal are sent a SIGTTIN ... signal by the kernel's terminal driver, which, unless caught, suspends the process.

In short, once curses (or anything for that matter) try to read from stdin your process is likely stopped (after it may have already written to your display). Keep it in the foreground to be able to have it use stdin (and by extension keyboard).

Side note: Not sure about distro and details of implementation of rc.local in your case, but aren't init scripts normally run with uid/gid 0 already (without wrapping individual calls through sudo?)

Upvotes: 0

Related Questions