Python Lirc blocks code even when blocking is off
Question: I'm trying to set up a scrolling weather feed using the **OWN (Open Weather
Network**)on my **Raspberry Pi B+** running the latest **Rasbian Wheezy**
distro and I'm having trouble adding IR support using **Python LIRC (Linux
Infrared Remote Control)**.

**_What I'm trying to do:_** There are four weather variables: **condition,
temperature, humidity, and wind speed**. They will appear on my 16x2 LCD
screen, centered with their title on the top line and value on the second.
They will stay on the screen for five seconds before being replaced with the
next. Once it reaches the end it will loop through again. After it has looped
through 180 times (roughly one hour) it will update the weather. I want to use
my IR remote's buttons 1-4 to jump to a specific tile then continue back with
it's loop.

**_What it's doing:_** When no button has been pressed, instead of skipping
the empty queue like it should with **LIRC** blocking off, it hangs on
**lirc.nextcode()** waiting for a button press, until I quit with
**KeyboardInterrupt**.

Everything worked great, until I added IR. Now it displays the first weather
variable, then when it tries to pull the next one, instead of skipping and
going to the next tile if there's no IR code in queue, **lirc.nextcode()**
halts the code until it receives an IR code, which shouldn't happen with
**LIRC** blocking turned off.

I have the latest versions of everything (**Python LIRC 1.2.1**), I know a
previous version of **Python LIRC** had a bug with the blocking parameter.
I've spent two days researching and trying every possible thing. Here is one
possible workaround that I found, but it's affected by the same problem this
one is: _"[Python LIRC blocking Signal workaround not
working](http://stackoverflow.com/questions/26435239/python-lirc-blocking-
signal-workaround-not-working)"_

I know lots of the code is improper, _ie global variables, stuff needs to be
in functions, OWN updates every three hours and I'm updating every hour_ , but
this is temporary to get it working. I'll be tidying it up and making it
object-oriented later. Sorry ahead of time if this makes it more difficult for
some to read.

    
    
    import pyowm
    from sys import exit
    import time
    import RPi.GPIO as GPIO
    from RPLCD import CharLCD, cleared, cursor
    import lirc
    
    # initialize lirc and turn of blocking
    sockid = lirc.init("weather", blocking=False)
    lirc.set_blocking(False, sockid)
    
    # initialize weather network
    owm = pyowm.OWM('API #')
    
    # initialize LCD
    lcd = CharLCD(pin_rs=26, pin_rw=None, pin_e=24, pins_data=[22, 18, 16, 12],
                      cols=16, rows=2)
    
    # weather data
    w = None # wind m/s
    wind = None # wind km/h
    windkm = None
    humidity = None
    temper = None
    COUNTER = 0 #number of cycles before update
    
    NEXT = 1
    
    # switches to next tile
    def next_tile():
        global NEXT
    

This is where the problem lies. **Lirc.nextcode()** should pull the next IR
code from the **LIRC** queue and add it to **codeIR** as a list, but if no
button has been pressed, and blocking is off, it should just skip over the
code. Instead it acts as though blocking is on, and hangs until a button is
pressed. and then it still won't continue my main loop. It just prints
**NEXT** and hangs until I **KeyboardInterrupt** out.

    
    
        codeIR = lirc.nextcode() # pulls IR code from LIRC queue.
        # checks if there's a code in codeIR and goes to that tile. If not, it 
        # goes to the next tile instead.
        if not codeIR: 
            if NEXT != 4: # if it's the last tile, cycle to the first 
                NEXT += 1
                print NEXT
                return NEXT
            else: # if not last tile, go to next
                NEXT -= 3
                print NEXT
                return NEXT
        else:
            NEXT = codeIR[0]
            print NEXT
            return NEXT
    

I've added the rest of my code, it all works fine, but I'm sure it'll help you
understand what I'm trying to accomplish.

    
    
    while True:
        try:
            if COUNTER == 0:
                COUNTER = 180
    
                # Search for current weather in London (UK)
                observation = owm.weather_at_place('City, State')
                w = observation.get_weather()
    
                # Weather details
                wind = w.get_wind()                  # {'speed': 4.6, 'deg': 330}
                windkm = (wind['speed'] * 3600) / 1000 #convet to km/h
                humidity = w.get_humidity() 
                # {'temp_max': 10.5, 'temp': 9.7, 'temp_min': 9.0}
                temper = w.get_temperature('celsius')  
            else:
                while NEXT == 1:
                    # prints condition to lcd
                    lcd.cursor_pos = (0, 4) #adjust cursor position
                    lcd.write_string('Weather') # write to lcd
                    lcd.cursor_pos = (1, 5) # adjust cursor position
                    lcd.write_string(w.get_status()) # write to lcd
                    time.sleep(5) # leave on lcd for 5 seconds
                    lcd.clear() # clear lcd
                    next_tile() # switches to next tile
    
                while NEXT == 2:
                    # prints temp to lcd
                    lcd.cursor_pos = (0, 2)
                    lcd.write_string('Temperature')
                    lcd.cursor_pos = (1, 6)
                    lcd.write_string(str(temper['temp']))
                    lcd.write_string(' C')
                    time.sleep(5)
                    lcd.clear()
                    next_tile()
    
                while NEXT == 3:
                    # prints temp to lcd
                    lcd.cursor_pos = (0, 4)
                    lcd.write_string('Humidity')
                    lcd.cursor_pos = (1, 6)
                    lcd.write_string(str(humidity))
                    lcd.write_string(' %')
                    time.sleep(5)
                    lcd.clear()
                    next_tile()
    
                while NEXT == 4:
                    # prints wind speed to lcd
                    lcd.cursor_pos = (0, 3)
                    lcd.write_string('Wind Speed')
                    lcd.cursor_pos = (1, 6)
                    lcd.write_string(str(int(windkm)))
                    lcd.write_string('km')
                    time.sleep(5)
                    lcd.clear()
                    COUNTER -= 1
                    codeIR = lirc.nextcode()
                    next_tile()
    
        # quit with ctrl+C
        except(KeyboardInterrupt, SystemExit):
            print 'quitting'
            lcd.close(clear=True)
            lirc.deinit()
            exit()
    

When I **KeyboardInterrupt** out, **Traceback** always leads to
**lirc.nextcode()** , I'd post the error, but I changed the code a bit and now
it only traces up to the function that contains **lirc.nextcode()**.

I've spent two days trying to work this out and I'm nearly pulling out my
hair, so I'll take any solution or workaround you guys can give me. Thanks
beforehand, I really appreciate any help I can find. I found a workaround
using a **Signal Module AlarmException** but the moment I switch from
raw_input() to lirc.nextcode() it also hangs the same way (even though it puts
a timer on raw_input() no problem) and blocks the alarm from working right.
Here's the link again: _"[Python LIRC blocking Signal workaround not
working](http://stackoverflow.com/questions/26435239/python-lirc-blocking-
signal-workaround-not-working)"_


Answer: Turns out the bug is still in **1.2.1** I suppose. I switched to **Pylirc2**
and it turned off blocking no problem with **pylirc.blocking(0)**. I also had
to remove the `return`'s from my **next_tile() function**.

Here's the finished code I ended up using if anyone is interested, it sure
would've saved me a load of time:

    
    
    import pyowm
    from sys import exit
    import time
    import RPi.GPIO as GPIO, feedparser, time
    from RPLCD import CharLCD, cleared, cursor
    import pylirc
    
    sockid = pylirc.init('weather')
    allow = pylirc.blocking(0)
    owm = pyowm.OWM('API Key')
    lcd = CharLCD(pin_rs=26, pin_rw=None, pin_e=24, pins_data=[22, 18, 16, 12],
                      cols=16, rows=2)
    
    
    class mail(object):
        def __init__(self):
            self.username = "email address"    
            self.password = "password"
            self.newmail_offset = 0
            self.current = 0
            GPIO.setmode(GPIO.BOARD)
            GPIO.setup(15, GPIO.OUT)
            GPIO.setup(13, GPIO.OUT)
            GPIO.setup(11, GPIO.OUT)
    
        def buzz(self):
            self.period = 1.0 / 250
            self.delay = self.period / 2
            self.cycles = 250
    
            for i in range(self.cycles):
                GPIO.output(11, True)
                time.sleep(self.delay)
    
                GPIO.output(11, False)
                time.sleep(self.delay)
    
        def check(self): 
            self.newmails = int(feedparser.parse("https://" + self.username + ":" + 
                                self.password +"@mail.google.com/gmail/feed/atom")
                                ["feed"]["fullcount"])
    
            if self.newmails > self.newmail_offset:
                GPIO.output(15, True)
                GPIO.output(13, False)
    
                if self.newmails > self.current:
                    self.buzz()
                    self.current += 1    
            else:
                GPIO.output(15, False)
                GPIO.output(13, True)
                self.current = 0
    
    ### will be a class
    class weather(object):
        def __init__(self):
            self.w = None
            self.wind = None
            self.windkm = None
            self.humidity = None
            self.temper = None
            self.counter = 0
            self.next = 1
    
        def update(self):
            if self.counter == 0:
                self.counter = 180
                self.observation = owm.weather_at_place('City, Country')
                self.w = self.observation.get_weather()
                self.wind = self.w.get_wind()
                self.windkm = (self.wind['speed'] * 3600) / 1000
                self.humidity = self.w.get_humidity()
                self.temper = self.w.get_temperature('celsius')
            else:
                pass
    
        def display_weather(self):
            lcd.cursor_pos = (0, 4)
            lcd.write_string('Weather')
            lcd.cursor_pos = (1, 5)
            lcd.write_string(self.w.get_status())
            time.sleep(3)
            lcd.clear()
    
        def display_temp(self):
            lcd.cursor_pos = (0, 2)
            lcd.write_string('Temperature')
            lcd.cursor_pos = (1, 6)
            lcd.write_string(str(self.temper['temp']))
            lcd.write_string(' C')
            time.sleep(3)
            lcd.clear()
    
        def display_hum(self):
            lcd.cursor_pos = (0, 4)
            lcd.write_string('Humidity')
            lcd.cursor_pos = (1, 6)
            lcd.write_string(str(self.humidity))
            lcd.write_string(' %')
            time.sleep(3)
            lcd.clear()
    
        def display_wind(self):
            lcd.cursor_pos = (0, 3)
            lcd.write_string('Wind Speed')
            lcd.cursor_pos = (1, 4)
            lcd.write_string(str(int(self.windkm)))
            lcd.write_string('km/h')
            time.sleep(3)
            lcd.clear()
    
        def next_tile(self):
            self.counter -= 1
            self.codeIR = pylirc.nextcode()
            if  not self.codeIR or self.codeIR[0] == self.next: 
                if self.next != 4:
                    self.next += 1
                else:
                    self.next -= 3
            else:
                self.next = int(self.codeIR[0])
    
    email = mail()
    weather = weather()
    weather.update()
    def up_next():
        weather.update()
        weather.next_tile()
    
    while True:
        try:
            while weather.next == 1:
                weather.display_weather()
                up_next()
    
            while weather.next == 2:
                weather.display_temp()
                up_next()
    
            while weather.next == 3:
                weather.display_hum()
                up_next()
    
            while weather.next == 4:
                weather.display_wind()
                email.check()
                up_next()
    
        except(KeyboardInterrupt, SystemExit):
            print 'quitting'
            lcd.close(clear=True)
            exit()
    

