11.【Orangepi Zero2】基于Linux的智能垃圾桶项目

基于Linux的垃圾分类项目

功能需求

  • 语音接入控制垃圾分类识别,并触发垃圾桶的开关盖

  • 回顾二阶段的Socket编程,实现Sockect发送指令远程控制垃圾分类识别,并触发垃圾桶的开关盖

  • 图像识别垃圾分类功能

  • 语音播报垃圾物品类型

  • OLED显示垃圾物品类型

  • 根据垃圾类型开关不同类型垃圾桶

图像处理使用阿里SDK支持Python和Java接口,目的是引入C语言的Python调用,感受大厂做的算法bug。

此接口是人工智能接口,阿里云识别模型是通过训练后的模型,精准度取决于训练程度,人工智能范畴 在常规嵌入式设备负责执行居多。

说白的嵌入式设备负责数据采集,然后转发给人工智能识别后,拿到结果进行执行器动作。

阿里云垃圾识别方案

接入阿里云

在垃圾分类的项目中,我们采用阿里云视觉智能开发平台的接口来做垃圾分类的识别方案,通过上传 本地的拍照下的垃圾图片,通过阿里提供的接口来识别出该垃圾是干垃圾、湿垃圾、回收垃圾还是有害 垃圾。

对应官网地址如下:

https://vision.aliyun.com/

然后在上面的输入框输入“垃圾分类”:

在这里插入图片描述

可以跳转到对应的垃圾分类的“免费开通"和”技术文档页面“:

能力展示-阿里云视觉智能开放平台 (aliyun.com)

在这里插入图片描述

可以先选择"技术文档"查看下使用方法:

在这里插入图片描述

根据上面描述的指引,蓝色为可点进去的详细说明,完成注册及运行环境的搭建。

重点:

  1. 开通阿里云账号及图像识别服务,用自己支付宝即可开通。
  2. 创建并获取AccessKey ID和Secret。
  3. 在Linux或开发板上安装所需的SDK。
  4. 根据示例代码进行修改垃圾分类识别。
  5. 选择免费开通,通过自己的支付宝或者账号登录即可。

在这里插入图片描述

在这里插入图片描述

  1. 登录完成后,即可在产品控制台->点击获取Acce Token获取 对应的AccessKey ID和AccessKey Secret

当然,在第一次获取到AccessKey ID和AccessKey Secret,需要点击创建AccessKey, 然后最好把 AccessKey.csv下载下来备份,不然会找不到AccessKey Secret就需要重新创建。

在这里插入图片描述

  1. 在ubuntu 22.04或者众志开发板(orangepi 3.0.6)上安装图像识别(imagerecog)SDK
sudo apt install python3-pip
pip3 install alibabacloud_imagerecog20190930 
  1. 同时配置Linux环境,根据自己实际的ACCESS_KEY_ID和ACCESS_KEY_SECRET,下面的两行写入到家目 录下的.bashrc中:
export ALIBABA_CLOUD_ACCESS_KEY_ID=“你的ID” #根据自己实际的ID填写
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="你的SECRET" #根据自己实际的SECRET填写
vi ~/.bashrc 和 /etc/profile #然后在末尾输入上面两行后保存

在这里插入图片描述

  1. 然后退出终端重新登录下,此时再执行export,能看到这两个Key的存在。

在这里插入图片描述

  1. 抄袭”文件在本地或文件不在同一地域OSS“示例代码,命名为rubbish.py。

在这里插入图片描述

  1. 同时将场景二注释,场景一代码打开,并输入自己测试图片的路径,如下:
rubbish.py
# -*- coding: utf-8 -*-
# 引入依赖包
# pip install alibabacloud_imagerecog20190930

import os
import io
from urllib.request import urlopen
from alibabacloud_imagerecog20190930.client import Client
from alibabacloud_imagerecog20190930.models import ClassifyingRubbishAdvanceRequest
from alibabacloud_tea_openapi.models import Config
from alibabacloud_tea_util.models import RuntimeOptions

config = Config(
  # 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。
  # 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html
  # 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。
  access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
  access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
  # 访问的域名
  endpoint='imagerecog.cn-shanghai.aliyuncs.com',
  # 访问的域名对应的region
  region_id='cn-shanghai'
)

def alicloud_classify_Rubbish():
	#场景一:文件在本地
    img = open(r'/home/orangepi/Project/rubbish/test.jpg', 'rb')
    #场景二:使用任意可访问的url
    #url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/imagerecog/ClassifyingRubbish/ClassifyingRubbish1.jpg'
    #img = io.BytesIO(urlopen(url).read())
    classifying_rubbish_request = ClassifyingRubbishAdvanceRequest()
    classifying_rubbish_request.image_urlobject = img
    runtime = RuntimeOptions()
    try:
       # 初始化Client
       client = Client(config)
       response = client.classifying_rubbish_advance(classifying_rubbish_request, runtime)
       # 获取整体结果
       print(response.body)
       return response.body.to_map()['Data']['Elements'][0]['Category']
    except Exception as error:
       # 获取整体报错信息
       print(error)
       # 获取单个字段
       print(error.code)
    
if __name__ == "__main__":
    alicloud_classify_Rubbish()

其中 "/home/orangepi/Project/rubbish/test.jpg" 为本地测试用图片(根据在线文档要求:图像类型:JPEG、JPG、PNG,图像大小:不大于3 MB,图像分辨率:不限制图像分辨率,但图像分辨率太高可能会导致API识别超时,超时时间为5秒) 测试图片如下:

在这里插入图片描述

然后用 python3 rubbish.py 命令测试运行:

orangepi@orangepizero2:~/Project/rubbish$ python3 rubbish.py
{'Data': {'Elements': [{'Category': '干垃圾', 'CategoryScore': 0.9020999999999999, 'Rubbish': '', 'RubbishScore': 0.0}], 'Sensitive': False}, 'RequestId': '75252D93-CF27-59CB-90A9-5F66D5D929BF'}

在这里插入图片描述

如上,测试成功,说明阿里云垃圾分类方案对接成功。

C语言调用阿里云Python接口

rubbish.py

采用上面的代码。

rubbish.c

参照有参python函数的做法, 实封装并现以下代码(rubbish.c):

#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void rubbish_Init(void)
{
    Py_Initialize();
    
    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString("."));
}

void rubbish_Finalize(void)
{
    Py_Finalize();
}

char *alicloud_rubbish_category(char *category)
{
    PyObject *pModule = PyImport_ImportModule("rubbish");
    if (!pModule)
    {
        PyErr_Print();
        printf("Error: failed to load rubbish.py\n");
        goto FAILED_MODULE;
    }
    
    PyObject *pFunc = PyObject_GetAttrString(pModule, "alicloud_classify_Rubbish");
    if (!pFunc)
    {
        PyErr_Print();
        printf("Error: failed to load classify_Rubbish\n");
        goto FAILED_FUNC;
    }
		
    PyObject *pValue = PyObject_CallObject(pFunc, NULL);
	if (!pValue)
    {
        PyErr_Print();
        printf("Error: function call failed\n");
        goto FAILED_VALUE;
    }
		
	char *result = NULL;
	if(!PyArg_Parse(pValue, "s", &result))
    {
        PyErr_Print();
        printf("Error: parse failed\n");
        goto FAILED_RESULT;
    }
    
    category = (char *)malloc(sizeof(char) * (strlen(result) + 1));
    memset(category, '\0', (strlen(result) + 1));
    strncpy(category, result, (strlen(result) + 1));
    
FAILED_RESULT:
    Py_DECREF(pValue);
FAILED_VALUE:
    Py_DECREF(pFunc);
FAILED_FUNC:
    Py_DECREF(pModule);
FAILED_MODULE:
    return category;
}

rubbish.h

头文件(rubbish.h)如下:

#ifndef _RUBBISH_H

#define _RUBBISH_H

void rubbish_Init(void);

void rubbish_Finalize(void);

char *alicloud_rubbish_category(char *category);

#endif

main.c

测试代码(main.c)如下:

#include <stdio.h>
#include <stdlib.h>
#include "rubbish.h"

int main()
{
    char *category = NULL;
 
    garbage_init();
 	category  = rubbish_category(category);
 	printf("category=%s\n", category);
 	rubbish_Finalize();
 
    free(category);
 	return 0;
}

然要编译和运行这个程序,可以使用以下命令(假设使用的是gcc编译器和Python 3.10版本):

gcc -o rubbish main.c rubbish.c rubbish.h -I /usr/include/python3.10/ -lpython3.10 ./garbagetest

输出:

category=干垃圾

香橙派使用摄像头

详细可参考《OrangePi_Zero2_H616用户手册v4.0.pdf》 中的3.13.6 USB摄像头测试章节。

语音模块配置

在这里插入图片描述

进入语音模块官网http://www.smartpi.cn/#/,配置词条和识别后的串口输入输出指令,如下:

Pin引脚配置:

在这里插入图片描述

唤醒词定义:

在这里插入图片描述

控制详情:

在这里插入图片描述

语音模块和阿里云结合

环境准备

将语音模块接在UART5的位置。

在这里插入图片描述

在orange pi 3.0.6上确认已经配置开启了uart5:(overlays=uart5)

orangepi@orangepizero2:~/garbage$ cat /boot/orangepiEnv.txt
verbosity=1
bootlogo=false
console=both
disp_mode=1920x1080p60
overlay_prefix=sun50i-h616
rootdev=UUID=15a0010c-94e1-412f-b030-199e90c16cb1
rootfstype=ext4
overlays=uart5 i2c3
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u

同时将USB摄像头接到香橙派上,确认已经运行了mjpg-streamer服务

orangepi@orangepizero2:~/garbage$ ps ax | grep mjpg

rubbish.py

同上

加入mySerial.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

int my_serialOpen (const char *device, const int baud)
{
  struct termios options ;
  speed_t myBaud ;
  int     status, fd ;

  	switch (baud)
  	{
    	case    9600:	myBaud =    B9600 ; break ;
    	case  115200:	myBaud =  B115200 ; break ;

    	default:
      	return -2 ;
  	}

  	if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
    return -1 ;

  	fcntl (fd, F_SETFL, O_RDWR) ;

// Get and modify current options:

  	tcgetattr (fd, &options) ;

    cfmakeraw   (&options) ;
    cfsetispeed (&options, myBaud) ;
    cfsetospeed (&options, myBaud) ;

    options.c_cflag |= (CLOCAL | CREAD) ;
    options.c_cflag &= ~PARENB ;
    options.c_cflag &= ~CSTOPB ;
    options.c_cflag &= ~CSIZE ;
    options.c_cflag |= CS8 ;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
    options.c_oflag &= ~OPOST ;

    options.c_cc [VMIN]  =   0 ;
    options.c_cc [VTIME] = 100 ;	// Ten seconds (100 deciseconds)

  	tcsetattr (fd, TCSANOW, &options) ;

  	ioctl (fd, TIOCMGET, &status);

  	status |= TIOCM_DTR ;
  	status |= TIOCM_RTS ;

  	ioctl (fd, TIOCMSET, &status);

  	usleep (10000) ;	// 10mS

 	return fd ;
}

void my_serialPuts(const int fd, const char *s, int len)
{
	int n_write = write(fd, s, len);

	if(n_write == -1)
	{
		perror("write");

		exit(-1);
	}

}

int my_serialGets(const int fd, unsigned char *buffer)
{
	int n_read = read(fd, buffer, 32);
	if(n_read == -1)
	{
		perror("read");

		exit(-1);
	}

	return n_read;
}

char* serialGetchar (const int fd)
{
	char *x;

  	if (read (fd, x, 1) != 1)
    exit(-1);

  	return x;
}

mySerial.h

#ifndef _MYSERIAL_H_
#define _MYSERIAL_H_

#define SERIAL_DEV "/dev/ttyS5"
#define BAUD 115200

int my_serialOpen (const char *device, const int baud);

void my_serialPuts(const int fd, unsigned char *s, int len);

int my_serialGets(const int fd, const char *buffer);

char* serialGetchar(const int fd);

#endif

rubbish.c

#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void rubbish_Init(void)
{
    Py_Initialize();
    
    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString("."));
}

void rubbish_Finalize(void)
{
    Py_Finalize();
}

char *alicloud_rubbish_category(char *category)
{
    PyObject *pModule = PyImport_ImportModule("rubbish");
    if (!pModule)
    {
        PyErr_Print();
        printf("Error: failed to load rubbish.py\n");
        goto FAILED_MODULE;
    }
    
    PyObject *pFunc = PyObject_GetAttrString(pModule, "alicloud_classify_Rubbish");
    if (!pFunc)
    {
        PyErr_Print();
        printf("Error: failed to load classify_Rubbish\n");
        goto FAILED_FUNC;
    }
		
    PyObject *pValue = PyObject_CallObject(pFunc, NULL);
	if (!pValue)
    {
        PyErr_Print();
        printf("Error: function call failed\n");
        goto FAILED_VALUE;
    }
		
	char *result = NULL;
	if(!PyArg_Parse(pValue, "s", &result))
    {
        PyErr_Print();
        printf("Error: parse failed\n");
        goto FAILED_RESULT;
    }
    
    category = (char *)malloc(sizeof(char) * (strlen(result) + 1));
    memset(category, '\0', (strlen(result) + 1));
    strncpy(category, result, (strlen(result) + 1));
    
FAILED_RESULT:
    Py_DECREF(pValue);
FAILED_VALUE:
    Py_DECREF(pFunc);
FAILED_FUNC:
    Py_DECREF(pModule);
FAILED_MODULE:
    return category;
}

rubbish.h

#ifndef _RUBBISH_H

#define _RUBBISH_H

#define WGET_CMD "wget http://127.0.0.1:8080/?action=snapshot -O /home/orangepi/Project/rubbish/rubbish.jpg"

#define RUBBISH_FILE "/home/orangepi/Project/rubbish/rubbish.jpg"

void rubbish_Init(void);

void rubbish_Finalize(void);

char *alicloud_rubbish_category(char *category);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>           /* Definition of AT_* constants */
#include <unistd.h>
#include "rubbish.h"
#include "mySerial.h"

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

int main()
{
    int len = -1;
    int serial_fd = -1;
    int result_detect_process = -1;
    char *category = NULL;
    char *ret_strstr = (char *)malloc(1024);
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};

    rubbish_Init();
    
    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
            buffer[2] = 0x00;
            system(WGET_CMD);

            printf("------------------------------------\n");
            if(access(RUBBISH_FILE, F_OK) == 0)
            {   
                printf("====================================\n");
                category = alicloud_rubbish_category(category);
                printf("category = %s\n", category);

                if(strstr(category, "干垃圾") != NULL)
                {
                    buffer[2] = 0x41;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "湿垃圾"))
                {
                    buffer[2] = 0x42;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "可回收垃圾"))
                {
                    buffer[2] = 0x43;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "有害垃圾"))
                {
                    buffer[2] = 0x44;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else
                {
                    buffer[2] = 0x45;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }
                //printf("ret_strstr = %s\n", ret_strstr);
            }
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }

            my_serialPuts(serial_fd, buffer, 6);
            buffer[2] = 0x00;
            remove(RUBBISH_FILE);
        }
    }

END:
    rubbish_Finalize();
    return 0;
}

增加垃圾桶及开关盖功能

实现功能:使用语音模块和摄像头在香橙派上做垃圾智能分类识别, 同时根据识别结果开关不同的垃圾桶的盖子。

环境准备

在这里插入图片描述

流程图

flowchart LR
    B(开始)
    B --> C[阿里云Python接口初始化]
    C --> D[香橙派 串口初始化]
    D --> E{判断是否打开失败}
    E --> F[香橙派读取语音模块数据]
    F --> G{是否读取到语晋模块AA 5546 00 55 AA数据}
    G --> |是| H[香橙派拍照]
    G --> |否| F[香橙派读取语音模块数据]
    H --> I{判断./rubbish.jpg文件是否存在}
    I --> |是| J{执行阿里云垃圾分类接口}
    I --> |否| K[写对应的AA 55 45 00 55 AA 串口数据给语音模块 语音摄报]
    J --> |是| L[写对应的AA 55 4* 00 55 AA 串口数据给语音模块,语音播报]
    J --> |否| F[香橙派读取语音模块数据]
    K --> F[香橙派读取语音模块数据]
    L --> F[香橙派读取语音模块数据]

在这里插入图片描述

pwm.c

#include <wiringPi.h>
#include <softPwm.h>

void pwm_write(int pwm_pin)
{
    pinMode(pwm_pin, OUTPUT);
    softPwmCreate(pwm_pin, 0, 200);
    softPwmWrite(pwm_pin, 25);
    delay(1000);
    softPwmStop(pwm_pin);
}

void pwm_stop(int pwm_pin)
{
    pinMode(pwm_pin, OUTPUT);
    softPwmCreate(pwm_pin, 0, 200);
    softPwmWrite(pwm_pin, 5);
    delay(1000);
    softPwmStop(pwm_pin);
}

pwm.h

#ifndef _PWM_H_
#define _PWM_H_

#define PWM_OTHER_RUBBISH       7
#define PWM_RECOVERABLE_RUBBISH 5

void pwm_write(int pwm_pin);

void pwm_stop(int pwm_pin);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <wiringPi.h>
#include "rubbish.h"
#include "mySerial.h"
#include "pwm.h"

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

int main()
{
    int len = -1;
    int serial_fd = -1;
    int result_detect_process = -1;
    char *category = NULL;
    char *ret_strstr = (char *)malloc(1024);
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};

    rubbish_Init();
    if (wiringPiSetup() == -1)
    {
        exit(1);
    }

    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
            buffer[2] = 0x00;
            system(WGET_CMD);

            printf("------------------------------------\n");
            if(access(RUBBISH_FILE, F_OK) == 0)
            {   
                printf("====================================\n");
                category = alicloud_rubbish_category(category);
                printf("category = %s\n", category);

                if(strstr(category, "干垃圾") != NULL)
                {
                    buffer[2] = 0x41;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "湿垃圾"))
                {
                    buffer[2] = 0x42;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "可回收垃圾"))
                {
                    buffer[2] = 0x43;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "有害垃圾"))
                {
                    buffer[2] = 0x44;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else
                {
                    buffer[2] = 0x45;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }
                //printf("ret_strstr = %s\n", ret_strstr);
            }
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }

            my_serialPuts(serial_fd, buffer, 6);

            if(buffer[2] == 0x43)
            {
                pwm_write(PWM_RECOVERABLE_RUBBISH);
                delay(2300);
                pwm_stop(PWM_RECOVERABLE_RUBBISH);
            }
            else if(buffer[2] != 0x45)
            {
                pwm_write(PWM_OTHER_RUBBISH);
                delay(2300);
                pwm_stop(PWM_OTHER_RUBBISH);
            }

            buffer[2] = 0x00;
            remove(RUBBISH_FILE);
        }
    }

END:
    rubbish_Finalize();
    return 0;
}

项目代码优化

在之前实现的代码中, 主函数是单线程执行的, 导致整个代码的可扩展性非常差,比如想加OLED显示 或者添加网络控制变得非常复杂, 而且执行一次识别开关盖的流程非常长。因此,调整下代码架构,增加并发功能、提升代码的可扩展性 和执行效率。

流程图

开始
阿里云Python接口初始化
串口初始化
香橙派读取语音模块数据线程
阿里云交互线程
网络线程
判断是否读取到语音模块AA 55 46 00 55 AA 数据
发送线程信号给阿里云交互线程
判断是否接收到线程信号
拍照
执行阿里云垃圾识别接口
垃圾桶开盖线程
语音播报垃圾类型线程
OLED显示线程
判断Sever是否接收到来自Client的open字符串

main.c

修改 main.c 代码,调整整体 main 函数的代码架构,利用多线程实现具体的功能(用到了线程里的条件变量控制线程间的数据同步)如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <wiringPi.h>
#include "rubbish.h"
#include "mySerial.h"
#include "pwm.h"

int len = -1;
int serial_fd = -1;
pthread_mutex_t mutex;
pthread_cond_t  cond;

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

void* send_voice(void *arg)
{
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;

    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(NULL != buffer)
    {
        my_serialPuts(serial_fd, buffer, 6);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* trash_can(void *arg)
{
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;
    
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(buffer[2] == 0x43)
    {
        pwm_write(PWM_RECOVERABLE_RUBBISH);
        delay(2300);
        pwm_stop(PWM_RECOVERABLE_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }
    else if(buffer[2] != 0x45)
    {
        pwm_write(PWM_OTHER_RUBBISH);
        delay(2300);
        pwm_stop(PWM_OTHER_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* get_voice()
{   

    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
//            system(WGET_CMD);
            pthread_mutex_lock(&mutex);
            buffer[2] = 0x00;
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
        }
    }
    pthread_exit(0);
}

void* get_category()
{
    char *category = NULL;
    pthread_t send_voice_tid;
    pthread_t trash_can_tid;
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    
    while(1)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);
        pthread_mutex_unlock(&mutex);
        
        buffer[2] = 0x00;
        system(WGET_CMD);
        
        if(access(RUBBISH_FILE, F_OK) == 0)
        {   
            category = alicloud_rubbish_category(category);
            printf("category = %s\n", category);
        
            if(strstr(category, "干垃圾") != NULL)
            {
                buffer[2] = 0x41;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "湿垃圾"))
            {
                buffer[2] = 0x42;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "可回收垃圾"))
            {
                buffer[2] = 0x43;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "有害垃圾"))
            {
                buffer[2] = 0x44;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
            //printf("ret_strstr = %s\n", ret_strstr);
        }
        else
        {
            buffer[2] = 0x45;
            printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
            //my_serialPuts(serial_fd, buffer, 6);
        }
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    
        if(pthread_create(&send_voice_tid, NULL, send_voice, buffer) != 0)
        {
            perror("pthread_create1");
            exit(-1);
        }
        
        if(pthread_create(&trash_can_tid, NULL, trash_can, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }
        remove(RUBBISH_FILE);
        
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    }
    
    pthread_exit(0);
}

int main()
{
    int result_detect_process = -1;
    char *ret_strstr = (char *)malloc(1024);
    pthread_t get_voice_tid;
    pthread_t get_category_tid;

    rubbish_Init();
    if (wiringPiSetup() == -1)
    {
        exit(1);
    }

    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    pthread_create(&get_voice_tid, NULL, get_voice, NULL);
    pthread_create(&get_category_tid, NULL, get_category, NULL);

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_join(get_voice_tid, NULL);
    pthread_join(get_category_tid, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    
    close(serial_fd);

END:
    rubbish_Finalize();
    return 0;
}

增加OLED显示功能

myOLED.c

直接添在rubbish项目中添加2个OLED实现代码文件 myoled.c

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>

#include "oled.h"
#include "font.h"
#include "myOLED.h"

struct display_info disp;

void oled_show(void *arg)
{
    int i;
    unsigned char *buffer = (unsigned char *)arg;

    oled_putstrto(&disp, 1, 9+1, "Rubbish recognition : ");
    disp.font = font2;
    oled_send_buffer(&disp);

    switch(buffer[2])
    {
        case 0x41:
                    oled_putstrto(&disp, 3, 18+2, "dry rubbish");
            break;
        
        case 0x42:
                    oled_putstrto(&disp, 1, 18+2, "wet rubbish");
            break;
        
        case 0x43:
                    oled_putstrto(&disp, 1, 18+2, "recyclable rubbish");
            break;

        case 0x44:
                    oled_putstrto(&disp, 1, 18+2, "hazardous rubbish");
            break;
        
        case 0x45:
                    oled_putstrto(&disp, 1, 18+2, "recognition failure");
            break;

        default:
            break;
    }
    disp.font = font2;
    oled_send_buffer(&disp);

    disp.font = font3;
    for (i = 0; i < 100; i++) {
		oled_putstrto(&disp, 135-i, 36+4, "===");
		oled_send_buffer(&disp);
	}

}

void show_error(int err, int add)
{
	printf("\nERROR: %i, %i\n\n", err, add);
}

void myOled_init(void)
{
    int e;
    disp.address = OLED_I2C_ADDR;
    disp.font = font2;

    e = oled_open(&disp, FILENAME);
    if (e < 0) 
    {
		show_error(1, e);
	}
    else
    {
		e = oled_init(&disp);
    }
}

myOLED.h

#ifndef _MYOLED_H_
#define _MYOLED_H_

#define FILENAME  "/dev/i2c-3"

void oled_show(void *argv);

void myOled_init(void);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <wiringPi.h>

#include "rubbish.h"
#include "mySerial.h"
#include "pwm.h"
#include "myOLED.h"

int len = -1;
int serial_fd = -1;
pthread_mutex_t mutex;
pthread_cond_t  cond;

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

void* send_voice(void *arg)
{
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;

    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(NULL != buffer)
    {
        my_serialPuts(serial_fd, buffer, 6);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* trash_can(void *arg)
{
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;
    
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(buffer[2] == 0x43)
    {
        pwm_write(PWM_RECOVERABLE_RUBBISH);
        delay(2300);
        pwm_stop(PWM_RECOVERABLE_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }
    else if(buffer[2] != 0x45)
    {
        pwm_write(PWM_OTHER_RUBBISH);
        delay(2300);
        pwm_stop(PWM_OTHER_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* myOled_show(void *arg)
{
   pthread_detach(pthread_self());
   myOled_init();
   oled_show(arg);
   pthread_exit(0);
}

void* get_voice()
{   

    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
//            system(WGET_CMD);
            pthread_mutex_lock(&mutex);
            buffer[2] = 0x00;
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
        }
    }
    pthread_exit(0);
}

void* get_category()
{
    char *category = NULL;
    pthread_t send_voice_tid;
    pthread_t trash_can_tid;
    pthread_t myOled_show_tid;
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    
    while(1)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);
        pthread_mutex_unlock(&mutex);
        
        buffer[2] = 0x00;
        system(WGET_CMD);
        
        if(access(RUBBISH_FILE, F_OK) == 0)
        {   
            category = alicloud_rubbish_category(category);
            printf("category = %s\n", category);
        
            if(strstr(category, "干垃圾") != NULL)
            {
                buffer[2] = 0x41;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "湿垃圾"))
            {
                buffer[2] = 0x42;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "可回收垃圾"))
            {
                buffer[2] = 0x43;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "有害垃圾"))
            {
                buffer[2] = 0x44;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
            //printf("ret_strstr = %s\n", ret_strstr);
        }
        else
        {
            buffer[2] = 0x45;
            printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
            //my_serialPuts(serial_fd, buffer, 6);
        }
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    
        if(pthread_create(&send_voice_tid, NULL, send_voice, buffer) != 0)
        {
            perror("pthread_create1");
            exit(-1);
        }
        
        if(pthread_create(&trash_can_tid, NULL, trash_can, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }

        if(pthread_create(&myOled_show_tid, NULL, myOled_show, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }

        remove(RUBBISH_FILE);
        
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    }
    
    pthread_exit(0);
}

int main()
{
    int result_detect_process = -1;
    char *ret_strstr = (char *)malloc(1024);
    pthread_t get_voice_tid;
    pthread_t get_category_tid;

    rubbish_Init();
    if (wiringPiSetup() == -1)
    {
        exit(1);
    }

    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    pthread_create(&get_voice_tid, NULL, get_voice, NULL);
    pthread_create(&get_category_tid, NULL, get_category, NULL);

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_join(get_voice_tid, NULL);
    pthread_join(get_category_tid, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    
    close(serial_fd);

END:
    rubbish_Finalize();
    return 0;
}

增加网络控制功能

TCP 心跳机制解决Soket异常断开问题

socket_Sever.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "socket_Sever.h"

int socket_init()
{
    int s_fd;
    struct sockaddr_in s_addr;
    memset(&s_addr, 0, sizeof(struct sockaddr_in));

    s_fd = socket(AF_INET,SOCK_STREAM,0);
    if(s_fd == -1)
    {
        perror("socket");
        exit(-1);
    }

    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(MY_PORT));
    inet_aton(MY_IP_ADDRESS, &s_addr.sin_addr);
    //2.bind
    int result_bind = bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
    if (-1 == result_bind)
    {
        perror("bind");
        return -1;
    }
    //3.listen
    int result_listen = listen(s_fd, 1);
    if (-1 == result_listen)
    {
        perror("listen");
        return -1;
    }

    return s_fd;
}

socket_Sever.h

#ifndef _SOCKET_SEVER_H_
#define _SOCKET_SEVER_H_

#define MY_IP_ADDRESS "192.168.1.82"
#define MY_PORT       "8888"

int socket_init();

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <wiringPi.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

#include "rubbish.h"
#include "mySerial.h"
#include "pwm.h"
#include "myOLED.h"
#include "socket_Sever.h"

int len = -1;
int serial_fd = -1;
pthread_mutex_t mutex;
pthread_cond_t  cond;

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

void* send_voice(void *arg)
{
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;

    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(NULL != buffer)
    {
        my_serialPuts(serial_fd, buffer, 6);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* trash_can(void *arg)
{
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;
    
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(buffer[2] == 0x43)
    {
        pwm_write(PWM_RECOVERABLE_RUBBISH);
        delay(2300);
        pwm_stop(PWM_RECOVERABLE_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }
    else if(buffer[2] != 0x45)
    {
        pwm_write(PWM_OTHER_RUBBISH);
        delay(2300);
        pwm_stop(PWM_OTHER_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* myOled_show(void *arg)
{
   pthread_detach(pthread_self());
   myOled_init();
   oled_show(arg);
   pthread_exit(0);
}

void* get_voice()
{   

    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
//            system(WGET_CMD);
            pthread_mutex_lock(&mutex);
            buffer[2] = 0x00;
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
        }
    }
    pthread_exit(0);
}

void* get_category()
{
    char *category = NULL;
    pthread_t send_voice_tid;
    pthread_t trash_can_tid;
    pthread_t myOled_show_tid;
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    
    while(1)
    {
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
        
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);
        pthread_mutex_unlock(&mutex);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
        
        buffer[2] = 0x00;
        system(WGET_CMD);
        
        if(access(RUBBISH_FILE, F_OK) == 0)
        {   
            category = alicloud_rubbish_category(category);
            printf("category = %s\n", category);
        
            if(strstr(category, "干垃圾") != NULL)
            {
                buffer[2] = 0x41;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "湿垃圾"))
            {
                buffer[2] = 0x42;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "可回收垃圾"))
            {
                buffer[2] = 0x43;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "有害垃圾"))
            {
                buffer[2] = 0x44;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
            //printf("ret_strstr = %s\n", ret_strstr);
        }
        else
        {
            buffer[2] = 0x45;
            printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
            //my_serialPuts(serial_fd, buffer, 6);
        }
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    
        if(pthread_create(&send_voice_tid, NULL, send_voice, buffer) != 0)
        {
            perror("pthread_create1");
            exit(-1);
        }
        
        if(pthread_create(&trash_can_tid, NULL, trash_can, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }

        if(pthread_create(&myOled_show_tid, NULL, myOled_show, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }

        remove(RUBBISH_FILE);
        
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
        
    }
    
    pthread_exit(0);
}

void* socket_sever()
{
    int s_fd;
    int c_fd;
    ssize_t n_receive;
    struct sockaddr_in c_addr;
    char receive_buf[8] = {'\0'};

    memset(&c_addr, 0, sizeof(struct sockaddr_in));

    s_fd = socket_init();

    printf("%s|%s|%d:s_fd=%d\n", __FILE__, __func__, __LINE__, s_fd); 

    sleep(3);

    int addrlen = sizeof(struct sockaddr_in);

    while(1)
    {   
        memset(receive_buf, '\0', sizeof(receive_buf));

        c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &addrlen);
        if(c_fd == -1)
        {
            perror("accept");
            
            continue;
        }
        
        int keepalive = 1;          // 开启TCP KeepAlive功能
        int keepidle = 5;           // tcp_keepalive_time 3s内没收到数据开始发送心跳包
        int keepcnt = 3;            // tcp_keepalive_probes 每次发送心跳包的时间间隔,单位秒
        int keepintvl = 3;          // tcp_keepalive_intvl 每3s发送一次心跳包
        setsockopt(c_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive, sizeof(keepalive));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPIDLE, (void *) &keepidle, sizeof(keepidle));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepcnt, sizeof(keepcnt));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(keepintvl));
        
        printf("%s|%s|%d: Accept a connection from %s : %d\n", __FILE__, __func__, __LINE__, inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port));
        
        //5.read
        while(1)
        {   
            memset(receive_buf, '\0', sizeof(receive_buf));
            n_receive = recv(c_fd, receive_buf, sizeof(receive_buf), 0);
            printf("%s|%s|%d : %s\n", __FILE__, __func__, __LINE__, receive_buf);
            
            if(n_receive > 0)
            {
                if(strstr(receive_buf, "open"))
                {   
                    printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);
                    pthread_mutex_lock(&mutex);
                    pthread_cond_signal(&cond);
                    pthread_mutex_unlock(&mutex);
                    
                    printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);
                }
            }
            /*
            if(strstr(receive_buf, "open") && n_receive > 0)
            {
                pthread_mutex_lock(&mutex);
                pthread_cond_(&cond);
                pthread_mutex_unlock(&mutex);
            }
            */
            
            else if(0 == n_receive || -1 == n_receive)
            {
                break;
            }
        }
        close(c_fd);
    }
    pthread_exit(0);
}

int main()
{
    int result_detect_process = -1;
    char *ret_strstr = (char *)malloc(1024);
    pthread_t get_voice_tid;
    pthread_t get_category_tid;
    pthread_t socket_sever_tid;

    rubbish_Init();
    if (wiringPiSetup() == -1)
    {
        exit(1);
    }

    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    pthread_create(&get_voice_tid, NULL, get_voice, NULL);
    pthread_create(&get_category_tid, NULL, get_category, NULL);
    pthread_create(&socket_sever_tid, NULL, socket_sever, NULL);

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_join(get_voice_tid, NULL);
    pthread_join(get_category_tid, NULL);
    pthread_join(socket_sever_tid, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    
    close(serial_fd);

END:
    rubbish_Finalize();
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/639698.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

五分钟”手撕“图书管理系统

前言&#xff1a; 图书馆管理系统需要结合JavaSE的绝大部分知识&#xff0c;是一个很好的训练项目。 为了让大家更加方便的查阅与学习&#xff0c;我把代码放开头&#xff0c;供大家查询。 还有对代码的分析&#xff0c;我将以类为单位分开讲解。 目录 全部代码 Main类 Us…

wordpress主题模板兔Modown 9.1开心版附送erphpdown v17.1插件

Modown 9.1开心版是一款模板兔开发的wordpress主题可&#xff0c;持续更新多年&#xff0c;优秀的资源下载类主题该模板基于Erphpdown&#xff0c;可以销售软件、视频教程、文章等等&#xff0c;通过主题和插件结合可以实现付费下载、付费阅读等功能&#xff0c;配合模板兔的一…

C++中获取int最大与最小值

不知道大家有没有遇到过这种要求&#xff1a;“返回值必须是int&#xff0c;如果整数数超过 32 位有符号整数范围 [−2^31, 2^31 − 1] &#xff0c;需要截断这个整数&#xff0c;使其保持在这个范围内。例如&#xff0c;小于 −2^31 的整数应该被固定为 −2^31 &#xff0c;大…

Pytest框架实战二

在Pytest框架实战一中详细地介绍了Pytest测试框架在参数化以及Fixture函数在API测试领域的实战案例以及具体的应用。本文章接着上个文章的内容继续阐述Pytest测试框架优秀的特性以及在自动化测试领域的实战。 conftest.py 在上一篇文章中阐述到Fixture函数的特性&#xff0c;第…

信息系统项目管理师0129:输入(8项目整合管理—8.7监控项目工作—8.7.1输入)

点击查看专栏目录 文章目录 8.7 监控项目工作8.7.1 输入8.7 监控项目工作 监控项目工作是跟踪、审查和报告整体项目进展,以实现项目管理计划中确定的绩效目标的过程。本过程的主要作用: 让干系人了解项目的当前状态并认可为处理绩效问题而采取的行动;通过成本和进度预测,让…

VTK9.2.0+QT5.14.0绘制三维显示背景

背景 上一篇绘制点云的博文中&#xff0c;使用的vtkCameraOrientationWidget来绘制的坐标轴&#xff0c;最近又学习到两种新的坐标轴绘制形式。 vtkOrientationMarkerWidget vtkAxesActor 单独使用vtkAxesActor能够绘制出坐标轴&#xff0c;但是会随着鼠标操作旋转和平移时…

弱监督语义分割-对CAM的生成过程进行改进3

三、擦除图像高响应部分以获取更多的分割领域 ECS-Net: Improving Weakly Supervised Semantic Segmentation by Using Connections Between Class Activation Maps&#xff08;ICCV,2021&#xff09; 1.引言 我们首先从图像中擦除高响应区域&#xff0c;并生成这些擦除图像…

Java进阶学习笔记2——static

static&#xff1a; 叫静态&#xff0c;可以修饰成员变量、成员方法。 成员变量按照有无static修饰&#xff0c;分为两种&#xff1a; 类变量&#xff1a;有static修饰&#xff0c;属于类&#xff0c;在计算机中只有一份&#xff0c;会被类的全部对象共享。静态成员变量。 实…

[Algorithm][动态规划][路径问题][下降路径最小和][最小路径和][地下城游戏]详细讲解

目录 1.下降路径最小和1.题目链接2.算法原理详解3.代码实现 2.最小路径和1.题目链接2.算法原理详解3.代码实现 3.地下城游戏1.题目链接2.算法原理详解3.代码实现 1.下降路径最小和 1.题目链接 下降路径最小和 2.算法原理详解 思路&#xff1a; 确定状态表示 -> dp[i][j]的…

CAN总线的终端电阻为什么要分布在两端?

CAN总线的终端节点需要分布在两端&#xff0c;主要是为了防止信号反射。 在任何传输线路中&#xff0c;当信号传输到线路的末端时&#xff0c;如果末端没有被正确匹配&#xff0c;就会产生反射信号。这个反射信号会沿着原来的路线返回&#xff0c;与原来的信号叠加&#xff0c;…

LINUX系统编程:命名管道

匿名管道的通信只能在&#xff0c;有血缘关系的进程中&#xff0c;本质就是&#xff0c;子进程会拷贝一份父进程的文件描述符表&#xff0c;父子进程就可以看到操作系统的同一块资源&#xff08;文件&#xff09;&#xff0c;以这块资源为媒介进行通信。 命名管道&#xff0c;…

C++ (week4):Linux基础

文章目录 零、Linux简介1.配置环境2.Linux历史3.Linux模型 一、vim二、Linux命令行 (shell命令)1.常用命令与快捷键(1)常用命令①man命令&#xff1a;查看帮助手册 (2)快捷键 2.用户子系统(1)Linux用户(2)用户命令 3.文件子系统命令(1)目录命令1.创建文件&#xff1a;mkdir2.删…

15、24年--信息系统管理——管理要点

1、数据管理 数据管理使指通过规划、控制与提供数据和信息资产的职能,包括开发、执行和监督有关数据的计划、策略、方案、项目、流程、方法和程序,以获取、控制、保护、交付和提高数据和信息资产价值。 DCMM定义了数据战略、数据治理、数据架构、数据应用、数据安全、…

分布式数据库HBase入门指南

目录 概述 HBase 的主要特点包括: HBase 的典型应用场景包括: 访问接口 1. Java API: 2. REST API: 3. Thrift API: 4. 其他访问接口: HBase 数据模型 概述 该模型具有以下特点&#xff1a; 1. 面向列: 2. 多维: 3. 稀疏: 数据存储: 数据访问: HBase 的数据模型…

Java入门基础学习笔记47——ArrayList

什么是集合呢&#xff1f; 集合是一种容器&#xff0c;用来装数据的&#xff0c;类似数组。 有数组&#xff0c;为什么还要学习集合呢&#xff1f; 数组定义完成并启动后&#xff0c;长度就固定了。 而集合是大小可变&#xff0c;开发中用的最多的。 集合的特点&#xff1a;大…

WSL调用docker

WSL&#xff08;windows subsystem linux&#xff09;是window系统的原生linux子系统&#xff0c;用于代码开发很方便。 希望在wsl里面运行docker&#xff0c;首先要安装docker在WSL中使用&#xff0c;大部分人的第一想法肯定是用以下命令行安装&#xff08;个人不推荐&#x…

Log360:护航安全,远离暗网风险

暗网有时候就像是一个神秘的地下世界&#xff0c;是互联网的隐蔽角落&#xff0c;没有任何规则。这是一个被盗数据交易、网络犯罪分子策划下一步攻击的地方。但仅仅因为它黑暗&#xff0c;不意味着你要对潜在的威胁视而不见。 暗网 这就是ManageEngine Log360的用武之地&…

Wireshark 4.2.5:发现 QUIC 和 VXLAN 协议的新功能

Wireshark 是一种先进且广泛使用的网络协议分析仪&#xff0c;最近发布了新版本 4.2.5&#xff0c;它提供了许多新功能和改进。 Wireshark 4.2.5 发行说明 什么是 Wireshark&#xff1f; Wireshark 是世界上最流行的网络协议分析器。它用于故障排除、分析、开发和教育。 Wiresh…

小短片创作-组装场景(一)

1、项目基础设置 通过第三人称模板&#xff0c;创建1个项目 1.自动曝光&#xff1a;关闭&#xff0c;因为要做专业的小短片&#xff0c;曝光需要手动控制。 2.扩展自动曝光中的默认亮度范围&#xff1a;启用 3.全局光照系统&#xff1a;选择屏幕空间光照&#xff08;SSGI&am…

react antd中transfer穿梭框组件中清除搜索框内容

如图&#xff1a;需要清除search搜索框内容 antd的transfer穿梭框组件未提供入口修改input框的值。 2种方法修改。 1、直接操作dom元素设置值&#xff08;不推荐&#xff09; useEffect(() > {const searchInput document.querySelector(.ant-transfer-list-search input)…