linux树莓派3b智能家居(五)双线程之FTP和语音控制

Linux多线程

创建线程

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

使用前先声明一个进程标识符变量pthread_t *thread;
以及声明固定格式函数void *task(void *arg)

 The attr argument points to a pthread_attr_t structure whose
 contents are used at  thread creation  time  to determine
 attributes for the new thread; this structure is initialized 
 using pthread_attr_init(3) and related functions. 

等待线程

       int pthread_join(pthread_t thread, void **retval);

线程退出

       void pthread_exit(void *retval);

创建线程时传递参数arg的设计

也可以使用全局变量(不推荐)

由于有共享资源,初始化不方便写在某个线程,所以自定义一个整型数组int fd[10]存放各种描述符

程序框架

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

int decoding(char *code){

	return -1;
}

int netInit(char **argv)
{
	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){
		printf("netInit error\n");
		perror("socket");
		exit(-1);
	}

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(argv[2]));
	inet_aton(argv[1],&s_addr.sin_addr);
	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

	listen(s_fd,10);

	return s_fd;

}


void *speakControl(void *arg)
{

	int fd_Serial = ((int *)arg)[0];
	int fd_Relay = ((int *)arg)[1];


	while(1){

	
	}	
	pthread_exit(NULL);	
}

void *netControl(void *arg)
{

	char code[4] = {0};
	int cmd = 0x01;

	int fd_Serial = ((int *)arg)[0];
	int fd_Relay = ((int *)arg)[1];

	int c_fd;
	int s_fd = ((int *)arg)[2];
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	socklen_t len = sizeof(struct sockaddr_in);

	while(1){

		c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&len);
		if(c_fd == -1){
			perror("accept");
			continue;
		}

		if(fork() == 0){
			printf("connet success from :%s\n",inet_ntoa(c_addr.sin_addr));

			while(1){



			}
		}
	}
	pthread_exit(NULL);

}


int main(int argc,char **argv)
{
	if(argc != 3){
		printf("parameter error\n");
		exit(-1);
	}

	int fd[3] = {0};//0 serial 1 relay 2 c_fd

	pthread_t task_Speak;
	pthread_t task_Net;
	int ret;

	fd[0] = serialOpen("/dev/ttyAMA0",9600);
	if(fd[0] == -1){
		printf("open serial fail\n");
		exit(-1);
	}

	fd[1] = open("/dev/relay",O_RDWR);
	if(fd[1] == -1){
		printf("open relay fail\n");
		perror("open");
		exit(-1);
	}

	fd[2] = netInit(argv);



	if(-1==wiringPiSetup())
	{
		printf("set up error\n");
		exit(-1);
	}	


	ret = pthread_create(&task_Speak,NULL,speakControl,(void *)fd);
	if(ret != 0){
		printf("create task1 fail\n");
		exit(-1);
	}

	ret = pthread_create(&task_Net,NULL,netControl,(void *)fd);
	if(ret != 0){
		printf("create task2 fail\n");
		perror("pthread_create");
		exit(-1);
	}


	pthread_join(task_Speak,NULL);
	pthread_join(task_Net,NULL);
	



	return 0;
}

程序测试

由于前面的测试,大大降低这次程序的测试难度,直接接上语音模块测试语音控制线程,运行客户端程序测试网络控制线程

现阶段总结

一丶使用了临界资源,却没有考虑资源竞争问题,应加上互斥锁
二丶main函数初始化可以考虑封装在一个函数,便于以后的拓展提升
三丶考虑改变ascll码指令的格式,之前使用“OA”,"OR"等英文单词缩写,目的是配合语音模块,考虑改成一些比较通用的无意义指令,如“41”,“42”。这样以后进行不同操作时,不需要修改decoding函数,只需合理分配指令,修改线程里面的操作。语音识别模块也只需要修改识别的内容,不需要修改发送的指令格式。

decoding函数

int decoding(char *code)
{
	if(strstr(code,"OA") != NULL) return 0x00;
	if(strstr(code,"OR") != NULL) return 0x10;
	if(strstr(code,"OG") != NULL) return 0x20;
	if(strstr(code,"OY") != NULL) return 0X30;
	if(strstr(code,"CA") != NULL) return 0x01;
	if(strstr(code,"CR") != NULL) return 0x11;
	if(strstr(code,"CG") != NULL) return 0x21;
	if(strstr(code,"CY") != NULL) return 0x31;
	if(strstr(code,"GD") != NULL) return 0x0f;
	if(strstr(code,"EX") != NULL) return 0xff;


	return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值