Search code examples
pythonexceptionsignalsalarmlirc

Python LIRC blocking Signal workaround not working


I've been having trouble with the Python LIRC function lirc.nextcode(). I turned off blocking, which allows the code lirc.nextcode() to be skipped if the LIRC queue is empty, by initializing with lirc.init("program", blocking=False) and tried lirc.set_blocking(False, sockid). Neither worked and the code would always hang, waiting for a button press, when it should continue on.

I found this workaround that puts a time limit on raw_input('prompt'). So even if my lirc.nextcodde() waits for a button press, an alarm will go off after 5 seconds if no button has been pressed to deactivate the alarm, and skips the code anyway:

import signal

class AlarmException(Exception):
    pass

def alarmHandler(signum, frame):
    raise AlarmException

def nonBlockingRawInput(prompt='', timeout=20):
    signal.signal(signal.SIGALRM, alarmHandler)
    signal.alarm(timeout)
    try:
        text = raw_input(prompt)
        signal.alarm(0)
        return text
    except AlarmException:
        print '\nPrompt timeout. Continuing...'
    signal.signal(signal.SIGALRM, signal.SIG_IGN)
    return ''

Then changed it to fit my needs:

import signal
import lirc

sockid = lirc.init('weather', blocking=False)

class AlarmException(Exception):
    pass

def alarmHandler(signum, frame):
    raise AlarmException

def nonBlockingRawInput(prompt='', timeout=5):
    signal.signal(signal.SIGALRM, alarmHandler)
    signal.alarm(timeout)
    try:
        text = lirc.nextcode()
        signal.alarm(0)
        print text
        return text
    except AlarmException:
        print '\nPrompt timeout. Continuing...'
    signal.signal(signal.SIGALRM, signal.SIG_IGN)
    print 'timed out'
    return ''


nonBlockingRawInput()

What I want to happen: If a button has been pressed and an IR code is in the LIRC queue, it should print the button that was pressed. If no button has been pressed and the LIRC queue is empty, it should print "Prompt timeout. Continuing..." and "timed out".

What actually happens: If a button has been pressed and an IR code is in the LIRC queue it prints the button, but if no button has been pressed and the queue is empty it hangs until I close it.
It works exactly as intended until I change text = raw_input(prompt) to text = lirc.nextcode(), then it hangs on that function until it closes and gives this error:

Traceback (most recent call last):
  File "/home/pi/time.py", line 27, in <module>
    nonBlockingRawInput()
  File "/home/pi/time.py", line 16, in nonBlockingRawInput
    text = lirc.nextcode()
  File "/home/pi/time.py", line 10, in alarmHandler
    raise AlarmException
__main__.AlarmException

So not only does turning off blocking for lirc.nextcode() not work, but it also prevents the Signal alarm code workaround from continuing as well.

Here is a link "Python Lirc blocks code even when blocking is off" to my original question regarding LIRC blocking, which is what this workaround was for. I'll gladly accept an answer for either.

Thanks ahead of time for any help, it's really appreciated.


Solution

  • Switching to Pylirc2 and using pylirc.blocking(0) fixed it.