智能家居系统:基于 C 语言服务器和 QT C++ 客户端的数据库交互

该智能家居系统通过 C 语言编写服务器,QT C++ 编写客户端,实现设备状态信息获取和建议生成。

数据库:

-- 创建用户表
CREATE TABLE IF NOT EXISTS users (
    uid INTEGER PRIMARY KEY AUTOINCREMENT,
    username varchar(10), 
    passwd varchar(10)
);


-- 创建智能家居状态表
CREATE TABLE IF NOT EXISTS Status (
    sid INTEGER PRIMARY KEY AUTOINCREMENT,
    uid INTEGER ,
    device_name varchar(10),
    device_state varchar(10),
    value varchar(10),
    mode varchar(10),
    FOREIGN KEY (uid) REFERENCES users (uid)
);

服务器代码 (C 语言):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sqlite3.h>

#define PORT 8888
#define MAX_BUFFER_SIZE 1024

// 数据库文件路径
const char* DB_FILE = "database.db";

// 回调函数,用于处理查询结果
int callback(void* data, int argc, char** argv, char** azColName) {
    // 获取客户端传递的建议数据
    char* suggestion = (char*)data;

    // 构造建议消息
    char buf[MAX_BUFFER_SIZE];
    snprintf(buf, MAX_BUFFER_SIZE, "设备:%s,数值:%s", argv[0], argv[1]);

    // 将建议消息追加到建议数据中
    strncat(suggestion, buf, MAX_BUFFER_SIZE - strlen(suggestion) - 1);

    return 0;
}

// 处理客户端请求
void handle_client_request(int client_socket) {
    char buffer[MAX_BUFFER_SIZE];
    char suggestion[MAX_BUFFER_SIZE] = "";

    // 接收客户端发送的userid
    if (recv(client_socket, buffer, MAX_BUFFER_SIZE, 0) <= 0) {
        printf("接收userid失败\n");
        return;
    }

    // 将userid转换为整数
    int uid = atoi(buffer);

    // 连接数据库
    sqlite3* db;
    int rc = sqlite3_open(DB_FILE, &db);
    if (rc) {
        printf("无法打开数据库: %s\n", sqlite3_errmsg(db));
        return;
    }

    // 查询最新的设备信息
    char sql[MAX_BUFFER_SIZE];
    snprintf(sql, MAX_BUFFER_SIZE, "SELECT device_name, value FROM Status WHERE uid = %d ORDER BY sid DESC LIMIT 1", uid);
    rc = sqlite3_exec(db, sql, callback, suggestion, NULL);
    if (rc != SQLITE_OK) {
        printf("查询数据库失败: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return;
    }

    // 关闭数据库连接
    sqlite3_close(db);

    // 发送建议消息给客户端
    if (strlen(suggestion) > 0) {
        if (send(client_socket, suggestion, strlen(suggestion), 0) <= 0) {
            printf("发送建议消息失败\n");
        }
    } else {
        if (send(client_socket, "没有建议", strlen("没有建议"), 0) <= 0) {
            printf("发送建议消息失败\n");
        }
    }
}

int main() {
    int server_socket, client_socket;
    struct sockaddr_in server_address, client_address;
    socklen_t client_address_length;

    // 创建服务器套接字
    server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket < 0) {
        printf("创建套接字失败\n");
        return 1;
    }

    // 设置服务器地址
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = INADDR_ANY;
    server_address.sin_port = htons(PORT);

    // 绑定服务器地址到套接字
    if (bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) {
        printf("绑定地址失败\n");
        return 1;
    }

    // 监听连接请求
    if (listen(server_socket, 5) < 0) {
        printf("监听失败\n");
        return 1;
    }

    printf("服务器启动,等待连接…\n");

    while (1) {
        // 接受客户端连接
        client_address_length = sizeof(client_address);
        client_socket = accept(server_socket, (struct sockaddr*)&client_address, &client_address_length);
        if (client_socket < 0) {
            printf("接受连接失败\n");
            continue;
        }

        printf("客户端连接成功\n");

        // 处理客户端请求
        handle_client_request(client_socket);

        // 关闭客户端套接字
        close(client_socket);
    }

    // 关闭服务器套接字
    close(server_socket);

    return 0;
}

客户端代码 (QT C++):

#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QTextEdit>
#include <QTcpSocket>
#include <QHostAddress>
#include <QString>

class MainWindow : public QWidget {
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr) : QWidget(parent) {
        // 创建按钮
        QPushButton* connectButton = new QPushButton("连接服务器", this);
        connectButton->setGeometry(10, 10, 100, 30);
        connect(connectButton, &QPushButton::clicked, this, &MainWindow::connectToServer);

        // 创建文本编辑框
        textEdit = new QTextEdit(this);
        textEdit->setGeometry(10, 50, 300, 200);
    }

private slots:
    void connectToServer() {
        // 创建 TCP 套接字
        socket = new QTcpSocket(this);

        // 连接服务器
        socket->connectToHost(QHostAddress("127.0.0.1"), 8888);

        // 连接成功
        if (socket->waitForConnected(5000)) {
            textEdit->append("连接成功!");
            // 发送用户 ID
            QString userId = "1"; // 替换为实际用户 ID
            socket->write(userId.toUtf8());
            socket->flush();

            // 接收服务器建议
            connect(socket, &QTcpSocket::readyRead, this, &MainWindow::readServerData);
        } else {
            // 连接失败
            textEdit->append("连接失败!");
        }
    }

    void readServerData() {
        // 接收服务器数据
        QByteArray data = socket->readAll();
        QString msg = QString::fromUtf8(data);
        textEdit->append(msg);
    }

private:
    QTcpSocket* socket;
    QTextEdit* textEdit;
};

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

工作流程:

  1. 客户端连接服务器。
  2. 客户端发送用户 ID (uid) 给服务器。
  3. 服务器根据用户 ID 从数据库查询最新的设备状态信息。
  4. 服务器分析设备状态信息,生成建议并发送给客户端。
  5. 客户端接收并显示服务器的建议。

注意:

  • 代码示例仅提供基本功能,需要根据实际应用场景进行完善。
  • 实际应用中需要进行错误处理和安全措施,例如数据校验、身份验证等。
  • 可以根据需要修改数据库结构和建议逻辑。

示例:

假设用户 ID 为 1,空调温度为 22 摄氏度,加湿器湿度为 30%。服务器分析后,生成以下建议:

“空调温度过低,建议提高温度至 26℃;加湿器湿度过低,建议调整加湿器湿度。”

该建议将显示在客户端的 GUI 上。

总结:

该智能家居系统实现了设备状态信息的获取和建议生成功能,可以帮助用户更好地管理和使用智能家居设备。

相关资源:

智能家居系统:基于 C 语言服务器和 QT C++ 客户端的数据库交互

原文地址: https://www.cveoy.top/t/topic/fB6J 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录