智能家居(中)

154 阅读4分钟

4月「掘金·日新计划」第29天

四、守护进程udev

守护智能家居进程(意外退出重启进程)

  1. 生存周期长[非必须],一般操作系统启动的时候就启动,关闭的时候关闭。

  2. 守护进程和终端无关联,也就是他们没有控制终端,所以当控制终端退出,也不会导致守护进程退出

  3. 守护进程是在后台运行,不会占着终端,终端可以执行其他命令

  4. 一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程

  5. 代码演示

    #include <unistd.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <time.h>
    #include <stdio.h>
    #include <stdbool.h>
    static bool flag = true;
    void handler(int sig)
    {
        printf("I got a signal %d\nI'm quitting.\n", sig);
        flag = false;
    }
    int judMent()
    {
        FILE *file;
        char buffer[128] = {'\0'};
        char *cmd = "ps -elf |grep SmartHome|grep -v grep";
        file = popen(cmd, "r");
        fgets(buffer, 128, file);
        if(strstr(buffer, "SmartHome") != NULL){
            return 0;
        }else{
            return -1;
        }
        printf("BUFFER:%s\n",buffer);
    }
    int main()
    {
        time_t t;
        int fd;
        //创建守护进程
        if(-1 == daemon(0, 0)){
            printf("daemon error\n");
            exit(1);
        }
        //设置信号处理函数
        struct sigaction act;
        act.sa_handler = handler;
        sigemptyset(&act.sa_mask);
        act.sa_flags = 0;
        if(sigaction(SIGQUIT, &act, NULL)){
            printf("sigaction error.\n");
            exit(0);
        }
        sleep(30);
        //进程工作内容
        while(flag){
            if( judMent() == -1){
                system("/home/pi/SmartHome &");
            }
            sleep(5);
        }
        return 0;
    }
    

五、监控视频储存

  1. 树莓派摄像头可以使用的2个库

    1. mjpg-streamer(网页显示监视画面)
    2. motion(提供网络摄像头的功能。当拍摄过程中画面发生变动时,Motion可以保存动作发生时的图片和视频)
  2. mjpg-streamer

    1. 开启网页显示监视画面

      1. 运行脚本:MjpgStreamer/mjpg-streamer/mjpg-streamer-experimental/start.sh
    2. 拍照

      1. raspistill -o image.jpg -t 1000

        1. -w, –width : 设置图像宽度 <尺寸> -h, –height : 设置图像高度 <尺寸> -q, –quality : 设置jpeg品质 <0到100> -t, –timeout : 拍照和关闭时的延时指定,未指定时默认是5s,毫秒为单位,1000便表示1秒 -o, –output : 输出文件名 <文件名>,如果要写到stdout,使用-o -,如果不特别指定,图像文件不会被保存 -rot:图像旋转角度,只支持 0、90、180、270 度
      2. wget http://192.168.43.207:8080/?action=snapshot -O ./a.jpg

    3. 视频储存

      1. raspivid -o b.h264 -t 10000 -w 1280 -h 720

        1. 录制一段十秒钟的名为b.h264的视频,且分辨率为1280x720
    4. 转mp4格式

      1. 安装:sudo apt-get install gpac
      2. MP4Box -fps 30 -add b.h264 b.mp4(每秒30帧)

六、遇到的问题和未解决的问题

  1. 驱动部分

    1. 改一个IO,另一个IO也变了(5可以单独改。改4, 5引脚也会变)

      1. 解决:加一个中间变量,直接赋值

      2. 因为寄存器值不一定,所以前面可能是乱的

        1. 例如寄存器的值是10101011101
        2. 要给01重新写入11,但是用|=的话,就会把本来其他值(乱值)也赋进去,造成乱了
  2. 应用层

    1. 给APP传cpu温度和火灾检测,传过去值乱了

      1. 解决:将错就错,增加把数16777216当1用

      2. 因为存在一个字节序问题,树莓派传过去的值大小端就反过来了

        1. app端,字符串可以成功解析出来,int类型解析不出来
        2. 解决方法,要么树莓派端把数反过来在发送,要么APP端将错就错
    2. bind: Address already in use(端口占用

      1. 服务器先退出,下一次启用服务器会端口占用

      2. 解决:

        if(setsockopt(s_fd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int)) < 0){  //解决bind,端口占用问题
            perror("setsockopt");
            goto Sfd;
        }
        
      3. SO_REUSEADDR可以让当前的端口立即重用

        1. 在服务端终止之后,会有一个TIME_WAIT的状态,再次打开会出现:bind的

          但是,服务器端可以尽可能的使用REUSEADDR(在绑定之前尽可能调用setsockopt来设置REUSEADDR)套接字选项,这样就可以使得不必等待TIME_WAIT状态就可以重启服务器了,也就是说:TIME_WAIT状态还是存在的,但是不影响我们重新启动服务器
          
        2. CTRL+C结束时,出现了TIME_WAIT,2-4分钟后释放

        3. CTRL+Z结束时,出现的是ESTABLISHED,永久,除非杀死进程

      4. 原文链接:blog.csdn.net/msdnwolaile…

    3. 摄像头切换功能,需要杀死相应进程

      1. ps -ef | grep 进程名| grep -v grep | grep -v mca |awk '{print $2}' | xargs kill -9

      2. ps -ef 表示查看全格式的全部进程。此处用-A也行:显示所有程序

        grep 是过滤

        grep -v 是反过滤,就是不要把它顾虑出来

        print 是打印

        $2 是第二列,也就是进程的ID

        awk 是对于文件中一行行的独处来执行操作 。

        awk '{print $2}' 是把每一行的第二列(进程ID)打印出来

        | xargs 是将"|" 前面获取到的进程号通过空格分割,传递给kill -9,将这些进程全部杀死 原文链接:blog.csdn.net/u011736532/…

  3. 安卓APP

    1. 内网穿透,粘包

      1. 服务器(树莓派)发送的数据会被当成一个数据发送(粘包)

      2. 客户端(安卓APP)接收数据出错

        1. 解决方法:因为是固定数据大小,所以直接拿到后按字节拆包
  4. 未解决

    1. 在人脸识别的时候,继续输入人脸识别命令会阻塞(在人脸识别完成之前app或uart端无法继续输入)

      1. 解决方法:fork一个进程去等待上一个命令处理完成(无法做到
      2. fork后,互斥锁被复制了2份,不在是同一个锁,导致线程间同步无法完成
    2. 外网访问,手机APP控制会有延迟(控制和灯锁显示都有,控制延迟小点)