智能家居

发布时间 2023-10-03 13:41:46作者: ⭐⭐-fighting⭐⭐

抽象工厂设计模式是一种创建型设计模式,它允许你创建一组相关或依赖对象的家族,而无需指定其具体类。这种模式通过提供一个抽象工厂接口来创建一系列相关的产品,每个产品对应一个具体工厂,以此来保证产品的一致性。

结构

抽象工厂设计模式通常由以下角色组成:

  1. 抽象工厂(Abstract Factory): 定义了创建一组相关产品的抽象方法。通常每个抽象方法对应一个产品类,用于创建该类的实例。
  2. 具体工厂(Concrete Factory): 实现了抽象工厂接口,负责创建一组相关的具体产品。每个具体工厂对应一个产品族,它负责创建该产品族的所有产品。
  3. 抽象产品(Abstract Product): 定义了产品的抽象接口。每个具体产品必须实现这个接口。
  4. 具体产品(Concrete Product): 实现了抽象产品接口,是某个具体工厂创建的对象。

工作流程

  1. 创建抽象工厂接口:首先,你需要创建一个抽象工厂接口,该接口声明了用于创建产品的抽象方法。
  2. 创建抽象产品接口:定义一个抽象产品接口,该接口声明了产品的通用操作。
  3. 实现具体产品:为每个产品族创建具体产品类,实现抽象产品接口,提供产品的具体实现。
  4. 实现具体工厂:创建具体工厂类,实现抽象工厂接口,负责创建该产品族的具体产品。
  5. 客户端使用:客户端代码通过抽象工厂接口访问产品,而不直接依赖具体产品类。这样客户端可以使用不同的具体工厂来创建不同的产品族,实现了产品族的替换和扩展。

智能家居项目

设备工厂:bathroomLight.c buzzer.c fire.c livingroomLight.c restaurantLight.c upstairLight.c

指令工厂:socketContrl.c voiceContrl.c

设备工厂

contrlDevices.h
#include <wiringPi.h>
#include <stdlib.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 pinNum);
       int (*changeStatus)(int status);

       struct Devices *next;
};

struct Devices *addBathroomLightToDeviceLink(struct Devices *phead);
struct Devices *addUpstairLightToDeviceLink(struct Devices *phead);
struct Devices *addLivingroomLightToDeviceLink(struct Devices *phead);
struct Devices *addRestaurantLightToDeviceLink(struct Devices *phead);
struct Devices *addFireToDeviceLink(struct Devices *phead);
struct Devices *addBuzzerToDeviceLink(struct Devices *phead);
bathroomLight.c
#include "contrlDevices.h"

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

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

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

int bathroomLightStatus(int status)
{
}

struct Devices bathroomLight = {
	.deviceName = "bathroomLight",
	.pinNum = 26,
	.open = bathroomLightOpen,
	.close = bathroomLightClose,
	.deviceInit = bathroomLightCloseInit,
	.changeStatus = bathroomLightStatus

};

struct Devices *addBathroomLightToDeviceLink(struct Devices *phead)
{
	if (phead == NULL)
	{
		return &bathroomLight;
	}
	else
	{
		bathroomLight.next = phead;
		phead = &bathroomLight;
		return phead;
	}
};

livingroomLight.c
#include "contrlDevices.h"

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

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

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

int livingroomLightStatus(int status)
{
}

struct Devices livingroomLight = {
	.deviceName = "livingroomLight",
	.pinNum = 28,
	.open = livingroomLightOpen,
	.close = livingroomLightClose,
	.deviceInit = livingroomLightCloseInit,
	.changeStatus = livingroomLightStatus

};

struct Devices *addLivingroomLightToDeviceLink(struct Devices *phead)
{
	if (phead == NULL)
	{
		return &livingroomLight;
	}
	else
	{
		livingroomLight.next = phead;
		phead = &livingroomLight;
		return phead;
	}
};

restaurantLight.c
#include "contrlDevices.h"

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

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

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

int restaurantLightStatus(int status)
{
}

struct Devices restaurantLight = {
	.deviceName = "restaurantLight",
	.pinNum = 29,
	.open = restaurantLightOpen,
	.close = restaurantLightClose,
	.deviceInit = restaurantLightCloseInit,
	.changeStatus = restaurantLightStatus

};

struct Devices *addRestaurantLightToDeviceLink(struct Devices *phead)
{
	if (phead == NULL)
	{
		return &restaurantLight;
	}
	else
	{
		restaurantLight.next = phead;
		phead = &restaurantLight;
		return phead;
	}
};

upstairLight.c
#include "contrlDevices.h"
#include <stdlib.h>

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

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

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

int upstairLightStatus(int status)
{
}

struct Devices upstairLight = {
	.deviceName = "upstairLight",
	.pinNum = 27,
	.open = upstairLightOpen,
	.close = upstairLightClose,
	.deviceInit = upstairLightCloseInit,
	.changeStatus = upstairLightStatus

};

struct Devices *addUpstairLightToDeviceLink(struct Devices *phead)
{
	if (phead == NULL)
	{
		return &upstairLight;
	}
	else
	{
		upstairLight.next = phead;
		phead = &upstairLight;
		return phead;
	}
};

buzzer.c
#include "contrlDevices.h"

struct Devices buzzer = {
	// “蜂鸣器”设备链表节点
	.deviceName = "buzzer",
	.pinNum = 22, // 树莓派gpio引脚29
	.deviceInit = buzzerInit,
	.open = buzzerOpen,
	.close = buzzerClose,
};

int buzzerInit(int pinNum) // 初始化函数
{
	pinMode(pinNum, OUTPUT);	// 配置引脚为输出引脚
	digitalWrite(pinNum, HIGH); // 引脚输出高电平,即默认为关闭状态
}

int buzzerOpen(int pinNum) // 打开函数
{
	digitalWrite(pinNum, LOW);
}

int buzzerClose(int pinNum) // 关闭函数
{
	digitalWrite(pinNum, HIGH);
}

struct Devices *addBuzzerToDeviceLink(struct Devices *phead) // 头插法将设备节点加入设备工厂链表函数
{
	if (phead == NULL)
	{
		return &buzzer;
	}
	else
	{
		buzzer.next = phead;
		phead = &buzzer;
		return phead;
	}
}
fire.c
#include "contrlDevices.h"

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

int fireStatusRead(int pinNum)
{
	return digitalRead(pinNum);
}

struct Devices fireIfOrNot = {
	.deviceName = "fireIfOrNot",
	.pinNum = 21,
	.deviceInit = fireIfOrNotInit,
	.readStatus = fireStatusRead

};

struct Devices *addFireToDeviceLink(struct Devices *phead)
{
	if (phead == NULL)
	{
		return &fireIfOrNot;
	}
	else
	{
		fireIfOrNot.next = phead;
		phead = &fireIfOrNot;
		return phead;
	}
};

指令工厂

InputCommand.h
#include <wiringPi.h>
#include <stdlib.h>

struct InputCommander
{
    char commandName[128];
    char deviceName[128];
    char command[32];
    int (*Init)(struct InputCommander *voicer, char *ipAddress, char *port);
    int (*getCommand)(struct InputCommander *voicer);
    char log[1024];
    int fd;
    char port[12];
    char ipAddress[32];
    int sfd;
    struct InputCommander *next;
};

struct InputCommander *addVoiceContrlToInputCommandLink(struct InputCommander *phead);
struct InputCommander *addSocketContrlToInputCommandLink(struct InputCommander *phead);

socketContrl.c
#include <wiringPi.h>
#include <stdio.h>
#include <wiringSerial.h>
#include <unistd.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>

#include "InputCommand.h"

int socketInit(struct InputCommander *socketMes, char *ipAddress, char *port)
{
	int s_fd;

	struct sockaddr_in s_addr;

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

	// 1 .socket
	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(socketMes->port));
	inet_aton(socketMes->ipAddress, &s_addr.sin_addr);

	// 2.bind

	bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
	// 3.listen

	listen(s_fd, 10);
	printf("socket Server listening......\n");
	socketMes->sfd = s_fd;
	return s_fd;
}

int socketGetCommand(struct InputCommander *socketMes)
{
	int c_fd;
	int n_read = 0;
	struct sockaddr_in c_addr;
	int clen = sizeof(struct sockaddr_in);
	memset(&c_addr, 0, sizeof(struct sockaddr_in));
	c_fd = accept(socketMes->sfd, (struct sockaddr *)&c_addr, &clen);

	n_read = read(c_fd, socketMes->command, sizeof(socketMes->command));
	if (n_read == -1)
	{
		perror("read");
	}
	else if (n_read > 0)
	{
		printf("\nget:%d\n", n_read);
	}
	else
	{
		printf("client quit\n");
	}
	return n_read;
}

struct InputCommander socketContrl = {
	.commandName = "socketServer",
	.command = {'\0'},
	.port = "8088",
	.ipAddress = "192.168.43.136",
	.Init = socketInit,
	.getCommand = socketGetCommand,
	.log = {'\0'},
	.next = NULL};

struct InputCommander *addSocketContrlToInputCommandLink(struct InputCommander *phead)
{
	if (phead == NULL)
	{
		return &socketContrl;
	}
	else
	{
		socketContrl.next = phead;
		phead = &socketContrl;
		return phead;
	}
};

voiceContrl.c
#include <wiringPi.h>
#include <stdio.h>
#include <wiringSerial.h>
#include <unistd.h>
#include <stdlib.h>
#include "InputCommand.h"
#include <string.h>

int voiceInit(struct InputCommander *voicer, char *ipAddress, char *port)
{
	int fd;
	if ((fd = serialOpen(voicer->deviceName, 9600)) == -1)
		exit(-1);
	voicer->fd = fd;
	return fd;
}

int voiceGetCommand(struct InputCommander *voicer)
{
	int nread = 0;
	memset(voicer->command, '\0', sizeof(voicer->command));
	nread = read(voicer->fd, voicer->command, sizeof(voicer->command));
	return nread;
}

struct InputCommander voiceContrl = {
	.commandName = "voice",
	.deviceName = "/dev/ttyAMA0",
	.command = {'\0'},
	.Init = voiceInit,
	.getCommand = voiceGetCommand,
	.log = {'\0'},
	.next = NULL};

struct InputCommander *addVoiceContrlToInputCommandLink(struct InputCommander *phead)
{
	if (phead == NULL)
	{
		return &voiceContrl;
	}
	else
	{
		voiceContrl.next = phead;
		phead = &voiceContrl;
		return phead;
	}
};

主函数

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "contrlDevices.h"
#include "InputCommand.h"
#include <unistd.h>
#include <pthread.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

struct Devices *pdeviceHead = NULL;
struct InputCommander *pCommandHead = NULL;
struct InputCommander *socketHandler = NULL;
int c_fd;

struct Devices *findDeviceByName(char *name, struct Devices *phead)
{
	struct Devices *tmp = phead;
	if (phead == NULL)
	{
		return NULL;
	}
	else
	{
		while (tmp != NULL)
		{
			if (strcmp(tmp->deviceName, name) == 0)
			{
				return tmp;
			}
			tmp = tmp->next;
		}
		return NULL;
	}
}

struct InputCommander *findCommandByName(char *name, struct InputCommander *phead)
{
	struct InputCommander *tmp = phead;
	if (phead == NULL)
	{
		return NULL;
	}
	else
	{
		while (tmp != NULL)
		{
			if (strcmp(tmp->commandName, name) == 0)
			{
				return tmp;
			}
			tmp = tmp->next;
		}
		return NULL;
	}
}

void *voice_thread(void *datas)
{
	struct InputCommander *voiceHandler;

	int nread;
	voiceHandler = findCommandByName("voice", pCommandHead);
	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("do device contrl:%s\n", voiceHandler->command);

				if (strcmp("kysd", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("bathroomLight", pdeviceHead);
					pdeviceHead->open(pdeviceHead->pinNum);
					printf("已打开浴室灯\n");
				}

				if (strcmp("gysd", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("bathroomLight", pdeviceHead);
					pdeviceHead->close(pdeviceHead->pinNum);
					printf("已关闭浴室灯\n");
				}

				if (strcmp("keld", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("upstairLight", pdeviceHead);
					pdeviceHead->open(pdeviceHead->pinNum);
				}

				if (strcmp("geld", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("upstairLight", pdeviceHead);
					pdeviceHead->close(pdeviceHead->pinNum);
				}

				if (strcmp("kktd", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("livingroomLight", pdeviceHead);
					pdeviceHead->open(pdeviceHead->pinNum);
				}

				if (strcmp("gktd", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("livingroomLight", pdeviceHead);
					pdeviceHead->close(pdeviceHead->pinNum);
				}

				if (strcmp("kctd", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("restaurantLight", pdeviceHead);
					pdeviceHead->open(pdeviceHead->pinNum);
				}

				if (strcmp("gctd", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("restaurantLight", pdeviceHead);
					pdeviceHead->close(pdeviceHead->pinNum);
				}

				if (strcmp("ksyd", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("bathroomLight", pdeviceHead);
					pdeviceHead->open(pdeviceHead->pinNum);

					pdeviceHead = findDeviceByName("upstairLight", pdeviceHead);
					pdeviceHead->open(pdeviceHead->pinNum);

					pdeviceHead = findDeviceByName("livingroomLight", pdeviceHead);
					pdeviceHead->open(pdeviceHead->pinNum);

					pdeviceHead = findDeviceByName("restaurantLight", pdeviceHead);
					pdeviceHead->open(pdeviceHead->pinNum);
				}

				if (strcmp("gsyd", voiceHandler->command) == 0)
				{
					pdeviceHead = findDeviceByName("bathroomLight", pdeviceHead);
					pdeviceHead->close(pdeviceHead->pinNum);

					pdeviceHead = findDeviceByName("upstairLight", pdeviceHead);
					pdeviceHead->close(pdeviceHead->pinNum);

					pdeviceHead = findDeviceByName("livingroomLight", pdeviceHead);
					pdeviceHead->close(pdeviceHead->pinNum);

					pdeviceHead = findDeviceByName("restaurantLight", pdeviceHead);
					pdeviceHead->close(pdeviceHead->pinNum);
				}
			}
		}
	}
}

void *read_thread(void *datas)
{
	int n_read;
	while (1)
	{
		memset(socketHandler->command, '\0', sizeof(socketHandler->command));
		n_read = read(c_fd, socketHandler->command, sizeof(socketHandler->command));
		if (n_read == -1)
		{
			perror("read");
		}
		else if (n_read == 0)
		{
			printf("\nNo receiving command\n ");
		}
		else
		{
			printf("Get socketCommand:%s\n", socketHandler->command);
			if (strcmp("kysd", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("bathroomLight", pdeviceHead);
				pdeviceHead->open(pdeviceHead->pinNum);
				printf("已打开浴室灯\n");
			}

			if (strcmp("gysd", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("bathroomLight", pdeviceHead);
				pdeviceHead->close(pdeviceHead->pinNum);
				printf("已关闭浴室灯\n");
			}

			if (strcmp("keld", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("upstairLight", pdeviceHead);
				pdeviceHead->open(pdeviceHead->pinNum);
			}

			if (strcmp("geld", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("upstairLight", pdeviceHead);
				pdeviceHead->close(pdeviceHead->pinNum);
			}

			if (strcmp("kktd", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("livingroomLight", pdeviceHead);
				pdeviceHead->open(pdeviceHead->pinNum);
			}

			if (strcmp("gktd", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("livingroomLight", pdeviceHead);
				pdeviceHead->close(pdeviceHead->pinNum);
			}

			if (strcmp("kctd", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("restaurantLight", pdeviceHead);
				pdeviceHead->open(pdeviceHead->pinNum);
			}

			if (strcmp("gctd", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("restaurantLight", pdeviceHead);
				pdeviceHead->close(pdeviceHead->pinNum);
			}

			if (strcmp("ksyd", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("bathroomLight", pdeviceHead);
				pdeviceHead->open(pdeviceHead->pinNum);

				pdeviceHead = findDeviceByName("upstairLight", pdeviceHead);
				pdeviceHead->open(pdeviceHead->pinNum);

				pdeviceHead = findDeviceByName("livingroomLight", pdeviceHead);
				pdeviceHead->open(pdeviceHead->pinNum);

				pdeviceHead = findDeviceByName("restaurantLight", pdeviceHead);
				pdeviceHead->open(pdeviceHead->pinNum);
			}

			if (strcmp("gsyd", socketHandler->command) == 0)
			{
				pdeviceHead = findDeviceByName("bathroomLight", pdeviceHead);
				pdeviceHead->close(pdeviceHead->pinNum);

				pdeviceHead = findDeviceByName("upstairLight", pdeviceHead);
				pdeviceHead->close(pdeviceHead->pinNum);

				pdeviceHead = findDeviceByName("livingroomLight", pdeviceHead);
				pdeviceHead->close(pdeviceHead->pinNum);

				pdeviceHead = findDeviceByName("restaurantLight", pdeviceHead);
				pdeviceHead->close(pdeviceHead->pinNum);
			}
		}
	}
}

void *socket_thread(void *datas)
{

	int n_read = 0;
	pthread_t readThread;
	struct sockaddr_in c_addr;
	memset(&c_addr, 0, sizeof(struct sockaddr_in));
	int clen = sizeof(struct sockaddr_in);

	socketHandler = findCommandByName("socketServer", pCommandHead);
	if (socketHandler == NULL)
	{
		printf("find socketHandler error\n");
		pthread_exit(NULL);
	}
	else
	{
		printf("%s init success\n", socketHandler->commandName);
	}
	socketHandler->Init(socketHandler, NULL, NULL);
	while (1)
	{
		c_fd = accept(socketHandler->sfd, (struct sockaddr *)&c_addr, &clen);
		pthread_create(&readThread, NULL, read_thread, NULL);
		// 只要有连接,就创建线程去对接。线程共用内存资源,同一时刻,所有设备只有一种状态。也可PV操作
	}
}

void *fire_thread(void *data)
{
	int status;
	struct Devices *firetmp = NULL;
	struct Devices *buztmp = NULL;

	firetmp = findDeviceByName("fireIfOrNot", pdeviceHead); // 寻找“火焰传感器”链表节点,返回给firetmp
	buztmp = findDeviceByName("buzzer", pdeviceHead);		// 寻找“蜂鸣器”链表节点,返回给buztmp

	while (1)
	{
		status = firetmp->readStatus(firetmp->pinNum); // 读取“火焰传感器”状态

		if (status == 0)
		{								  // 检测到火焰或强光源
			buztmp->open(buztmp->pinNum); // 打开蜂鸣器
			delay(1000);				  // 延时1000毫秒=1秒
		}

		if (status == 1)
		{								   // 未检测到火焰、强光源或解除警报
			buztmp->close(buztmp->pinNum); // 关闭蜂鸣器
		}
	}
}

int main()
{
	struct Devices *tmp = NULL;
	pthread_t voiceThread;
	pthread_t socketThread;
	pthread_t fireThread;

	if (-1 == wiringPiSetup())
		return -1;
	// 1.指令工厂初始化
	pCommandHead = addVoiceContrlToInputCommandLink(pCommandHead);
	pCommandHead = addSocketContrlToInputCommandLink(pCommandHead);

	// 2.设备控制工厂初始化
	pdeviceHead = addBathroomLightToDeviceLink(pdeviceHead);
	pdeviceHead = addUpstairLightToDeviceLink(pdeviceHead);
	pdeviceHead = addLivingroomLightToDeviceLink(pdeviceHead);
	pdeviceHead = addRestaurantLightToDeviceLink(pdeviceHead);
	pdeviceHead = addFireToDeviceLink(pdeviceHead);
	pdeviceHead = addBuzzerToDeviceLink(pdeviceHead);

	struct Devices *tmpequiphead = pdeviceHead;
	while (tmpequiphead != NULL)
	{ // 设备工厂所有设备初始化
		tmpequiphead->deviceInit(tmpequiphead->pinNum);
		tmpequiphead = tmpequiphead->next;
	}

	// 3.线程池建立

	// 3.1语音线程
	pthread_create(&voiceThread, NULL, voice_thread, NULL);

	pthread_create(&socketThread, NULL, socket_thread, NULL);

	// 3.4火灾线程
	pthread_create(&fireThread, NULL, fire_thread, NULL);

	pthread_join(voiceThread, NULL);
	pthread_join(socketThread, NULL);
	pthread_join(fireThread, NULL);
	return 0;
}