树莓派WiFi无线电脚本问题

3 投票
4 回答
668 浏览
提问于 2025-04-18 18:08

我遇到了一个问题,由于我对Python了解不多,希望能有人帮我理解我的问题所在。

我正在制作一个便携式无线电。我的树莓派使用Pianobar去连接Pandora的服务器,登录我的账户,获取我的电台,然后开始播放第一个电台。

我在按照Adafruit的官方指南进行操作:https://learn.adafruit.com/pi-wifi-radio/overview

我一直按照指南进行,直到Pianobar可以正常工作为止。我可以在命令行中运行“pianobar”,它连接后不到10秒就开始播放音乐。

但是,当我启动那个让16x2 LCD键盘与Pianobar连接的脚本时,它却不工作。

更具体地说,脚本的前半部分是可以运行的。LCD显示了IP地址,并显示“正在获取电台列表...”。但过了10秒后,脚本就退出了,显示了这些内容。

pi@pandora ~/Python-WiFi-Radio $ sudo python PiPhi.py

Spawning pianobar...
Receiving station list...
Traceback (most recent call last):
  File "PiPhi.py", line 288, in <module>
    stationList, stationIDs = getStations()
  File "PiPhi.py", line 190, in getStations
    pianobar.expect('Select station: ', timeout=10)
  File "/usr/local/lib/python2.7/dist-packages/pexpect.py", line 1311, in expect
    return self.expect_list(compiled_pattern_list, timeout, searchwindowsize)
  File "/usr/local/lib/python2.7/dist-packages/pexpect.py", line 1325, in expect_list
    return self.expect_loop(searcher_re(pattern_list), timeout, searchwindowsize)
  File "/usr/local/lib/python2.7/dist-packages/pexpect.py", line 1409, in expect_loop
    raise TIMEOUT (str(e) + '\n' + str(self))
pexpect.TIMEOUT: Timeout exceeded in read_nonblocking().
<pexpect.spawn object at 0xb6b305b0>
version: 2.3 ($Revision: 399 $)
command: /usr/bin/sudo
args: ['/usr/bin/sudo', '-u', 'pi', 'pianobar']
searcher: searcher_re:
    0: re.compile("Select station: ")
TIME: -03:35/03:43
TIME: -03:35/03:43
after: <class 'pexpect.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 2315
child_fd: 5
closed: False
timeout: 30
delimiter: <class 'pexpect.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1

pi@pandora ~/Python-WiFi-Radio $ 

http://pastebin.com/6Lm3dTwx - 这是我尝试运行的脚本

根据我基本的知识,似乎是获取电台列表的时间超过了某个超时限制。请帮帮我,我完全搞不懂。谢谢!

4 个回答

0

我知道这个问题已经有点久了,但我最近也遇到了同样的问题。我发现如果在

pianobar.send('s')

之前执行以下命令

pianobar.expect('Select station: ', timeout=20)

就能强制 pianobar 更新电台列表。

0

这里可能有两个问题。我在启动这个程序时遇到了困难。这表现为在 pianobar.excect 中出现了一个 EOF 错误,错误信息是 'Get stations...Ok.\r\n'。为了了解发生了什么,可以处理这个 EOF 异常,并打印出 pianobar.before 的内容:

# Launch pianobar as pi user (to use same config data, etc.) in background:
print('Spawning pianobar...')
pianobar = pexpect.spawn('sudo -u pi /home/pi/pianobar/pianobar', timeout=60)
print('Receiving station list...')
expectIdx = pianobar.expect(['Get stations... Ok.\r\n', pexpect.EOF, pexpect.TIMEOUT])
if expectIdx == 0:
    stationList, stationIDs = getStations()
    try:    # Use station name from last session
        stationNum = stationList.index(defaultStation)
    except: # Use first station in list
        stationNum = 0
    print 'Selecting station ' + stationIDs[stationNum]
    pianobar.sendline(stationIDs[stationNum])
elif expectIdx == 1: # EOF
    print 'pianobar.expect EOF error'
    print pianobar.before # shows response from pianobar spawn
    pianobar.kill(0)
elif expectIdx == 2: # TIMEOUT
    print 'pianobar.expect TIMEOUT error'
    pianobar.kill(0)

我通过指定 pianobar 的完整路径解决了我的问题(如上所示)。

第二个问题可能是因为你在 pianobar 的配置中有一个有效的默认电台。如果是这样的话,启动时不会显示选择电台的列表,你需要手动请求这个列表。这个错误出现在 getStations() 的 pianobar.expect 中。我通过在初始请求超时时请求电台列表来解决这个问题:

    expectIdx = pianobar.expect(['Select station: ', pexpect.EOF, pexpect.TIMEOUT], timeout=10)
    if expectIdx == 1: # EOF
        print 'pianobar.expect EOF error at getStations'
        print pianobar.before # shows response from pianobar spawn
        pianobar.kill(0)
    elif expectIdx == 2: # TIMEOUT
        # try requesting the station list
        pianobar.send('s')
        pianobar.expect('Select station', timeout=10)
0

我发现“pi”这个用户ID在PiPhi.py文件里是写死的!修改第33行(PICKLEFILE)和第286行(pepect.spawn('sudo -u pi...)解决了我的问题。

希望这能帮到你们……

0

我也遇到过同样的问题。为了简单解决,我在启动脚本里让系统向谷歌发送了10次请求。这样做给了系统足够的时间来稳定网络连接。

撰写回答