赞
踩
前面两篇,我们介绍了工厂模式;以及工厂模式实际运用在灯上的案例,还有火灾线程,如果有遗忘的这里有传送门。
1、前言
这一节我们来介绍一哈怎么来控制这些灯,以及其他外设(火灾是线程实时监控,无需控制),这里我们选择语音与网络两种模式来控制。网络会用到安卓app,不过这里先介绍网络的框架,安卓app后期呈上。
2、语音模块
一、LDChip.c文件修改
(1)、这里我们的语音模块选择的是LD3320,使用串口的方式与树莓派联系,本模块的驱动程序已经是写好的,需要做的就是进行应用程序的修改,修改为可以进行灯控制的方式。
(2)、模块的使用,分为一级指令与二级指令,一级指令为语音模块的名字,二级指令为需要说的语音。模块出厂的名字叫“小杰”,可以自己修改,我修改为“小明同学”。
(3)、一级指令的修改,要依据原厂件的代码进行修改uint8 code sRecog[DATE_A][DATE_B] ,这里的第一条便是一级指令(也就是语音模块的名字,要先有一级指令,才能有二级指令),还要修改对应的地址码,这个也是在这个文件夹内,是uint8 code pCode[DATE_A],对应的CODE——CMD,后面这个地方还要进行修改,注意只能用拼音。
(4)、二级指令的修改,和一级指令一样,uint8 code sRecog[DATE_A][DATE_B],写上对应的修改词条,uint8 code pCode[DATE_A]表示对应的地址码。
- //打开LDChip.c文件夹
-
-
- uint8 LD_AsrAddFixed()
- {
- uint8 k, flag;
- uint8 nAsrAddLength;
- #define DATE_A 10 /*数组二维数值*/
- #define DATE_B 20 /*数组一维数值*/
- uint8 code sRecog[DATE_A][DATE_B] = {
- "xiao ming tong xue",\
- "kai chu fang deng",\
- "guan chu fang deng",\
- "kai er lou deng",\
- "guan er lou deng",\
- "kai ke ting deng",\
- "guan ke ting deng",\
- "wo hui jia le",\
- "da kai jian kong"
- }; /*添加关键词,用户修改*/
- uint8 code pCode[DATE_A] = {
- CODE_CMD,\
- CODE_KCFD,\
- CODE_GCFD,\
- CODE_KELD,\
- CODE_GELD,\
- CODE_KKTD,\
- CODE_GKTD,\
- CODE_WHJL,\
- CODE_DKJK
- }; /*添加识别码,用户修改*/
二、LDCHIP.c文件修改
(1)、这里便是对于地址的修改,注意0x00是一级指令,也就是名字,这里不能修改,其他根据上面的地址符号,对应,可以从0x01开始写
- //识别码客户修改处
- #define CODE_CMD 0x00 //该命令码0x00用户不可进行修改。
- #define CODE_KCFD 0x01 //开厨房灯
- #define CODE_GCFD 0x02 //关厨房灯
- #define CODE_KELD 0x04 //开二楼灯
- #define CODE_GELD 0x05 //关二楼灯
- #define CODE_KKTD 0x16 //开卧室灯
- #define CODE_GKTD 0x17 //关卧室灯
- #define CODE_WHJL 0x2f //开摄像头人脸识别
- #define CODE_DKJK 0x03 //打开监控
-
- //数值越大越灵敏识别距离越远,但误识别率就越大, 根据自己的实际情况调节。
- #define MIC_VOL 0x55 //咪头增益(灵敏度调节) 范围:00-7f
- #endif
三、main.c文件的修改
(1)、因为是使用串口打印,所以当识别成功后,要输出相应的值,这里在对应的switch的case中进行修改,还有在PrintCom写上要串口发生的值,因为这里后面这里发送后,会在树莓派中识别,然后进行相应的运行
- /***********************************************************
- * 名 称:用户执行函数
- * 功 能:识别成功后,执行动作可在此进行修改
- * 入口参数: 无
- * 出口参数:无
- * 说 明:
- **********************************************************/
- void User_handle(uint8 dat)
- {
- //UARTSendByte(dat);//串口识别码(十六进制)
- if(0==dat)
- {
- G0_flag=ENABLE;
- LED=0;
- PrintCom("receive !\r\n"); /*text.....*/
- }
- else if(ENABLE==G0_flag)
- {
- G0_flag=DISABLE;
- LED=1;
- switch(dat) /*对结果执行相关操作,客户可删除Printcom 串口输出语句替换为其他需要控制的代码*/
- {
- case CODE_KCFD: /*命令“测试”*/
- PrintCom("1 KCFD\r\n"); /*text.....*/
- break;
- case CODE_GCFD: /*命令“全开”*/
- PrintCom("2 GCFD\r\n"); /*text.....*/
- break;
- case CODE_KELD: /*命令“复位”*/
- PrintCom("3 KELD\r\n"); /*text.....*/
- break;
- case CODE_GELD: /*命令“复位”*/
- PrintCom("4 GELD\r\n"); /*text.....*/
- break;
- case CODE_KKTD: /*命令“复位”*/
- PrintCom("5 KKTD\r\n"); /*text.....*/
- break;
- case CODE_GKTD: /*命令“复位”*/
- PrintCom("6 GKTD\r\n"); /*text.....*/
- break;
- case CODE_WHJL: /*命令“复位”*/
- PrintCom("7 WHJL\r\n"); /*text.....*/
- break;
- case CODE_DKJK: /*命令“复位”*/
- PrintCom("8 DKJK\r\n"); /*text.....*/
- break;
- default:PrintCom("请重新识别发口令\r\n"); /*text.....*/break;
- }
- }
- else
- {
- PrintCom("please say again once cmd\r\n"); /*text.....*/
- }
- }
四、烧录与语音口令
(1)、使用STC-ISP进行烧录,这里是使用51烧录,相信大家都会,烧录时候,记得拔插一哈GND这根线,方便烧录成功。
(2)、弄好之后,可以打开STC-ISP上面的串口助手,就可以显示,使用方法,以我的来举例。 eg:小明同学 开厨房灯;小明同学 关厨房灯。
(3)、注意:念了一级口令后,上面的知识点会变红,当变红了后,再说出二级口令。
3、树莓派串口编写
(1)、这里的串口模式我们也使用工厂模式来编写,不过在使用串口前,要在树莓派里面进行以下串口配置。
cd /boot
sudo vim cmdline.txt
删除部分内容 console=serial0,115200
然后重启,就可以进行串口模式的编写,还要记住串口要加上#include "wiringSerial.h"
(2)、使用工厂模式进行串口编写
usartinit.c文件,这里进行串口框架编写
- #include "InputCommand.h"
-
- /*
- #include <wiringSerial.h>
-
- fg=serialOpen("/dev/ttyAMA0",9600);
-
-
- struct Inputcommand{
- char commandName[128];
- char command[32];
- int (*Init)(char *name, char *ipAdress, char *port);
- int (*Getcommand)(char *cmd);
- char log[1024];
-
- struct Inputcommand *next;
-
-
-
- };
-
-
- */
-
- int voiceInit(struct Inputcommand *voicer,char *ipAdress, char *port){
- int fg;
- fg=serialOpen(voicer->toolname,9600);
- if(fg==-1){
- printf("ttyAMA0 init error\n");
- return -1;
- }
- voicer->fg=fg; //赋值
-
- return fg; //可能有问题,为什么不是返回的 voicer->fg
-
- }
-
-
- int voiceGetcommand(struct Inputcommand *voicecmd){
- int buf=0;
- memset(voicecmd->command , 0 , sizeof(voicecmd->command));
- buf=read(voicecmd->fg,voicecmd->command,sizeof(voicecmd->command));
- if(buf<=0){
- printf("time over\n"); //这样可以再来,不用退出
- //return -1;
- }
- return buf;
- }
-
-
-
- struct Inputcommand voice={
- .commandName="voicer",
- .command={"0"},
- .toolname="/dev/ttyAMA0",
- .fg=0,
- .Init=voiceInit,
- .Getcommand=voiceGetcommand
-
-
- };
-
- //链表
- struct Inputcommand *insertVoiceList(struct Inputcommand *phead){
- if(phead==NULL){
- phead=&voice;
- return phead;
- }else{
- voice.next=phead;
- phead=&voice;
- return phead;
- }
- }
-
InputCommand.h文件,这里面存放结构体
- //这里面包含了网络和串口的,我就一起写了
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <wiringPi.h>
- #include <wiringSerial.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <string.h>
- #include <strings.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <pthread.h>
-
-
- struct Inputcommand{
- char commandName[128];
- char command[64];
- char toolname[128];
- int fg; //usart
- char port[12];
- char ip[32];
- int s_fd; //socket
- int accpetfg; //如果这里不行,就用全局变量
-
- int (*Init)(struct Inputcommand *voicer,char *ipAdress, char *port);
- int (*Getcommand)(struct Inputcommand *voicecmd);
- char log[1024];
-
- struct Inputcommand *next;
-
-
-
- };
-
-
- struct Inputcommand *insertVoiceList(struct Inputcommand *phead);
- struct Inputcommand *insertSocketList(struct Inputcommand *phead);
-
-
-
-
main.c文件
- #include "contrlDevices.h"
- #include "InputCommand.h"
-
- struct Inputcommand *socketHandler;
- struct Devices *head=NULL;
- struct Inputcommand *cmdhead=NULL; //因为子函数,要调用这个,所以全局变量
- typedef unsigned int bool;
-
-
-
- //设备查找
- struct Devices *foundDeviceslist(char *name,struct Devices *head ){
-
- struct Devices *tmp=head;
- if(head==NULL){
- printf("none is list\n");
- return NULL;
- }else{
- while(tmp !=NULL){
- if(strcmp(tmp->devicename,name) == 0){
- printf("find %s sussendfully\n",tmp->devicename);
- return tmp;
- }
- tmp=tmp->next;
- }
- printf("found %s error\n",name);
- return NULL;
- }
- }
-
-
- //命令查找
- struct Inputcommand *foundInputcommandlist(char *name,struct Inputcommand *head ){
-
- struct Inputcommand *tmp=head;
- if(head==NULL){
- printf("none is list\n");
- return NULL;
- }else{
- while(tmp !=NULL){
- if(strcmp(tmp->commandName,name) == 0){
- printf("find %s sussendfully\n",tmp->commandName);
- return tmp;
- }
- tmp=tmp->next;
- }
- printf("found %s error\n",name);
- return NULL;
- }
- }
-
-
-
-
-
-
- //语音
-
- void *voice_Thread(){
- struct Inputcommand *voiceHandler;
- struct Devices *tmp; //设备赋值
- pthread_t monitorThread;
-
- int nread;
- voiceHandler=foundInputcommandlist("voicer",cmdhead);
- if(voiceHandler==NULL){
- printf("voice can not found\n");
- pthread_exit(NULL);
- }else{
- if(voiceHandler->Init(voiceHandler,NULL,NULL)<0){
- printf("voice init error\n");
- pthread_exit(NULL);
- }else{
- printf("voice main work sussendfully\n");
- while(1){
- memset(voiceHandler->command,0,sizeof(voiceHandler->command));
- nread=voiceHandler->Getcommand(voiceHandler);
- if(nread<=0){
- printf("no voice date\n");
- }
-
- else if(strstr(voiceHandler->command,"receive") != NULL){
- printf("please say second cmd\n");
- }
- //printf("voice is %s\n",voiceHandler->command); //后续开发,就可以加在这个地方,因为 voiceHandler->command就是存放数据的地方,是一个数组,可以就是name
- else if(strstr(voiceHandler->command,"1") != NULL){
- tmp=foundDeviceslist("restaurantlight",head); //重头进去查询
- if(tmp !=NULL){
- //初始化引脚
- tmp->devicesinit(tmp->pin);
- tmp->open(tmp->pin);
- delayMicroseconds(1500000);
-
- printf("open the restaurantlight light\n");
- }
-
- }
-
- else if(strstr(voiceHandler->command,"2") != NULL){
- tmp=foundDeviceslist("restaurantlight",head); //重头进去查询
- if(tmp !=NULL){
- //初始化引脚
- tmp->devicesinit(tmp->pin);
- tmp->close(tmp->pin);
-
- printf("close the restaurantlight light\n");
- }
-
- }
-
- else if(strstr(voiceHandler->command,"3") != NULL){
- tmp=foundDeviceslist("upstairlight",head); //重头进去查询
- if(tmp !=NULL){
- //初始化引脚
- tmp->devicesinit(tmp->pin);
- tmp->open(tmp->pin);
- delayMicroseconds(1500000);
-
- printf("open the upstairlight light\n");
- }
-
- }
-
-
- else if(strstr(voiceHandler->command,"4") != NULL){
- tmp=foundDeviceslist("upstairlight",head); //重头进去查询
- if(tmp !=NULL){
- //初始化引脚
- tmp->devicesinit(tmp->pin);
- tmp->close(tmp->pin);
-
- printf("close the upstairlight light\n");
- }
-
- }
-
-
- else if(strstr(voiceHandler->command,"5") != NULL){
- tmp=foundDeviceslist("livingroomlight",head); //重头进去查询
- if(tmp !=NULL){
- //初始化引脚
- tmp->devicesinit(tmp->pin);
- tmp->open(tmp->pin);
- delayMicroseconds(1500000);
-
- printf("open the livingroomlight light\n");
- }
-
- }
-
-
- else if(strstr(voiceHandler->command,"6") != NULL){
- tmp=foundDeviceslist("livingroomlight",head); //重头进去查询
- if(tmp !=NULL){
- //初始化引脚
- tmp->devicesinit(tmp->pin);
- tmp->close(tmp->pin);
-
- printf("close the livingroomlight light\n");
- }
-
- }
-
-
- else if(strstr(voiceHandler->command,"9") != NULL){
- tmp=foundDeviceslist("bathroomlight",head);
- if(tmp !=NULL){
- //初始化引脚
- tmp->devicesinit(tmp->pin);
- tmp->open(tmp->pin);
- delayMicroseconds(1500000);
-
- printf("open the bathroomlight light\n");
- }
-
- }
-
- else if(strstr(voiceHandler->command,"10") != NULL){
- tmp=foundDeviceslist("bathroomlight",head);
- if(tmp !=NULL){
- //初始化引脚
- tmp->devicesinit(tmp->pin);
- tmp->close(tmp->pin);
-
- printf("close the bathroomlight light\n");
- }
-
- }
-
-
-
- //后续灯,直接加上,写入链表就完事了,很简单的
-
-
-
-
-
- }
- }
- }
- }
-
-
- void *fire_Thread(){
-
- int status;
- struct Devices *firetmp = NULL;
- struct Devices *buztmp = NULL;
-
- firetmp = foundDeviceslist("fire",head);
- if(firetmp != NULL){
- firetmp->devicesinit();
- }
-
- buztmp = foundDeviceslist("fengming",head);
- if(buztmp != NULL){
- buztmp->devicesinit();
- }
-
-
- while(1){
- status = firetmp->readstatus(firetmp->pinNum);
-
- if(status == 0){
- buztmp->open(buztmp->pinNum);
- delay(1000);
- }
-
- if(status == 1){
- buztmp->close(buztmp->pinNum);
- }
-
- }
-
- }
-
-
-
- int main(){
-
- pthread_t voiceThread; //线程最好少用参数
- pthread_t socketThread;
- pthread_t fireThread;
-
-
-
-
- if(wiringPiSetup()==-1){
- printf("wiringPi init error\n");
- return -1;
- }
-
-
-
-
- //设备控制初始化
- //struct Devices *head=NULL; 全局变量
- head=insertbathroomlightlist(head);
- head=insertupstairlightlist(head);
- head=insertlivingroomlightlist(head);
- head=insertrestaurantlightlist(head);
- head=insertfirelist(head);
- head=insertcamerafacelist(head);
- head=insertlockdoorlist(head);
- head=insertmonitortoollist(head);
- head=insertvocielist(head);
-
-
-
-
-
-
-
- //指令工程初始化
- //struct Inputcommand *cmdhead=NULL; 全局变量
- cmdhead=insertVoiceList(cmdhead);
-
-
-
-
- //语音线程
- pthread_create(&voiceThread, NULL, voice_Thread, NULL);
-
- //火灾
- pthread_create(&fireThread, NULL, fire_Thread, NULL);
-
-
-
- pthread_join(voiceThread,NULL);
- pthread_join(fireThread,NULL);
- }
这里我在main.c文件中写完了所有的控制,并且把之前输入模块控制,改成了语音控制,现在使用:小明同学 开二楼灯,就打开相应的灯。
4、socket网络编程
这里我们使用TCP网络编程来实现,也使用工厂模式来编写框架,后面会加上安卓app来控制,这里只介绍服务器框架。
socket.c文件 这里是网络框架
- #include "InputCommand.h"
-
- /*
- #include <wiringSerial.h>
-
- fg=serialOpen("/dev/ttyAMA0",9600);
-
-
- struct Inputcommand{
- char commandName[128];
- char command[32];
- int (*Init)(char *name, char *ipAdress, char *port);
- int (*Getcommand)(char *cmd);
- char log[1024];
-
- struct Inputcommand *next;
-
-
-
- };
-
-
- */
-
- int socketInit(struct Inputcommand *socketer,char *ipAdress, char *port){
- int sockfg;
- int bindfg;
- struct sockaddr_in sin; //这个不是文件描述符,是结构体而已 ,用于构建使用
- //socket
- sockfg=socket(AF_INET,SOCK_STREAM,0);//IPV4 ,TCP
- if(sockfg<0)
- {
- perror("socket error");
- return -1;
- }
-
- //struct jie_gou_ti == 0
- bzero(&sin,sizeof(sin));
-
-
- //bind
- sin.sin_family=AF_INET; //IPV4
- sin.sin_port=htons(atoi(socketer->port)); //socketer->port,这个是字符串,还需要把字符串转为整数int,才能把本地字节序弄成网络字节序
- sin.sin_addr.s_addr=inet_addr(socketer->ip); //IPV4 di_zhi
- //sin.sin_addr.s_addr=INADDR_ANY; //INADDR_ANY will find all IPV4
-
-
- bindfg=bind(sockfg,(struct sockaddr *)&sin ,sizeof(sin));
- if(bindfg<0) //right return 0 ,error return -1
- {
- perror("bind error");
- return -1;
- }
-
- //listen
- int listfg;
- listfg=listen(sockfg,5);//creat 11 list (5*2+1)
- if(listfg<0)
- {
- printf("listen error");
- return -1;
- }
-
- socketer->s_fd=sockfg;
- printf("socket listen sussendfully\n");
-
- return sockfg;
-
- }
-
-
-
-
-
-
-
- int socketGetcommand(struct Inputcommand *socketercmd){
- int accefg=-1;
- int nread=0;
- struct sockaddr_in cin;
-
- memset(&cin,0,sizeof(struct sockaddr_in));
- socklen_t socklend=sizeof(cin);
-
- accefg=accept(socketercmd->s_fd,(struct sockaddr *)&cin,&socklend); //socketercmd->s_fd 要用上面初始化的函数才可以进行,也就是上面一个的初始化过程 cin不是文件描述符
- if(accefg<0){
- perror("accept arror");
- return -1;
- }
-
- nread=read(accefg,socketercmd->command,sizeof(socketercmd->command)); //接收就是用新的了,如同 accept就是新的了 ,cin又不是文件描述符
- if(nread<0){
- printf("read error is <0 \n");
- return -1;
- }else if(nread==0){
- printf("socket time out\n");
- }else{
- printf("read is : %d \n",nread);
- }
-
- return nread;
- }
-
-
-
- struct Inputcommand socketer={
- .commandName="socket",
- .command={"0"},
- .port="5006",
- .ip="192.168.43.???",//这里写自己电脑的ip地址
- .s_fd=0,
- .accpetfg=0,
-
- .Init=socketInit,
- .Getcommand=socketGetcommand
-
-
- };
-
- //链表
- struct Inputcommand *insertSocketList(struct Inputcommand *phead){
- if(phead==NULL){
- phead=&socketer;
- return phead;
- }else{
- socketer.next=phead;
- phead=&socketer;
- return phead;
- }
- }
-
-
InputCommand.h文件,这里面存放结构体
- //这里面包含了网络和串口的,我就一起写了
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <wiringPi.h>
- #include <wiringSerial.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <string.h>
- #include <strings.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <pthread.h>
-
-
- struct Inputcommand{
- char commandName[128];
- char command[64];
- char toolname[128];
- int fg; //usart
- char port[12];
- char ip[32];
- int s_fd; //socket
- int accpetfg; //如果这里不行,就用全局变量
-
- int (*Init)(struct Inputcommand *voicer,char *ipAdress, char *port);
- int (*Getcommand)(struct Inputcommand *voicecmd);
- char log[1024];
-
- struct Inputcommand *next;
-
-
-
- };
-
-
- struct Inputcommand *insertVoiceList(struct Inputcommand *phead);
- struct Inputcommand *insertSocketList(struct Inputcommand *phead);
-
-
main.c文件
- void *read_Thread(){
- int nread;
- memset(socketHandler->command , 0 , sizeof(socketHandler->command));
- nread=read(socketHandler->accpetfg,socketHandler->command,sizeof(socketHandler->command)); //接收就是用新的了,如同 accept就是新的了 ,cin又不是文件描述符
- if(nread<0){
- perror("socket read");
- }else if(nread==0){
- printf("socket time out\n");
- }else{
- printf("read is : %d and %s \n",nread,socketHandler->command);
- }
-
- }
-
-
- void *socket_Thread(){
- pthread_t read;
- int accpetfg=0;
- struct sockaddr_in cin;// 配置
- memset(&cin,0,sizeof(struct sockaddr_in));
- socklen_t clen=sizeof(cin);
-
- socketHandler=foundInputcommandlist("socket",cmdhead);
- if(socketHandler==NULL){
- printf("socket not found \n");
- pthread_exit(NULL);
- }else{
- socketHandler->Init(socketHandler,NULL,NULL);
- printf("socket TCP main work sussendfully\n");
- while(1){
-
- socketHandler->accpetfg=accept(socketHandler->s_fd,(struct sockaddr *)&cin, &clen);
- pthread_create(&read,NULL,read_Thread,NULL);
- }
- }
- }
-
-
-
- int main(){
-
- pthread_t voiceThread; //线程最好少用参数
- pthread_t socketThread;
- pthread_t fireThread;
-
-
-
-
- if(wiringPiSetup()==-1){
- printf("wiringPi init error\n");
- return -1;
- }
-
-
-
-
-
-
-
- //指令工程初始化
- //struct Inputcommand *cmdhead=NULL; 全局变量
- cmdhead=insertSocketList(cmdhead);
-
-
- //socket
- pthread_create(&socketThread, NULL, socket_Thread, NULL);
-
-
-
-
- pthread_join(socketThread,NULL);
-
- }
这里我只写了网络需要写的,其实加上之前的main.c里面就可以,这里的main.c写的是伪代码。写好的可以通过网络调试助手进行检验。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。