以下是一个示例代码,演示了如何在客户端 Qt C++ 和 Linux C 服务器之间进行 TCP/IP 数据通信,并从 SQLite 数据库中获取最新的智能家居状态并发送建议给客户端。

数据库表结构

创建用户表

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)
);

客户端代码 (Qt C++)

#include <QtWidgets>
#include <QTcpSocket>

class Client : public QWidget
{
    Q_OBJECT

public:
    Client(QWidget *parent = nullptr);
    ~Client();

private slots:
    void connectToServer();
    void sendMessage();
    void receiveMessage();
    void getServerAdvice();

private:
    QLineEdit *ipLineEdit;
    QLineEdit *portLineEdit;
    QLineEdit *sendLineEdit;
    QLineEdit *receiveLineEdit;
    QLineEdit *adviceLineEdit;
    QPushButton *connectButton;
    QPushButton *sendButton;
    QPushButton *getAdviceButton;
    QTcpSocket *socket;
};

Client::Client(QWidget *parent)
    : QWidget(parent)
{
    ipLineEdit = new QLineEdit(this);
    portLineEdit = new QLineEdit(this);
    sendLineEdit = new QLineEdit(this);
    receiveLineEdit = new QLineEdit(this);
    adviceLineEdit = new QLineEdit(this);
    connectButton = new QPushButton('Connect', this);
    sendButton = new QPushButton('Send', this);
    getAdviceButton = new QPushButton('Get Advice', this);

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(new QLabel('IP:', this));
    layout->addWidget(ipLineEdit);
    layout->addWidget(new QLabel('Port:', this));
    layout->addWidget(portLineEdit);
    layout->addWidget(new QLabel('Send Message:', this));
    layout->addWidget(sendLineEdit);
    layout->addWidget(sendButton);
    layout->addWidget(new QLabel('Received Message:', this));
    layout->addWidget(receiveLineEdit);
    layout->addWidget(getAdviceButton);
    layout->addWidget(new QLabel('Server Advice:', this));
    layout->addWidget(adviceLineEdit);
    layout->addWidget(connectButton);
    setLayout(layout);

    socket = new QTcpSocket(this);

    connect(connectButton, &QPushButton::clicked, this, &Client::connectToServer);
    connect(sendButton, &QPushButton::clicked, this, &Client::sendMessage);
    connect(socket, &QTcpSocket::readyRead, this, &Client::receiveMessage);
    connect(getAdviceButton, &QPushButton::clicked, this, &Client::getServerAdvice);
}

Client::~Client()
{
    socket->disconnectFromHost();
    socket->waitForDisconnected();
}

void Client::connectToServer()
{
    QString ip = ipLineEdit->text();
    qint16 port = portLineEdit->text().toInt();

    socket->connectToHost(ip, port);

    if (socket->waitForConnected()) {
        qDebug() << 'Connected to server';
    } else {
        qDebug() << 'Failed to connect to server';
    }
}

void Client::sendMessage()
{
    QString message = sendLineEdit->text();
    socket->write(message.toUtf8());
}

void Client::receiveMessage()
{
    QByteArray data = socket->readAll();
    receiveLineEdit->setText(data);
}

void Client::getServerAdvice()
{
    // Query the database and get the advice from the server
    // Update the adviceLineEdit with the received advice
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    Client client;
    client.show();

    return a.exec();
}

#include "main.moc"

服务器端代码 (Linux C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sqlite3.h>

#define MAX_BUFFER_SIZE 1024

void analyzeStatusAndSendAdvice(int clientSocket);

int main()
{
    int serverSocket, clientSocket;
    struct sockaddr_in serverAddress, clientAddress;
    socklen_t clientAddressLength;

    // Create a socket
    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == -1) {
        perror('Failed to create socket');
        exit(EXIT_FAILURE);
    }

    // Set server address and port
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    serverAddress.sin_port = htons(12345);

    // Bind the socket to the specified address and port
    if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == -1) {
        perror('Failed to bind socket');
        exit(EXIT_FAILURE);
    }

    // Listen for incoming connections
    if (listen(serverSocket, 5) == -1) {
        perror('Failed to listen for connections');
        exit(EXIT_FAILURE);
    }

    printf('Server listening on port 12345\n');

    while (1) {
        // Accept a new connection
        clientAddressLength = sizeof(clientAddress);
        clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, &clientAddressLength);
        if (clientSocket == -1) {
            perror('Failed to accept connection');
            exit(EXIT_FAILURE);
        }

        printf('Client connected: %s\n', inet_ntoa(clientAddress.sin_addr));

        // Analyze status and send advice to the client
        analyzeStatusAndSendAdvice(clientSocket);

        close(clientSocket);
    }

    close(serverSocket);

    return 0;
}

void analyzeStatusAndSendAdvice(int clientSocket)
{
    sqlite3 *db;
    char *errorMessage = 0;
    int result;

    // Open the SQLite database
    result = sqlite3_open('database.db', &db);
    if (result != SQLITE_OK) {
        fprintf(stderr, 'Failed to open database: %s\n', sqlite3_errmsg(db));
        exit(EXIT_FAILURE);
    }

    // Query the latest status from the Status table
    const char *sql = 'SELECT device_name, device_state, value, mode FROM Status ORDER BY sid DESC LIMIT 1';
    sqlite3_stmt *stmt;
    result = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    if (result != SQLITE_OK) {
        fprintf(stderr, 'Failed to prepare statement: %s\n', sqlite3_errmsg(db));
        exit(EXIT_FAILURE);
    }

    // Get the values from the query result
    result = sqlite3_step(stmt);
    if (result == SQLITE_ROW) {
        const unsigned char *deviceName = sqlite3_column_text(stmt, 0);
        const unsigned char *deviceState = sqlite3_column_text(stmt, 1);
        const unsigned char *value = sqlite3_column_text(stmt, 2);
        const unsigned char *mode = sqlite3_column_text(stmt, 3);

        // Analyze the status and send advice to the client
        char advice[MAX_BUFFER_SIZE];
        snprintf(advice, sizeof(advice), 'Analyze the status and send advice to the client');

        // Send the advice to the client
        send(clientSocket, advice, strlen(advice), 0);
    }

    sqlite3_finalize(stmt);
    sqlite3_close(db);
}

请注意,此代码仅为示例,并且可能需要根据您的需求进行修改和调整。确保在运行代码之前,您已经安装了 SQLite 和 Qt 开发环境,并创建了名为"database.db"的 SQLite 数据库文件。

代码说明

  1. 数据库表结构: 创建了两个表,分别是用户表 users 和智能家居状态表 Status
  2. 客户端代码:
    • 使用 QTcpSocket 类建立 TCP/IP 连接到服务器。
    • 使用 QLineEdit 类显示 IP 地址、端口号、发送的消息、接收的消息和服务器建议。
    • 使用 QPushButton 类实现连接、发送消息和获取建议的功能。
    • getServerAdvice 函数中,您可以添加从服务器获取建议并更新 adviceLineEdit 的代码。
  3. 服务器端代码:
    • 使用 socket 函数创建 TCP/IP 套接字。
    • 使用 bind 函数将套接字绑定到指定的地址和端口。
    • 使用 listen 函数开始监听连接请求。
    • 使用 accept 函数接受连接请求。
    • analyzeStatusAndSendAdvice 函数中,您可以添加从 SQLite 数据库中获取最新的状态数据并根据这些数据生成建议的代码。
    • 使用 send 函数将建议发送给客户端。

注意事项

  • 需要安装 SQLite 和 Qt 开发环境。
  • 需要创建名为 "database.db" 的 SQLite 数据库文件。
  • 需要在 getServerAdvice 函数和 analyzeStatusAndSendAdvice 函数中添加具体的逻辑代码。
  • 实际应用中,建议根据您的具体需求进行修改和调整。

其他

  • 本文主要介绍了如何实现简单的 TCP/IP 数据通信和 SQLite 数据库交互。
  • 您可以根据您的具体需求添加更多功能,例如:
    • 支持多种智能家居设备。
    • 实现更复杂的数据分析和建议生成算法。
    • 提供更友好的 GUI 界面。
  • 希望本文能够帮助您了解如何使用 Qt C++ 和 Linux C 实现智能家居状态数据分析与建议发送功能。
智能家居状态数据分析与建议发送 - Qt C++ 客户端和 Linux C 服务器示例

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

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