树莓派做遥控豆瓣播放器(1)

Step 1, 红外设置

树莓派B+的红外设置网上很多,简单来说就是通过ssh连接到树莓派之后,进行执行以下命令:“apt-get install lirc”. 如果一切顺利,那么这个时候可以参照之前的博客,树莓派 红外接收 RPi2 gpio chip not found lirc_rpi。如果和我一样不幸遇到无法检测到红外设备的情况,也可以参照之前的博客进行troubleshooting。
当你成功录制按键之后,接下来需要的是配置lircrc, 目录是在/etc/lirc/lircrc 。这个文件的目的就是让红外lirc后台程序运行时候,接收到每个按键会触发什么行为。这个配置文件的编写占据了比较大的effort。现附上我的配置文件,再进行详细解释。

begin
    prog = irexec
    button = stop
    repeat = 2
    delay = 2
    config = /root/douban_fm/fifowrite.exe q
end

begin
    prog = irexec
    button = mute
    config = /root/douban_fm/fifowrite.exe m
end

begin
    prog = irexec
    button = next
    config = /root/douban_fm/fifowrite.exe n
end

begin
    prog = irexec
    button = pause
    config = /root/douban_fm/fifowrite.exe p
end

begin
    prog = irexec
    button = volume_up
    config = /root/douban_fm/fifowrite.exe o
end

begin
    prog = irexec
    button = volume_down
    config = /root/douban_fm/fifowrite.exe i
end

begin
    prog = irexec
    button = power
    repeat = 2 
    delay = 2 
    config = sudo sh /root/douban_fm/start_douban.sh
end

在这个配置文件中,比较重要的有三个部分:

1)fifowrite.exe

这个文件是用来和播放豆瓣的主程序进行通信的程序。将command写入一个pipe文件中,然后播放主程序再通过一个fiforead.exe 程序进行读取。涉及到的按键就是音量增,音量减,暂停,切歌,静音以及退出。

fiforead.c

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

int main()
{
    const char *fifo_name = "/root/douban_fm/my_fifo";
    int pipe_fd = -1;
    int data_fd = -1;
    int res = 0;
    const int open_mode = O_RDONLY;
    char buffer[2];
    int bytes_read = 0;
    int bytes_write = 0;

    memset(buffer, '\0', sizeof(buffer));

//    printf("Process %d opening FIFO O_RDINLY\n", getpid());
    pipe_fd = open(fifo_name, open_mode);
//    data_fd = open("DataFormFIFO.txt", O_WRONLY|O_CREAT, 0644);
//    printf("Process %d result %d\n", getpid(), pipe_fd);

    if(pipe_fd != -1)
    {
        do
        {
            res = read(pipe_fd, buffer, 1);
            if(res <= 0)
                break;
            printf("%s\n", buffer);
//            bytes_write = write(data_fd, buffer, res);
            bytes_read += res;
        }while(res > 0);
        close(pipe_fd);
//        close(data_fd);
    }
    else
        exit(EXIT_FAILURE);

//    printf("Process %d finished, %d bytes read\n", getpid(), bytes_read);
    exit(EXIT_SUCCESS);
}

fifowrite.c

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
    const char *fifo_name = "/root/douban_fm/my_fifo";
    int pipe_fd = -1;
    int data_fd = -1;
    int res = 0;
    const int open_mode = O_WRONLY;
    int bytes_sent = 0;
    char buffer[2];

    if(access(fifo_name, F_OK)==-1)
    {
        //PIPE file not exist
        //Create it
        res = mkfifo(fifo_name, 0777);
        if(res != 0)
        {
            fprintf(stderr, "Could not creat fifo %s\n", fifo_name);
            exit(EXIT_FAILURE);
        }
    }

//    printf("Process %d opening FIFO O_WRONLY\n", getpid());

    pipe_fd = open(fifo_name, open_mode);
//    data_fd = open("Data.txt", O_RDONLY);
//    printf("Process %d result %d\n", getpid(), pipe_fd);
    if(pipe_fd != -1)
    {
//        int bytes_read = 0;
//        bytes_read = read(data_fd, buffer, PIPE_BUF);
        buffer[0] = *argv[1];
        buffer[1] = '\0';
        res = write(pipe_fd, buffer, 1);
/*        while(bytes_read > 0)
        {
            res = write(pipe_fd, buffer, bytes_read);
            if(res == -1)
            {
                fprintf(stderr, "Write err on pipe\n");
                exit(EXIT_FAILURE);
            }
            bytes_sent +=res;
            bytes_read = read(data_fd, buffer, PIPE_BUF);
            buffer[bytes_read] = '\0';
        }*/
        close(pipe_fd);
//        close(data_fd);
    }
    else
        exit(EXIT_FAILURE);

//    printf("Process %d finished\n", getpid());
    exit(EXIT_SUCCESS);
}

把这两段代码在树莓派中分别创建两个.c 文件之后,执行命令:
gcc -o ./fifowrite.exe fifowrite.c -lm
gcc -o ./fiforead.exe fiforead.c -lm
这样控制程序的命令就可以通过这段文件共享了。

2)start_douban.sh

这段shell做的工作就是在起进程之前先检查系统中是否已经有播放程序在执行了。如果没有就把程序起起来,如果有就退出。

#!/bin/bash

num=`ps aux|grep /root/douban_fm/play_douban.py|grep -v "grep"|wc -l`
if test $num -eq 0 ; 
then
    aplay /usr/share/scratch/Media/Sounds/Effects/Bubbles.wav 
    nohup /root/douban_fm/play_douban.py >> /root/mlog/douban_fm.log &
else
    exit
fi

在实际过程中遇到的问题是有可能遇到连击或者红外信号的连续发送导致在同一时间起了多个这样的脚本,还是会导致多个播放程序在后台启动。一开始的解决方案是在shell中生成随机数,让其sleep几秒钟,由于sleep时间是随机的,也就可以保证同时起的shell都会启动播放程序。可参见Linux 实现随机数多种方法。本人亲测通过时间的方法获取随机数不成。之后的方法也没有进行尝试。这个问题究其根本就是红外读取信号的时候会在短时间内重复获取信号。
这就是配置文件中第三部分要注意的。

3) repeat = 2 delay = 2

repeat 和delay的含义可以参见官方文档lircrc 配置文件详解
repeat
告诉程序如果key重复按键之后应该做什么,如果设置成2 就是连按两下会出发什么动作。当默认是0的时候就会忽略重复按键。

好了,现在基本的外围设置已经完成。接下来就是需要进行豆瓣播放程序的开发。详见下一篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值