Smart Home Based on Raspberry Pi 4B

foreword

The Raspberry Pi 4B used in the smart home in this blog post is used as the driver board. Of course, the STM32 driver board equipped with freeRtos can also be used. Due to the rush of time, there is no way to write the tutorial from 0 to 1 in the blog post. If I have time in the future, I will A blog post about building this smart home from 0 to 1 will be published, and some new functions will be added at that time, such as touch screen, infrared remote control, and so on.
insert image description here

Simple factory pattern in C language

Introduction to factory pattern

The factory pattern is one of the most commonly used design patterns, which belongs to the creation pattern and provides an optimal way to create objects. In the factory mode, when an object is created, the creation logic is not exposed to the client, and a common interface is used to point to the newly created object.That is, the factory mode separates the two processes of creating objects and using objects. For users who don't need to care about how the objects are created, they can directly specify an object to use the method of the object.

  • C language is not an object-oriented language, but a process-oriented language, but C language also supports object-oriented programming, that is, supports simple factory mode.
  • The factory mode is the inheritance of classes. The C language uses function pointers to implement class inheritance. The devices in the factory are linked by a linked list.

classes and objects

  • Class : A user-defined data type, also known as a class type, such as a structure.
  • Object : An instantiation of a class, such as a struct assignment.

Advantages and disadvantages of factory pattern

advantage

  • When creating an object, you only need to know the name of the object, and the code is highly maintainable.
  • When you need to add a device, you only need to add an object, code scalability.

shortcoming

  • Code readability becomes complicated.
  • When the number of devices increases, the number of objects increases, which increases the complexity of the code.

Smart Home Framework

The smart home introduced in this blog post consists of two factories and several devices, namely the product factory and the instruction factory. Contains the following functions:
The figure is an example of a factory producing only one device

product factory

The factory is mainly used to produce some equipment for people to use, such as lighting equipment, equipment for collecting environmental data, testing safety equipment and so on.

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

//创建产品工厂的类,即产品工厂的生产线
struct Devices
{
    
    
	char devicesName[128];  //设备名称
	int status;  //设备状态
	int pinNum;  //设备引脚
	unsigned long databuf;  //设备数据存储区
	
	/* 设备功能 */
	int (*open)(int pinNum);
	int (*close)(int pinNum);
	int (*devicesInit)(int pinNum);
	int (*readStatus)(int pinNum);
	int (*changeStatus)(int status);
	int (*readData)(struct Devices *devices,int pinNum);
	
	struct Devices *next;  //链表链接节点
};

/* 告知工厂,对应的设备已经上线成为商品了 */
struct Devices* addBashroomLightToDevicesLink(struct Devices *phead);
struct Devices* addsecondfloorLightToDevicesLink(struct Devices *phead);
struct Devices* addrestaurantLightToDevicesLink(struct Devices *phead);
struct Devices* addlivingroomLightToDevicesLink(struct Devices *phead);
struct Devices* addswimmingLightToDevicesLink(struct Devices *phead);
struct Devices* addlockToDevicesLink(struct Devices *phead);
struct Devices* addfireToDevicesLink(struct Devices *phead);
struct Devices* addbuzzerToDevicesLink(struct Devices *phead);
struct Devices* addishockToDevicesLink(struct Devices *phead);
struct Devices* addfanToDevicesLink(struct Devices *phead);
struct Devices* addsensorToDevicesLink(struct Devices *phead);

.

Bathroom lighting equipment

#include "controlDevices.h"

int bashroomLightOpen(int pinNum)
{
    
    
	digitalWrite(pinNum,LOW);
}

int bashroomLightClose(int pinNum)
{
    
    
	digitalWrite(pinNum,HIGH);
}

int bashroomLightInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 继承产品工厂的类,生产卫生间灯设备 */
struct Devices bashroomLight = {
    
    
	.devicesName = "bathroom",
	.pinNum = 23,
	.open = bashroomLightOpen,
	.close = bashroomLightClose,
	.devicesInit = bashroomLightInit,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addBashroomLightToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &bashroomLight;
		return phead;
	}else{
    
    
		bashroomLight.next = phead;
		phead = &bashroomLight;
		return phead;
	}
}

.

Lighting equipment on the second floor

#include "controlDevices.h"

int secondfloorLightOpen(int pinNum)
{
    
    
	digitalWrite(pinNum,LOW);
}

int secondfloorLightClose(int pinNum)
{
    
    
	digitalWrite(pinNum,HIGH);
}

int secondfloorLightInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 继承产品工厂的类,生产二楼灯设备 */
struct Devices secondfloorLight = {
    
    
	.devicesName = "secondfloor",
	.pinNum = 21,
	.open = secondfloorLightOpen,
	.close = secondfloorLightClose,
	.devicesInit = secondfloorLightInit,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addsecondfloorLightToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &secondfloorLight;
		return phead;
	}else{
    
    
		secondfloorLight.next = phead;
		phead = &secondfloorLight;
		return phead;
	}
}

.

Restaurant Lighting Equipment

#include "controlDevices.h"

int restaurantLightOpen(int pinNum)
{
    
    
	digitalWrite(pinNum,LOW);
}

int restaurantLightClose(int pinNum)
{
    
    
	digitalWrite(pinNum,HIGH);
}

int restaurantLightInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 继承产品工厂的类,生产餐厅灯设备 */
struct Devices restaurantLight = {
    
    
	.devicesName = "restaurant",
	.pinNum = 22,
	.open = restaurantLightOpen,
	.close = restaurantLightClose,
	.devicesInit = restaurantLightInit,
	.next = NULL,
};
	
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addrestaurantLightToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &restaurantLight;
		return phead;
	}else{
    
    
		restaurantLight.next = phead;
		phead = &restaurantLight;
		return phead;
	}
}

.

Living room lighting equipment

#include "controlDevices.h"

int livingroomLightOpen(int pinNum)
{
    
    
	digitalWrite(pinNum,LOW);
}

int livingroomLightClose(int pinNum)
{
    
    
	digitalWrite(pinNum,HIGH);
}

int livingroomLightInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 继承产品工厂的类,生产客厅灯设备 */
struct Devices livingroomLight = {
    
    
	.devicesName = "livingroom",
	.pinNum = 24,
	.open = livingroomLightOpen,
	.close = livingroomLightClose,
	.devicesInit = livingroomLightInit,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addlivingroomLightToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &livingroomLight;
		return phead;
	}else{
    
    
		livingroomLight.next = phead;
		phead = &livingroomLight;
		return phead;
	}
}

.

Pool lighting equipment

#include "controlDevices.h"

int swimmingLightOpen(int pinNum)
{
    
    
	digitalWrite(pinNum,LOW);
}

int swimmingLightClose(int pinNum)
{
    
    
	digitalWrite(pinNum,HIGH);
}

int swimmingLightInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 继承产品工厂的类,生产泳池灯设备 */
struct Devices swimmingLight = {
    
    
	.devicesName = "swimming",
	.pinNum = 25,
	.open = swimmingLightOpen,
	.close = swimmingLightClose,
	.devicesInit = swimmingLightInit,
	.next = NULL,
};
	
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addswimmingLightToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &swimmingLight;
		return phead;
	}else{
    
    
		swimmingLight.next = phead;
		phead = &swimmingLight;
		return phead;
	}
}

.

fan equipment

#include "controlDevices.h"

int fanOpen(int pinNum)
{
    
    	
	digitalWrite(pinNum,LOW);
}

int fanClose(int pinNum)
{
    
    
	digitalWrite(pinNum,HIGH);
}

int fanInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 继承产品工厂的类,生产风扇设备 */
struct Devices fan = {
    
    
	.devicesName = "fan",
	.pinNum = 29,
	.open = fanOpen,
	.close = fanClose,
	.devicesInit = fanInit,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addfanToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &fan;
		return phead;
	}else{
    
    
		fan.next = phead;
		phead = &fan;
		return phead;
	}
}

.

lock device

#include "controlDevices.h"

int lockOpen(int pinNum)
{
    
    
	digitalWrite(pinNum,LOW);
}

int lockClose(int pinNum)
{
    
    
	digitalWrite(pinNum,HIGH);
}

int lockInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 继承产品工厂的类,生产锁设备 */
struct Devices lock = {
    
    
	.devicesName = "lock",
	.pinNum = 28,
	.open = lockOpen,
	.close = lockClose,
	.devicesInit = lockInit,
	.next = NULL,
};
	
/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addlockToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &lock;
		return phead;
	}else{
    
    
		lock.next = phead;
		phead = &lock;
		return phead;
	}
}

.

siren equipment

#include "controlDevices.h"

int buzzerOpen(int pinNum)
{
    
    	
	digitalWrite(pinNum,LOW);
}

int buzzerClose(int pinNum)
{
    
    
	digitalWrite(pinNum,HIGH);
}

int buzzerInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 继承产品工厂的类,生产警报器设备 */
struct Devices buzzer = {
    
    
	.devicesName = "buzzer",
	.pinNum = 27,
	.open = buzzerOpen,
	.close = buzzerClose,
	.devicesInit = buzzerInit,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addbuzzerToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &buzzer;
		return phead;
	}else{
    
    
		buzzer.next = phead;
		phead = &buzzer;
		return phead;
	}
}

.

Earthquake Monitoring Equipment

#include "controlDevices.h"

int shockInit(int pinNum)
{
    
    
	pinMode(pinNum,INPUT);
	digitalWrite(pinNum,HIGH);
}

/* 检测地震发生情况 */
int shockReadStatus(int pinNum)
{
    
    
	return digitalRead(pinNum);
}

/* 继承产品工厂的类,生产地震监测设备 */
struct Devices shock = {
    
    
	.devicesName = "shock",
	.pinNum = 6,
	.devicesInit = shockInit,
	.readStatus = shockReadStatus,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addishockToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &shock;
		return phead;
	}else{
    
    
		shock.next = phead;
		phead = &shock;
		return phead;
	}
}

.

fire monitoring equipment

#include "controlDevices.h"

int fireInit(int pinNum)
{
    
    
	pinMode(pinNum,INPUT);
	digitalWrite(pinNum,HIGH);
}

/* 检测火灾发生情况 */
int fireReadStatus(int pinNum)
{
    
    
	return digitalRead(pinNum);
}

/* 继承产品工厂的类,生产火灾监测设备 */
struct Devices fire = {
    
    
	.devicesName = "fire",
	.pinNum = 4,
	.devicesInit = fireInit,
	.readStatus = fireReadStatus,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addfireToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &fire;
		return phead;
	}else{
    
    
		fire.next = phead;
		phead = &fire;
		return phead;
	}
}

.

Temperature and humidity detection equipment

#include "controlDevices.h"

int sensorInit(int pinNum)
{
    
    
	pinMode(pinNum,OUTPUT);
	digitalWrite(pinNum,HIGH);
}

/* 获取温度传感器的数据 */
int sensorReadData(struct Devices *sensorMsg,int pinNum)
	{
    
    
		char crc;
		char i;
		unsigned long databuf;  //温湿度存储地址
		
		pinMode(pinNum, OUTPUT); 
		digitalWrite(pinNum, 0); 
		delay(25);
		digitalWrite(pinNum, 1); 
		
		pinMode(pinNum, INPUT);	
		pullUpDnControl(pinNum, PUD_UP);//启用上拉电阻,引脚电平拉倒3.3v
	
		delayMicroseconds(27);
		if (digitalRead(pinNum) == 0) 
		{
    
    
			while (!digitalRead(pinNum));
	
			for (i = 0; i < 32; i++)
			{
    
    
				while (digitalRead(pinNum));
					 
				while (!digitalRead(pinNum));
	
				delayMicroseconds(32);
				databuf *= 2;
				if (digitalRead(pinNum) == 1)
				{
    
    
					databuf++;
				}
			}
	
			for (i = 0; i < 8; i++)
			{
    
    
				while (digitalRead(pinNum));
	
				while (!digitalRead(pinNum));
	
				delayMicroseconds(32);
				crc *= 2;
				if (digitalRead(pinNum) == 1) 
				{
    
    
					crc++;
				}
			}
			sensorMsg->databuf = databuf;
			return 1;
		}
		else
		{
    
    
			return 0;
		}
	}

/* 继承产品工厂的类,生产温度检测设备 */
struct Devices sensor = {
    
    
	.devicesName = "sensor",
	.pinNum = 1,
	.devicesInit = sensorInit,
	.readData = sensorReadData,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct Devices* addsensorToDevicesLink(struct Devices *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &sensor;
		return phead;
	}else{
    
    
		sensor.next = phead;
		phead = &sensor;
		return phead;
	}
}

.

command factory

The factory is mainly used to produce some equipment for people to issue commands to control, such as voice equipment, server equipment, camera equipment, etc. These equipment can control the equipment of the product factory to perform some control actions.

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

//创建指令工厂的类,即指令工厂的生产线
struct InputCmd
{
    
    
	int fd;  //文件的fd
	char deviceName[128];  //设备名称
	char cmd[64];  //指令内容
	char cmdName[128];  //指令名称
	char log[1024];  //日志
	
	int sfd;  //server的fd
	char port[12];  //端口号
	char ipAress[32];  //IP地址

	char *img_buf;  //指向主人的人脸图片数据存储区的指针
	char *camera_buf;  //指向临时的人脸图片数据存储区的指针
	float face_data;  //人脸识别匹配度

	/* 设备功能 */
	int (*Init)(struct InputCmd *voicer,char *ipAdress,char *port);
	int (*getCmd)(struct InputCmd *voicer);
	int (*ReadHandle)(void *ptr, size_t size, size_t nmemb, void *stream);

	struct InputCmd *next;  //链表链接节点
};

//告知工厂,对应的设备已经上线成为商品了
struct InputCmd* addvoiceControlToInputCmdLink(struct InputCmd *phead);
struct InputCmd* addserverControlToInputCmdLink(struct InputCmd *phead);
struct InputCmd* addcameraControlToInputCmdLink(struct InputCmd *phead);

.

voice control device

The device obtains the owner's command words through the voice module su-03, and converts the corresponding command words into strings and sends them to the Raspberry Pi through the serial port through the smart AD platform.

#include "inputCmd.h"

/* 语音控制设备初始化,启用串口 */
int voiceInit(struct InputCmd *voicer,char *ipAdress,char *port)
{
    
    
	int fd;
	if((fd = serialOpen(voicer->deviceName,9600))==-1){
    
      //打开串口
		exit(-1);
	}
	voicer->fd = fd;
	return fd;
}

/* 读取来自语音控制设备的命令 */
int voiceGetCmd(struct InputCmd *voicer)
{
    
    
	char tmp[128];
	int nread;
	memset(tmp,'\0',sizeof(tmp));
	nread = read(voicer->fd,tmp,sizeof(tmp));  //一切皆文件,串口也是文件,读串口数据

	if(nread == 0){
    
    
		printf("usart for voice read overtime\n");
	}else if(nread > 0){
    
    
		memset(voicer->cmd,'\0',sizeof(voicer->cmd));	
		
		/* 对串口数据进行优化 */
		if(strstr(tmp,"open ba") != NULL){
    
    
			strcat(voicer->cmd,"open bathroom light");
		}
		if(strstr(tmp,"close ba") != NULL){
    
    
			strcat(voicer->cmd,"close bathroom light");
		}
		if(strstr(tmp,"open li") != NULL){
    
    
			strcat(voicer->cmd,"open livingroom light");
		}
		if(strstr(tmp,"close li") != NULL){
    
    
			strcat(voicer->cmd,"close livingroom light");
		}
		if(strstr(tmp,"open re") != NULL){
    
    
			strcat(voicer->cmd,"open restaurant light");
		}
		if(strstr(tmp,"close re") != NULL){
    
    
			strcat(voicer->cmd,"close restaurant light");
		}
		if(strstr(tmp,"open se") != NULL){
    
    
			strcat(voicer->cmd,"open secondfloor light");
		}
		if(strstr(tmp,"close se") != NULL){
    
    
			strcat(voicer->cmd,"close secondfloor light");
		}
		if(strstr(tmp,"open sw") != NULL){
    
    
			strcat(voicer->cmd,"open swimming light");
		}
		if(strstr(tmp,"close sw") != NULL){
    
    
			strcat(voicer->cmd,"close swimming light");
		}
		if(strstr(tmp,"open bu") != NULL){
    
    
			strcat(voicer->cmd,"open buzzer light");
		}
		if(strstr(tmp,"close bu") != NULL){
    
    
			strcat(voicer->cmd,"close buzzer light");
		}
		if(strstr(tmp,"open fn") != NULL){
    
    
			strcat(voicer->cmd,"open fan light");
		}
		if(strstr(tmp,"close fn") != NULL){
    
    
			strcat(voicer->cmd,"close fan light");
		}
		if(strstr(tmp,"open fac") != NULL){
    
    
			strcat(voicer->cmd,"open face light");
		}
		if(strstr(tmp,"open lo") != NULL){
    
    
			strcat(voicer->cmd,"open lock light");
		}
		if(strstr(tmp,"close lo") != NULL){
    
    
			strcat(voicer->cmd,"close lock light");
		}

		return nread;
	}else{
    
    
		printf("read is fali\n");
	}

}

/* 继承指令工厂的类,生产语音控制设备 */
struct InputCmd voiceControl = {
    
    
	.cmdName = "voice",
	.deviceName = "/dev/ttyAMA0",
	.cmd = {
    
    '\0'},
	.Init = voiceInit,
	.getCmd = voiceGetCmd,
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct InputCmd* addvoiceControlToInputCmdLink(struct InputCmd *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &voiceControl;
		return phead;
	}else{
    
    
		voiceControl.next = phead;
		phead = &voiceControl;
		return phead;
	}
}

.

server control device

The device is to set up a socket server to monitor the connection of the client.

#include "inputCmd.h"

/* server控制设备初始化,为套接字绑定端口号和IP地址 */
int serverInit(struct InputCmd *serverMsg,char *ipAdress,char *port)
{
    
    
	int s_fd;

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

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

	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(serverMsg->port));
	inet_aton(serverMsg->ipAress,&s_addr.sin_addr);

	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

	listen(s_fd,10);	
	
	serverMsg->sfd = s_fd;
	return s_fd;
}

/* 继承指令工厂的类,生产server控制设备 */
struct InputCmd serverControl = {
    
    
	.cmdName = "server",
	.cmd = {
    
    '\0'},
	.log = {
    
    '\0'},
	.Init = serverInit,
	.port = "8801",
	.ipAress = "192.168.104.61",
	.next = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct InputCmd* addserverControlToInputCmdLink(struct InputCmd *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &serverControl;
		return phead;
	}else{
    
    
		serverControl.next = phead;
		phead = &serverControl;
		return phead;
	}
}

.

face recognition device

The device accesses the website by using the curl third-party library, and calls Xiangyun face recognition platform for face recognition.

#include "inputCmd.h"

char post_info[500];

/* 人脸识别设备初始化 */
int cameraInit(struct InputCmd *camera,char *ipAdress,char *port)
{
    
    
	int fd;
	int imgSize=0;
	char cmd[30];
	
	memset(post_info,'\0',500);
	curl_global_init(CURL_GLOBAL_ALL);  //curl库初始化
	
	/* 获取主人的人脸图片的base64编码 */
	fd = open("imgfile.txt",O_RDWR,0666);  //打开用来存放主人的人脸图片的base64编码的文件
	imgSize = lseek(fd,0,SEEK_END);  
	camera->img_buf = (char *)malloc(imgSize + 8);
	memset(camera->img_buf,'\0',imgSize + 8);
	lseek(fd,0,SEEK_SET);
	read(fd,camera->img_buf,imgSize);  //将主人的人脸图片的base64编码读到img_buf数据存储区
	close(fd);

	system("raspistill -q 5 -o haozi.jpg");  //调用树莓派摄像头拍摄图片,-q 5为降低画质
	while(access("./haozi.jpg",F_OK) != 0);  //等待拍摄完成
	
	sprintf(cmd,"base64 %s >camerafile.txt","haozi.jpg");  //字符串拼接
	if(system(cmd) == 256){
    
      //生成摄像头拍摄图片的base64编码的图像地址
		return -1;
	}

	/* 获取临时拍摄的人脸图片的base64编码 */
	fd = open("camerafile.txt",O_RDWR,0666);  //打开用来存放临时拍摄的人脸图片的base64编码的文件
	imgSize = lseek(fd,0,SEEK_END);
	camera->camera_buf = (char *)malloc(imgSize + 8);
	memset(camera->camera_buf,'\0',imgSize + 8);
	lseek(fd,0,SEEK_SET);
	read(fd,camera->camera_buf,imgSize);  //将临时拍摄的人脸图片的base64编码读到camera_buf数据存储区
	close(fd);

	system("rm camerafile.txt");
	system("rm haozi.jpg");
	
	if((camera->img_buf == NULL)||(camera->camera_buf == NULL)){
    
    
		printf("img dont exist!\n");
		return -1;
	}
	return 0;
}

/* 获取祥云平台的人脸识别结果数据 */
int cameraReadHandle( void *ptr, size_t size, size_t nmemb, void *stream)
{
    
    
	int buf_size=size*nmemb;
	char *buf=malloc(buf_size+1);
	memset(buf,'\0',buf_size+1);
	strncpy(buf,ptr,buf_size);  //获取祥云平台的人脸识别结果
	memset(post_info,'\0',sizeof(post_info));
	strcat(post_info,buf);
	free(buf);
	return buf_size;
}

/* 调用祥云平台进行人脸识别 */
int cameraGetCmd(struct InputCmd *camera)
{
    
    
	CURL *curl;
	CURLcode res;
	char *PostString;
	
	/* 祥云平台的个人基本信息 */
	char *key="6M9M9rFAa3DuG33Awu9hKq";
	char *secret="db56882c3a0b4a3dbeeaed2af79f026c";
	int typeId=21;
	char *format="xml";

	char *result_str = NULL;
	float result_data;
	int len = strlen(camera->img_buf)+strlen(camera->camera_buf)+strlen(key)+strlen(secret)+sizeof(typeId)+strlen(format) + 24;

	PostString=malloc(len);
	
	sprintf(PostString,"&img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",camera->img_buf,camera->camera_buf,key,secret,typeId,format);  //设置需要发送给祥云平台的数据格式

	curl = curl_easy_init();  //获取句柄
	if (curl){
    
    
		
		curl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/faceliu.do");  //设置访问的URL,即祥云人脸识别的接口地址
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS,PostString);  //向祥云平台发送数据,调用人脸识别功能
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, camera->ReadHandle);  //设置回调函数,该函数用来接收人脸识别的结果

		res = curl_easy_perform(curl);//错误检测,0没有错误,非0出现错误
		curl_easy_cleanup(curl);

		/* 处理人脸识别的结果数据 */
		result_str = strstr(post_info,"CDATA");
		if(result_str != NULL){
    
    
			result_str += 6;
			result_str = strtok(result_str,"]");
			result_data = atof(result_str);
		}else{
    
    
			printf("get result error!\n");
		}
	}else{
    
    
		printf("get result error!\n");
	}
	camera->face_data = result_data;
	
	return result_data;
}

/* 继承指令工厂的类,生产人脸识别设备 */
struct InputCmd cameraControl = {
    
    
	.cmdName = "camera",
	.cmd = {
    
    '\0'},
	.log = {
    
    '\0'},
	.Init = cameraInit,
	.getCmd = cameraGetCmd,
	.ReadHandle = cameraReadHandle,
	.next = NULL,
	.img_buf = NULL,
	.camera_buf = NULL,
};

/* 头插法加入链表,提供购买渠道,以供客户购买 */
struct InputCmd* addcameraControlToInputCmdLink(struct InputCmd *phead)
{
    
    
	if(phead == NULL){
    
    
		phead = &cameraControl;
		return phead;
	}else{
    
    
		cameraControl.next = phead;
		phead = &cameraControl;
		return phead;
	}
}


.

Main file main.c

insert image description here

main thread main()

.

voice thread

/* 语音线程执行函数 */
void *voice_thread(void *data)
{
    
    
	struct InputCmd *voiceHandle = NULL;
	struct Devices *devicesHandle = NULL;

	char behavior[32];
	char room[32];
	char *tmp;
	int n_read = 0;

	voiceHandle = findCmdByName("voice",pCmdHead);  //找到指令工厂的语音控制设备
	if(voiceHandle == NULL){
    
    
		printf("find voiceHandle error\n");
		pthread_exit(NULL);
	}else{
    
    
		if(voiceHandle->Init(voiceHandle,NULL,NULL) < 0){
    
    
			printf("voice Init error\n");
			pthread_exit(NULL);
		}
		while(1){
    
      
			n_read = voiceHandle->getCmd(voiceHandle);
			if(n_read == 0){
    
    
				printf("no data from voice\n");
			}else{
    
    
			
				/* 获取命令和设备名称 */
				memset(behavior,'\0',sizeof(behavior));
				tmp = strtok(voiceHandle->cmd," ");
				strcat(behavior,tmp);  //命令:open or close
				printf("behavior:%s\n",behavior);
				memset(room,'\0',sizeof(room));
				tmp = strtok(NULL," ");
				strcat(room,tmp);  //产品工厂的设备名称
				printf("room:%s\n",room);
				
				devicesHandle = findDeviceByName(room,pDevicesHead);  //找到产品工厂的设备
				if(devicesHandle != NULL && strcmp(behavior,"open") == 0){
    
    
					devicesHandle->devicesInit(devicesHandle->pinNum);
					devicesHandle->open(devicesHandle->pinNum);
				}
				 
				if(devicesHandle != NULL && strcmp(behavior,"close") == 0){
    
    
					devicesHandle->devicesInit(devicesHandle->pinNum);
					devicesHandle->close(devicesHandle->pinNum);
				}

				/* 如果是人脸识别命令,则拍照并进行人脸识别 */
				if(strcmp(room,"face") == 0){
    
    	
					pthread_create(&camera_pid,NULL,camera_thread,NULL);  //摄像头线程建立
					pthread_join(camera_pid,NULL);
				}
	
				
			}
		}
	}
}

The main functions of this thread are:
Receive the owner's command, according to the command to call different equipment in the product factory to achieve different functions, such as turning on the light, turning off the light, face recognition, etc., when using the face recognition device, a face recognition thread will be established.

.

face recognition thread

/* 人脸识别线程执行函数 */
void *camera_thread(void *data)
{
    
    
	struct InputCmd *cameraHandle = NULL;
	struct Devices *devicesHandle = NULL;

	float face_result;
	
	cameraHandle = findCmdByName("camera",pCmdHead);  //找到指令工厂的人脸识别设备
	if(cameraHandle == NULL){
    
    
		printf("find voiceHandle error\n");
		pthread_exit(NULL);
	}else{
    
    
		if(cameraHandle->Init(cameraHandle,NULL,NULL) < 0){
    
    
			printf("camera Init error\n");
			pthread_exit(NULL);
		}
		cameraHandle->getCmd(cameraHandle);  //调用祥云平台进行人脸识别

		/* 根据人脸识别结果进行控制行为 */
		if(cameraHandle->face_data > 0.75){
    
      //主人回家了,开门
			printf("same\n");
			devicesHandle = findDeviceByName("lock",pDevicesHead);  //找到产品工厂的锁设备
			if(devicesHandle != NULL){
    
    
				devicesHandle->devicesInit(devicesHandle->pinNum);
				devicesHandle->open(devicesHandle->pinNum);

				sleep(10);
				devicesHandle->close(devicesHandle->pinNum);
				pthread_exit(NULL);
			}
		}else{
    
    
			printf("no same\n");  //不是主人回家了,不开门,并报警
			devicesHandle = findDeviceByName("buzzer",pDevicesHead);  //找到指令工厂的警报器设备
			if(devicesHandle != NULL){
    
    
				devicesHandle->devicesInit(devicesHandle->pinNum);
				devicesHandle->open(devicesHandle->pinNum);

				sleep(3);
				devicesHandle->close(devicesHandle->pinNum);
				pthread_exit(NULL);
			}
		}
	}
}

The main functions of this thread are:
Call the camera to take pictures for face recognition. If the face recognition is not performed by the owner, it will call the siren device to alarm. If it is the face recognition performed by the owner, it will call the lock device to unlock.
.

fire monitoring thread

/* 火灾监测线程执行函数 */
void *fire_thread(void *data)
{
    
    
	struct Devices *fireHandle = NULL;
	struct Devices *devicesHandle = NULL;

	int fireStatus = 1;
	
	fireHandle = findDeviceByName("fire",pDevicesHead);  //找到产品工厂的火灾设备
	if(fireHandle == NULL){
    
    
		printf("find fireHandle error\n");
		pthread_exit(NULL);
	}else{
    
    
		fireHandle->devicesInit(fireHandle->pinNum);
		while(1){
    
    
			fireStatus = fireHandle->readStatus(fireHandle->pinNum);
			//printf("fireStatus:%d\n",fireStatus);
			delay(125);
		
			if((fireStatus) == 0){
    
    
				firetype = 1;
				devicesHandle = findDeviceByName("buzzer",pDevicesHead);  //找到指令工厂的报警器设备
				if(devicesHandle != NULL){
    
    
					devicesHandle->open(devicesHandle->pinNum);
				}
				
			}else if(fireStatus == 1){
    
    
				firetype = 0;
				devicesHandle = findDeviceByName("buzzer",pDevicesHead);  //找到指令工厂的报警器设备
				if(devicesHandle != NULL){
    
    
					devicesHandle->close(devicesHandle->pinNum);
				}
			}
			
		}
	}
}

The main functions of this thread are:
Monitor the occurrence of fires near the house. If a fire occurs, the alarm device will be called to give an alarm. At the same time, the occurrence of the fire will be displayed on the mobile phone APP. The following sever control thread will describe it in detail.
.

Earthquake Monitoring Thread

/* 地震监测线程执行函数 */
void *shock_thread(void *data)
{
    
    
	struct Devices *shockHandle = NULL;
	struct Devices *devicesHandle = NULL;

	int shockStatus = 1;
	
	shockHandle = findDeviceByName("shock",pDevicesHead);  //找到产品工厂的地震监测设备
	if(shockHandle == NULL){
    
    
		printf("find shockHandle error\n");
		pthread_exit(NULL);
	}else{
    
    
		shockHandle->devicesInit(shockHandle->pinNum);
		while(1){
    
    
			shockStatus = shockHandle->readStatus(shockHandle->pinNum);
			//printf("shockStatus:%d\n",shockStatus);
			delay(125);
		
			if((shockStatus) == 0){
    
    
				shocktype = 1;
				devicesHandle = findDeviceByName("buzzer",pDevicesHead);  //找到指令工厂的报警器设备
				if(devicesHandle != NULL){
    
    
					devicesHandle->open(devicesHandle->pinNum);
				}
				
			}else if(shockStatus == 1){
    
    
				shocktype = 0;
				devicesHandle = findDeviceByName("buzzer",pDevicesHead);  //找到指令工厂的报警器设备
				if(devicesHandle != NULL){
    
    
					devicesHandle->close(devicesHandle->pinNum);
				}
			}
		}
	}
}

The main functions of this thread are:
Monitor the occurrence of earthquakes near the house. If an earthquake occurs, the alarm device will be called to give an alarm. At the same time, the occurrence of the earthquake will also be displayed on the mobile APP. The following sever control thread will describe it in detail.
.

Temperature and humidity detection thread

/* 温度检测线程执行函数 */
void *sensor_thread(void *data){
    
    
	
	struct Devices *sensorHandle = NULL;

	sensorHandle = findDeviceByName("sensor",pDevicesHead);  //找到产品工厂的温湿度检测设备
	if(sensorHandle == NULL){
    
    
		printf("find sensorHandle error\n");
		pthread_exit(NULL);
	}else{
    
    
		sensorHandle->devicesInit(sensorHandle->pinNum);

		while(1){
    
    
			sensorHandle->devicesInit(sensorHandle->pinNum);
			delay(2000);
			/* 获取空气中的温室度 */
			if (sensorHandle->readData(sensorHandle,sensorHandle->pinNum)){
    
    
            	printf("Congratulations ! Sensor data read ok!\n");
	            printf("RH:%d.%d\n", (sensorHandle->databuf >> 24) & 0xff, (sensorHandle->databuf >> 16) & 0xff);
	            printf("TMP:%d.%d\n", (sensorHandle->databuf >> 8) & 0xff, sensorHandle->databuf & 0xff);
	            
				memset(sensorToStr,'\0',sizeof(sensorToStr));
				sprintf(sensorToStr,"Temperature: %d.%dC        Humidity: %d.%dhPa",(sensorHandle->databuf >> 8) & 0xff, sensorHandle->databuf & 0xff,(sensorHandle->databuf >> 24) & 0xff, (sensorHandle->databuf >> 16) & 0xff);

				sensorHandle->databuf = 0;
				printf("%s\n",sensorToStr);
	        }
	        else{
    
    
	            printf("Sorry! Sensor dosent ans!\n");
	            sensorHandle->databuf = 0;
	        }
		}
		
	}
}

The main functions of this thread are:
Call the temperature and humidity detection device to obtain the temperature and humidity in the air, and at the same time, the temperature and humidity in the air will also be displayed on the mobile APP, which will be detailed in the following server control thread.
.

server control thread

/* sever控制线程执行函数 */
void *server_thread(void *data)
{
    
    
	int clen = sizeof(struct sockaddr_in);	
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof(struct sockaddr_in));

	pthread_t connect_pid;

	serverHandle = findCmdByName("server",pCmdHead);  //找到指令工厂的server控制设备
	if(serverHandle == NULL){
    
    
		printf("find serverHandle error\n");
		pthread_exit(NULL);
	}else{
    
    
		
		if(serverHandle->Init(serverHandle,NULL,NULL) < 0){
    
    
			printf("server Init error\n");
			pthread_exit(NULL);
		}
		while(1){
    
    
			c_fd = accept(serverHandle->sfd,(struct sockaddr *)&c_addr,&clen);
			printf("have people\n");
			pthread_create(&connect_pid,NULL,connect_thread,NULL);  //建立客户端连接后处理线程
		}
	}
}

The main functions of this thread are:
Call the server to control the device, set up a socket server, and wait for the connection of the client. When the client connects, it will establish a thread for processing after the client connection.
.

Processing thread after client connection

/* 客户端连接后处理线程执行函数 */
void *connect_thread(void *data)
{
    
    	
	int n_read; 
	struct Devices *devicesHandle = NULL;
	char behavior[32];
	char room[32];
	char *tmp;
	
	pthread_create(&sendData_pid,NULL,sendData_thread,NULL);  //建立发送数据线程

	n_read = read(c_fd,serverHandle->cmd,sizeof(serverHandle->cmd));  //读取客户端的数据
	if(n_read == -1){
    
    
		perror("read");
	}else if(n_read > 0){
    
    
	
		printf("cmd: %s\n",serverHandle->cmd);
		/* 获取命令和设备名称 */
		memset(behavior,'\0',sizeof(behavior));
		tmp = strtok(serverHandle->cmd," ");  //命令:open or close
		strcat(behavior,tmp);
		printf("behavior:%s\n",behavior);
		memset(room,'\0',sizeof(room));  
		tmp = strtok(NULL," ");
		strcat(room,tmp);  //产品工厂的设备名称
		printf("room:%s\n",room);		
		
		devicesHandle = findDeviceByName(room,pDevicesHead);  //找到产品工厂的设备
		if(devicesHandle != NULL && strcmp(behavior,"open") == 0){
    
    
			devicesHandle->devicesInit(devicesHandle->pinNum);
			devicesHandle->open(devicesHandle->pinNum);
		}
				 
		if(devicesHandle != NULL && strcmp(behavior,"close") == 0){
    
    
			devicesHandle->devicesInit(devicesHandle->pinNum);
			devicesHandle->close(devicesHandle->pinNum);
		}

		/* 如果是人脸识别命令,则拍照并进行人脸识别 */
		if(strcmp(room,"face") == 0){
    
    	
			pthread_create(&camera_pid,NULL,camera_thread,NULL);  //摄像头线程建立
			pthread_join(camera_pid,NULL);
		}
		
	}else{
    
    
		printf("client is quit\n");
	}
}

The main functions of this thread are:
Receive APP commands, call different devices according to the commands to achieve different functions, such as turning on lights, turning off lights, face recognition, etc. When using face recognition devices, a face recognition thread will be established, and a data sending thread will be established at the same time. The occurrence of fires and earthquakes and the temperature and humidity of the air are sent to the APP, and the information is displayed on the APP.
.

send data thread

/* 发送数据线程执行函数 */
void *sendData_thread(void *data){
    
    
	while(1){
    
    
		delay(1000);
		if(firetype == 1){
    
    
			write(c_fd,"fire",4);
		}else if(shocktype == 1){
    
    
			write(c_fd,"shock",5);
		}else{
    
    
			write(c_fd,"1",1);  //随便发个数据与客户端进行响应
		}
		write(c_fd,sensorToStr,strlen(sensorToStr));	
	}
}

The main functions of this thread are:
The occurrence of fires and earthquakes and the temperature and humidity of the air are sent to the APP, and the information is displayed on the APP. APP will be realized through Java and Android. If the length of this article is limited, it will be implemented in the next article.
.

Smart Home APP

The APP implements the following functions:

  • Set up the client to establish a network connection with the Raspberry Pi.
  • Receive fire and earthquake information from the Raspberry Pi, as well as the temperature and humidity in the air and display them on the display page.
  • Display the monitoring screen of the Raspberry Pi camera on the display page.
  • Call different devices in the product factory on the control page to achieve different functions, such as turning on and off the lights and so on.
    .

AndroidManiFest.xml

This file is mainly about the configuration of APP:

  • some permissions
  • SDK version of the target machine
  • App name
  • App configuration
  • Configure the first startup page to be loaded
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.haozige.learn"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.haozige.learn.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.example.haozige.learn.DisplayActivity"
            android:label="@string/title_activity_display" >
        </activity>
        <activity
            android:name="com.example.haozige.learn.ControlActivity"
            android:label="@string/title_activity_control" >
        </activity>
    </application>

</manifest>

.

countdown page

java file

package com.example.haozige.learn;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {
    
    

	public TextView time; 
	public Handler h;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        time = (TextView) findViewById(R.id.daojishi);
        
        h = new Handler(){
    
    @Override
        public void handleMessage(Message msg) {
    
    
        	super.handleMessage(msg);
        	
        	time.setText("" + msg.what);
        	
        }};
        
        new Thread(new Runnable() {
    
    
			
			public void run() {
    
    
					
				for(int i = 5;i>0;i--){
    
    	
					Message msg = new Message();//事件的信息
					msg.what = i;
					
					//打电话,去把UI线程要显示(要处理)的事件交给Handler
					h.sendMessage(msg);//成员方法textfun操控成员变量h
					
					try {
    
    
						Thread.sleep(1000);
					} catch (InterruptedException e) {
    
    
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
				
				//新建一个对象并且实例化为Intent来设置跳转的页面
		        Intent intent = new Intent(MainActivity.this,DisplayActivity.class);
		        
		        //跳转
		        startActivity(intent);
					
			}
		}).start();
        
    }

    public void goMainDisplay(View v){
    
    
    	//新建一个对象并且实例化为Intent来设置跳转的页面
        Intent intent = new Intent(this,DisplayActivity.class);
        
        //跳转
        startActivity(intent);
    }
  
}

.

xml file

<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/b1"
    tools:context=".MainActivity" >

    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        
        <LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="5"
            android:gravity="center">
            
            <TextView 
        		android:layout_width="wrap_content"
        		android:layout_height="wrap_content"
        		android:text="欢迎来到浩子哥的智能家居APP"
        		android:textSize="30dp"
        		android:textStyle="bold"
        		android:textColor="#ffc0cb"/>
        
        </LinearLayout>
        
        <LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="5"
            android:gravity="center">
            
            <TextView 
        		android:layout_width="wrap_content"
        		android:layout_height="wrap_content"
        		android:text="5"
        		android:textSize="60dp"
        		android:textStyle="bold"
        		android:textColor="#000000"
        		android:id="@+id/daojishi"/>
        
        </LinearLayout>
        
        <LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            
            <Button
        		android:layout_width="match_parent"
        		android:layout_height="wrap_content"
        		android:text="跳转到显示页面" 
        		android:onClick="goMainDisplay"
        		android:background="@drawable/btn_selector"/>

        </LinearLayout>
        
    </LinearLayout>
    
</RelativeLayout>

.

page display

insert image description here
.

display page

java file

package com.example.haozige.learn;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.TextView;

@SuppressLint("HandlerLeak") public class DisplayActivity extends Activity {
    
    

	public Handler h;
	public TextView fire;
	public TextView shock;
	public TextView wendu;
	//public TextView shidu;
	
	
	
	protected void onCreate(Bundle savedInstanceState) {
    
    
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_display);
		
		fire = (TextView)findViewById(R.id.fire);
		shock = (TextView)findViewById(R.id.shock);
		wendu = (TextView)findViewById(R.id.wendu);
		//shidu = (TextView)findViewById(R.id.shidu);
		
		h = new Handler(){
    
    
        	//区分事件的类型
        	@SuppressLint("HandlerLeak") public void handleMessage(Message msg) {
    
    

        		super.handleMessage(msg);
        		
        		Bundle b = msg.getData();
        		String string = b.getString("dataMsg");
        		
    			//fire.setTextColor(0xff0000ff);
    			
    			if(string.contains("shock") == true){
    
    
    				shock.setText("Shock: abnormal");
    			}else if(string.contains("fire") == true){
    
    
    				fire.setText("Fire: abnormal");
    			}else if(string.contains("Temperature") == true){
    
    
    				wendu.setText(string);
    			}else if(string.contains("Humidity") == true){
    
    
    				//shidu.setText(string);
    			}else{
    
    
    				fire.setText("Fire: normal");
    				shock.setText("Shock: normal");
    			}
        		
        		
        		
        		
        	}
        };
		
        View v = findViewById(R.id.beijing);
        v.getBackground().setAlpha(230);
        
		
		//系统默认会通过手机浏览器打开网页
        final WebView wb = (WebView) findViewById(R.id.webView);
        //想要直接通过WebView显示网页,需要调用以下方法
        wb.setWebViewClient(new WebViewClient());
        
        final EditText et = (EditText) findViewById(R.id.et);
        //按下回车获取文本框内容
        et.setOnEditorActionListener(new TextView.OnEditorActionListener() {
    
    
			
			public boolean onEditorAction(TextView arg0, int arg1, KeyEvent event) {
    
    
				String str = et.getText().toString();
				wb.loadUrl(str);
				
				return (event.getKeyCode() == KeyEvent.KEYCODE_ENTER);
			}
		});
		
		
	}

public void requestServer(final String cmd){
    
    
    	
    	new Thread(new Runnable() {
    
    
			
			public void run() {
    
    
				
				try {
    
    
		    		final Socket client = new Socket("192.168.104.61", 8801);
		    		
		    		OutputStream out = null;
		    		out = client.getOutputStream();
		    		out.write(cmd.getBytes());
		    	
		    		new Thread(new Runnable() {
    
    
		    			
		    			byte[]data = new byte[128];
		    			int readDataLen = 0;
		    			
		    			//创建一个输入流对象,并且获得通道的输入流,在方法中,对变量赋值要在创建变量时完成
		    			InputStream  in = client.getInputStream();
		    			
		    			public void run() {
    
    
		    				
		    				String str;
		    				while(true){
    
    
		    					try {
    
    
		    						readDataLen = in.read(data);
		    					} catch (IOException e) {
    
    

		    						e.printStackTrace();
		    					}
		    					//网络通信的数据类型都是byte类型,将byte类型数据转换为String类型
		    					str = new String(data, 0, readDataLen);
		    					
		    					Message msg = new Message();  //类Message用于发送数据
		    		    		
		    		    		Bundle b = new Bundle();  //类Bundle用于发数据
		    		    		b.putString("dataMsg", str);//根据键值获取数据
		    		    		
		    		    		msg.setData(b);  //
		    		    		
		    		    		h.sendMessage(msg);
		    					
		    					Arrays.fill(data,(byte)0);//byte类型数组清0的方法
		    					readDataLen = 0;
		    				}
		    			}

		    		}){
    
    }.start();
		    		
		    	
		    	} catch (UnknownHostException e) {
    
    
		    		// TODO Auto-generated catch block
		    		e.printStackTrace();
		    	} catch (IOException e) {
    
    
		    		// TODO Auto-generated catch block
		    		e.printStackTrace();
		    	}
				
			}
		}).start();
    	
    }
    
    public void requestData(View v){
    
    
    	

    	
    	if(v.getId() == R.id.requestButton){
    
    
    		
    		requestServer("open haozige light");
    		
    	}
    	
    }
	
	
	public void goControl(View v){
    
    
    	//新建一个对象并且实例化为Intent来设置跳转的页面
        Intent intent = new Intent(this,ControlActivity.class);
        
        //跳转
        startActivity(intent);
    }
}

.

xml file

<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/zhutoucai"
	
    tools:context=".DisplayActivity" >

    <LinearLayout 
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <LinearLayout 
           	android:layout_width="match_parent" 
           	android:layout_height="0dp"
           	android:layout_weight="4"
           	android:orientation="vertical"
           	android:background="#ffffff"
           	android:id="@+id/beijing">
           	
            <LinearLayout 
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:layout_gravity="center">
                
                <LinearLayout 
           			android:layout_width="0dp" 
           			android:layout_height="match_parent"
           			android:layout_weight="1"
           			android:gravity="center_vertical">
           			
            		<TextView 
        				android:layout_width="wrap_content"
        				android:layout_height="wrap_content"
        				android:text="Temperature: 32.5C        Humidity: 68.5hPa"
        				android:textSize="20dp"
        				android:textStyle="bold"
        				android:textColor="#ffc0cb"
        				android:id="@+id/wendu"/>
            		
        		</LinearLayout>
                
            </LinearLayout>
                
            <LinearLayout 
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:gravity="center_vertical">
                
                <TextView 
        				android:layout_width="wrap_content"
        				android:layout_height="wrap_content"
        				android:text="Fire: normal"
        				android:textSize="20dp"
        				android:textStyle="bold"
        				android:textColor="#ffc0cb"
        				android:id="@+id/fire"/>
                	
            </LinearLayout>
           
            <LinearLayout 
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:gravity="center_vertical">
                
                <LinearLayout 
           			android:layout_width="0dp" 
           			android:layout_height="match_parent"
           			android:layout_weight="2"
           			android:gravity="center_vertical">
            		
            		<TextView 
        				android:layout_width="wrap_content"
        				android:layout_height="wrap_content"
        				android:text="Shock: normal"
        				android:textSize="20dp"
        				android:textStyle="bold"
        				android:textColor="#ffc0cb"
        				android:id="@+id/shock"/>
            		
        		</LinearLayout>
                
                <LinearLayout 
           			android:layout_width="0dp" 
           			android:layout_height="match_parent"
           			android:layout_weight="1"
           			android:gravity="center_vertical">
            		
            		<Button 
            		    android:layout_width="wrap_content"
            		    android:layout_height="wrap_content"
            		    android:text="获取服务器数据"
            		    android:background="@drawable/xuanzhe"
            		    android:layout_marginBottom="3dp"
            		    android:layout_marginLeft="3dp"
            		    android:paddingLeft="10dp"
            		    android:paddingRight="10dp"
            		    android:id="@+id/requestButton"
            		    android:onClick="requestData"/>
            		
        		</LinearLayout>
                	
            </LinearLayout>
            
        </LinearLayout>
        
        <LinearLayout 
           	android:layout_width="match_parent" 
           	android:layout_height="0dp"
            android:layout_weight="10"
            android:orientation="vertical">
            
            <EditText 
        		android:layout_width="match_parent"
        		android:layout_height="wrap_content"
        		android:hint="请输入网址"
        		android:id="@+id/et"
        		android:background="#ffcfcb"/>
            
            <WebView 
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/webView"/>
            
        </LinearLayout>
        
        <LinearLayout 
           	android:layout_width="match_parent" 
           	android:layout_height="0dp"
            android:layout_weight="2"
            android:orientation="vertical">
            
            <TextureView 
	                android:layout_width="match_parent"
        			android:layout_height="0dp"
        			android:layout_weight="1"/>
            
            <Button 
	            	android:layout_width="match_parent"
	            	android:layout_height="0dp"
	            	android:layout_weight="1"
	            	android:text="前往控制页面"
	            	android:onClick="goControl"    
	            	android:id="@+id/gotoCmd"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>
            
        </LinearLayout>
        
    </LinearLayout>

</RelativeLayout>

.

page display

insert image description here
.

control page

java file

package com.example.haozige.learn;

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

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class ControlActivity extends Activity {
    
    

	protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_control);
        
       
    }
   
    public void sendHandle(final String cmd){
    
    
    	
    	new Thread(new Runnable() {
    
    
			
			public void run() {
    
    
				
				try {
    
    
		    		final Socket client = new Socket("192.168.104.61", 8801);
		    		
		    		OutputStream out = null;
		    		out = client.getOutputStream();
		    		out.write(cmd.getBytes());

		    	} catch (UnknownHostException e) {
    
    
		    		// TODO Auto-generated catch block
		    		e.printStackTrace();
		    	} catch (IOException e) {
    
    
		    		// TODO Auto-generated catch block
		    		e.printStackTrace();
		    	}
				
			}
		}).start();
    	
    }
    
    public void sendcmd(View v){
    
    
    	
    	switch(v.getId()){
    
    
    		case R.id.opsecond:
    			sendHandle("open secondfloor light");
    			break;
    		case R.id.clsecond:
    			sendHandle("close secondfloor light");
    			break;
    		case R.id.opliving:
    			sendHandle("open livingroom light");
    			break;
    		case R.id.clliving:
    			sendHandle("close livingroom light");
    			break;
    		case R.id.opbath:
    			sendHandle("open bathroom light");
    			break;
    		case R.id.clbath:
    			sendHandle("close bathroom light");
    			break;
    		case R.id.oprestaurant:
    			sendHandle("open restaurant light");
    			break;
    		case R.id.clrestaurant:
    			sendHandle("close restaurant light");
    			break;
    		case R.id.opswimming:
    			sendHandle("open swimming light");
    			break;
    		case R.id.clswimming:
    			sendHandle("close swimming light");
    			break;
    		case R.id.opfan:
    			sendHandle("open fan light");
    			break;
    		case R.id.clfan:
    			sendHandle("close fan light");
    			break;
    		case R.id.oplock:
    			sendHandle("open lock light");
    			break;
    		case R.id.cllock:
    			sendHandle("close lock light");
    			break;
    		case R.id.opbuzzer:
    			sendHandle("open buzzer light");
    			break;
    		case R.id.clbuzzer:
    			sendHandle("close buzzer light");
    			break;
    		
    	}
    	
    }
    
    public void goDisplay(View v){
    
    
    	//新建一个对象并且实例化为Intent来设置跳转的页面
        Intent intent = new Intent(this,DisplayActivity.class);
        
        //跳转
        startActivity(intent);
    }

	
    
}




.

xml file

<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="#ffffff"
    tools:context=".MainActivity" >
    
    <LinearLayout 
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">

	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="1"
	            	android:layout_height="wrap_content"
	            	android:text="前往显示页面"
	            	android:onClick="goDisplay"    
	            	android:id="@+id/gotoDisplay"
	            	android:textColor="#000000"
	            	android:background="@drawable/xuanzhe"/>
	        	
		</LinearLayout>
        
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">
	        
            	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"/> 
            
	            <Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="开二楼灯"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/opsecond"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>
	            
	            <TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="2"/> 
	            
	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="关二楼灯"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/clsecond"/>
	        	
	        	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"/> 
	        	
		</LinearLayout>
        
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">
	        
            	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"/> 
            
	            <Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="开客厅灯"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/opliving"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>

	            <TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="2"/> 
	            
	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="关客厅灯"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/clliving"/>
	        	
	        	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"/> 
	        	
		</LinearLayout>
		
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">
	        
            	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
            
	            <Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="开泳池灯"
	            	
	            	android:onClick="sendcmd"    
	            	android:id="@+id/opswimming"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>

	            <TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="2"
	                /> 
	            
	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="关泳池灯"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/clswimming"/>
	        	
	        	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
	        	
		</LinearLayout>
		
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">
	        
            	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
            
	            <Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="开卫生间灯"
	            	
	            	android:onClick="sendcmd"    
	            	android:id="@+id/opbath"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>

	            <TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="2"
	                /> 
	            
	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="关卫生间灯"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/clbath"/>
	        	
	        	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
	        	
		</LinearLayout>
		
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">
	        
            	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
            
	            <Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="开餐厅灯"
	            	
	            	android:onClick="sendcmd"    
	            	android:id="@+id/oprestaurant"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>

	            <TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="2"
	                /> 
	            
	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="关餐厅灯"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/clrestaurant"/>
	        	
	        	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
	        	
		</LinearLayout>
		 
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">
	        
            	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
            
	            <Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="开报警器"
	            	
	            	android:onClick="sendcmd"    
	            	android:id="@+id/opbuzzer"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>

	            <TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="2"
	                /> 
	            
	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="关报警器"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/clbuzzer"/>
	        	
	        	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
	        	
		</LinearLayout>
		
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">
	        
            	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
            
	            <Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="开风扇"
	            	
	            	android:onClick="sendcmd"    
	            	android:id="@+id/opfan"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>

	            <TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="2"
	                /> 
	            
	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="关风扇"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/clfan"/>
	        	
	        	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
	        	
		</LinearLayout>
		
        <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="0dp"
	        android:layout_weight="1">
	        
            	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
            
	            <Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="开门"
	            	
	            	android:onClick="sendcmd"    
	            	android:id="@+id/oplock"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"/>

	            <TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="2"
	                /> 
	            
	        	<Button 
	            	android:layout_width="0dp"
	            	android:layout_weight="10"
	            	android:layout_height="wrap_content"
	            	android:text="关门"
	            	android:textColor="#000000"
	            	android:background="@drawable/btn_selector"
	            	android:onClick="sendcmd"    
	            	android:id="@+id/cllock"/>
	        	
	        	<TextureView 
	                android:layout_width="0dp"
        			android:layout_height="wrap_content"
        			android:layout_weight="1"
	                /> 
	        	
		</LinearLayout>
        
        
    </LinearLayout>
        

</RelativeLayout>

.

page display

insert image description here

Guess you like

Origin blog.csdn.net/weixin_54076783/article/details/130688445
Recommended