๐Ÿ˜Ž ๊ณต๋ถ€ํ•˜๋Š” ์ง•์ง•์•ŒํŒŒ์นด๋Š” ์ฒ˜์Œ์ด์ง€?

[BSS ์•ˆ์ „ํ•˜๊ณ  ๊นจ๋—ํ•œ ์ง€ํ•˜์ฒ  ํƒ‘์Šน ๋ฐ ์šดํ–‰ 7] MQTT์˜ SUB ์„ ์ด์šฉํ•ด Sqlite3์œผ๋กœ DB ์ €์žฅํ•˜๊ธฐ ๋ณธ๋ฌธ

๐Ÿ‘ฉ‍๐Ÿ’ป IoT (Embedded)/Arduino

[BSS ์•ˆ์ „ํ•˜๊ณ  ๊นจ๋—ํ•œ ์ง€ํ•˜์ฒ  ํƒ‘์Šน ๋ฐ ์šดํ–‰ 7] MQTT์˜ SUB ์„ ์ด์šฉํ•ด Sqlite3์œผ๋กœ DB ์ €์žฅํ•˜๊ธฐ

์ง•์ง•์•ŒํŒŒ์นด 2023. 12. 22. 09:56
728x90
๋ฐ˜์‘ํ˜•

โญ Sqlite3

sqlite3 dbํŒŒ์ผ๋ช….db

>> .mode table

>> .tables

>> select * from ํ…Œ์ด๋ธ”๋ช…;

 

โญ db ํŒŒ์ผ (main.c) ์‹คํ–‰ํ•˜๊ธฐ

// gcc -g -o main main.c -lpaho-mqtt3c -lsqlite3

 

โœ… Ultrasonic + button

// main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

// C์–ธ์–ด๋กœ ๊ตฌํ˜„๋œ SQL ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์—”์ง„
#include <sqlite3.h>
#include <time.h>
#include <unistd.h>

//  MQ Telemetry Transport ๋ฒ„์ „ 3.1 ํ”„๋กœํ† ์ฝœ์— ๋Œ€ํ•œ
// C ๊ตฌํ˜„์˜ ํด๋ผ์ด์–ธํŠธ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋œ 32๋น„ํŠธ Windows ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
#include <MQTTClient.h>

#define MQTT_HOST "192.168.0.154"
#define MQTT_PORT 1883
#define MQTT_CLIENT_ID1 "sqlClient1"
#define MQTT_CLIENT_ID2 "sqlClient2"
#define MQTT_CLIENT_ID3 "sqlClient3"
#define MQTT_CLIENT_ID4 "sqlClient4"
#define TOPIC_ultra_1 "sensor/ultrasonic_1"
#define TOPIC_ultra_2 "sensor/ultrasonic_2"
#define TOPIC_button_1 "sensor/button_1"
#define TOPIC_button_2 "sensor/button_2"

#define DATABASE_FILE "statin_mqtt.db"

// SQLite3 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด
sqlite3 *db;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
    int i;
    for (i = 0; i < argc; i++)
    {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

char ultrasonic_1[5];
char ultrasonic_2[5];
char button_1[5];
char button_2[5];

int sql_message() {
    // printf("%s", ultrasonic_1);
    // printf("%s", ultrasonic_2);
    // printf("%s", button_1);
    // printf("%s", button_2);

    char insertSql[200];
    // message->payload : payloadptr
    snprintf(insertSql, sizeof(insertSql), "INSERT INTO station_data (ultrasonic_1, ultrasonic_2, button_1, button_2) VALUES ('%s', '%s', '%s', '%s');", ultrasonic_1, ultrasonic_2, button_1, button_2);
    char *zErrMsg = 0;

    pthread_mutex_lock(&mutex);
    // SQL ๋ช…๋ น์„ ์‹คํ–‰
    // (open ํ•œ DB, SQL ๋ฌธ์žฅ, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฆ„, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž, ERROR ๋ณ€์ˆ˜)
    int sql_rc = sqlite3_exec(db, insertSql, callback, 0, &zErrMsg);
    pthread_mutex_unlock(&mutex);

    // SQLITE_OK : ์ฝ”๋“œ๋Š” ์ž‘์—…์ด ์„ฑ๊ณตํ–ˆ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ์—†์—ˆ์Œ
    if (sql_rc != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    else
    {
        putchar('\n');
        fprintf(stdout, "Record inserted successfully\n");
    }
    return 1;
}

int on_message_ultra_1(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(ultrasonic_1, message->payload);

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_ultra_2(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(ultrasonic_2, message->payload);


    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_button_1(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(button_1, message->payload);

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_button_2(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(button_2, message->payload);

    sql_message();
    
    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}


int main()
{
    int sql_rc, mqtt_ultra_1, mqtt_ultra_2, mqtt_button_1, mqtt_button_2 ;
    MQTTClient client1, client2, client3, client4;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

    // ------------------------------------------ SQLite ------------------------------------------
    // DB ํŒŒ์ผ์„ ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜
    sql_rc = sqlite3_open(DATABASE_FILE, &db);

    // ์—ฐ๊ฒฐ ์‹คํŒจ์‹œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ
    if (sql_rc)
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        return 0;
    }
    else
    {
        fprintf(stdout, "Opened database successfully\n");
    }

    char *sql = "CREATE TABLE IF NOT EXISTS station_data("
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                "ultrasonic_1 TEXT NOT NULL,"
                "ultrasonic_2 TEXT NOT NULL,"
                "button_1 TEXT NOT NULL,"
                "button_2 TEXT NOT NULL,"
                "created_at DATETIME DEFAULT (DATETIME('now', 'localtime')));";

    pthread_mutex_lock(&mutex);
    // SQL ๋ช…๋ น์„ ์‹คํ–‰
    // (open ํ•œ DB, SQL ๋ฌธ์žฅ, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฆ„, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž, ERROR ๋ณ€์ˆ˜)
    sql_rc = sqlite3_exec(db, sql, callback, 0, 0);
    pthread_mutex_unlock(&mutex);


    // SQLITE_OK : ์ฝ”๋“œ๋Š” ์ž‘์—…์ด ์„ฑ๊ณตํ–ˆ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ์—†์—ˆ์Œ
    if (sql_rc != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
        return 0;
    }
    else
    {
        fprintf(stdout, "Table created successfully\n");
    }

    // ------------------------------------------ MQTT ------------------------------------------
    // (์ƒˆ๋กœ ์ž‘์„ฑํ•œ ํด๋ผ์ด์–ธํŠธ์˜ ํ•ธ๋“ค์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ, ์ˆ˜์‹ ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์š”์ฒญ์„ ๋ชจ๋‹ˆํ„ฐํ•˜๋Š” MQTT ํฌํŠธ์˜ URI,
    // ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ด๋ฆ„, ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ณด๋ฅ˜ ์ค‘์œผ๋กœ ์‹œ์Šคํ…œ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ ์†์‹ค)
    mqtt_ultra_1 = MQTTClient_create(&client1, MQTT_HOST, MQTT_CLIENT_ID1, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_ultra_2 = MQTTClient_create(&client2, MQTT_HOST, MQTT_CLIENT_ID2, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_button_1 = MQTTClient_create(&client3, MQTT_HOST, MQTT_CLIENT_ID3, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_button_2 = MQTTClient_create(&client4, MQTT_HOST, MQTT_CLIENT_ID4, MQTTCLIENT_PERSISTENCE_NONE, NULL);


    // TCP/IP ์—ฐ๊ฒฐ์ด ๋‹ซํžˆ์ง€ ์•Š๋„๋ก ์ž‘์€ "ํ™œ์„ฑ ์œ ์ง€(keepalive)" ๋ฉ”์‹œ์ง€๋ฅผ 20์ดˆ๋งˆ๋‹ค ๋ณด๋‚ด๊ธฐ
    conn_opts.keepAliveInterval = 10;
    // true๋กœ ์„ค์ •๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „ ์—ฐ๊ฒฐ์—์„œ ๋‚จ์•„ ์žˆ๋Š” ์ž‘์„ฑ ์ค‘์ด๋˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๊ณ  ์„ธ์…˜์ด ์‹œ์ž‘
    conn_opts.cleansession = 1;

    // ํด๋ผ์ด์–ธํŠธ๋ฅผ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•˜๊ธฐ ์ „์— ์ฝœ๋ฐฑ์„ ์„ค์ •
    mqtt_ultra_1 = MQTTClient_setCallbacks(client1, NULL, NULL, on_message_ultra_1, NULL);
    mqtt_ultra_2 = MQTTClient_setCallbacks(client2, NULL, NULL, on_message_ultra_2, NULL);
    mqtt_button_1 = MQTTClient_setCallbacks(client3, NULL, NULL, on_message_button_1, NULL);
    mqtt_button_2 = MQTTClient_setCallbacks(client4, NULL, NULL, on_message_button_2, NULL);
    
    // ํด๋ผ์ด์–ธํŠธ ํ•ธ๋“ค ๋ฐ ํฌ์ธํ„ฐ๋ฅผ ์—ฐ๊ฒฐ ์˜ต์…˜์— ์ธ์ˆ˜๋กœ ์ „๋‹ฌ
    if (((mqtt_ultra_1 = MQTTClient_connect(client1, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_ultra_2 = MQTTClient_connect(client2, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_button_1 = MQTTClient_connect(client3, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_button_2 = MQTTClient_connect(client4, &conn_opts)) != MQTTCLIENT_SUCCESS))

    {
        fprintf(stderr, "Failed to connect, return code \n");
        return 0;
    }

    // ์„ ํƒํ•œ ํ† ํ”ฝ์— ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ๋… (client, TOPIC, QOS);
    // QoS ์„ค์ •์€ ์ด ๊ตฌ๋…์ž์—๊ฒŒ ์†ก์‹ ๋œ ๋ฉ”์‹œ์ง€์— ์ ์šฉ๋˜๋Š” ์ตœ๋Œ€ ์„œ๋น„์Šค ํ’ˆ์งˆ(QoS)์„ ํŒ๋ณ„
    // ์„œ๋ฒ„๋Š” ์ด ์„ค์ •์˜ ๋‚ฎ์€ ๊ฐ’ ๋ฐ ์›๋ž˜ ๋ฉ”์‹œ์ง€์˜ QoS์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์†ก์‹ 
    mqtt_ultra_1 = MQTTClient_subscribe(client1, TOPIC_ultra_1, 0);
    mqtt_ultra_2 = MQTTClient_subscribe(client2, TOPIC_ultra_2, 0);
    mqtt_button_1 = MQTTClient_subscribe(client3, TOPIC_button_1, 0);
    mqtt_button_2 = MQTTClient_subscribe(client4, TOPIC_button_2, 0);

    // ์—ฐ๊ฒฐ ํ˜ธ์ถœ์ด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋žจ์€ ์˜ค๋ฅ˜ ์ฝ”๋“œ -1๋กœ ์ข…๋ฃŒ
    // ์—ฐ๊ฒฐ ํ˜ธ์ถœ์ด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋žจ์€ ์˜ค๋ฅ˜ ์ฝ”๋“œ -1๋กœ ์ข…๋ฃŒ
    if ((mqtt_ultra_1 != MQTTCLIENT_SUCCESS) || (mqtt_ultra_2 != MQTTCLIENT_SUCCESS) ||
        (mqtt_button_1 != MQTTCLIENT_SUCCESS) || (mqtt_button_1 != MQTTCLIENT_SUCCESS))
    {
        fprintf(stderr, "Failed to subscribe, return code \n");
        return 0;
    }

    printf("Subscribed to topic: %s\n", TOPIC_ultra_1);
    printf("Subscribed to topic: %s\n", TOPIC_ultra_2);
    printf("Subscribed to topic: %s\n", TOPIC_button_1);
    printf("Subscribed to topic: %s\n", TOPIC_button_2);

    for (;;)
    {
        usleep(1000000); // Sleep for 1 second
    }

    // ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ ๋Š๊ธฐ (client, ์ œํ•œ์‹œ๊ฐ„)
    // ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์—์„œ ์—ฐ๊ฒฐ์„ ๋Š๊ณ  ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ์ž‘์„ฑ ์ค‘์ธ ๋ฉ”์‹œ์ง€๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆผ
    // ์ œํ•œ์‹œ๊ฐ„์„ ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„๋กœ ์ง€์ • (์—ฐ๊ฒฐ์„ ๋Š๊ธฐ ์ „์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๋‹ค๋ฅธ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์ตœ๋Œ€ 10์ดˆ ๋™์•ˆ ๊ธฐ๋‹ค๋ฆผ)
    MQTTClient_disconnect(client1, 10000);
    MQTTClient_disconnect(client2, 10000);
    MQTTClient_disconnect(client3, 10000);
    MQTTClient_disconnect(client4, 10000);
    // ํด๋ผ์ด์–ธํŠธ์— ์‚ฌ์šฉ๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋น„์šฐ๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒ
    MQTTClient_destroy(&client1);
    MQTTClient_destroy(&client2);
    MQTTClient_destroy(&client3);
    MQTTClient_destroy(&client4);

    // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋‹ซ๊ธฐ
    sqlite3_close(db);
    return 0;
}

 

โœ… MQ135 * 3

// main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

// C์–ธ์–ด๋กœ ๊ตฌํ˜„๋œ SQL ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์—”์ง„
#include <sqlite3.h>
#include <time.h>
#include <unistd.h>

//  MQ Telemetry Transport ๋ฒ„์ „ 3.1 ํ”„๋กœํ† ์ฝœ์— ๋Œ€ํ•œ
// C ๊ตฌํ˜„์˜ ํด๋ผ์ด์–ธํŠธ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋œ 32๋น„ํŠธ Windows ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
#include <MQTTClient.h>

#define MQTT_HOST "192.168.0.154"
#define MQTT_PORT 1883
#define MQTT_CLIENT_ID1 "sqlClient1"
#define MQTT_CLIENT_ID2 "sqlClient2"
#define MQTT_CLIENT_ID3 "sqlClient3"

#define TOPIC_mq135_1 "sensor/mq135/_1"
#define TOPIC_mq135_2 "sensor/mq135/_2"
#define TOPIC_mq135_3 "sensor/mq135/_3"

#define DATABASE_FILE "subway_mqtt.db"

// SQLite3 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด
sqlite3 *db;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
    int i;
    for (i = 0; i < argc; i++)
    {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

char mq135_1[5];
char mq135_2[5];
char mq135_3[5];

int sql_message() {
    // printf("%s", ultrasonic_1);
    // printf("%s", ultrasonic_2);
    // printf("%s", button_1);
    // printf("%s", button_2);

    char insertSql[200];
    // message->payload : payloadptr
    snprintf(insertSql, sizeof(insertSql), "INSERT INTO subway_data (mq135_1, mq135_2, mq135_3) VALUES ('%s', '%s', '%s');", mq135_1, mq135_2, mq135_3);
    char *zErrMsg = 0;
    printf("%s", insertSql);

    pthread_mutex_lock(&mutex);
    // SQL ๋ช…๋ น์„ ์‹คํ–‰
    // (open ํ•œ DB, SQL ๋ฌธ์žฅ, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฆ„, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž, ERROR ๋ณ€์ˆ˜)
    int sql_rc = sqlite3_exec(db, insertSql, callback, 0, &zErrMsg);
    pthread_mutex_unlock(&mutex);

    // SQLITE_OK : ์ฝ”๋“œ๋Š” ์ž‘์—…์ด ์„ฑ๊ณตํ–ˆ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ์—†์—ˆ์Œ
    if (sql_rc != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    else
    {
        putchar('\n');
        fprintf(stdout, "Record inserted successfully\n");
    }
    return 1;
}

int on_message_mq135_1(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(mq135_1, message->payload);

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_mq135_2(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(mq135_2, message->payload);

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_mq135_3(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(mq135_3, message->payload);

    sql_message();

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}


int main()
{
    int sql_rc, mqtt_mq135_1, mqtt_mq135_2, mqtt_mq135_3 ;
    MQTTClient client1, client2, client3;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

    // ------------------------------------------ SQLite ------------------------------------------
    // DB ํŒŒ์ผ์„ ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜
    sql_rc = sqlite3_open(DATABASE_FILE, &db);

    // ์—ฐ๊ฒฐ ์‹คํŒจ์‹œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ
    if (sql_rc)
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        return 0;
    }
    else
    {
        fprintf(stdout, "Opened database successfully\n");
    }

    char *sql = "CREATE TABLE IF NOT EXISTS subway_data("
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                "mq135_1 TEXT NOT NULL,"
                "mq135_2 TEXT NOT NULL,"
                "mq135_3 TEXT NOT NULL,"
                "created_at DATETIME DEFAULT (DATETIME('now', 'localtime')));";

    pthread_mutex_lock(&mutex);
    // SQL ๋ช…๋ น์„ ์‹คํ–‰
    // (open ํ•œ DB, SQL ๋ฌธ์žฅ, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฆ„, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž, ERROR ๋ณ€์ˆ˜)
    sql_rc = sqlite3_exec(db, sql, callback, 0, 0);
    pthread_mutex_unlock(&mutex);


    // SQLITE_OK : ์ฝ”๋“œ๋Š” ์ž‘์—…์ด ์„ฑ๊ณตํ–ˆ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ์—†์—ˆ์Œ
    if (sql_rc != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
        return 0;
    }
    else
    {
        fprintf(stdout, "Table created successfully\n");
    }

    // ------------------------------------------ MQTT ------------------------------------------
    // (์ƒˆ๋กœ ์ž‘์„ฑํ•œ ํด๋ผ์ด์–ธํŠธ์˜ ํ•ธ๋“ค์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ, ์ˆ˜์‹ ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์š”์ฒญ์„ ๋ชจ๋‹ˆํ„ฐํ•˜๋Š” MQTT ํฌํŠธ์˜ URI,
    // ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ด๋ฆ„, ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ณด๋ฅ˜ ์ค‘์œผ๋กœ ์‹œ์Šคํ…œ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ ์†์‹ค)
    mqtt_mq135_1 = MQTTClient_create(&client1, MQTT_HOST, MQTT_CLIENT_ID1, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_mq135_2 = MQTTClient_create(&client2, MQTT_HOST, MQTT_CLIENT_ID2, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_mq135_3 = MQTTClient_create(&client3, MQTT_HOST, MQTT_CLIENT_ID3, MQTTCLIENT_PERSISTENCE_NONE, NULL);


    // TCP/IP ์—ฐ๊ฒฐ์ด ๋‹ซํžˆ์ง€ ์•Š๋„๋ก ์ž‘์€ "ํ™œ์„ฑ ์œ ์ง€(keepalive)" ๋ฉ”์‹œ์ง€๋ฅผ 20์ดˆ๋งˆ๋‹ค ๋ณด๋‚ด๊ธฐ
    conn_opts.keepAliveInterval = 10;
    // true๋กœ ์„ค์ •๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „ ์—ฐ๊ฒฐ์—์„œ ๋‚จ์•„ ์žˆ๋Š” ์ž‘์„ฑ ์ค‘์ด๋˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๊ณ  ์„ธ์…˜์ด ์‹œ์ž‘
    conn_opts.cleansession = 1;

    // ํด๋ผ์ด์–ธํŠธ๋ฅผ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•˜๊ธฐ ์ „์— ์ฝœ๋ฐฑ์„ ์„ค์ •
    mqtt_mq135_1 = MQTTClient_setCallbacks(client1, NULL, NULL, on_message_mq135_1, NULL);
    mqtt_mq135_2 = MQTTClient_setCallbacks(client2, NULL, NULL, on_message_mq135_2, NULL);
    mqtt_mq135_3 = MQTTClient_setCallbacks(client3, NULL, NULL, on_message_mq135_3, NULL);
    
    // ํด๋ผ์ด์–ธํŠธ ํ•ธ๋“ค ๋ฐ ํฌ์ธํ„ฐ๋ฅผ ์—ฐ๊ฒฐ ์˜ต์…˜์— ์ธ์ˆ˜๋กœ ์ „๋‹ฌ
    if (((mqtt_mq135_1 = MQTTClient_connect(client1, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_mq135_2 = MQTTClient_connect(client2, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_mq135_3 = MQTTClient_connect(client3, &conn_opts)) != MQTTCLIENT_SUCCESS))

    {
        fprintf(stderr, "Failed to connect, return code \n");
        return 0;
    }

    // ์„ ํƒํ•œ ํ† ํ”ฝ์— ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ๋… (client, TOPIC, QOS);
    // QoS ์„ค์ •์€ ์ด ๊ตฌ๋…์ž์—๊ฒŒ ์†ก์‹ ๋œ ๋ฉ”์‹œ์ง€์— ์ ์šฉ๋˜๋Š” ์ตœ๋Œ€ ์„œ๋น„์Šค ํ’ˆ์งˆ(QoS)์„ ํŒ๋ณ„
    // ์„œ๋ฒ„๋Š” ์ด ์„ค์ •์˜ ๋‚ฎ์€ ๊ฐ’ ๋ฐ ์›๋ž˜ ๋ฉ”์‹œ์ง€์˜ QoS์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์†ก์‹ 
    mqtt_mq135_1 = MQTTClient_subscribe(client1, TOPIC_mq135_1, 0);
    mqtt_mq135_2 = MQTTClient_subscribe(client2, TOPIC_mq135_2, 0);
    mqtt_mq135_3 = MQTTClient_subscribe(client3, TOPIC_mq135_3, 0);

    // ์—ฐ๊ฒฐ ํ˜ธ์ถœ์ด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋žจ์€ ์˜ค๋ฅ˜ ์ฝ”๋“œ -1๋กœ ์ข…๋ฃŒ
    // ์—ฐ๊ฒฐ ํ˜ธ์ถœ์ด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋žจ์€ ์˜ค๋ฅ˜ ์ฝ”๋“œ -1๋กœ ์ข…๋ฃŒ
    if ((mqtt_mq135_1 != MQTTCLIENT_SUCCESS) || (mqtt_mq135_2 != MQTTCLIENT_SUCCESS) ||
        (mqtt_mq135_3 != MQTTCLIENT_SUCCESS))
    {
        fprintf(stderr, "Failed to subscribe, return code \n");
        return 0;
    }

    printf("Subscribed to topic: %s\n", TOPIC_mq135_1);
    printf("Subscribed to topic: %s\n", TOPIC_mq135_2);
    printf("Subscribed to topic: %s\n", TOPIC_mq135_3);

    for (;;)
    {
        usleep(1000000); // Sleep for 1 second
    }

    // ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ ๋Š๊ธฐ (client, ์ œํ•œ์‹œ๊ฐ„)
    // ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์—์„œ ์—ฐ๊ฒฐ์„ ๋Š๊ณ  ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ์ž‘์„ฑ ์ค‘์ธ ๋ฉ”์‹œ์ง€๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆผ
    // ์ œํ•œ์‹œ๊ฐ„์„ ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„๋กœ ์ง€์ • (์—ฐ๊ฒฐ์„ ๋Š๊ธฐ ์ „์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๋‹ค๋ฅธ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์ตœ๋Œ€ 10์ดˆ ๋™์•ˆ ๊ธฐ๋‹ค๋ฆผ)
    MQTTClient_disconnect(client1, 10000);
    MQTTClient_disconnect(client2, 10000);
    MQTTClient_disconnect(client3, 10000);

    // ํด๋ผ์ด์–ธํŠธ์— ์‚ฌ์šฉ๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋น„์šฐ๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒ
    MQTTClient_destroy(&client1);
    MQTTClient_destroy(&client2);
    MQTTClient_destroy(&client3);

    // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋‹ซ๊ธฐ
    sqlite3_close(db);
    return 0;
}

 

โœ… Ultrasonic + button + MQ135 * 3 ๊ฐœ ์ดํ•ฉ

// main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

// C์–ธ์–ด๋กœ ๊ตฌํ˜„๋œ SQL ๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ์—”์ง„
#include <sqlite3.h>
#include <time.h>
#include <unistd.h>

//  MQ Telemetry Transport ๋ฒ„์ „ 3.1 ํ”„๋กœํ† ์ฝœ์— ๋Œ€ํ•œ
// C ๊ตฌํ˜„์˜ ํด๋ผ์ด์–ธํŠธ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋œ 32๋น„ํŠธ Windows ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
#include <MQTTClient.h>

#define MQTT_HOST "192.168.0.154"
#define MQTT_PORT 1883
#define MQTT_CLIENT_ID1 "sqlClient1"
#define MQTT_CLIENT_ID2 "sqlClient2"
#define MQTT_CLIENT_ID3 "sqlClient3"
#define MQTT_CLIENT_ID4 "sqlClient4"

#define MQTT_CLIENT_ID5 "sqlClient5"
#define MQTT_CLIENT_ID6 "sqlClient6"
#define MQTT_CLIENT_ID7 "sqlClient7"

#define TOPIC_ultra_1 "sensor/ultrasonic_1"
#define TOPIC_ultra_2 "sensor/ultrasonic_2"
#define TOPIC_button_1 "sensor/button_1"
#define TOPIC_button_2 "sensor/button_2"

#define TOPIC_mq135_1 "sensor/mq135/_1"
#define TOPIC_mq135_2 "sensor/mq135/_2"
#define TOPIC_mq135_3 "sensor/mq135/_3"

#define DATABASE_FILE "mqtt.db"

// SQLite3 ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด
sqlite3 *db;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

static int callback(void *NotUsed, int argc, char **argv, char **azColName)
{
    int i;
    for (i = 0; i < argc; i++)
    {
        printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("\n");
    return 0;
}

char ultrasonic_1[5];
char ultrasonic_2[5];
char button_1[5];
char button_2[5];

char mq135_1[5];
char mq135_2[5];
char mq135_3[5];

int sql_message_subway() {
    char insertSql[200];
    // message->payload : payloadptr
    snprintf(insertSql, sizeof(insertSql), "INSERT INTO subway_data (mq135_1, mq135_2, mq135_3) VALUES ('%s', '%s', '%s');", mq135_1, mq135_2, mq135_3);
    char *zErrMsg = 0;
    printf("%s", insertSql);

    pthread_mutex_lock(&mutex);
    // SQL ๋ช…๋ น์„ ์‹คํ–‰
    // (open ํ•œ DB, SQL ๋ฌธ์žฅ, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฆ„, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž, ERROR ๋ณ€์ˆ˜)
    int sql_rc_subway = sqlite3_exec(db, insertSql, callback, 0, &zErrMsg);
    pthread_mutex_unlock(&mutex);

    // SQLITE_OK : ์ฝ”๋“œ๋Š” ์ž‘์—…์ด ์„ฑ๊ณตํ–ˆ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ์—†์—ˆ์Œ
    if (sql_rc_subway != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    else
    {
        putchar('\n');
        fprintf(stdout, "Record inserted successfully\n");
    }
    return 1;
}


int on_message_mq135_1(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(mq135_1, message->payload);

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_mq135_2(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(mq135_2, message->payload);

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_mq135_3(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(mq135_3, message->payload);

    sql_message_subway();

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}


int sql_message_station() {
    // printf("%s", ultrasonic_1);
    // printf("%s", ultrasonic_2);
    // printf("%s", button_1);
    // printf("%s", button_2);

    char insertSql[200];
    // message->payload : payloadptr
    snprintf(insertSql, sizeof(insertSql), "INSERT INTO station_data (ultrasonic_1, ultrasonic_2, button_1, button_2) VALUES ('%s', '%s', '%s', '%s');", ultrasonic_1, ultrasonic_2, button_1, button_2);
    char *zErrMsg = 0;

    printf("%s", insertSql);

    pthread_mutex_lock(&mutex);
    // SQL ๋ช…๋ น์„ ์‹คํ–‰
    // (open ํ•œ DB, SQL ๋ฌธ์žฅ, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฆ„, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž, ERROR ๋ณ€์ˆ˜)
    int sql_rc_station = sqlite3_exec(db, insertSql, callback, 0, &zErrMsg);
    pthread_mutex_unlock(&mutex);

    // SQLITE_OK : ์ฝ”๋“œ๋Š” ์ž‘์—…์ด ์„ฑ๊ณตํ–ˆ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ์—†์—ˆ์Œ
    if (sql_rc_station != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    else
    {
        putchar('\n');
        fprintf(stdout, "Record inserted successfully\n");
    }
    return 1;
}

int on_message_ultra_1(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(ultrasonic_1, message->payload);

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_ultra_2(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(ultrasonic_2, message->payload);


    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_button_1(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(button_1, message->payload);

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}

int on_message_button_2(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    printf("Message arrived\n");
    printf("     topic: %s\n", topicName);
    printf("     message: ");
    printf("%s", message->payload);
    strcpy(button_2, message->payload);

    sql_message_station();

    // ๋ฉ”์‹œ์ง€ ํŽ˜์ด๋กœ๋“œ์— ํ• ๋‹น๋œ ์ถ”๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํฌํ•จํ•˜์—ฌ MQTT ๋ฉ”์‹œ์ง€์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ•ด์ œ
    MQTTClient_freeMessage(&message);
    //  MQTT C ํด๋ผ์ด์–ธํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ• ๋‹นํ•œ ๋ฉ”๋ชจ๋ฆฌ, ํŠนํžˆ topic ์ด๋ฆ„์„ ํ•ด์ œ
    MQTTClient_free(topicName);
    return 1;
}


int main()
{
    int sql_rc_station, sql_rc_subway, mqtt_ultra_1, mqtt_ultra_2, mqtt_button_1, mqtt_button_2, mqtt_mq135_1, mqtt_mq135_2, mqtt_mq135_3 ;
    MQTTClient client1, client2, client3, client4, client5, client6, client7;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;

    // ------------------------------------------ SQLite ------------------------------------------
    // DB ํŒŒ์ผ์„ ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜
    sql_rc_station = sqlite3_open(DATABASE_FILE, &db);
    sql_rc_subway = sqlite3_open(DATABASE_FILE, &db);

    // ์—ฐ๊ฒฐ ์‹คํŒจ์‹œ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€ ์ถœ๋ ฅ
    if (sql_rc_station)
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        return 0;
    } else if (sql_rc_subway)
    {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        return 0;
    }
    else
    {
        fprintf(stdout, "Opened database successfully\n");
    }

    char *sql_station = "CREATE TABLE IF NOT EXISTS station_data("
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                "ultrasonic_1 TEXT NOT NULL,"
                "ultrasonic_2 TEXT NOT NULL,"
                "button_1 TEXT NOT NULL,"
                "button_2 TEXT NOT NULL,"
                "created_at DATETIME DEFAULT (DATETIME('now', 'localtime')));";

    char *sql_subway = "CREATE TABLE IF NOT EXISTS subway_data("
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                "mq135_1 TEXT NOT NULL,"
                "mq135_2 TEXT NOT NULL,"
                "mq135_3 TEXT NOT NULL,"
                "created_at DATETIME DEFAULT (DATETIME('now', 'localtime')));";

    pthread_mutex_lock(&mutex);
    // SQL ๋ช…๋ น์„ ์‹คํ–‰
    // (open ํ•œ DB, SQL ๋ฌธ์žฅ, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฆ„, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž, ERROR ๋ณ€์ˆ˜)
    sql_rc_station = sqlite3_exec(db, sql_station, callback, 0, 0);
    pthread_mutex_unlock(&mutex);

    pthread_mutex_lock(&mutex);
    // SQL ๋ช…๋ น์„ ์‹คํ–‰
    // (open ํ•œ DB, SQL ๋ฌธ์žฅ, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ด๋ฆ„, ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ž, ERROR ๋ณ€์ˆ˜)
    sql_rc_subway = sqlite3_exec(db, sql_subway, callback, 0, 0);
    pthread_mutex_unlock(&mutex);

    // SQLITE_OK : ์ฝ”๋“œ๋Š” ์ž‘์—…์ด ์„ฑ๊ณตํ–ˆ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ์—†์—ˆ์Œ
    if (sql_rc_station != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
        return 0;
    } else if (sql_rc_subway != SQLITE_OK)
    {
        fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
        return 0;
    }
    else
    {
        fprintf(stdout, "Table created successfully\n");
    }

    // ------------------------------------------ MQTT ------------------------------------------
    // (์ƒˆ๋กœ ์ž‘์„ฑํ•œ ํด๋ผ์ด์–ธํŠธ์˜ ํ•ธ๋“ค์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ, ์ˆ˜์‹ ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ ์—ฐ๊ฒฐ ์š”์ฒญ์„ ๋ชจ๋‹ˆํ„ฐํ•˜๋Š” MQTT ํฌํŠธ์˜ URI,
    // ํด๋ผ์ด์–ธํŠธ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ์ด๋ฆ„, ํด๋ผ์ด์–ธํŠธ ์ƒํƒœ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋ณด๋ฅ˜ ์ค‘์œผ๋กœ ์‹œ์Šคํ…œ ์žฅ์• ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ ์†์‹ค)
    mqtt_ultra_1 = MQTTClient_create(&client1, MQTT_HOST, MQTT_CLIENT_ID1, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_ultra_2 = MQTTClient_create(&client2, MQTT_HOST, MQTT_CLIENT_ID2, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_button_1 = MQTTClient_create(&client3, MQTT_HOST, MQTT_CLIENT_ID3, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_button_2 = MQTTClient_create(&client4, MQTT_HOST, MQTT_CLIENT_ID4, MQTTCLIENT_PERSISTENCE_NONE, NULL);

    mqtt_mq135_1 = MQTTClient_create(&client5, MQTT_HOST, MQTT_CLIENT_ID5, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_mq135_2 = MQTTClient_create(&client6, MQTT_HOST, MQTT_CLIENT_ID6, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    mqtt_mq135_3 = MQTTClient_create(&client7, MQTT_HOST, MQTT_CLIENT_ID7, MQTTCLIENT_PERSISTENCE_NONE, NULL);


    // TCP/IP ์—ฐ๊ฒฐ์ด ๋‹ซํžˆ์ง€ ์•Š๋„๋ก ์ž‘์€ "ํ™œ์„ฑ ์œ ์ง€(keepalive)" ๋ฉ”์‹œ์ง€๋ฅผ 20์ดˆ๋งˆ๋‹ค ๋ณด๋‚ด๊ธฐ
    conn_opts.keepAliveInterval = 10;
    // true๋กœ ์„ค์ •๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ „ ์—ฐ๊ฒฐ์—์„œ ๋‚จ์•„ ์žˆ๋Š” ์ž‘์„ฑ ์ค‘์ด๋˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜์ง€ ์•Š๊ณ  ์„ธ์…˜์ด ์‹œ์ž‘
    conn_opts.cleansession = 1;

    // ํด๋ผ์ด์–ธํŠธ๋ฅผ ์„œ๋ฒ„์— ์—ฐ๊ฒฐํ•˜๊ธฐ ์ „์— ์ฝœ๋ฐฑ์„ ์„ค์ •
    mqtt_ultra_1 = MQTTClient_setCallbacks(client1, NULL, NULL, on_message_ultra_1, NULL);
    mqtt_ultra_2 = MQTTClient_setCallbacks(client2, NULL, NULL, on_message_ultra_2, NULL);
    mqtt_button_1 = MQTTClient_setCallbacks(client3, NULL, NULL, on_message_button_1, NULL);
    mqtt_button_2 = MQTTClient_setCallbacks(client4, NULL, NULL, on_message_button_2, NULL);
    
    mqtt_mq135_1 = MQTTClient_setCallbacks(client5, NULL, NULL, on_message_mq135_1, NULL);
    mqtt_mq135_2 = MQTTClient_setCallbacks(client6, NULL, NULL, on_message_mq135_2, NULL);
    mqtt_mq135_3 = MQTTClient_setCallbacks(client7, NULL, NULL, on_message_mq135_3, NULL);
    
    // ํด๋ผ์ด์–ธํŠธ ํ•ธ๋“ค ๋ฐ ํฌ์ธํ„ฐ๋ฅผ ์—ฐ๊ฒฐ ์˜ต์…˜์— ์ธ์ˆ˜๋กœ ์ „๋‹ฌ
    if (((mqtt_ultra_1 = MQTTClient_connect(client1, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_ultra_2 = MQTTClient_connect(client2, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_button_1 = MQTTClient_connect(client3, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_button_2 = MQTTClient_connect(client4, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    (((mqtt_mq135_1 = MQTTClient_connect(client5, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_mq135_2 = MQTTClient_connect(client6, &conn_opts)) != MQTTCLIENT_SUCCESS) ||
    ((mqtt_mq135_3 = MQTTClient_connect(client7, &conn_opts)) != MQTTCLIENT_SUCCESS)))

    {
        fprintf(stderr, "Failed to connect, return code \n");
        return 0;
    }

    // ์„ ํƒํ•œ ํ† ํ”ฝ์— ํด๋ผ์ด์–ธํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ๋… (client, TOPIC, QOS);
    // QoS ์„ค์ •์€ ์ด ๊ตฌ๋…์ž์—๊ฒŒ ์†ก์‹ ๋œ ๋ฉ”์‹œ์ง€์— ์ ์šฉ๋˜๋Š” ์ตœ๋Œ€ ์„œ๋น„์Šค ํ’ˆ์งˆ(QoS)์„ ํŒ๋ณ„
    // ์„œ๋ฒ„๋Š” ์ด ์„ค์ •์˜ ๋‚ฎ์€ ๊ฐ’ ๋ฐ ์›๋ž˜ ๋ฉ”์‹œ์ง€์˜ QoS์—์„œ ๋ฉ”์‹œ์ง€๋ฅผ ์†ก์‹ 
    mqtt_ultra_1 = MQTTClient_subscribe(client1, TOPIC_ultra_1, 0);
    mqtt_ultra_2 = MQTTClient_subscribe(client2, TOPIC_ultra_2, 0);
    mqtt_button_1 = MQTTClient_subscribe(client3, TOPIC_button_1, 0);
    mqtt_button_2 = MQTTClient_subscribe(client4, TOPIC_button_2, 0);

    mqtt_mq135_1 = MQTTClient_subscribe(client5, TOPIC_mq135_1, 0);
    mqtt_mq135_2 = MQTTClient_subscribe(client6, TOPIC_mq135_2, 0);
    mqtt_mq135_3 = MQTTClient_subscribe(client7, TOPIC_mq135_3, 0);

    // ์—ฐ๊ฒฐ ํ˜ธ์ถœ์ด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋žจ์€ ์˜ค๋ฅ˜ ์ฝ”๋“œ -1๋กœ ์ข…๋ฃŒ
    // ์—ฐ๊ฒฐ ํ˜ธ์ถœ์ด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ ํ”„๋กœ๊ทธ๋žจ์€ ์˜ค๋ฅ˜ ์ฝ”๋“œ -1๋กœ ์ข…๋ฃŒ
    if ((mqtt_ultra_1 != MQTTCLIENT_SUCCESS) || (mqtt_ultra_2 != MQTTCLIENT_SUCCESS) ||
        (mqtt_button_1 != MQTTCLIENT_SUCCESS) || (mqtt_button_1 != MQTTCLIENT_SUCCESS) ||
        (mqtt_mq135_1 != MQTTCLIENT_SUCCESS) || (mqtt_mq135_2 != MQTTCLIENT_SUCCESS) ||
        (mqtt_mq135_3 != MQTTCLIENT_SUCCESS))
    {
        fprintf(stderr, "Failed to subscribe, return code \n");
        return 0;
    }

    printf("Subscribed to topic: %s\n", TOPIC_ultra_1);
    printf("Subscribed to topic: %s\n", TOPIC_ultra_2);
    printf("Subscribed to topic: %s\n", TOPIC_button_1);
    printf("Subscribed to topic: %s\n", TOPIC_button_2);

    printf("Subscribed to topic: %s\n", TOPIC_mq135_1);
    printf("Subscribed to topic: %s\n", TOPIC_mq135_2);
    printf("Subscribed to topic: %s\n", TOPIC_mq135_3);

    for (;;)
    {
        usleep(1000000); // Sleep for 1 second
    }

    // ํด๋ผ์ด์–ธํŠธ์˜ ์—ฐ๊ฒฐ ๋Š๊ธฐ (client, ์ œํ•œ์‹œ๊ฐ„)
    // ํด๋ผ์ด์–ธํŠธ๋Š” ์„œ๋ฒ„์—์„œ ์—ฐ๊ฒฐ์„ ๋Š๊ณ  ์ฝœ๋ฐฑ ํ•จ์ˆ˜์—์„œ ์ž‘์„ฑ ์ค‘์ธ ๋ฉ”์‹œ์ง€๊ฐ€ ์™„๋ฃŒ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆผ
    // ์ œํ•œ์‹œ๊ฐ„์„ ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„๋กœ ์ง€์ • (์—ฐ๊ฒฐ์„ ๋Š๊ธฐ ์ „์— ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๋‹ค๋ฅธ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์ตœ๋Œ€ 10์ดˆ ๋™์•ˆ ๊ธฐ๋‹ค๋ฆผ)
    MQTTClient_disconnect(client1, 10000);
    MQTTClient_disconnect(client2, 10000);
    MQTTClient_disconnect(client3, 10000);
    MQTTClient_disconnect(client4, 10000);

    MQTTClient_disconnect(client5, 10000);
    MQTTClient_disconnect(client6, 10000);
    MQTTClient_disconnect(client7, 10000);

    // ํด๋ผ์ด์–ธํŠธ์— ์‚ฌ์šฉ๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋น„์šฐ๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒ
    MQTTClient_destroy(&client1);
    MQTTClient_destroy(&client2);
    MQTTClient_destroy(&client3);
    MQTTClient_destroy(&client4);

    MQTTClient_destroy(&client5);
    MQTTClient_destroy(&client6);
    MQTTClient_destroy(&client7);

    // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ๋‹ซ๊ธฐ
    sqlite3_close(db);
    return 0;
}

 

 

728x90
๋ฐ˜์‘ํ˜•

'๐Ÿ‘ฉโ€๐Ÿ’ป IoT (Embedded) > Arduino' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[BSS ์•ˆ์ „ํ•˜๊ณ  ๊นจ๋—ํ•œ ์ง€ํ•˜์ฒ  ํƒ‘์Šน ๋ฐ ์šดํ–‰ ์ตœ์ข…] Station (๋‚™์ƒ์‚ฌ๊ณ , ์Šคํฌ๋ฆฐ ๋„์–ด ๊ณ ์žฅ, ์ง€ํ•˜์ฒ  ๋‚ด Co2 ๋†๋„ ์‹œ๊ฐํ™”)  (0) 2023.12.22
[BSS ์•ˆ์ „ํ•˜๊ณ  ๊นจ๋—ํ•œ ์ง€ํ•˜์ฒ  ํƒ‘์Šน ๋ฐ ์šดํ–‰ ์ตœ์ข…] Subway (Co2 ๋†๋„ ์ธก์ •ํ•˜์—ฌ LCD ๋กœ ์‹œ๊ฐํ™”ํ•˜๊ธฐ)  (0) 2023.12.22
[BSS ์•ˆ์ „ํ•˜๊ณ  ๊นจ๋—ํ•œ ์ง€ํ•˜์ฒ  ํƒ‘์Šน ๋ฐ ์šดํ–‰ 6] MQTT ์—์„œ MQ135 ๊ฐ’ 3๊ฐœ FreeRTOS๋ฅผ ํ†ตํ•ด pub ํ•˜๊ธฐ  (1) 2023.12.22
[BSS ์•ˆ์ „ํ•˜๊ณ  ๊นจ๋—ํ•œ ์ง€ํ•˜์ฒ  ํƒ‘์Šน ๋ฐ ์šดํ–‰ 5] MQTT ์—์„œ Ultrasonic ์ดˆ์ŒํŒŒ ์„ผ์„œ pub ๊ฐ’์„ sub ์—์„œ lcd ๋กœ ์ถœ๋ ฅํ•˜๊ธฐ  (0) 2023.12.22
[BSS ์•ˆ์ „ํ•˜๊ณ  ๊นจ๋—ํ•œ ์ง€ํ•˜์ฒ  ํƒ‘์Šน ๋ฐ ์šดํ–‰ 4] MQTT ์—์„œ MQ135 pub ๊ฐ’์„ sub ์—์„œ lcd ๋กœ ์ถœ๋ ฅํ•˜๊ธฐ  (0) 2023.12.22
Comments