C语言socket编程实现智能家居服务器端:根据数据库信息向客户端发送建议
C语言socket编程实现智能家居服务器端:根据数据库信息向客户端发送建议
本文介绍如何使用C语言socket编程实现一个简单的智能家居服务器端。该服务器端可以根据数据库中的设备状态信息,向客户端发送相应的建议。
代码分析
以下是服务器端代码的主要部分:
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include 'handle.h'
// ... 其他函数定义 ...
void handleClientRequest(ServerContext *context) {
// 接收客户端发送的userid
int userid = receiveUserId(context->sockfd);
if (userid == -1) {
perror('接收userid失败');
return;
}
printf('客户端已连接\n');
printf('userid:%d\n', userid);
// 根据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 ) {
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_name, '加湿器') == 0) {
// 如果加湿器开启,则更新加湿器状态并生成建议
if (strcmp(device_state, '开启') == 0){
updateAcStatus(&humidifierStatus, uid, device_state, value);
generateHumidifierSuggestion(&humidifierStatus, humidifierSuggestion);
humidifierOpened = 1;
}
}
}
}
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');
}
// ... 其他函数定义 ...
问题分析
您遇到的问题是,即使加湿器和空调都开启,服务器仍然会向客户端发送“加湿器未开启”和“空调未开启”的提示信息。
问题原因:
在代码中,用于标识空调和加湿器是否开启的变量 acOpened 和 humidifierOpened 在每次循环迭代中都会被重置。也就是说,如果数据库中有多条关于空调或加湿器的记录,即使其中一条记录显示设备已开启,但只要有一条记录显示设备未开启,最终 acOpened 和 humidifierOpened 的值都会是0,导致发送错误的提示信息。
解决方案:
将 acOpened 和 humidifierOpened 的初始化移到循环外部,确保这两个变量的值能够正确反映空调和加湿器的最终开启状态。
修改后的代码
void handleClientRequest(ServerContext *context) {
// ...
// 用于标识空调和加湿器是否开启
int acOpened = 0;
int humidifierOpened = 0;
while (sqlite3_step(stmt) == SQLITE_ROW) {
// ...
// 判断设备类型
if (device_name != NULL && device_state != NULL && value != NULL ) {
if (strcmp(device_name, '空调') == 0) {
// 如果空调开启,则更新空调状态并生成建议
if (strcmp(device_state, '开启') == 0){
// ...
acOpened = 1; // 更新acOpened状态
}
} else if (strcmp(device_name, '加湿器') == 0) {
// 如果加湿器开启,则更新加湿器状态并生成建议
if (strcmp(device_state, '开启') == 0){
// ...
humidifierOpened = 1; // 更新humidifierOpened状态
}
}
}
}
// ...
}
通过以上修改,代码就能正确判断空调和加湿器的开启状态,并向客户端发送正确的建议信息。
原文地址: https://www.cveoy.top/t/topic/fDPY 著作权归作者所有。请勿转载和采集!