18.阿里云方案-智能家居项目

阿里云方案-智能家居项目

1.前期准备

一些oled显示、结构体等

全局结构体:

global.h

#ifndef __GLOBAL__H
#define __GLOBAL__H
typedef struct{
    mqd_t mqd;
    struct control *ctrl_phead;
} ctrl_info_t;
#endif

1.1.自定义线程结构体

control.c

#include <stdio.h>
#include "control.h"

struct control *add_interface_to_ctrl_list(struct control *phead,struct control *control_interface)
{
    //头插法
    if(NULL == phead){
        phead = control_interface;
    }else{
        control_interface->next = phead; 
        phead = control_interface;
    }
    return phead;
}

control.h

#ifndef __CONTROL__H
#define __CONTROL__H
struct control
{
    char control_name[128]; //监听模块名称
    int (*init)(void); //初始化函数
    void (*final)(void);//结束释放函数
    void *(*get)(void *arg);//监听函数,如语音监听
    void *(*set)(void *arg); //设置函数,如语音播报
    struct control *next;
};
struct control *add_interface_to_ctrl_list(struct control *phead,struct control *control_interface);
#endif

1.2.自定义外设结构体

gdevice.c

#include "gdevice.h"
#if 0
struct gdevice *add_device_to_gdevice_list(struct gdevice *pgdevHead,struct gdevice *gdev)
{
    //头插法
    if(NULL == pgdevHead){
        pgdevHead = gdev;
    }else{
        gdev->next = pgdevHead;
        pgdevHead = gdev;
    }
    return pgdevHead;
}
#endif   
struct gdevice *find_device_by_key(struct gdevice *pgdevHead, int key)
{
    struct gdevice *p = NULL;
    if(NULL == pgdevHead){
        return NULL;
    }
    p = pgdevHead;
    while (p != NULL)
    {
        if(p->key == key){
            return p;
        }
        p = p->next;
    }
    return NULL;
}
int set_gpio_gdevice_status(struct gdevice *pdev)
{
    if(NULL == pdev){
        return -1;
    }
    if(-1 != pdev->gpio_pin){
        pinMode(pdev->gpio_pin,pdev->gpio_mode);
    }
    if(-1 != pdev->gpio_status){
        digitalWrite(pdev->gpio_pin,pdev->gpio_status);
    }
    return 0;
}

gdevice.h

#ifndef __GDEVICE__H
#define __GDEVICE__H

#include <stdio.h>
#include <wiringPi.h>

struct gdevice
{
    char dev_name[128]; //设备名称
    int key; //key值,用于匹配控制指令的值
    int gpio_pin; //控制的gpio引脚
    int gpio_mode; //输入输出模式
    int gpio_status; //高低电平状态
    int check_face_status; //是否进行人脸检测状态
    int voice_set_status; //是否语音语音播报
    struct gdevice *next;
};

//struct gdevice *add_device_to_gdevice_list(struct gdevice *pgdevHead,struct gdevice *gdev);
struct gdevice *find_device_by_key(struct gdevice *pgdevHead, int key);
int set_gpio_gdevice_status(struct gdevice *gdev);
#endif

1.3.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"
#define FILENAME  "/dev/i2c-3"
static struct display_info disp;

int oled_show(void *arg) 
{
    oled_clear(&disp);
	unsigned char *buffer = (unsigned char *)arg;
	oled_putstrto(&disp, 0, 9+1, "This home show:");
	disp.font = font2;
    oled_putstrto(&disp, 0, 20, buffer);
    disp.font = font2;
	oled_send_buffer(&disp);

	return 0;
}
int myoled_init(void)
{
    int e = -1;
	disp.address = OLED_I2C_ADDR;
	disp.font = font2;
	e = oled_open(&disp, FILENAME);
    e = oled_init(&disp);
    oled_clear(&disp);
    return e;
} 

myoled.h

#ifndef __MYOLED__H
#define __MYOLED_H
    int myoled_init(void);
    int oled_show(void *arg);
#endif

1.4.网络相关的socket

socket.c

#include "socket.h"
int socket_init(const char *ipaddr,const char *ipport)
{
    int s_fd = -1;
    int ret = -1;
    struct sockaddr_in s_addr;
    memset(&s_addr,0,sizeof(struct sockaddr_in));
    //1.socket
    s_fd = socket(AF_INET,SOCK_STREAM,0);
    if(-1 == s_fd){
        perror("socket");
        return -1;
    }
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(ipport));
    inet_aton(ipaddr,&s_addr.sin_addr);
    //2.bind
    ret = bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
    if(-1 == ret){
        perror("bind");
        return -1;
    }
    //3.listen
    ret = listen(s_fd,1);
    if(-1 == ret){
        perror("listen");
        return -1;
    }
    return s_fd;
}

socket.h

#ifndef __SOCKET__H
#define __SOCKET__H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <errno.h>
#define IPADDR "192.168.4.129" //填写自己实际的ip地址
#define IPPORT "8989"
#define BUF_SIZE 6
    int socket_init(const char *ipaddr, const char *ipport);
#endif

1.5.串口相关

uartTool.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>
#include "wiringSerial.h"

int mySerialOpen (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 serialSendString (const int fd, const unsigned char *s,int len)
{
	int ret;
	ret = write (fd, s, len) ;
	if (ret < 0)
		 printf("Serial Putchar Error\n");
}

int serialGetString (const int fd,unsigned char *buffer)
{
	int n_read;
  n_read = read (fd,buffer,32);
  return n_read;
}

uartTool.h

#ifndef __UAERT__H
#define __UAERT__H

int mySerialOpen (const char *device, const int baud);
void serialSendString (const int fd, const unsigned char *s ,int len);
int serialGetString (const int fd,unsigned char *buffer);

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

#endif

1.6.ini解析相关

gdevice.ini

[lock]
key=0x44
gpio_pin=8
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=1
voice_set_status=1
[beep]
key=0x45
gpio_pin=9
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=1
[BR led]
key=0x42
gpio_pin=5
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0
[LV led]
key=0x41
gpio_pin=2
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0
[fan]
key=0x43
gpio_pin=7
gpio_mode=OUTPUT
gpio_status=HIGH
check_face_status=0
voice_set_status=0

ini.c

/* inih -- simple .INI file parser

SPDX-License-Identifier: BSD-3-Clause

Copyright (C) 2009-2020, Ben Hoyt

inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:

https://github.com/benhoyt/inih

*/

#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include "ini.h"

#if INI_CUSTOM_ALLOCATOR
#include <stddef.h>
void* ini_malloc(size_t size);
void ini_free(void* ptr);
void* ini_realloc(void* ptr, size_t size);
#else
#include <stdlib.h>
#define ini_malloc malloc
#define ini_free free
#define ini_realloc realloc
#endif

#define MAX_SECTION 50
#define MAX_NAME 50

bool ini_allow_multiline = INI_ALLOW_MULTILINE;
bool ini_allow_bom = INI_ALLOW_BOM;
char* ini_start_comment_prefixes = INI_START_COMMENT_PREFIXES;
bool ini_allow_inline_comments = INI_ALLOW_INLINE_COMMENTS;
char* ini_inline_comment_prefixes = INI_INLINE_COMMENT_PREFIXES;
bool ini_use_stack = INI_USE_STACK;
int ini_max_line = INI_MAX_LINE;
bool ini_allow_realloc = INI_ALLOW_REALLOC;
int ini_initial_alloc = INI_INITIAL_ALLOC;
bool ini_stop_on_first_error = INI_STOP_ON_FIRST_ERROR;
static bool ini_call_handler_on_new_section = false;
bool ini_allow_no_value = INI_ALLOW_NO_VALUE;

/* Used by ini_parse_string() to keep track of string parsing state. */
typedef struct {
    const char* ptr;
    size_t num_left;
} ini_parse_string_ctx;

/* Strip whitespace chars off end of given string, in place. Return s. */
static char* rstrip(char* s)
{
    char* p = s + strlen(s);
    while (p > s && isspace((unsigned char)(*--p)))
        *p = '\0';
    return s;
}

/* Return pointer to first non-whitespace char in given string. */
static char* lskip(const char* s)
{
    while (*s && isspace((unsigned char)(*s)))
        s++;
    return (char*)s;
}

/* Return pointer to first char (of chars) or inline comment in given string,
   or pointer to NUL at end of string if neither found. Inline comment must
   be prefixed by a whitespace character to register as a comment. */
static char* find_chars_or_comment(const char* s, const char* chars)
{
if (ini_allow_inline_comments) {
    int was_space = 0;
    while (*s && (!chars || !strchr(chars, *s)) &&
           !(was_space && strchr(ini_inline_comment_prefixes, *s))) {
        was_space = isspace((unsigned char)(*s));
        s++;
    }
} else {
    while (*s && (!chars || !strchr(chars, *s))) {
        s++;
    }
}
    return (char*)s;
}

/* Similar to strncpy, but ensures dest (size bytes) is
   NUL-terminated, and doesn't pad with NULs. */
static char* strncpy0(char* dest, const char* src, size_t size)
{
    /* Could use strncpy internally, but it causes gcc warnings (see issue #91) */
    size_t i;
    for (i = 0; i < size - 1 && src[i]; i++)
        dest[i] = src[i];
    dest[i] = '\0';
    return dest;
}

/* See documentation in header file. */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
                     void* user)
{
    /* Uses a fair bit of stack (use heap instead if you need to) */
    char line_buf[ini_use_stack ? ini_max_line : 0];
    char* line;
    size_t max_line;
    if (ini_use_stack) {
        line = line_buf;
        max_line = ini_max_line;
    } else {
        max_line = ini_initial_alloc;
    }
    char* new_line;
    size_t offset;
    char section[MAX_SECTION] = "";
    char prev_name[MAX_NAME] = "";

    char* start;
    char* end;
    char* name;
    char* value;
    int lineno = 0;
    int error = 0;

if (!ini_use_stack) {
    line = (char*)ini_malloc(ini_initial_alloc);
    if (!line) {
        return -2;
    }
}

#if INI_HANDLER_LINENO
#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
#else
#define HANDLER(u, s, n, v) handler(u, s, n, v)
#endif

    /* Scan through stream line by line */
    while (reader(line, (int)max_line, stream) != NULL) {
if (ini_allow_realloc && !ini_use_stack) {
        offset = strlen(line);
        while (offset == max_line - 1 && line[offset - 1] != '\n') {
            max_line *= 2;
            if (max_line > ini_max_line)
                max_line = ini_max_line;
            new_line = ini_realloc(line, max_line);
            if (!new_line) {
                ini_free(line);
                return -2;
            }
            line = new_line;
            if (reader(line + offset, (int)(max_line - offset), stream) == NULL)
                break;
            if (max_line >= ini_max_line)
                break;
            offset += strlen(line + offset);
        }
}

        lineno++;

        start = line;
        if (ini_allow_bom && lineno == 1 && (unsigned char)start[0] == 0xEF &&
                           (unsigned char)start[1] == 0xBB &&
                           (unsigned char)start[2] == 0xBF) {
            start += 3;
        }
        start = lskip(rstrip(start));

        if (strchr(ini_start_comment_prefixes, *start)) {
            /* Start-of-line comment */
        }
        else if (ini_allow_multiline && *prev_name && *start && start > line) {
            /* Non-blank line with leading whitespace, treat as continuation
               of previous name's value (as per Python configparser). */
            if (!HANDLER(user, section, prev_name, start) && !error)
                error = lineno;
        }
        else if (*start == '[') {
            /* A "[section]" line */
            end = find_chars_or_comment(start + 1, "]");
            if (*end == ']') {
                *end = '\0';
                strncpy0(section, start + 1, sizeof(section));
                *prev_name = '\0';
                if (ini_call_handler_on_new_section && !HANDLER(user, section, NULL, NULL) && !error)
                    error = lineno;
            }
            else if (!error) {
                /* No ']' found on section line */
                error = lineno;
            }
        }
        else if (*start) {
            /* Not a comment, must be a name[=:]value pair */
            end = find_chars_or_comment(start, "=:");
            if (*end == '=' || *end == ':') {
                *end = '\0';
                name = rstrip(start);
                value = end + 1;
            if (ini_allow_inline_comments) {
                end = find_chars_or_comment(value, NULL);
                if (*end)
                    *end = '\0';
            }
                value = lskip(value);
                rstrip(value);

                /* Valid name[=:]value pair found, call handler */
                strncpy0(prev_name, name, sizeof(prev_name));
                if (!HANDLER(user, section, name, value) && !error)
                    error = lineno;
            }
            else if (!error) {
                /* No '=' or ':' found on name[=:]value line */
if (ini_allow_no_value) {
                *end = '\0';
                name = rstrip(start);
                if (!HANDLER(user, section, name, NULL) && !error)
                    error = lineno;
} else {
                error = lineno;
}
            }
        }

        if (ini_stop_on_first_error && error)
            break;
    }

if (!ini_use_stack) {
    ini_free(line);
}

    return error;
}

/* See documentation in header file. */
int ini_parse_file(FILE* file, ini_handler handler, void* user)
{
    return ini_parse_stream((ini_reader)fgets, file, handler, user);
}

/* See documentation in header file. */
int ini_parse(const char* filename, ini_handler handler, void* user)
{
    FILE* file;
    int error;

    file = fopen(filename, "r");
    if (!file)
        return -1;
    error = ini_parse_file(file, handler, user);
    fclose(file);
    return error;
}

/* An ini_reader function to read the next line from a string buffer. This
   is the fgets() equivalent used by ini_parse_string(). */
static char* ini_reader_string(char* str, int num, void* stream) {
    ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream;
    const char* ctx_ptr = ctx->ptr;
    size_t ctx_num_left = ctx->num_left;
    char* strp = str;
    char c;

    if (ctx_num_left == 0 || num < 2)
        return NULL;

    while (num > 1 && ctx_num_left != 0) {
        c = *ctx_ptr++;
        ctx_num_left--;
        *strp++ = c;
        if (c == '\n')
            break;
        num--;
    }

    *strp = '\0';
    ctx->ptr = ctx_ptr;
    ctx->num_left = ctx_num_left;
    return str;
}

/* See documentation in header file. */
int ini_parse_string(const char* string, ini_handler handler, void* user) {
    ini_parse_string_ctx ctx;

    ctx.ptr = string;
    ctx.num_left = strlen(string);
    return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
                            user);
}

ini.h

/* inih -- simple .INI file parser

SPDX-License-Identifier: BSD-3-Clause

Copyright (C) 2009-2020, Ben Hoyt

inih is released under the New BSD license (see LICENSE.txt). Go to the project
home page for more info:

https://github.com/benhoyt/inih

*/

#ifndef INI_H
#define INI_H

/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <stdbool.h>

/* Nonzero if ini_handler callback should accept lineno parameter. */
#ifndef INI_HANDLER_LINENO
#define INI_HANDLER_LINENO 0
#endif

/* Typedef for prototype of handler function. */
#if INI_HANDLER_LINENO
typedef int (*ini_handler)(void* user, const char* section,
                           const char* name, const char* value,
                           int lineno);
#else
typedef int (*ini_handler)(void* user, const char* section,
                           const char* name, const char* value);
#endif

/* Typedef for prototype of fgets-style reader function. */
typedef char* (*ini_reader)(char* str, int num, void* stream);

/* Parse given INI-style file. May have [section]s, name=value pairs
   (whitespace stripped), and comments starting with ';' (semicolon). Section
   is "" if name=value pair parsed before any section heading. name:value
   pairs are also supported as a concession to Python's configparser.

   For each name=value pair parsed, call handler function with given user
   pointer as well as section, name, and value (data only valid for duration
   of handler call). Handler should return nonzero on success, zero on error.

   Returns 0 on success, line number of first error on parse error (doesn't
   stop on first error), -1 on file open error, or -2 on memory allocation
   error (only when INI_USE_STACK is zero).
*/
int ini_parse(const char* filename, ini_handler handler, void* user);

/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
   close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file, ini_handler handler, void* user);

/* Same as ini_parse(), but takes an ini_reader function pointer instead of
   filename. Used for implementing custom or string-based I/O (see also
   ini_parse_string). */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
                     void* user);

/* Same as ini_parse(), but takes a zero-terminated string with the INI data
instead of a file. Useful for parsing INI data from a network socket or
already in memory. */
int ini_parse_string(const char* string, ini_handler handler, void* user);

/* Nonzero to allow multi-line value parsing, in the style of Python's
   configparser. If allowed, ini_parse() will call the handler with the same
   name for each subsequent line parsed. */
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 1
#endif
extern bool ini_allow_multiline;

/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
   the file. See https://github.com/benhoyt/inih/issues/21 */
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
#endif
extern bool ini_allow_bom;

/* Chars that begin a start-of-line comment. Per Python configparser, allow
   both ; and # comments at the start of a line by default. */
#ifndef INI_START_COMMENT_PREFIXES
#define INI_START_COMMENT_PREFIXES ";#"
#endif
extern char* ini_start_comment_prefixes;

/* Nonzero to allow inline comments (with valid inline comment characters
   specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
   Python 3.2+ configparser behaviour. */
#ifndef INI_ALLOW_INLINE_COMMENTS
#define INI_ALLOW_INLINE_COMMENTS 1
#endif
extern bool ini_allow_inline_comments;
#ifndef INI_INLINE_COMMENT_PREFIXES
#define INI_INLINE_COMMENT_PREFIXES ";"
#endif
extern char* ini_inline_comment_prefixes;

/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */
#ifndef INI_USE_STACK
#define INI_USE_STACK 1
#endif
extern bool ini_use_stack;

/* Maximum line length for any line in INI file (stack or heap). Note that
   this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */
#ifndef INI_MAX_LINE
#define INI_MAX_LINE 200
#endif
extern int ini_max_line;

/* Nonzero to allow heap line buffer to grow via realloc(), zero for a
   fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is
   zero. */
#ifndef INI_ALLOW_REALLOC
#define INI_ALLOW_REALLOC 0
#endif
extern bool ini_allow_realloc;

/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK
   is zero. */
#ifndef INI_INITIAL_ALLOC
#define INI_INITIAL_ALLOC 200
#endif
extern int ini_initial_alloc;

/* Stop parsing on first error (default is to keep parsing). */
#ifndef INI_STOP_ON_FIRST_ERROR
#define INI_STOP_ON_FIRST_ERROR 0
#endif
extern bool ini_stop_on_first_error;

/* Nonzero to call the handler at the start of each new section (with
   name and value NULL). Default is to only call the handler on
   each name=value pair. */
#ifndef INI_CALL_HANDLER_ON_NEW_SECTION
#define INI_CALL_HANDLER_ON_NEW_SECTION 0
#endif
//extern bool ini_call_handler_on_new_section;

/* Nonzero to allow a name without a value (no '=' or ':' on the line) and
   call the handler with value NULL in this case. Default is to treat
   no-value lines as an error. */
#ifndef INI_ALLOW_NO_VALUE
#define INI_ALLOW_NO_VALUE 0
#endif
extern bool ini_allow_no_value;

/* Nonzero to use custom ini_malloc, ini_free, and ini_realloc memory
   allocation functions (INI_USE_STACK must also be 0). These functions must
   have the same signatures as malloc/free/realloc and behave in a similar
   way. ini_realloc is only needed if INI_ALLOW_REALLOC is set. */
#ifndef INI_CUSTOM_ALLOCATOR
#define INI_CUSTOM_ALLOCATOR 0
#endif


#ifdef __cplusplus
}
#endif

#endif /* INI_H */

2.消息队列mqueue

msg_queue.c

#include "msg_queue.h"

mqd_t msg_queue_create()
{
    //创建消息队列
    mqd_t mqd = -1;
    struct mq_attr attr;
    attr.mq_flags = 0;//阻塞标志, 0(阻塞)或O_NONBLOCK
    attr.mq_maxmsg = 10;//最大消息数
    attr.mq_msgsize = 256; //每个消息最大大小
    attr.mq_curmsgs = 0;//当前消息数
    mqd = mq_open(QUEUE_NAME, O_RDWR|O_CREAT, 0644, &attr);
    printf("%s|%s|%d: mqd = %d\n",__FILE__,__func__,__LINE__,mqd);
    return mqd;
}

void msg_queue_final(mqd_t mqd)
{
    if(-1 != mqd){
        mq_close(mqd);
        mq_unlink(QUEUE_NAME);
        mqd = -1;
    }
}
int send_message(mqd_t mqd, void *msg, int msg_len)
{
    int byte_send = -1;
    byte_send = mq_send(mqd, (char *)msg, msg_len, 0);
    unsigned char * buffer = (unsigned char *)msg;
    printf("%s|%s|%d:0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n", __FILE__, __func__,__LINE__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],buffer[5]);
    printf("%s|%s|%d:byte_send=%d\n", __FILE__, __func__, __LINE__, byte_send);
    return byte_send;
}

msg_queue.h

#ifndef __MSG_QUEUE__H
#define __MSG_QUEUE__H
#include <mqueue.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define QUEUE_NAME  "/smarthome_queue"

mqd_t msg_queue_create();
void msg_queue_final(mqd_t mqd);
int send_message(mqd_t mqd, void *msg, int msg_len);
#endif

3.阿里云人脸识别

face.py

# -*- coding: utf-8 -*-
# 引入依赖包
# pip install alibabacloud_facebody20191230

import os
import io
from urllib.request import urlopen
from alibabacloud_facebody20191230.client import Client
from alibabacloud_facebody20191230.models import SearchFaceAdvanceRequest
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='facebody.cn-shanghai.aliyuncs.com',
    # 访问的域名对应的region
    region_id='cn-shanghai'
)

def alibaba_face():
  search_face_request = SearchFaceAdvanceRequest()
  #场景一:文件在本地
  stream0 = open(r'/tmp/SearchFace.jpg', 'rb')
  search_face_request.image_url_object = stream0

  #场景二:使用任意可访问的url
  #url = 'http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/facebody/SearchFace/SearchFace1.png'
  #img = urlopen(url).read()
  #search_face_request.image_url_object = io.BytesIO(img)
  search_face_request.db_name = 'default'
  search_face_request.limit = 5

  runtime_option = RuntimeOptions()
  try:
    # 初始化Client
    client = Client(config)
    response = client.search_face_advance(search_face_request, runtime_option)
    # 获取整体结果
    print(response.body)
    print("======================")
    match_list = response.body.to_map()['Data']['MatchList']
    scores = [item['Score'] for item in match_list[0]['FaceItems']] #set集合,无序不重复
    maxScores = max(scores)
    print(f"最大 Score 值: {maxScores}")
    value = round(maxScores,2)
    print(value)
    print("======================")
    return value;
  except Exception as error:
    # 获取整体报错信息
    print(error)
    # 获取单个字段
    print(error.code)
    # tips: 可通过error.__dict__查看属性名称
    return 0.0
  #关闭流
  #stream0.close()
if __name__ == "__main__":
  alibaba_face()

face.c

#include <Python.h>
#include <string.h>
#include "face.h"

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

void face_final(void)
{
	Py_Finalize();
}

double face_identify(void)
{
	double result = 0.0;
	system(WGET_CMD);
	if(0 != access(SEARCHFACE_FILE,F_OK)){
		printf("SEARCHFACE_FILE not found!\n");
		return result;
	}
	PyObject *pModule = PyImport_ImportModule("face");
	if(!pModule)
	{
		PyErr_Print();
		printf("Error:failed to load face.py\n");
		goto FAILED_MODULE;
	}
	PyObject *pFunc = PyObject_GetAttrString(pModule,"alibaba_face");
	if(!pFunc)
	{
		PyErr_Print();
		printf("Error:failed to load func alibaba_face\n");
		goto FAILED_FUNC;
	}
	PyObject *pValue = PyObject_CallObject(pFunc,NULL);
	if(!pValue){
		PyErr_Print();
		printf("Error:function call failed\n");
		goto FAILED_VALUE;
	}

	if(!PyArg_Parse(pValue,"d",&result)){
		PyErr_Print();
		printf("Error: parse failed");
		goto FAILED_VALUE;
	}
	printf("result:%lf\n",result);

FAILED_VALUE:
	Py_DECREF(pValue);
FAILED_FUNC:
	Py_DECREF(pFunc);
FAILED_MODULE:	
	Py_DECREF(pModule);
    
	return result;
}

face.h

#ifndef __FACE__H
#define __FACE__H

void face_init(void);
void face_final(void);
double face_identify(void);

#define WGET_CMD	    "wget http://127.0.0.1:8080/?action=snapshot -O /tmp/SearchFace.jpg"
#define SEARCHFACE_FILE	"/tmp/SearchFace.jpg"

#endif

4.语音播报线程

voice_interface.c

#if 0
struct control
{
    char control_name[128]; //监听模块名称
    int (*init)(void); //初始化函数
    void (*final)(void);//结束释放函数
    void *(*get)(void *arg);//监听函数,如语音监听
    void *(*set)(void *arg); //设置函数,如语音播报
    struct control *next;
};
#endif

#include "voice_interface.h"
#include "msg_queue.h"
#include "uartTool.h"
#include "global.h"

static int serial_fd = -1;

static int voice_init(void)
{
    printf("%s start \n",__func__);
    serial_fd = mySerialOpen (SERIAL_DEV, BAUD);
    return serial_fd;
}
static void voice_final(void)
{
    if(-1 != serial_fd){
        close(serial_fd);
        serial_fd = -1;
    }
}
//接收指令
static void *voice_get(void *arg)//mqd 来着线程传参
{
    mqd_t mqd = -1;
	unsigned char buffer[6] = {0x00, 0x00, 0x00, 0x00, 0X00, 0x00};
	int len = 0;
    ctrl_info_t *ctrl_info = NULL;
    if(NULL != arg){
        ctrl_info = (ctrl_info_t *)arg;
    }
	if(-1 == serial_fd){
        printf("%s|%s|%d:\n",__FILE__,__func__,__LINE__);
        serial_fd = voice_init();
        if(-1 == serial_fd){
            printf("%s|%s|%d:open serial failed\n",__FILE__,__func__,__LINE__);
            pthread_exit(0);
        }
	}

    mqd = ctrl_info->mqd;
    if(-1 == mqd){
        printf("%s|%s|%d:mqd=%d\n",__FILE__,__func__,__LINE__,mqd);
        pthread_exit(0);
    }

    //分离父线程,不需要父线程等待子线程
	pthread_detach(pthread_self());
	printf("%s thread start \n",__func__);
	while(1){
        len = serialGetString(serial_fd,buffer);
        printf("%s|%s|%d:0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n", __FILE__, __func__,__LINE__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],buffer[5]);
        printf("%s|%s|%d:len=%d\n", __FILE__, __func__, __LINE__, len);
		if(len > 0){
            if(buffer[0] == 0xAA && buffer[1]== 0x55 
                && buffer[5] == 0xAA && buffer[4]== 0x55){
                printf("%s|%s|%d:0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n", __FILE__, __func__,__LINE__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],buffer[5]);
                send_message(mqd, buffer, 6);
            }
            memset(buffer, 0, sizeof(buffer));
		}
	}
    pthread_exit(0);
}
//语音播报
static void *voice_set(void *arg)
{
	//分离父线程,不需要父线程等待子线程
	pthread_detach(pthread_self());
	unsigned char *buffer = (unsigned char *)arg;
	printf("%s|%s|%d:\n",__FILE__,__func__,__LINE__);
	if(-1 == serial_fd){
        printf("%s|%s|%d:\n",__FILE__,__func__,__LINE__);
        serial_fd = voice_init();
        if(-1 == serial_fd){
            printf("%s|%s|%d:open serial failed\n",__FILE__,__func__,__LINE__);
            pthread_exit(0);
        }
	}
	if(NULL != buffer){
		printf("%s|%s|%d:\n",__FILE__,__func__,__LINE__);
		serialSendString(serial_fd,buffer,6);
	}
	pthread_exit(0);
}

struct control voice_control = {
    .control_name = "voice", //监听模块名称
    .init  = voice_init, //初始化函数
    .final = voice_final,//结束释放函数
    .get = voice_get,//监听函数,如语音监听
    .set = voice_set, //设置函数,如语音播报
    .next = NULL
};

struct control *add_voice_to_ctrl_list(struct control *phead)
{
    //头插法
    return add_interface_to_ctrl_list(phead,&voice_control);
}

voice_interface.h

#ifndef __VOICE_INTERFACE__H
#define __VOICE_INTERFACE__H
#include "control.h"
struct control *add_voice_to_ctrl_list(struct control *phead);
#endif

5.网络控制线程

socket_interface.c

#include "socket_interface.h"
#include "msg_queue.h"
#include "socket.h"
#include "global.h"

static int s_fd = -1;
static int tcpsocket_init(void)
{
    printf("%s start \n",__func__);
	s_fd = socket_init(IPADDR,IPPORT);
    return s_fd;
}
static void tcpsocket_final(void)
{
    close(s_fd);
    s_fd = -1;
}
//接收指令
static void *tcpsocket_get(void *arg)//mqd 来着线程传参
{
    mqd_t mqd = -1;
	int c_fd = -1;
	unsigned char buffer[BUF_SIZE] = {0x00, 0x00, 0x00, 0x00, 0X00, 0x00};
	int n_read = -1;
    int ret = -1;
	struct sockaddr_in c_addr;
    int len = sizeof(struct sockaddr_in);
    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发送一次心跳包
    ctrl_info_t *ctrl_info = NULL;
    if(NULL != arg){
        ctrl_info = (ctrl_info_t *)arg;
    }
    mqd = ctrl_info->mqd;
    if(-1 == mqd){
        printf("%s|%s|%d:mqd=%d\n",__FILE__,__func__,__LINE__,mqd);
        pthread_exit(0);
    }

    if(-1 == s_fd)
    {
        s_fd = tcpsocket_init();
        if(-1 == s_fd){
            printf("%s|%s|%d: tcpsocket init faile \n", __FILE__, __func__,__LINE__);
            pthread_exit(0);
        }
    }
    printf("%s|%s|%d: tcpsocket thread start \n", __FILE__, __func__,__LINE__);
    //memset(&c_addr,0,sizeof(sockaddr_in));

    //分离父线程,不需要父线程等待子线程
	pthread_detach(pthread_self());
    printf("%s thread start \n",__func__);
    while(1){
		c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&len);
		if(-1 == c_fd){
			perror("accept");
			continue;
		}

		ret = setsockopt(c_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive,sizeof(keepalive));
        if(-1 == ret){
            perror("SO_KEEPALIVE");
            break;
        }
		ret = setsockopt(c_fd, SOL_TCP, TCP_KEEPIDLE, (void *) &keepidle, sizeof(keepidle));
        if(-1 == ret){
            perror("TCP_KEEPIDLE");
            break;
        }
		ret = setsockopt(c_fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepcnt, sizeof(keepcnt));
                if(-1 == ret){
            perror("TCP_KEEPCNT");
            break;
        }
		ret = setsockopt(c_fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof(keepintvl));
        if(-1 == ret){
            perror("TCP_KEEPINTVL");
            break;
        }

		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));
		while (1)
		{
			memset(buffer,0,sizeof(buffer));
			n_read = recv(c_fd,buffer,BUF_SIZE,0);
            printf("%s|%s|%d:0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n", __FILE__, __func__,__LINE__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],buffer[5]);
			if(n_read > 0){
                if(buffer[0] == 0xAA && buffer[1]== 0x55 
                    && buffer[5] == 0xAA && buffer[4]== 0x55){
                    printf("%s|%s|%d:0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n", __FILE__, __func__,__LINE__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],buffer[5]);
                    send_message(mqd, buffer, n_read);
                }
            }else if( 0 == n_read || -1 == n_read){
				break;
			}
		}
		close(c_fd);
	}
	pthread_exit(0);
}
static void *tcpsocket_set(void *arg)
{

}

struct control tcpsocket_control = {
    .control_name = "tcpsocket", //监听模块名称
    .init  = tcpsocket_init, //初始化函数
    .final = tcpsocket_final,//结束释放函数
    .get = tcpsocket_get,//监听函数,如语音监听
    .set = tcpsocket_set, //设置函数,如语音播报
    .next = NULL
};

struct control *add_tcpsocket_to_ctrl_list(struct control *phead)
{
    return add_interface_to_ctrl_list(phead,&tcpsocket_control);
}

socket_interface.h

#ifndef __SOCKET_INTERFACE__H
#define __SOCKET_INTERFACE__H
#include "control.h"
struct control *add_tcpsocket_to_ctrl_list(struct control *phead);
#endif

6.烟雾监控线程

smoke_interface.c

#include <pthread.h>
#include <wiringPi.h>

#include "socket_interface.h"
#include "msg_queue.h"
#include "global.h"


#define SMOKE_PIN 6
#define SMOKE_MODE INPUT

static int smoke_init(void)
{
    printf("%s start \n",__func__);
    pinMode(SMOKE_PIN,SMOKE_MODE);
    return 0;
}
static void smoke_final(void)
{
    //do nothing
}
//接收指令
static void *smoke_get(void *arg)//mqd 来着线程传参
{
    mqd_t mqd = -1;
    int status = HIGH; 
    int switch_status = 0;
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    ssize_t byte_send = -1;
    ctrl_info_t *ctrl_info = NULL;
    if(NULL != arg){
        ctrl_info = (ctrl_info_t *)arg;
    }
    mqd = ctrl_info->mqd;
    if(-1 == mqd){
        printf("%s|%s|%d:mqd=%d\n",__FILE__,__func__,__LINE__,mqd);
        pthread_exit(0);
    }

    //分离父线程,不需要父线程等待子线程
	pthread_detach(pthread_self());
    printf("%s thread start \n",__func__);
    while(1){
        status = digitalRead(SMOKE_PIN);
        if(LOW == status){
            printf("%s|%s|%d:status=%d\n",__FILE__,__func__,__LINE__,status);
            buffer[2] = 0x45;
            buffer[3] = 0x00;
            switch_status = 1;
            byte_send = send_message(mqd, buffer, 6);
            if(-1 == byte_send){
                send_message(mqd, buffer, 6);
                if(-1 == byte_send){
                    continue;
                }
            }
        }else if(HIGH == status && switch_status == 1){
            buffer[2] = 0x45;
            buffer[3] = 0x01;   
            switch_status = 0;
            if(-1 == byte_send){
                send_message(mqd, buffer, 6);
                if(-1 == byte_send){
                    continue;
                }
            }
        }
        sleep(3);
    }
   	pthread_exit(0); 
}
static void *smoke_set(void *arg)
{

}

struct control smoke_control = {
    .control_name = "smoke", //监听模块名称
    .init  = smoke_init, //初始化函数
    .final = smoke_final,//结束释放函数
    .get = smoke_get,//监听函数,如语音监听
    .set = smoke_set, //设置函数,如语音播报
    .next = NULL
};

struct control *add_smoke_to_ctrl_list(struct control *phead)
{
    return add_interface_to_ctrl_list(phead,&smoke_control);
}

smoke_interface.h

#ifndef __SMOKE_INTERFACE__H
#define __SMOKE_INTERFACE__H
#include "control.h"
struct control *add_smoke_to_ctrl_list(struct control *phead);
#endif

7.接收信息线程

recevice_interface.c

#include <mqueue.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "recevice_interface.h"
#include "msg_queue.h"
#include "global.h"
#include "myoled.h"
#include "face.h"
#include "gdevice.h"
#include "ini.h"

#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0

typedef struct{
    int msg_len;
    unsigned char *buffer;
    ctrl_info_t *ctrl_info;
} rev_msg_t;

static int oled_fd = -1;
static struct gdevice *pgdevHead = NULL;

static int handler_device(void* user, const char* section, const char* name,const char* value)
{
    struct gdevice *pdev = NULL;
    if(NULL == pgdevHead){
        pgdevHead = (struct gdevice *)malloc(sizeof(struct gdevice));
        pgdevHead->next = NULL;
        memset(pgdevHead,0,sizeof(struct gdevice));
        strcpy(pgdevHead->dev_name,section);
    }else if(0 != strcmp(pgdevHead->dev_name,section)){
        pdev = (struct gdevice *)malloc(sizeof(struct gdevice));
        memset(pdev,0,sizeof(struct gdevice));
        strcpy(pdev->dev_name,section);
        pdev->next = pgdevHead;
        pgdevHead = pdev;
    }
    if(NULL != pgdevHead){
        if(MATCH(pgdevHead->dev_name,"key")){
            sscanf(value,"%x",&pgdevHead->key);
            printf("%d|pgdevHead->key=%x\n",__LINE__,pgdevHead->key);
        }else if(MATCH(pgdevHead->dev_name,"gpio_pin")){
            pgdevHead->gpio_pin = atoi(value);
        }else if(MATCH(pgdevHead->dev_name,"gpio_mode")){
            if(strcmp(value,"OUTPUT") == 0){
                pgdevHead->gpio_mode = OUTPUT;
            }else if(strcmp(value,"INPUT") == 0){
                pgdevHead->gpio_mode = INPUT;
            }
        }else if(MATCH(pgdevHead->dev_name,"gpio_status")){
            if(strcmp(value,"LOW") == 0){
                pgdevHead->gpio_status = LOW;
            }else if(strcmp(value,"HIGH") == 0){
                pgdevHead->gpio_status = HIGH;
            }
        }else if(MATCH(pgdevHead->dev_name,"check_face_status")){
            pgdevHead->check_face_status = atoi(value);
        }else if(MATCH(pgdevHead->dev_name,"voice_set_status")){
            pgdevHead->voice_set_status = atoi(value);
        }
    }
    return 1;
}
static int recevice_init(void)
{
    printf("%s start \n",__func__);
    if (ini_parse("/etc/gdevice.ini", handler_device, NULL) < 0) {
        printf("Can't load 'gdevice.ini'\n");
        return -1;
    }
    #if 0
    struct gdevice *pdev = pgdevHead;
    while (pdev)
    {
       printf("dev_name=%s,",pdev->dev_name);
       printf("key=%x,",pdev->key);
       printf("gpio_pin=%d,",pdev->gpio_pin);
       printf("gpio_mode=%d,",pdev->gpio_mode);
       printf("gpio_status=%d,",pdev->gpio_status);
       printf("check_face_status=%d,",pdev->check_face_status);
       printf("voice_set_status=%d \n",pdev->voice_set_status);
       pdev = pdev->next;
    }
    #endif
    //oled初始化
    oled_fd = myoled_init();
    face_init();
    return oled_fd;
}
static void recevice_final(void)
{
    face_final();
    if(-1 != oled_fd){
        close(oled_fd);
        oled_fd = -1;
    }
}
static void *handle_device(void *arg)
{
    rev_msg_t *rev_msg = NULL;
    unsigned char *buffer;
    struct gdevice *cur_gdev = NULL;
    char success_of_failed[20] = "success";
    int ret = -1;
    int smoke_status = 0;
    double face_result = 0.0;
    pthread_t tid = -1;
    pthread_detach(pthread_self());
    if(NULL != arg){
        rev_msg = (rev_msg_t *)arg;
        printf("rev_msg->msg_len:%d \n",rev_msg->msg_len);
        printf("%s|%s|%d:handle: 0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n", __FILE__, __func__,__LINE__, 
            rev_msg->buffer[0], rev_msg->buffer[1], rev_msg->buffer[2], rev_msg->buffer[3], rev_msg->buffer[4],rev_msg->buffer[5]);
    }
    if(NULL != rev_msg && NULL != rev_msg->buffer){
        cur_gdev = find_device_by_key(pgdevHead,rev_msg->buffer[2]);
    }
    if(NULL != cur_gdev){
        cur_gdev->gpio_status = rev_msg->buffer[3] == 0? LOW:HIGH;
        if(1 == cur_gdev->check_face_status){
            face_result = face_identify();
            if(face_result > 0.6){
                rev_msg->buffer[2] = 0x47;
                ret = set_gpio_gdevice_status(cur_gdev); 
            }else{
                rev_msg->buffer[2] = 0x46;
            }
        }else{
            ret = set_gpio_gdevice_status(cur_gdev);
        }
        printf("%s|%s|%d:voice_set_status\n",__FILE__,__func__,__LINE__);
        if( 1 == cur_gdev->voice_set_status){
            printf("%s|%s|%d: voice_set_status send \n",__FILE__,__func__,__LINE__);
            if(NULL != rev_msg->ctrl_info && NULL != rev_msg->ctrl_info->ctrl_phead)
            {
                struct control *pcontrol = rev_msg->ctrl_info->ctrl_phead;
                while (NULL != pcontrol)
                {

                    if(strstr(pcontrol->control_name,"voice")){
                        if(0x45 == rev_msg->buffer[2] && 0 == rev_msg->buffer[3]){
                            smoke_status = 1;
                        }
                        pthread_create(&tid,NULL,pcontrol->set,(void *)rev_msg->buffer);
                        break;
                    }
                    pcontrol = pcontrol->next;
                }
            }  
        }
        printf("%s|%s|%d:oled show start\n",__FILE__,__func__,__LINE__);
        char oled_msg[512];
        char *change_status = cur_gdev->gpio_status == HIGH?"CLOSE":"OPEN";
        printf("%s|%s|%d:oled show memset\n",__FILE__,__func__,__LINE__);
        if(-1 == ret){
            memset(success_of_failed,0,sizeof(success_of_failed));
            strncpy(success_of_failed,"failed",6);
        }else{
            memset(success_of_failed,0,sizeof(success_of_failed));
            strncpy(success_of_failed,"success",7);
        }
        printf("%s|%s|%d:oled show sprintf\n",__FILE__,__func__,__LINE__);
        if(1 == smoke_status){
            smoke_status = 0;
              sprintf(oled_msg,"A risk fire!");
        }else{
              sprintf(oled_msg,"%s %s %s!",change_status,cur_gdev->dev_name,success_of_failed);
        }
        oled_show(oled_msg);
        printf("%s|%s|%d:oled show end\n",__FILE__,__func__,__LINE__);

        //人脸识别成功,5秒后自动关锁
        if(1 == cur_gdev->check_face_status && 0 == ret && face_result > 0.6){
            sleep(5);
            cur_gdev->gpio_status = HIGH;
            set_gpio_gdevice_status(cur_gdev);
            printf("%s|%s|%d:auto close lock!\n",__FILE__,__func__,__LINE__);
        }
    }
    pthread_exit(0);

}
//接收指令
static void *recevice_get(void *arg)//mqd 来着线程传参
{
    rev_msg_t *rev_msg = NULL;
    struct mq_attr attr;
    ssize_t read_len = -1;
    unsigned char *buffer;
    pthread_t tid;
    if(NULL != arg){
        rev_msg = (rev_msg_t *)malloc(sizeof(rev_msg_t));
        rev_msg->ctrl_info = (ctrl_info_t *) arg;//获取到mqd与phead(struct control)
        rev_msg->msg_len = -1;
        rev_msg->buffer = NULL;
    }else{
        pthread_exit(0);
    }

    if(-1 == mq_getattr(rev_msg->ctrl_info->mqd,&attr)){
        pthread_exit(0);
    }
    rev_msg->buffer = (unsigned char *)malloc(attr.mq_msgsize);
    buffer = (unsigned char *)malloc(attr.mq_msgsize);
    memset(rev_msg->buffer,0,attr.mq_msgsize);
    memset(buffer,0,attr.mq_msgsize);

    //分离父线程,不需要父线程等待子线程
	pthread_detach(pthread_self());
    printf("%s thread start \n",__func__);
    while (1)
    {
        read_len = mq_receive(rev_msg->ctrl_info->mqd,buffer,attr.mq_msgsize,0);
        printf("%s|%s|%d:0x%x, 0x%x,0x%x, 0x%x, 0x%x,0x%x\n", __FILE__, __func__,__LINE__, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],buffer[5]);
        printf("%s|%ld:read_len", __func__,read_len);
        if(-1 == read_len){
            if(errno == EAGAIN)
            {
                printf("queue is empty \n");
            }else{
                break;
            }
        }else if(buffer[0]== 0xAA && buffer[1] == 0x55 
            && buffer[5]== 0xAA && buffer[4] == 0x55){
                rev_msg->msg_len = read_len;
                memcpy(rev_msg->buffer,buffer,read_len);
                pthread_create(&tid,NULL,handle_device,(void *)rev_msg);
        }
    }
	pthread_exit(0);
}
static void *recevice_set(void *arg)
{

}

struct control recevice_control = {
    .control_name = "recevice", //监听模块名称
    .init  = recevice_init, //初始化函数
    .final = recevice_final,//结束释放函数
    .get = recevice_get,//监听函数,如语音监听
    .set = recevice_set, //设置函数,如语音播报
    .next = NULL
};

struct control *add_recevice_to_ctrl_list(struct control *phead)
{
    return add_interface_to_ctrl_list(phead,&recevice_control);
}

recevice_interface.h

#ifndef __RECEVICE_INTERFACE__H
#define __RECEVICE_INTERFACE__H
#include "control.h"
struct control *add_recevice_to_ctrl_list(struct control *phead);
#endif

8.main函数入口

main.c

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <wiringPi.h>
#include "voice_interface.h"
#include "socket_interface.h"
#include "smoke_interface.h"
#include "recevice_interface.h"
#include "msg_queue.h"
#include "global.h"
#include "control.h"
int main(int argc, char *argv[])
{
    pthread_t thread_id;
    struct control *pointer = NULL;
    ctrl_info_t *ctrl_info = NULL;
    ctrl_info = (ctrl_info_t *)malloc(sizeof(ctrl_info_t));
    ctrl_info->mqd = -1;
    ctrl_info->ctrl_phead = NULL;

    if(-1 == wiringPiSetup()){
        printf("%s|%s|%d:wiringPiSetup failed\n",__FILE__,__func__,__LINE__);
        return -1;   
    }   
    ctrl_info->mqd = msg_queue_create();
    if(-1 == ctrl_info->mqd){
        printf("%s|%s|%d:ctrl_info->mqd=%d\n",__FILE__,__func__,__LINE__,ctrl_info->mqd);
        return -1;
    }
    int node_num = 0;
    ctrl_info->ctrl_phead = add_voice_to_ctrl_list(ctrl_info->ctrl_phead);
    ctrl_info->ctrl_phead = add_tcpsocket_to_ctrl_list(ctrl_info->ctrl_phead);
    ctrl_info->ctrl_phead = add_smoke_to_ctrl_list(ctrl_info->ctrl_phead);
    ctrl_info->ctrl_phead = add_recevice_to_ctrl_list(ctrl_info->ctrl_phead);

    pointer = ctrl_info->ctrl_phead ;
    while(NULL != pointer){
        if(NULL != pointer->init){
            pointer->init();
        }
        pointer = pointer->next;
        node_num++;
    }
    pthread_t *tid = malloc(sizeof(int)*node_num);
    pointer = ctrl_info->ctrl_phead;
    for(int i = 0;i<node_num;i++){
        pthread_create(&tid[i],NULL,(void *)pointer->get,(void *)ctrl_info);
        pointer = pointer->next;
    }
    pointer = ctrl_info->ctrl_phead;
    for(int i = 0;i<node_num;i++){
        pthread_join(tid[i],NULL);
    }
    for(int i = 0;i<node_num;i++){
        if(NULL != pointer->final){
            pointer->final();
        }
        pointer = pointer->next;
    }
    pointer = ctrl_info->ctrl_phead;
    msg_queue_final(ctrl_info->mqd);
    if(ctrl_info != NULL){
        free(ctrl_info);
    }

    if(NULL != tid){
        free(tid);
    }
    return 0;
}

9.makefile文件编译输出

makefile

CC := aarch64-linux-gnu-gcc
SRC := $(shell find src -name "*.c")
INC :=	./inc \
	./3rd/usr/local/include \
	./3rd/usr/include \
	./3rd/usr/include/python3.10 \
	./3rd/usr/include/aarch64-linux-gnu \
	./3rd/usr/include/aarch64-linux-gnu/python3.10  \

OBJ := $(subst src/,obj/,$(SRC:.c=.o))

TARGET = obj/smarthome

CFLAGS := $(foreach item,$(INC),-I$(item)) #-I./3rd/usr/include
LIBS_PAHT :=./3rd/usr/local/lib \
			./3rd/lib/aarch64-linux-gnu \
			./3rd/usr/lib/aarch64-linux-gnu \
			./3rd/usr/lib/python3.10
LDFLAGS := $(foreach item,$(LIBS_PAHT),-L$(item))	#-L./3rd/usr/local/lib

LIBS := -lwiringPi -lpython3.10 -pthread -lexpat -lz -lcrypt
obj/%.o:src/%.c
	mkdir -p obj
	$(CC) -o $@ -c $< $(CFLAGS)
$(TARGET) :$(OBJ)
	$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LIBS)
	scp ./obj/smarthome ./src/face.py ./ini/gdevice.ini orangepi@192.168.4.129:/home/orangepi/
compile : $(TARGET)

clean :
	rm $(TARGET) obj $(OBJ) -rf
debug:
	echo $(CC)
	echo $(SRC)
	echo $(INC)
	echo $(OBJ)
	echo $(TARGET)
	echo $(CFLAGS)
	echo $(LDFLAGS)
	echo $(LIBS)
.PHONY: clean compile debug

posted @ 2025-05-29 11:40  站着说话不腰疼  阅读(48)  评论(0)    收藏  举报