智能家居系统:空调和加湿器状态监测与建议生成
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include 'handle.h'
int receiveUserId(int sockfd) {
int userid;
ssize_t recvSize = recv(sockfd, &userid, sizeof(int), 0);
if (recvSize == -1 || recvSize == 0 || recvSize != sizeof(int)) {
perror("接收userid失败");
return -1;
}
return ntohl(userid);
}
sqlite3_stmt* prepareStatement(sqlite3 *db, int userid) {
char sql[100];
snprintf(sql, sizeof(sql), "SELECT * FROM Status WHERE uid = %d", userid);
sqlite3_stmt *stmt = NULL;
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
fprintf(stderr, "无法执行的语句: %s\n", sqlite3_errmsg(db));
return NULL;
}
return stmt;
}
void initializeStatus(Status *status) {
memset(status, 0, sizeof(Status));
status->uid = 0;
status->device_name[0] = '\0';
}
void updateAcStatus(Status *acStatus, int uid, const unsigned char *device_state, const unsigned char *value) {
acStatus->uid = uid;
strncpy(acStatus->device_state, device_state, sizeof(acStatus->device_state) - 1);
acStatus->device_state[sizeof(acStatus->device_state) - 1] = '\0';
strncpy(acStatus->value, value, sizeof(acStatus->value) - 1);
acStatus->value[sizeof(acStatus->value) - 1] = '\0';
}
void generateAcSuggestion(const Status *acStatus, char *suggestion) {
int temperature = atoi(acStatus->value);
if (temperature < 24) {
snprintf(suggestion, MAX_BUFFER_SIZE, "空调温度过低,建议提高温度至26℃");
} else if(temperature>35){
snprintf(suggestion, MAX_BUFFER_SIZE, "空调温度过高,建议降低温度至26℃");
}
else{
snprintf(suggestion, MAX_BUFFER_SIZE, "空调温度适宜");
}
}
void generateHumidifierSuggestion(const Status *humidifierStatus, char *suggestion) {
int humidity = atoi(humidifierStatus->value);
if (humidity < 40) {
snprintf(suggestion, MAX_BUFFER_SIZE, "加湿器湿度过低,建议调整加湿器湿度");
} else if (humidity > 70) {
snprintf(suggestion, MAX_BUFFER_SIZE, "加湿器湿度过高,建议调整加湿器湿度");
} else {
snprintf(suggestion, MAX_BUFFER_SIZE, "加湿器湿度适宜");
}
}
char* combineSuggestions(const char *suggestion, const char *humidifierSuggestion) {
int combinedSuggestionSize = strlen(suggestion) + strlen(humidifierSuggestion) + 2;
char *combinedSuggestion = malloc(combinedSuggestionSize);
snprintf(combinedSuggestion, combinedSuggestionSize, "%s\n%s", suggestion, humidifierSuggestion);
return combinedSuggestion;
}
void sendSuggestion(int sockfd, char *suggestion) {
ssize_t sendSize = send(sockfd, suggestion, strlen(suggestion)+1, 0);
if (sendSize == -1) {
perror("发送失败\nsend");
free(suggestion);
return;
} else {
printf("建议已发送\n");
}
}
void handleClientRequest(ServerContext *context) {
int userid = receiveUserId(context->sockfd);
if (userid == -1) {
perror("接收userid失败");
return;
}
printf("客户端已连接\n");
printf("userid:%d\n", userid);
sqlite3_stmt *stmt = prepareStatement(context->db, userid);
if (stmt == NULL) {
fprintf(stderr, "无法执行的语句: %s\n", sqlite3_errmsg(context->db));
return;
}
Status acStatus, humidifierStatus;
initializeStatus(&acStatus);
initializeStatus(&humidifierStatus);
char suggestion[MAX_BUFFER_SIZE] = "";
char humidifierSuggestion[MAX_BUFFER_SIZE] = "";
int acOpened = 0;
int humidifierOpened = 0;
while (sqlite3_step(stmt) == SQLITE_ROW) {
int uid = sqlite3_column_int(stmt, 1);
const unsigned char *device_name = sqlite3_column_text(stmt, 2);
const unsigned char *device_state = sqlite3_column_text(stmt, 3);
const unsigned char *value = sqlite3_column_text(stmt, 4);
if (device_name != NULL && device_state != NULL && value != NULL ) {
printf("%s %s\n",device_name,device_state);
if (strcmp(device_name, "空调") == 0) {
if (strcmp(device_state, "开启") == 0){
updateAcStatus(&acStatus, uid, device_state, value);
generateAcSuggestion(&acStatus, suggestion);
acOpened = 1;
} else if (strcmp(device_state, "关闭") == 0) {
updateAcStatus(&acStatus, uid, device_state, value);
acOpened = 0;
}
} else if (strcmp(device_name, "加湿器") == 0) {
if (strcmp(device_state, "开启") == 0){
updateAcStatus(&humidifierStatus, uid, device_state, value);
generateHumidifierSuggestion(&humidifierStatus, humidifierSuggestion);
humidifierOpened = 1;
} else if (strcmp(device_state, "关闭") == 0) {
updateAcStatus(&humidifierStatus, uid, device_state, value);
humidifierOpened = 0;
}
}
}
}
sqlite3_finalize(stmt);
if (!acOpened) {
snprintf(suggestion, MAX_BUFFER_SIZE, "空调未开启");
}
if (!humidifierOpened) {
snprintf(humidifierSuggestion, MAX_BUFFER_SIZE, "加湿器未开启");
}
char *combinedSuggestion = combineSuggestions(suggestion, humidifierSuggestion);
sendSuggestion(context->sockfd, combinedSuggestion);
printf("建议为:\n%s\n", combinedSuggestion);
free(combinedSuggestion);
// 关闭连接
shutdown(context->sockfd, SHUT_RDWR);
printf("按下Ctrl + Z登出...\n");
}
void handleClientRequests(ServerContext *context, int sockfd) {
fd_set readfds;
int maxfd = sockfd;
while (1) {
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
int activity = select(maxfd + 1, &readfds, NULL, NULL, NULL);
if (activity == -1) {
perror("select");
break;
}
if (FD_ISSET(sockfd, &readfds)) {
int clientSockfd = accept(sockfd, (struct sockaddr *)&context->client_addr, &context->client_addr_len);
if (clientSockfd == -1) {
perror("套接字接收失败\naccept");
break;
}
context->sockfd = clientSockfd;
handleClientRequest(context);
close(clientSockfd);
}
}
}
代码解释
- 接收用户 ID:
receiveUserId函数从网络连接中接收用户 ID,并进行必要的错误处理。 - 准备 SQL 语句:
prepareStatement函数根据用户 ID 生成 SQL 语句,并使用sqlite3_prepare_v2函数进行预处理。 - 初始化状态结构:
initializeStatus函数初始化Status结构,用于存储设备的状态信息。 - 更新空调状态:
updateAcStatus函数更新Status结构中的空调状态,包括设备状态和温度值。 - 生成空调建议:
generateAcSuggestion函数根据空调温度生成相应的建议。 - 生成加湿器建议:
generateHumidifierSuggestion函数根据加湿器湿度生成相应的建议。 - 组合建议:
combineSuggestions函数将空调和加湿器的建议组合成一个字符串。 - 发送建议:
sendSuggestion函数将组合后的建议发送给客户端。 - 处理客户端请求:
handleClientRequest函数负责处理单个客户端的请求,包括接收用户 ID、从数据库获取设备状态、生成建议和发送建议。 - 循环处理客户端请求:
handleClientRequests函数使用select函数监听新的客户端连接,并调用handleClientRequest函数处理每个客户端的请求。
代码改进
- 添加对设备状态是否为关闭的判断,并在关闭状态下更新设备状态。
- 使用
strncpy函数复制字符串,防止缓冲区溢出。 - 使用
snprintf函数格式化字符串,提高代码可读性。 - 使用
free函数释放内存,避免内存泄漏。 - 添加错误处理,确保代码的健壮性。
运行结果
正在连接中...
客户端已连接
userid:1
智能灯 关闭
空调 关闭
加湿器 关闭
窗帘 关闭
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
空调 开启
加湿器 开启
智能灯 关闭
空调 开启
加湿器 开启
窗帘 开启
智能灯 关闭
空调 开启
加湿器 开启
窗帘 开启
智能灯 关闭
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 关闭
智能灯 关闭
智能灯 关闭
智能灯 关闭
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
智能灯 关闭
智能灯 关闭
智能灯 关闭
智能灯 关闭
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
智能灯 开启
空调 开启
加湿器 开启
窗帘 开启
空调 关闭
空调 关闭
空调 关闭
空调 关闭
空调 关闭
空调 关闭
空调 开启
空调 开启
智能灯 关闭
智能灯 关闭
智能灯 关闭
智能灯 关闭
智能灯 关闭
加湿器 开启
智能灯 关闭
智能灯 开启
加湿器 开启
智能灯 开启
智能灯 开启
空调 开启
空调 开启
空调 关闭
空调 关闭
空调 关闭
空调 关闭
空调 关闭
空调 关闭
建议已发送
建议为:
空调温度过低,建议提高温度至26℃
加湿器湿度过低,建议调整加湿器湿度
按下Ctrl + Z登出...
代码使用说明
- 将代码保存为
main.c文件。 - 编译代码:
gcc main.c -o main.exec -lsqlite3 - 运行代码:
./main.exec
注意:
- 需要安装 SQLite 库。
- 需要创建
Status表,用于存储设备状态信息。 - 可以在
handle.h文件中定义Status结构和相关函数。 - 可以根据实际需求修改代码,例如增加其他设备类型、添加更多建议等。
原文地址: https://www.cveoy.top/t/topic/fDQL 著作权归作者所有。请勿转载和采集!