即使关闭禁用,Python Lirc也会阻止代码 [英] Python Lirc blocks code even when blocking is off

查看:111
本文介绍了即使关闭禁用,Python Lirc也会阻止代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用运行最新 Rasbian Wheezy 发行版,并且在使用 Python LIRC(Linux红外远程控制)添加IR支持时遇到了问题.

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).

我要做什么: 天气变量有四个:条件,温度,湿度和风速.它们将出现在我的16x2 LCD屏幕上,标题居中,第一行居中.它们将在屏幕上停留五秒钟,然后被下一个替换.一旦到达终点,它将再次循环通过.循环180次(约一小时)后,它将更新天气.我想使用红外遥控器的按钮1-4跳到特定的图块,然后继续循环播放.

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.

正在做什么: 当没有按钮被按下时,它没有挂起 LIRC 那样跳过空队列,而是挂在 lirc.nextcode()上,等待按钮按下,直到我退出了 KeyboardInterrupt .

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.

一切正常,直到我添加IR.现在,它显示第一个天气变量,然后当它尝试拉出下一个天气变量时,如果队列中没有IR代码,则不跳过并转到下一个图块,而 lirc.nextcode()会暂停代码直到它收到IR代码为止,这应该不会在 LIRC 阻止功能关闭的情况下发生.

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.

我拥有所有软件的最新版本( Python LIRC 1.2.1 ),我知道 Python LIRC 的先前版本存在阻塞参数的错误.我花了两天时间研究并尝试所有可能的事情.这是我发现的一种可能的解决方法,但受到与此相同的问题的影响:"

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"

我知道很多代码是不正确的,例如全局变量,某些东西需要包含在函数中,OWN每三个小时更新一次,而我每小时更新一次,但这是暂时的在职的.我将整理它,并在以后使其面向对象.抱歉,如果这样会使某些人更难以阅读.

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

这就是问题所在. Lirc.nextcode()应该提取下一个IR LIRC 队列中的代码,并将其作为列表添加到 codeIR 按下按钮,并且阻止功能已关闭,应该跳过 代码.相反,它的作用就好像阻塞已打开,并挂起直到 按下一个按钮.然后它仍然不会继续我的主循环.它 只需打印 NEXT 并挂起,直到我 KeyboardInterrupt 退出.

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()

当我 KeyboardInterrupt 出局时, Traceback 总是会导致 lirc.nextcode(),我会发布错误,但是我更改了进行一点编码,现在它只能追溯到包含 lirc.nextcode()的函数.

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().

我花了两天时间来解决这个问题,而且我几乎要拔头发了,所以我会采取你们可以给我的任何解决方案或解决方法.在此先感谢您,我非常感谢能找到的任何帮助.我发现使用 Signal Module AlarmException 的解决方法,但是从我从raw_input()切换到lirc.nextcode()的那一刻,它也以相同的方式挂起(即使它在raw_input()上放置了一个计时器也没问题) )并阻止警报正常运行.再次是此链接:" Python LIRC阻止信号变通方法不起作用"

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"

推荐答案

我认为该错误仍在 1.2.1 中.我切换到 Pylirc2 ,它关闭了 pylirc.blocking(0)的所有问题.我还必须从我的 next_tile()函数中删除return.

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()

这篇关于即使关闭禁用,Python Lirc也会阻止代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆