Python Lirc即使在禁用阻塞时也会阻塞代码
我正在运行最新的Rasbian Wheeezy发行版,试图在我的Raspberry Pi B+上使用自己的开放天气网络(Open weather Network)设置滚动天气提要,我在使用Python LIRC(Linux红外线遥控器)添加红外支持时遇到问题 我想做什么: 有四个天气变量:条件、温度、湿度和风速。它们将出现在我的16x2 LCD屏幕上,标题在顶行居中,值在第二行居中。它们将在屏幕上停留五秒钟,然后被下一个替换。一旦到达终点,它将再次循环。经过180次循环(大约1小时)后,它将更新天气。我想使用我的红外遥控器的按钮1-4跳转到一个特定的磁贴,然后继续它的循环 它在做什么: 当没有按下按钮时,它不会像关闭LIRC阻塞时那样跳过空队列,而是挂起LIRC.nextcode()等待按下按钮,直到我使用键盘中断退出 在我添加IR之前,一切都很顺利。现在它显示第一个天气变量,然后当它尝试拉取下一个天气变量时,lirc.nextcode()停止代码,直到它收到一个IR代码,而不是在队列中没有IR代码时跳过并转到下一个磁贴,lirc阻塞关闭时不应该发生这种情况 我有所有东西的最新版本(pythonlirc 1.2.1),我知道以前版本的pythonlirc有一个带有阻塞参数的bug。我花了两天时间研究并尝试了所有可能的事情。我发现了一个可能的解决方法,但它受到与此相同的问题的影响:“ 我知道很多代码是不合适的,比如全局变量,函数中需要有东西,每三个小时更新一次,我每一个小时更新一次,但这只是暂时的。我稍后会整理它并使其成为面向对象的。如果这让一些人阅读起来更困难,请提前道歉Python Lirc即使在禁用阻塞时也会阻塞代码,python,linux,raspberry-pi,infrared,lirc,Python,Linux,Raspberry Pi,Infrared,Lirc,我正在运行最新的Rasbian Wheeezy发行版,试图在我的Raspberry Pi B+上使用自己的开放天气网络(Open weather Network)设置滚动天气提要,我在使用Python LIRC(Linux红外线遥控器)添加红外支持时遇到问题 我想做什么: 有四个天气变量:条件、温度、湿度和风速。它们将出现在我的16x2 LCD屏幕上,标题在顶行居中,值在第二行居中。它们将在屏幕上停留五秒钟,然后被下一个替换。一旦到达终点,它将再次循环。经过180次循环(大约1小时)后,它将更新
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,如果没有
按钮已按下,且阻塞已关闭,应跳过
密码。相反,它的行为就像阻塞已打开一样,并一直挂起,直到
按下一个按钮。然后它仍然不会继续我的主循环。信息技术
只需打印下一个并挂起,直到I键盘中断退出
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
我已经添加了我的代码的其余部分,它们都可以正常工作,但我相信它会帮助您理解我试图实现的目标
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()
当我键盘中断退出时,回溯总是导致lirc.nextcode(),我会发布错误,但我稍微更改了代码,现在它只跟踪到包含lirc.nextcode()的函数
我花了两天的时间试图解决这个问题,我几乎要拔头发了,所以我会采取你们能给我的任何解决方案或解决办法。事先谢谢,我真的很感激能找到的任何帮助。我找到了一个解决办法,使用了信号模块AlarmException,但当我从原始输入()切换到lirc.nextcode()时,它也以同样的方式挂起(即使它在原始输入()上设置了计时器,也没有问题),并阻止了警报正常工作。这里又是一个链接:“我想这个bug仍然在1.2.1中。我切换到pyrirc 2,它关闭了阻塞功能pyrirc没有问题。阻塞(0)。我还必须从我的next_tile()函数中删除
return
下面是我最终使用的完成代码,如果有人感兴趣,它肯定会为我节省大量时间:
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()
再看一看。异步/等待语法和使用lirc的非阻塞编程。