基于树莓派4B的智能家居系统设计

news2024/11/15 15:34:42

目录

一、项目介绍

二、前期准备

1.硬件准备

2.开发环境

三、C语言的简单工厂模式

1.工厂模式介绍

2.类和对象

3.工厂模式的优缺点

四、树莓派的基本使用

1.树莓派刷机和登入

2.树莓派WiringPi库介绍

3.树莓派 CSI 摄像头配置

4.树莓派与其他模块接线

五、智能家居设计框架

1.产品工厂

2.指令工厂

六、项目总结


一、项目介绍

        该项目主控为树莓派4B开发板,使用 wiringPi 库结合 DHT11 温湿度传感器、火焰传感器、振动传感器、烟雾传感器、蓝牙模块、L298N电机驱动模块、继电器组模块、SU-03T语音模块、CSI 摄像头模块、风扇模块等,可实现语音控制、网络控制、自制蓝牙手机APP或者安卓APP控制继电器状态从而控制灯、风扇、警报器的开关,可以结合 mjpg-streamer 库,CSI 摄像头实现视频监控和通过翔云人工智能开放平台或阿里云进行人脸识别进而通过 PWM 控制舵机旋转模拟开关门状态,当有火花或振动时会触发报警器报警,报警器状态、温湿度采集和通风扇状态可在手机APP上查看。

        采用工厂模式,将以上模块分为指令工厂和设备工厂,语音模块通过串口产生的指令和手机 app 通过串口蓝牙或 socket 产生的指令为指令工厂,其余模块为设备工厂,指令工厂和设备工厂分别用单链表进行链接,指令工厂产生指令,树莓派4B收到指令然后通过指令在设备工厂寻找设备从而进行控制。

        扩展:后续可以自行增加其他模块和功能,例如红外遥控、人体红外模块、使用OpenCV实现人脸识别、QT上位机控制下位机树莓派、增加MQTT协议等,等暑假有时间我再把扩展功能一起实现呈现给大家。

二、前期准备

1.硬件准备

首先我们需要一块树莓派作为主控,树莓派3B、4B、5B都行,然后需要准备两盒电池和各种各样的模块,下面我列出硬件清单。

硬件清单:

树莓派、CSI 摄像头模块、DHT11 温湿度传感器、火焰传感器、振动传感器、烟雾传感器、蓝牙模块、L298N电机驱动模块、继电器组模块、SU-03T语音模块、风扇模块、sg90舵机、红外遥控、红外模块、oled屏幕、人体红外模块、面包板加电池供电。

2.开发环境

做该项目需要先学习C语言、单片机、linux系统编程、ARM开发、QT等知识。

开发环境主要有:

  • ubuntu
  • mobaxterm
  • 手机APP
  • QT上位机(后续扩展)

三、C语言的简单工厂模式

1.工厂模式介绍

工厂模式是最常用的设计模式之一,属于创建型模式,提供一种创建对象的最佳方式。在工厂模式中,创建对象时,不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。即工厂模式把创建对象和使用对象的两个过程分离,对于使用者无需关心对象时如何创建出来的,直接指定一个对象即可使用该对象的方法。

C语言不是一门面向对象的语言,而是一门面向过程的语言,但C语言一样支持面向对象编程,即支持简单工厂模式。
工厂模式就是类的继承,C语言使用函数指针来实现类的继承,工厂中的设备用链表来链接起来。


2.类和对象

  • 类:一种用户定义的数据类型,也称类类型,例如结构体。
  • 对象:类的一种实例化,例如结构体赋值。

具体介绍可看类和对象详细介绍

3.工厂模式的优缺点

优点

  • 在创建对象时,只需要知道对象的名字就行,代码维护性强。
  • 需要添加设备时,只需要添加一个对象就行了,代码扩展性。

缺点

  • 代码阅读性变复杂。
  • 设备增多时会使对象增多,提高了代码复杂度。

四、树莓派的基本使用

1.树莓派刷机和登入

在这里使用的是开发板ssh登入,具体看我之前写过的文章,链接如下:树莓派刷机和登入

2.树莓派WiringPi库介绍

具体看我之前写过的文章,链接如下:树莓派WiringPi库总结

3.树莓派 CSI 摄像头配置

具体看我之前写过的文章,链接如下:树莓派 CSI 摄像头配置

4.树莓派与其他模块接线

下载完 WiringPi 库后输入命令 gpio readall  查看树莓派引脚

具体接线:

  • 火焰传感器:GPIO 0
  • 烟雾传感器:GPIO 1
  • SG90舵机:GPIO 2
  • 温湿度传感器:GPIO 7
  • OLED模块:SDA连对应SDA、SCL连对应SCL
  • 蓝牙模块或者语音模块:Tx连Rx、Rx连Tx
  • 继电器组控制四盏灯:GPIO 21-24
  • 报警器:GPIO 25
  • 风扇模块电机驱动:GPIO 27 28
  • 振动传感器:GPIO 29

五、智能家居设计框架

该智能家居由两个工厂和若干个设备组成,分别是产品工厂和指令工厂。包含功能如下:

1.产品工厂

该工厂主要是用来生产一些供人们使用的设备,如各种灯设备、OLED屏幕显示设备、环境数据检测设备、检测安全设备等等。

创建产品工厂的类,即产品工厂的生产线:

  • 设备名称
  • 设备状态
  • 设备引脚
  • 设备数据存储区
  • 设备功能
    • 打开
    • 关闭
    • 设备初始化
    • 读状态位
    • 改变状态位
    • 读数据
  • 链表链接节点,使对应的设备上线成为商品

controlDevices.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;  // 链表链接节点
};

具体产品设备有:

  • 一楼灯设备
  • 二楼灯设备
  • 餐厅灯设备
  • 卧室灯设备
  • OLED屏幕显示设备
  • 风扇设备
  • 锁设备
  • 警报器设备
  • 地震监测设备
  • 火灾监测设备
  • 烟雾监测设备
  • 温湿度监测设备

四盏灯设备代码示例:代码基本相同,只列举一个

#include "controlDevices.h"

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

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

struct Devices bathroomLight = {
	.devicesName = "bathroom",
	.pinNum		 = 21,
	.open		 = bathroomLightOpen,
	.close		 = bathroomLightClose,
	.devicesInit = bathroomLightInit,
	.next        = NULL,
};

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

风扇设备代码示例:

#include "controlDevices.h"

int fanOpen(int pinNum)
{	
	digitalWrite(27,LOW);
	digitalWrite(28,HIGH);	
}
	
int fanClose(int pinNum)
{
	digitalWrite(27,LOW);
	digitalWrite(28,LOW);	
}

int fanInit(int pinNum)
{
	pinMode(27,OUTPUT);
	pinMode(28,OUTPUT);
	
	digitalWrite(27,LOW);
	digitalWrite(28,LOW);

}

struct Devices fan = {
	.devicesName = "fan",
	.pinNum		 = 27,
	.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;
	}
}

火灾、地震、烟雾监测设备代码示例:代码基本相同,只列举一个

#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		 = 0,
	.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;
	}
}

温湿度监测代码示例:

#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 = 7,
	.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;
	}
}

2.指令工厂

该工厂主要是用来生产一些供人们发出指令控制的设备,如语音设备、蓝牙设备、server设备、人脸识别设备等等,这些设备可以控制产品工厂的设备做出一些控制行为。

创建指令工厂的类,即指令工厂的生产线:

  • 指令内容
  • 指令名称
  • 日志
  • 语言模块或蓝牙模块
    • 文件的fd
    • 设备名称
  • 网络通信
    • server的fd
    • 端口号
    • IP地址
  • 人脸识别
    • 指向主人的人脸图片
    • 指向临时的人脸图片
    • 人脸识别匹配度
  • 设备功能
    • 指令设备初始化
    • 获取指令设备
    • 处理函数
  • 链表链接节点,使对应的设备上线成为商品

inputCmd.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;  //链表链接节点
};

具体指令设备有:

  • 语音设备
  • 蓝牙设备
  • server设备
  • 人脸识别设备

树莓派串口通信详细介绍可看我之前写过的文章,链接如下:树莓派串口通信

语音设备、蓝牙设备代码示例:代码基本相同,只列举一个。

#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 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;
	}
}

网络通信详细介绍和编程可看我之前写过的文章,链接如下:

网络通信TCP、UDP介绍

网络通信TCP、UDP编程详解

server设备代码示例:

#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 = "8888",
	.ipAress = "192.168.137.115", // 树莓派ip地址
	.next = NULL,
};

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

人脸识别设备代码示例:该设备通过使用 curl 第三方库访问网站,调用祥云人脸识别平台进行人脸识别。

#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;
	}
}

完整代码我后续再上传到资源

编译时要链接 wiringPi 库跟线程库:gcc *.c *.h -lwiringPi -lpthread

编译调试图示:

六、项目总结

总体来说,只要掌握好C语言、裸机外设和Linux,整个项目做下来其实难度并不大,从这个项目中我们可以学到面向对象的编程思想和练习对多个外设模块进行控制。

该项目还有很多可以扩展的地方,后续我打算用IMX6ULL 加 MQTT 重新实现一下智能家居,再用QT作为上位机控制下位机(选择 IMX6ULL),使用 OpenCV 进行人脸识别从而进行开关锁,计划在暑假实现全部扩展功能,让不同的开发板也可以完美实现该项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1500139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】生成条形码工具类

报销单需要根据单号生成条形码 先看效果图 直接上代码&#xff0c;复制即可使用 /*** Description:生成条形码*/ public class BarCodeUtils {/*** 默认图片宽度*/private static final int DEFAULT_PICTURE_WIDTH 300;/*** 默认图片高度*/private static final int DEFAULT_…

【C++杂货铺】详解string

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 为什么学习string &#x1f4c1; 认识string&#xff08;了解&#xff09; &#x1f4c1; string的常用接口 &#x1f4c2; 构造函数 &#x1f4c2; string类对象的容量操作 &#x1f4c2; string类对象的访问以及遍历操…

智慧油气场站:油气行业实现数字化转型的关键一步

智慧油气场站&#xff1a;油气行业实现数字化转型的关键一步 在现代社会&#xff0c;能源供应是国家经济发展和人民生活的重要保障。而油气场站作为能源的重要供应和储存基地&#xff0c;扮演着至关重要的角色。此外&#xff0c;油气场站还可以为石油和天然气的生产提供支持。…

前端手册-实现挂坠灯笼效果

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

网红老阳推荐的蓝海项目,视频号带货怎么样?有优势吗?

老阳是一位在互联网创业领域颇具影响力的任务&#xff0c;他经常会在自己的社交媒体平台上分享一些他认为有潜力的蓝海项目和创业机会。近期&#xff0c;老阳推荐了一个备受关注的蓝海项目——视频号带货。那么&#xff0c;这个项目究竟怎么样呢?我们来分析一下。 首先&#x…

TypeScript 基础(一)

目录 一、概述 二、开发环境 三、数据类型 1.boolean 2.number 3.string 4.Array 5.type 6.tuple 7.enum 8.any 9.null / undefined 10.never 11.object 结束 一、概述 TypeScript 是一种由微软开发的开源编程语言。它是 JavaScript 的一个超集&#xff0c;这意…

【排序算法】推排序算法解析:从原理到实现

目录 1. 引言 2. 推排序算法原理 3. 推排序的时间复杂度分析 4. 推排序的应用场景 5. 推排序的优缺点分析 5.1 优点&#xff1a; 5.2 缺点&#xff1a; 6. Java、JavaScript 和 Python 实现推排序算法 6.1 Java 实现&#xff1a; 6.2 JavaScript 实现&#xff1a; 6.…

使用langchain搭建本地知识库系统(新)

使用langchain搭建自己的本地知识库系统&#xff08;新&#xff09; 前些时候字节上了自己的扣子&#xff0c;用来构建我们自己的 agent [AI 实战&#xff1a;手把手教你使用「扣子/coze」来搭建个人blog知识库 受到启发&#xff0c;想在本地或者自己的服务器上面搭建一个知识…

震惊!性能一下子提升10倍,用Performance面板分析性能瓶颈全流程!

工作中发现了一个下拉框打开的数据比较慢&#xff0c;并且打开弹框的时候会有相当长一段时间的延迟&#xff0c;下拉的弹框不是使用组件库的&#xff0c;而是自己封装的一个组件&#xff0c;怀疑存在数据量过大影响的情况&#xff0c;所以借助性能分析工具来找出具体的原因。 如…

渲染农场与并行处理:大规模渲染任务的高效解决方案

随着数字技术与计算机图形学的突飞猛进&#xff0c;大规模渲染任务已成为电影制作、游戏开发、建筑设计以及科学计算等诸多行业的常态化需求。面对这些日益增长的需求&#xff0c;渲染农场与并行处理技术凭借其卓越的效率和精准度&#xff0c;已然成为应对这些挑战的核心高效解…

bigemap在水利科学研究院是如何应用的?

使用场景&#xff1a; 1.数据采集&#xff1a;客户主要是做科研方向的&#xff0c;前期的工作内容就是野外调查使用Bigemap APP去采集点位数据回传到电脑上&#xff0c;电脑端再进行查看分类、二次编辑标注和统计数据。 2.矢量处理&#xff1a;客户其他部门用GPS采集回来的项目…

YUNBEE-腾讯云TDSQL MySQL和PostgreSQL TCA初级认证考试

腾讯云TDSQL(MySQL版)‍ TCA 数据库交付运维工程师-腾讯云TDSQL(MySQL版) - 课程体系 - 云贝教育 (yunbee.net) 培训概述 数据库交付运维工程师-腾讯云TDSQL&#xff08;MySQL版&#xff09;培训&#xff0c;将通过理论与上机演练相结合的方式&#xff0c;以腾讯分布式OLTP数…

波卡 Alpha 计划启动,呼唤先锋创新者重新定义 Web3 开发

原文&#xff1a;https://polkadot.network/blog/the-polkadot-alpha-program-a-new-era-for-decentralized-building-collaboration/ 编译&#xff1a;OneBlock 区块链领域不断发展&#xff0c;随之而来的是发展和创新机会的增加。而最新里程碑是令人振奋的 Polkadot Alpha …

OceanMind海睿思数据资产管理平台更新,文件资产管理能力大幅提升!

海睿思数据资产管理平台 再度迎来重磅更新&#xff01; 新版本的文件资产管理能力得到了大幅提升&#xff0c;更贴合项目实际使用场景&#xff0c;安全性更高、功能更全、使用更便捷。 本期更新亮点&#xff1a; 新增文件资产注册功能新增资产标签管理功能新增文件资产打标签…

非父子通信- event bus 事件总线

非父子通信 (兄弟) - event bus 事件总线 作用&#xff1a;非父子组件之间&#xff0c;进行简易消息传递。(复杂场景 → Vuex) 创建一个都能访问到的事件总线 (空 Vue 实例) → utils/EventBus.js import Vue from vue const Bus new Vue() export default Bus. A 组件(接收…

Springboot多环境切换最灵活配置,没有之一

在日常的开发中&#xff0c;一般都会分好几种环境&#xff0c;比如通常的 开发环境&#xff1a;一般在开发的过程中&#xff0c;一个比较随意地环境&#xff0c;通常可以随意重启&#xff0c;删除数据 测试环境&#xff1a;面向测试同学的环境&#xff0c;需要相对稳定&…

测试点点延迟和带宽的脚本总结

从队列中获取节点名 我们有时候需要从任务队列中取出完整的节点名称&#xff0c;比如cn[8044-8046,8358-8360,8926-8928,9002-9004]&#xff0c;可以给定参数input_str也可以在脚本中直接写死。 import re import subprocess import sysinput_str "cn[7512-7519,7545-75…

音视频数字化(视频线缆与接口)

目录 1、DVI接口 2、DP接口 之前的文章【音视频数字化(线缆与接口)】提到了部分视频线缆,今天再补充几个。 视频模拟信号连接从莲花头的“复合”线开始,经历了S端子、色差分量接口,通过亮度、色度尽量分离的办法提高画面质量,到VGA已经到了模拟的顶峰,实现了RGB的独立…

面试问答之MySQL数据库进阶

文章目录 &#x1f412;个人主页&#xff1a;信计2102罗铠威&#x1f3c5;JavaEE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380; MySQL架构&#x1f415;数据库引擎&#x1f415; InnoDB存储存储引擎&#x1f415;MYISAM &#x1f3e8;索引&#x1f415;哪些情况需要创建…

学习c语言:预处理详解(宏定义)

1.预定义符号 C语⾔设置了⼀些预定义符号&#xff0c;可以直接使⽤&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编译的时间 __STDC__ //如果编译器遵循ANSI C&…