当前位置:   article > 正文

智能家具项目_项目名称:项目3智意家居 任务名称:任务1双机单工通信(发送) 任务内容:通过串

项目名称:项目3智意家居 任务名称:任务1双机单工通信(发送) 任务内容:通过串

本项目使用工厂模式来编写代码,其中包括指令工厂和设备工厂,使用工厂模式的目的是为了让各模块代码更加独立,并且让C语言具有所谓的面向对象的属性;
本项目使用树莓派作为主控芯片,开发环境选择ubuntu下的Linux,通过使用交叉编译工具链,将x86架构下的代码,交叉编译成为arm架构下可执行程序,置于树莓派中;
控制方案采用socket网络控制线程和串口控制线程,其中串口控制使用的是LD3320语音模块,通过对该模块的二次开发,使其成为能够在特定语音环境下向串口输出特定的字符串,与树莓派通过串口进行通信,在树莓派获得LD3320发送的数据后经过相应的处理,来对设备进行控制;socket网络控制采用TCP协议,通过IP地址和端口号与树莓派建立连接,通过向树莓派发送数据,树莓派接收到相应数据之后进行处理,实现对设备的控制;
为了实现可以使用Android手机进行控制,在eclipse中使用java开发手机app,利用java的socket类实现手机和服务端相连,通过按钮发送特定的字符串到服务端,服务端接收到字符串,解析字符串并调用相关函数对设备进行操作;

指令工程头文件:inputCommand.h

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


struct InputCommand{
	char commandName[128];                  //命令控制名(串口控制/语音控制)
	char deviceName[128];                   //用于调用open函数传递设备名称
	char command[32];         				//获得命令后存放于command中
	int (*init)(struct InputCommand *device ,char * ipAddress,char *port);           //对串口和socket进行初始化的init()函数  
	int (*getCommand)(struct InputCommand *device);   		//通过串口和socket获取命令函数
	int fd;													//用于socket()返回的文件描述符
	char port[12];											//用于socket连接时的端口号
	char ipAddress[32];										//用于socket连接时的IP地址
 	char log[1024];											//用于记录命令记录

	struct InputCommand *next;
};


struct InputCommand *addVoiceIntoCommandLink(struct InputCommand *head);    //将语音控制加入到指令工厂链表中,让main.c调用
struct InputCommand *addSocketIntoCommandLink(struct InputCommand *head);   //将socket命令加入到指令链表中,好让main.c调用

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

设备工厂头文件 controlDevice.h

#include <stdio.h>
#include <wiringPi.h>
struct Devices{
		char deviceName[128];       //设备名称
		int status;             	//谁被当前状态
		int pinNum;                 //设备连接到树莓派的引脚
		int (*open)(int pinNum);    //开启设备函数指针
		int (*close)(int pinNum);   //关闭设备函数指针
		int (*deviceinit)(int pinNum);   //初始化设备函数指针

		int (*readStatus)();      //获取当前设备状态指针
		int (*changeStatus)(int status,int pinNum);    //改变当前设备状态函数指针   

		struct Devices* next;
};


struct Devices *addBathRoomIntoLink(struct Devices *head);  //将设备放入到设备工厂中,方便后面main函数调用
struct Devices *addBedRoomIntoLink(struct Devices *head);
struct Devices *addlockIntoLink(struct Devices *head);
struct Devices *addtoiletIntoLink(struct Devices *head);
struct Devices *addFireIntoLink(struct Devices *head);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

设备1源文件 :bathroom.c

#include "controlDevice.h"

int bathRoomInit(int pinNum)      //设备初始化函数
{
	pinMode(pinNum,OUTPUT);       //配置引脚为输出模式
	digitalWrite(pinNum,HIGH);    //初始化状态
	return 0;
}

int bathRoomopen(int pinNum)    //开启设备函数
{	
	digitalWrite(pinNum,LOW);   //将引脚置低
	return 0}

int bathRoomClose(int pinNum)   //关闭设备函数
{
	digitalWrite(pinNum,HIGH);  
	return 0;
}

int bathroomchange(int status,int pinNum)        //改变设备状态函数
{
	return 0;
}

struct Devices bathRoom = {
	.pinNum = 22,                    //设备引脚为22
	.deviceName = "bathRoomLight",   //设备名称
	.deviceinit = bathRoomInit,      //为设备初始化函数指针赋值
	.open = bathRoomopen,            //设备开启函数指针
	.close = bathRoomClose,          //设备关闭函数指针
	.changeStatus = bathroomchange   //设备状态改变函数指针

     .next = NULL;
};

struct Devices *addBathRoomIntoLink(struct Devices *head)    //将设备放入链表函数实现
{
		if(head == NULL){
			head = &bathRoom;
		}else{
			bathRoom.next = head;
			head = &bathRoom;
		}

		return head;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

设备2源文件:bedroom.c

#include "controlDevice.h"

int bedRoomInit(int pinNum)     //设备初始化函数
{
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
	return 0;
}

int bedRoomopen(int pinNum)       //开启设备函数
{	
	digitalWrite(pinNum,LOW);
	return 0;
}

int bedRoomClose(int pinNum)      //关闭设备函数
{
	digitalWrite(pinNum,HIGH);
	return 0;
}

int bedroomchange(int status,int pinNum)    //改变状态函数
{
	return 0;
}

struct Devices bedRoom = {
	.pinNum = 23,                   //连接到树莓派的引脚
	.deviceName = "bedRoomLight",   //设备名
	.deviceinit = bedRoomInit,      //设备初始化
	.open = bedRoomopen,            //开启设备 
	.close = bedRoomClose,          //关闭设备
	.changeStatus = bedroomchange   //改变设备状态

     .next = NULL;
};

struct Devices *addBedRoomIntoLink(struct Devices *head)     //将设备放入到设备链表中
{
		if(head == NULL){
			head = &bedRoom;
		}else{
			bedRoom.next = head;
			head = &bedRoom;
		}

		return head;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

设备3源文件 fire.c

#include "controlDevice.h"

int fireInit(int pinNum)   //设备初始化
{
	pinMode(pinNum,INPUT);
	digitalWrite(pinNum,HIGH);
}

int fireReadStatus(int pinNum)   //读取当前设备状态
{
	return digitalRead(pinNum);
}


struct Devices fire = {
	.pinNum = 4,                    //连接到树莓派引脚
	.deviceName = "fireDetect",     //设备名
	.deviceinit = fireInit,         //设备初始化
	.readStatus = fireReadStatus    //读取设备状态
	.next = NULL;
};

struct Devices *addFireIntoLink(struct Devices *head)              //将设备放入到设备链表中
{
		if(head == NULL){
			head = &fire;
		}else{
			fire.next = head;
			head = &fire;
		}

		return head;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

设备4源文件:lock.c

#include "controlDevice.h"

int lockInit(int pinNum)                //初始化设备
{
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

int lockopen(int pinNum)               //打开设备
{	
	digitalWrite(pinNum,LOW);
}

int lockClose(int pinNum)              //关闭设备
{
	digitalWrite(pinNum,HIGH);
}

int lockchange(int status,int pinNum)     //改变设备状态
{

}

struct Devices lock = {
	.pinNum = 24,                  //连接到树莓派的引脚 
	.deviceName = "lock",          //设备名称
	.deviceinit = lockInit,        //初始化设备
	.open = lockopen,              //打开设备
	.close = lockClose,            //关闭设备
	.changeStatus = lockchange     //改变设备状态

	.next = NULL;
};

struct Devices *addlockIntoLink(struct Devices *head)                 //将设备放入到设备链表中
{
		if(head == NULL){
			head = &lock;
		}else{
			lock.next = head;
			head = &lock;
		}

		return head;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

socket网络控制源文件 socketComand.c

#include "inputCommand.h"

int socketInit(struct InputCommand* socketMsg ,char * ipAddress,char *port)          //socket网络初始化,IP地址和端口号在结构体struct InputCommand* socketMsg中
{
	int s_fd;        //socket()函数的文件描述符
	int bind_ret;    //bind()函数的返回值
	struct sockaddr_in s_addr;   //用于定义连接信息的结构体
	
	memset(&s_addr,0,sizeof(struct sockaddr_in));   //将上述结构体先清空
	
	s_fd = socket(AF_INET,SOCK_STREAM,0);           //socket函数,定义网络协议
	if(s_fd ==-1){                                  //判断是否创建成功
		perror("socket");
		exit(-1);
	}
	
	s_addr.sin_family = AF_INET;            //选择协议簇为IPV4
	s_addr.sin_port = htons(atoi(socketMsg->port));      //设置端口号,由于结构体中是字符串,所以需要转换整型,并且将字节序转换为网络字节序 

	inet_aton(socketMsg->ipAddress,&s_addr.sin_addr);   //对结构体总的IP地址进行定义 
	
	bind_ret = bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));    //绑定
	if(bind_ret == -1){                              //判断是否绑定成功
		perror("bind");
		exit(-1);
	}

	int listen_ret;
	listen_ret = listen(s_fd,10);                  //监听

	if(listen_ret == -1){					       //判断监听是否成功
		perror("listen");
		exit(-1);
	}else{
		printf("listening....\n");
	}
	
	socketMsg->fd = s_fd;                         //将socket函数返回的文件描述符赋值给socket命令的结构体中,方便之后应用
	return s_fd;
}

int socketGetCommand(struct InputCommand* socketMsg)       //socket获取命令函数
{
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof(struct sockaddr_in));             
	
	int  c_addr_len = sizeof(struct sockaddr_in);
	int c_fd = accept(socketMsg->fd,(struct sockaddr *)&c_addr,&c_addr_len);     //接受完成三次握手的连接

	if(c_fd == -1){                     //判断是否接受成功

		perror("accept");
		exit(-1);
	}
	printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));
	//read
	memset(socketMsg->command,'\0',sizeof(socketMsg->command));         //将结构体中的命令清空,防止上一次的命令影响下一次命令
	int nread = read(c_fd,socketMsg->command,sizeof(socketMsg->command));      //读取信息
	if(nread ==-1){
		printf("read failure\n");
	}else if(nread >0){
		printf("read from client  %d byte,context:%s",nread,sizeof(socketMsg->command));   //打印信息
	}else{
		printf("client quit!\n");
	}

	return nread;
}


struct InputCommand socketControl = {           //初始化socket命令结构体
	.commandName = "socketServer",              //命令名称
	.command = {'\0'},                          //调用getCommand函数得到的命令赋值给command
	.ipAddress = "192.168.43.80",               //树莓派IP地址
	.port = "8088",							    //端口号
	.init = socketInit,                         //socket初始化函数
	.getCommand = socketGetCommand,             //获取指令函数
	.log = {'\0'},                              //命令记录
	.next = NULL
};


struct InputCommand *addSocketIntoCommandLink(struct InputCommand *head)        //将指令放入到指令工厂中
{
	if(head == NULL){
		head = &socketControl;
	}else{
		socketControl.next = head;
		head = &socketControl;
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

语音指令源文件voiceControl.c

#include "inputCommand.h"

int voiceInit(struct InputCommand* voice ,char * ipAddress,char *port)       //语音控制初始化
{
	int fd;                                                                 //串口打开文件描述符
	if((fd = serialOpen(voice->deviceName,9600)) == -1){                   //打开串口
			exit(-1);
	}
	voice->fd = fd;                                                        //将文件描述符赋值到语音控制结构体中的fd
	return fd;
}

int voiceGetCommand(struct InputCommand* voice)                              //语音获取命令函数
{
	int nread = 0;
	memset(voice->command,'\0',sizeof(voice->command));                     //这里将结构体中的命令清除是防止上一次的命令遗留,影响下一次命令
	nread = read(voice->fd,voice->command,sizeof(voice->command));          //读取命令
	return nread;
}


struct InputCommand voiceControl = {
	.commandName = "voiceControl",             //命令名
	.command = {'\0'},                         //调用getCommand函数获取的指令存放于这
	.deviceName = "/dev/ttyAMA0",		       //调用open打开串口是需要用的串口文件路径
	.init = voiceInit,                         //串口初始化函数
	.getCommand = voiceGetCommand,             //获取命令函数
	.log = {'\0'},                             //命令记录
	.next = NULL
};


struct InputCommand *addVoiceIntoCommandLink(struct InputCommand *head)       //将命令放入到指令工厂中
{
	if(head == NULL){
		head = &voiceControl;
	}else{
		voiceControl.next = head;
		head = &voiceControl;
	}
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

主函数main.c

#include "controlDevice.h"
#include "inputCommand.h"
#include <string.h>
struct Devices *deviceHead = NULL;      //因为函数中会用到这些变量,而且使用的是多线程,尽量避免传参,因此使用全局变量
struct InputCommand *commandHead = NULL;
struct InputCommand *socketHandler = NULL;
int c_fd;

struct Devices *findDeviceInLink(char *name,struct Devices *head)     //根据设备名从设备工厂链表中找到对应设备
{
	if(head == NULL){
		printf("the link is empty\n");
		return NULL;
	}
	while(head != NULL){
		if(strcmp(head->deviceName,name)==0){
			return head;
		}
		head = head->next;
	}

	return NULL;
}

struct InputCommand *findCommandDeviceInLink(char *name,struct InputCommand *head)    //从命令工厂中找到对应命令
{
	if(head == NULL){
		printf("the link is empty\n");
		return NULL;
	}
	while(head != NULL){
		if(strcmp(head->commandName,name)==0){
			return head;
		}
		head = head->next;
	}

	return NULL;
}

void controlDeviceDoCommand(char *command)   //语音线程和socket线程在接收到客户端的命令的时候调用这个函数,会对设备进行操作
{
	if(strstr(command,"bath") != NULL){       //判断是否为bathroom的命令
			struct Devices *BathRoom = findDeviceInLink("bathRoomLight",deviceHead);    //在设备工厂链表中找到该设备
			BathRoom->deviceinit(BathRoom->pinNum);   //初始化设备
			if(strstr(command,"open") != NULL){       //判断获得的指令是不是开
					BathRoom->open(BathRoom->pinNum);    //如果是开就调用设备open函数指针
			}else if(strstr(command,"close") != NULL){  
					BathRoom->close(BathRoom->pinNum);  //如果是关则调用设备close函数指针
			}
	}else if(strstr(command,"bed") != NULL){   //bedroom
			struct Devices *BedRoom = findDeviceInLink("bedRoomLight",deviceHead);
			BedRoom->deviceinit(BedRoom->pinNum);   //init  device;
			if(strstr(command,"open") != NULL){       //open command
					BedRoom->open(BedRoom->pinNum);
			}else if(strstr(command,"close") != NULL){  //close  command
					BedRoom->close(BedRoom->pinNum);
			}
	}else if(strstr(command,"lock") != NULL){   //bedroom
			struct Devices *Lock = findDeviceInLink("lock",deviceHead);
			Lock->deviceinit(Lock->pinNum);   //init  device;
			if(strstr(command,"open") != NULL){       //open command
					Lock->open(Lock->pinNum);
			}else if(strstr(command,"close") != NULL){  //close  command
					Lock->close(Lock->pinNum);
			}
	}else{                                 //如果收到的指令并没有对应的设备,则打印信息
		printf("no such device\n");
	}
}

void *voice_threadFunc(void *data)				//语音线程函数
{
	 struct InputCommand *voiceHandler = NULL;
	 int nread;
	 voiceHandler = findCommandDeviceInLink("voiceControl",commandHead);   //在指令工厂中寻找语音控制指令
	 if(voiceHandler == NULL){							//判断是否找到命令结构体
			printf("find voiceHandler error\n");
			pthread_exit(NULL);
	 }else{
		if(voiceHandler->init(voiceHandler,NULL,NULL)<0){       //找到结构体后对命令进行初始化
			printf("voice init error\n");
			pthread_exit(NULL);									//初始化不成功退出线程
		}else{
			printf("%s init success\n",voiceHandler->commandName);  //调试信息
		}
		
		while(1){                                               //为了能够一直读信息使用死循环                  
				nread = voiceHandler->getCommand(voiceHandler);    //读取指令
				if(nread == 0){
					printf("no data from voice\n");
				}else{
					printf("get command:%s\n",voiceHandler->command);   //打印读取的信息用于调试
					controlDeviceDoCommand(voiceHandler->command);      //获取到命令后调用控制设备的函数
				}
			}
	 }
}

void * socketReadFunc(void *data)
{	
	while(1){                     //为了让socket能够持续读取加一个死循环
		memset(socketHandler->command,'\0',sizeof(socketHandler->command));
		int nread = read(c_fd,socketHandler->command,sizeof(socketHandler->command));
		if(nread == 0){
				printf("no data from voice\n");
		}else if(nread<0){
				printf("socket read error\n");
				pthread_exit(NULL);
		}else{
				printf("get command:%s\n",socketHandler->command);
				controlDeviceDoCommand(socketHandler->command);       //获取到客户端的命令之后调用处理函数

		}
	}
}

void *socket_threadFunc(void *data)             //socket网络命令控制线程
{
	struct sockaddr_in c_addr;               
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	
	int  c_addr_len = sizeof(struct sockaddr_in);
	 
	pthread_t socketRead;                 //socket读信息线程
	 socketHandler = findCommandDeviceInLink("socketServer",commandHead);     //在指令链表中按照指令明寻找到对应的命令
	 if(socketHandler == NULL){                          //判断是否找到socket命令
	 	printf("find socketHandler error\n");	
		pthread_exit(NULL);
	 }else{
		printf("%s init success\n",socketHandler->commandName);    //打印读取信息进行调试
	 }

	 int s_fd = socketHandler->init(socketHandler,NULL,NULL);		//初始化命令
	 while(1){
		c_fd = accept(socketHandler->fd,(struct sockaddr *)&c_addr,&c_addr_len);    //获取完成三次握手的连接
		pthread_create(&socketRead,NULL,socketReadFunc,NULL);		//线程读取信息函数创建
	 }
	
}

int main()
{
	if(wiringPiSetup() == -1){
		return -1;
	}

	pthread_t voice_thread;
	pthread_t socket_thread;
	pthread_t camera_thread;
	pthread_t fire_thread;
	
   char name[128];
  
   deviceHead = addBathRoomIntoLink(deviceHead);              //添加设备进设备工厂链表
   deviceHead = addBedRoomIntoLink(deviceHead);
   deviceHead = addtoiletIntoLink(deviceHead);
   deviceHead = addlockIntoLink(deviceHead);
   deviceHead = addFireIntoLink(deviceHead);

   commandHead = addVoiceIntoCommandLink(commandHead);         //添加指令进指令工厂链表
   commandHead = addSocketIntoCommandLink(commandHead);

   pthread_create(&voice_thread,NULL,voice_threadFunc,NULL);          //创建语音控制线程
   pthread_create(&socket_thread,NULL,socket_threadFunc,NULL);		  //创建网络控制线程
   
   pthread_join(voice_thread,NULL);                                //线程等待
   pthread_join(socket_thread,NULL);
   
	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172

使用Qt实现的串口调试助手,用于串口控制设备
界面布局:
在这里插入图片描述
widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSerialPort>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    bool getPortInfo();      //设置串口信息,返回是否打开串口

private slots:
    void on_openButton_clicked();    //串口开关槽函数

    void on_sendButton_clicked();    //发送按钮槽函数

    void on_SerialPoirtReadyRead();    //串口接收数据槽函数

private:
    Ui::Widget *ui;

    bool buttonStatus;   //定义打开按钮状态
    QString m_PortName;  //定义端口名字
    QString m_Baudrate;  //定义波特率
    QString m_databit;   //定义数据位
    QString m_checkbit;  //定义校验位
    QString m_stop;      //定义停止位

    QSerialPort  m_serialPort;  //定义串口

};
#endif // WIDGET_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QList>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    buttonStatus = false;
    ui->sendButton->setEnabled(false);   //当串口是关闭状态时发送按钮不能点击
    QList<QSerialPortInfo>ListPort =QSerialPortInfo::availablePorts();    //将可用的串口设置为List
    int cnt =ListPort.count();      //统计有多少个可用的串口
    for(int i = 0;i<cnt;i++){
        ui->portBox->addItem(ListPort.at(i).portName());    //将串口智能添加到portBox中
    }

    //接收区数据不能认为输入
    ui->receive->setEnabled(false);

    connect(&m_serialPort,SIGNAL(readyRead()),this,SLOT(on_SerialPoirtReadyRead()));

    //清空接收区数据
    connect(ui->cleanreceive,&QPushButton::clicked,[=](){
        ui->receive->clear();
    });

    //清空发送区数据
    connect(ui->cleansend,&QPushButton::clicked,[=](){
       ui->send->clear();
    });
}

Widget::~Widget()
{
    delete ui;
}

bool Widget::getPortInfo(){
    //获取串口配置
    m_PortName = ui->portBox->currentText();
    m_Baudrate = ui->baudBox->currentText();
    m_databit = ui->dataBit->currentText();
    m_checkbit = ui->checkBit->currentText();
    m_stop = ui->stopBit->currentText();

    //设置串口配置
    m_serialPort.setPortName(m_PortName); //设置串口

    if(m_Baudrate == "9600"){   //ui界面中波特率是字符串形式,所以要进行判断,然后在设置的时候设置成int形式
        m_serialPort.setBaudRate(9600);
    }else if(m_Baudrate == "19200"){
         m_serialPort.setBaudRate(19200);
    }else if(m_Baudrate == "115200"){
         m_serialPort.setBaudRate(115200);
    }

    if(m_databit == "5"){        //设置数据位
        m_serialPort.setDataBits(QSerialPort::Data5);
    }else if(m_databit == "6"){
         m_serialPort.setDataBits(QSerialPort::Data6);
    }else if(m_databit == "7"){
        m_serialPort.setDataBits(QSerialPort::Data7);
    }else if(m_databit == "8"){
        m_serialPort.setDataBits(QSerialPort::Data8);
    }

    if(m_checkbit == "None"){    //设置校验位
        m_serialPort.setParity(QSerialPort::NoParity);
    }else if(m_checkbit == "Odd"){
        m_serialPort.setParity(QSerialPort::OddParity);
    }else if(m_checkbit == "Even"){
        m_serialPort.setParity(QSerialPort::EvenParity);
    }

    if(m_stop == "1"){          //设置停止位
        m_serialPort.setStopBits(QSerialPort::OneStop);
    }else if(m_stop == "2"){
        m_serialPort.setStopBits(QSerialPort::TwoStop);
    }

    m_serialPort.open(QSerialPort::ReadWrite);
    return m_serialPort.isOpen();
}

void Widget::on_openButton_clicked()   //打开串口槽函数
{
        if(buttonStatus == true){      //串口助手处于打开状态时按下按钮
            m_serialPort.close();
            ui->openButton->setText("打开");
            buttonStatus = false;
            ui->baudBox->setEnabled(true);        //因为处于关闭状态所以将设置使能
            ui->dataBit->setEnabled(true);
            ui->portBox->setEnabled(true);
            ui->checkBit->setEnabled(true);
            ui->stopBit->setEnabled(true);
            ui->sendButton->setEnabled(false);
        }else{                         //串口助手处于关闭状态时按下按钮
            if(getPortInfo() == true){
                ui->openButton->setText("断开");
                buttonStatus = true;

                ui->baudBox->setEnabled(false);   //因为处于开启状态所以将设置失能
                ui->dataBit->setEnabled(false);
                ui->portBox->setEnabled(false);
                ui->checkBit->setEnabled(false);
                ui->stopBit->setEnabled(false);
                ui->sendButton->setEnabled(true);
            }else{
                buttonStatus = false;    //设置按钮状态为关闭
            }
        }
}

void Widget::on_sendButton_clicked()  //发送数据槽函数
{
    if(buttonStatus == true){     //当串口是打开状态
        m_serialPort.write(ui->send->toPlainText().toStdString().c_str());   //转换成字符串指针
    }

}

void Widget::on_SerialPoirtReadyRead()   //接收数据槽函数
{
    if(buttonStatus == true){     //当串口是打开状态
        QByteArray recvData = m_serialPort.readAll();
        ui->receive->append(QString(recvData));   //追加到之前的信息之后防止之前的信息被覆盖掉
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132

使用JAVA在eclipse中创建Android程序实现手机控制:
监控使用的是mjpg-stream,利用花生壳,对其实现了一个内外那个穿透,让外网可以访问到我的局域网;
在这里插入图片描述
UI界面布局:
activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   	android:background="@drawable/abc"
    tools:context=".MainActivity" >

    <WebView       //网页,用于打开监控界面
        android:id="@+id/wb"
        android:layout_height="650dp"
        android:layout_width="match_parent"
        android:layout_marginTop="10dp"
        />
    
    <LinearLayout     //线性布局按钮
        android:layout_alignParentBottom="true"
	    android:layout_width="match_parent"        
        android:layout_height="wrap_content"
        android:layout_marginBottom="30dp"
        android:orientation="vertical"
        android:layout_centerHorizontal="true"
        >
         <LinearLayout 
        
        android:layout_width="match_parent"
        android:id="@+id/openbutton"
        android:layout_height="80dp"  
        android:layout_weight="1" 
        android:orientation="horizontal"
		android:layout_centerHorizontal="true"
        >
        <Button
            android:id="@+id/bedopen"
            android:layout_weight="1"
            android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:onClick="sendMes"                //按钮点击时的函数,类似于Qt中的信号
			android:text="开卧室灯"             
            />
        <Button
            android:id="@+id/bathopen"
            android:layout_weight="1"
            android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:onClick="sendMes"
			android:text="开卫生间灯"             
            />
        <Button
            android:id="@+id/lockopen"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:onClick="sendMes"
			android:layout_height="wrap_content"
			android:text="开厨房灯"             
            />
    </LinearLayout>
     <LinearLayout 
      
        android:layout_width="match_parent"
        android:layout_below="@id/openbutton"
        android:layout_height="80dp"
        android:layout_weight="1"
        android:orientation="horizontal"
		android:layout_centerInParent="true"
        >

        <Button
            android:id="@+id/bedclose"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="sendMes"
            android:text="关卧室灯" />

        <Button
            android:id="@+id/bathclose"
            android:layout_weight="1"
            android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:onClick="sendMes"
			android:text="关卫生间灯"             
            />
        <Button
            android:id="@+id/lockclose"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:onClick="sendMes"
			android:layout_height="wrap_content"
			android:text="关厨房灯"             
            />
    </LinearLayout>
    </LinearLayout>
   
   
   

</RelativeLayout>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98

MainAcitvity.java

package com.example.caohai;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        WebView wb = (WebView) findViewById(R.id.wb);     //创建的网页访问,使用网页控件需要取AndroidManifest.xml中把使用网络权限打开
        wb.loadUrl("http://4d1842z006.zicp.vip");         //设置网页访问的内容
        wb.setWebViewClient(new WebViewClient());        //防止网页先进入默认网址
    }

    public void sendMesHandler(final String deviceCommand){      //封装的向服务端发送信息的函数
    	new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				Socket client;
				try {
					client = new Socket("192.168.43.80",8088);
					OutputStream out = client.getOutputStream();
					
					out.write(deviceCommand.getBytes());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				
			}
		}){}.start();
    }
    
    public void sendMes(View V){
    	switch(V.getId()){                //不同按钮按下之后对应的发送命令处理函数
    		case R.id.bathclose :     
    			sendMesHandler("bathclose");	
    			break;
    		case R.id.bathopen:
    			sendMesHandler("bathopen");
    			break;
    		case R.id.bedclose:
    			sendMesHandler("bedclose");
    			break;
    		case R.id.bedopen:
    			sendMesHandler("bedopen");
    			break;
    		case R.id.lockclose:
    			sendMesHandler("lockclose");
    			break;
    		case R.id.lockopen:
    			sendMesHandler("lockopen");
    			
    	}
    }
   
    
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/689176
推荐阅读
相关标签
  

闽ICP备14008679号