智能家居服务器与客户端 HTTP 通信实现

本教程将指导您构建一个智能家居服务器,使用 C 语言和 SQLite 数据库来接收客户端的 JSON 请求,分析数据,并向客户端提供建议。

数据库结构:

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

客户端代码 (已完成):

#ifndef PROCESSION_H
#define PROCESSION_H

#include <QWidget>
#include <QNetworkAccessManager>
#include <QNetworkReply>

namespace Ui {
class Procession;
}

class Procession : public QWidget
{
    Q_OBJECT

public:
    explicit Procession(int userid,QWidget *parent = nullptr);
    ~Procession();
    void processionWidget();

private slots:
    void connectToServer();//和服务器通信
    void handleServerResponse(QNetworkReply *reply);//和服务器连接回应

private:
    Ui::Procession *ui;
    int userid;
    QNetworkAccessManager *networkManager;
};

#endif // PROCESSION_H

#include "procession.h"
#include "ui_procession.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>

//通过发送POST请求将用户ID发送到指定的服务器,并将服务器的响应显示在界面上。

Procession::Procession(int userid,QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Procession),
    userid(userid)
{
    ui->setupUi(this);
    processionWidget();
    connect(ui->connectServerBtn,&QPushButton::clicked,this,[=](){
       this->connectToServer();
    });
    connect(networkManager, &QNetworkAccessManager::finished, this, &Procession::handleServerResponse);


}

Procession::~Procession()
{
    delete ui;
}

void Procession::processionWidget()
{
    setWindowTitle('服务器通信');
    setAutoFillBackground(true);
    QPalette palette=this->palette();
    QPixmap pixmap(':/user/image/image/net.jpg');
    palette.setBrush(QPalette::Window, QBrush(pixmap));
    setPalette(palette);
    setFixedSize(600,400);
}
void Procession::connectToServer()
{
    QJsonObject json;
    json['userid'] = this->userid;

    QJsonDocument doc(json);
    QByteArray postData = doc.toJson();

    QNetworkRequest request(QUrl(ui->serverIP->text()));
    request.setHeader(QNetworkRequest::ContentTypeHeader, 'application/json');

    networkManager->post(request, postData);
}

void Procession::handleServerResponse(QNetworkReply *reply)
{
    if (reply->error() == QNetworkReply::NoError) {
            QByteArray response = reply->readAll();
            ui->message->setText(response);
        } else {
            ui->message->setText('连接失败!');
        }

        reply->deleteLater();
}

服务器代码 (C 语言):

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

#define MAX_CLIENTS 10
#define DATABASE "smart_home.db"

typedef struct {
    int client_socket;
    sqlite3 *db;
} client_data;

void *handle_client(void *arg) {
    client_data *data = (client_data *)arg;
    int client_socket = data->client_socket;
    sqlite3 *db = data->db;
    char buffer[1024];
    memset(buffer, 0, sizeof(buffer));

    // Read client request
    ssize_t bytes_read = read(client_socket, buffer, sizeof(buffer));
    if (bytes_read <= 0) {
        perror("Error reading client request");
        close(client_socket);
        free(data);
        return NULL;
    }

    // Parse JSON request
    struct json_object *json_request = json_tokener_parse(buffer);
    if (json_request == NULL) {
        fprintf(stderr, "Error parsing JSON request: %s\n", buffer);
        close(client_socket);
        free(data);
        return NULL;
    }

    // Get user ID from JSON request
    struct json_object *json_userid;
    json_object_object_get_ex(json_request, "userid", &json_userid);
    int userid = json_object_get_int(json_userid);

    // Query database for device status
    char query[256];
    sprintf(query, "SELECT device_name, value FROM Status WHERE uid = %d", userid);
    sqlite3_stmt *stmt;
    if (sqlite3_prepare_v2(db, query, -1, &stmt, NULL) != SQLITE_OK) {
        fprintf(stderr, "Error preparing database query: %s\n", sqlite3_errmsg(db));
        close(client_socket);
        free(data);
        return NULL;
    }

    // Process query results
    char response[1024];
    memset(response, 0, sizeof(response));
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        const char *device_name = (const char *)sqlite3_column_text(stmt, 0);
        const char *value = (const char *)sqlite3_column_text(stmt, 1);

        // Analyze device status and generate suggestion
        if (strcmp(device_name, "air_conditioner") == 0) {
            int temperature = atoi(value);
            if (temperature < 24) {
                strcat(response, "Air conditioner temperature is too low. Please increase it to 26°C.\n");
            }
        } else if (strcmp(device_name, "humidifier") == 0) {
            int humidity = atoi(value);
            if (humidity < 40 || humidity > 70) {
                strcat(response, "Humidifier humidity is too high or too low. Please adjust the humidity.\n");
            }
        }
    }

    // Send response to client
    if (strlen(response) > 0) {
        write(client_socket, response, strlen(response));
    } else {
        write(client_socket, "No suggestion.", 14);
    }

    // Clean up
    sqlite3_finalize(stmt);
    close(client_socket);
    free(data);
    return NULL;
}

int main() {
    // Initialize SQLite database
    sqlite3 *db;
    if (sqlite3_open(DATABASE, &db) != SQLITE_OK) {
        fprintf(stderr, "Error opening database: %s\n", sqlite3_errmsg(db));
        return 1;
    }

    // Create socket
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (server_socket == -1) {
        perror("Error creating socket");
        return 1;
    }

    // Bind socket to IP and port
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(8080);
    server_address.sin_addr.s_addr = INADDR_ANY;
    if (bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address)) == -1) {
        perror("Error binding socket");
        return 1;
    }

    // Listen for incoming connections
    if (listen(server_socket, MAX_CLIENTS) == -1) {
        perror("Error listening for connections");
        return 1;
    }

    printf("Server listening on port 8080...\n");

    while (1) {
        // Accept incoming connection
        struct sockaddr_in client_address;
        socklen_t client_address_length = sizeof(client_address);
        int client_socket = accept(server_socket, (struct sockaddr *)&client_address, &client_address_length);
        if (client_socket == -1) {
            perror("Error accepting connection");
            continue;
        }

        // Create thread to handle client
        client_data *data = malloc(sizeof(client_data));
        data->client_socket = client_socket;
        data->db = db;
        pthread_t thread;
        if (pthread_create(&thread, NULL, handle_client, data) != 0) {
            perror("Error creating thread");
            close(client_socket);
            free(data);
        }
    }

    // Close SQLite database
    sqlite3_close(db);

    // Close server socket
    close(server_socket);

    return 0;
}

注意:

  • 以上代码示例仅供参考,您可能需要根据您的具体需求进行修改和调整。
  • 服务器和客户端之间的通信使用了 JSON 格式,需要使用相应的库来解析和生成 JSON 数据。
  • 服务器需要根据实际情况分析设备状态并提供相应的建议。
  • 建议使用安全的连接方式,例如 HTTPS,来保护数据传输的安全。
  • 服务器和客户端都需要进行必要的错误处理,以确保系统稳定运行。

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

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