MQTT IoT 통신 시스템 구현

HKTUOHA·2024년 6월 25일

IoT 프로토콜 

목록 보기
2/3
post-thumbnail

Windows (실패)

gcc 컴파일러 사용을 위해 MinGW 설치 필요
https://m.blog.naver.com/dorergiverny/223032334186

기본 통신 구현


📌Windows 트러블슈팅

mingw32-make 오류

  • paho.mqtt.c 라이브러리 빌드 중에 mingw32-make가 되지 않는다면 파일 경로에 [ ]이 없는지 확인하자...
  • [ ]는 명령 프롬프트나 PowerShell에서 파일명 패턴 매칭을 위해 사용되는 메타 문자로 인식

...가상 IoT 시스템 구현 실패...
paho.mqtt.c 빌드 왜 실패되는걸까...

Windows에서 실행하려고 MinGW, CMake, mosquitto 다 설치했는데 paho.mqtt.c 빌드 실패...

→ Windows는 나중에 다시 해보기




Ubuntu (성공)

1. MQTT 브로커(Mosquitto) 설치

sudo apt update
sudo apt install mosquitto mosquitto-clients libmosquitto-dev

2. 기본 IoT 시스템 통신 구현

2-1. client_light.c

  • 밝기 값을 MQTT 브로커에 발행
// client_light.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mosquitto.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <brightness>\n", argv[0]);
        return 1;
    }

    int brightness = atoi(argv[1]);
    struct mosquitto *mosq = mosquitto_new(NULL, true, NULL);

    mosquitto_connect(mosq, "localhost", 1883, 60);
    char payload[20];
    snprintf(payload, 20, "%d", brightness);
    mosquitto_publish(mosq, NULL, "room/light", strlen(payload), payload, 0, false);

    mosquitto_disconnect(mosq);
    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();

    return 0;
}

2-2. client_switch.c

// client_switch.c
#include <stdio.h>
#include <stdlib.h>
#include <mosquitto.h>

void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg) {
    int brightness = atoi((char *)msg->payload);

    printf("room/light b'%s'\n", (char *)msg->payload);

    if (brightness <= 20) {
        printf("Turn on light\n");
    } else {
        printf("Turn off light\n");
    }
}

void on_connect(struct mosquitto *mosq, void *obj, int rc) {
    printf("rc: %d\n", rc);
    if (rc == 0) {
        mosquitto_subscribe(mosq, NULL, "room/light", 0);
    }
}

void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos) {
    printf("Subscribed: %d\n", mid);
}

int main() {
    mosquitto_lib_init();
    struct mosquitto *mosq = mosquitto_new(NULL, true, NULL);

    mosquitto_connect_callback_set(mosq, on_connect);
    mosquitto_message_callback_set(mosq, on_message);
    mosquitto_subscribe_callback_set(mosq, on_subscribe);

    mosquitto_connect(mosq, "localhost", 1883, 60);
    mosquitto_loop_forever(mosq, -1, 1);

    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();

    return 0;
}

2-3. 컴파일 및 실행

gcc -o client_light client_light.c -lmosquitto
gcc -o client_switch client_switch.c -lmosquitto

2-4. 실행 결과

  • 밝기센서와 스위치로 구성된 가상 IoT 시스템


3. 복잡 IoT 시스템 통신 구현

3-1. client_light.c

  • 밝기센서에서 IoT로 밝기값 전달
// client_light.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mosquitto.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <brightness>\n", argv[0]);
        return 1;
    }   

    int brightness = atoi(argv[1]);
    struct mosquitto *mosq = mosquitto_new(NULL, true, NULL);

    if (mosquitto_connect(mosq, "localhost", 1883, 60)) {
        fprintf(stderr, "Unable to connect.\n");
        return 1;
    }   

    char payload[20];
    snprintf(payload, 20, "%d", brightness);
    mosquitto_publish(mosq, NULL, "room/get/light", strlen(payload), payload, 0, false);

    mosquitto_disconnect(mosq);
    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();

    return 0;
}

3-2. client_switch.c

  • IoT로부터 전달 받은 제어 명령어 출력
  • 스위치에서 IoT로 스위치 제어 결과 전달
// client_switch.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mosquitto.h>

void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg) {
    printf("%s b'%s'\n", msg->topic, (char *)msg->payload);

    char result[20];
    if (strcmp((char *)msg->payload, "ON") == 0) {
        printf("Turn on light\n");
        strcpy(result, "Turn on complete");
    } else {
        printf("Turn off light\n");
        strcpy(result, "Turn off complete");
    }   

    mosquitto_publish(mosq, NULL, "room/get/switch", strlen(result), result, 0, false);
}

void on_connect(struct mosquitto *mosq, void *obj, int rc) {
    printf("rc: %d\n", rc);
    if (rc == 0) {
        mosquitto_subscribe(mosq, NULL, "room/put/switch", 0); 
    }   
}

void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos) {
    printf("Subscribed: %d\n", mid);
}

int main() {
    mosquitto_lib_init();
    struct mosquitto *mosq = mosquitto_new(NULL, true, NULL);

    mosquitto_connect_callback_set(mosq, on_connect);
    mosquitto_message_callback_set(mosq, on_message);
    mosquitto_subscribe_callback_set(mosq, on_subscribe);

    if (mosquitto_connect(mosq, "localhost", 1883, 60)) {
        fprintf(stderr, "Unable to connect.\n");
        return 1;
    }   

    mosquitto_loop_forever(mosq, -1, 1); 

    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();

    return 0;
}

3-3. server_iot.c

  • 밝기센서로부터 전달 받은 밝기값 출력
  • 밝기값에 따라 스위치 제어 명령어 전달
  • 스위치로부터 전달 받은 제어 결과 출력
// server_iot.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mosquitto.h>

void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg) {
    if (strcmp(msg->topic, "room/get/light") == 0) {
        printf("LIGHT : %s b'%s'\n", msg->topic, (char *)msg->payload);
        int brightness = atoi((char *)msg->payload);

        char command[4];
        if (brightness <= 20) {
            strcpy(command, "ON");
        } else {
            strcpy(command, "OFF");
        }
        mosquitto_publish(mosq, NULL, "room/put/switch", strlen(command), command, 0, false);
    } else if (strcmp(msg->topic, "room/get/switch") == 0) {
        printf("SWITCH: %s b'%s'\n", msg->topic, (char *)msg->payload);
    }   
}

void on_connect(struct mosquitto *mosq, void *obj, int rc) {
    printf("rc: %d\n", rc);
    if (rc == 0) {
        mosquitto_subscribe(mosq, NULL, "room/get/light", 0); 
        mosquitto_subscribe(mosq, NULL, "room/get/switch", 0); 
    }   
}

void on_subscribe(struct mosquitto *mosq, void *obj, int mid, int qos_count, const int *granted_qos) {
    printf("Subscribed: %d\n", mid);
}

int main() {
    mosquitto_lib_init();
    struct mosquitto *mosq = mosquitto_new(NULL, true, NULL);

    mosquitto_connect_callback_set(mosq, on_connect);
    mosquitto_message_callback_set(mosq, on_message);
    mosquitto_subscribe_callback_set(mosq, on_subscribe);

    if (mosquitto_connect(mosq, "localhost", 1883, 60)) {
        fprintf(stderr, "Unable to connect.\n");
        return 1;
    }   

    mosquitto_loop_forever(mosq, -1, 1); 

    mosquitto_destroy(mosq);
    mosquitto_lib_cleanup();

    return 0;
}

3-4. 컴파일 및 실행

gcc -o client_light client_light.c -lmosquitto
gcc -o client_switch client_switch.c -lmosquitto
gcc -o server_iot server_iot.c -lmosquitto

3-5. 실행 결과


📌복잡 IoT 시스템 트러블슈팅

출력 오류

  • Mosquitto 라이브러리는 mosquitto_message_callback_set 함수는 한 번에 하나의 메시지 콜백 함수만 설정할 수 있다.
  • 따라서 다수의 콜백 함수를 설정해도 실제로는 마지막으로 설정된 콜백 함수만 호출된다.

트러블슈팅 이전

...
...

void on_light_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg) {
    printf("LIGHT : %s b'%s'\n", msg->topic, (char *)msg->payload);
    int brightness = atoi((char *)msg->payload);

    char command[4];
    if (brightness <= 20) {
        strcpy(command, "ON");
    } else {
        strcpy(command, "OFF");
    }   

    mosquitto_publish(mosq, NULL, "room/put/switch", strlen(command), command, 0, false);
}

void on_switch_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg) {
    printf("SWITCH: %s b'%s'\n", msg->topic, (char *)msg->payload);
}

...
...

int main() {
    mosquitto_lib_init();
    struct mosquitto *mosq = mosquitto_new(NULL, true, NULL);

    mosquitto_connect_callback_set(mosq, on_connect);
   
   --------------------- 이 부분이 문제 -------------------------
    mosquitto_message_callback_set(mosq, on_light_message);
    mosquitto_message_callback_set(mosq, on_switch_message);
   ------------------------------------------------------------
    
    mosquitto_subscribe_callback_set(mosq, on_subscribe);
    
...
...

트러블슈팅 이후

...
...

void on_message(struct mosquitto *mosq, void *obj, const struct mosquitto_message *msg) {
    if (strcmp(msg->topic, "room/get/light") == 0) {
        printf("LIGHT : %s b'%s'\n", msg->topic, (char *)msg->payload);
        int brightness = atoi((char *)msg->payload);

        char command[4];
        if (brightness <= 20) {
            strcpy(command, "ON");
        } else {
            strcpy(command, "OFF");
        }
        mosquitto_publish(mosq, NULL, "room/put/switch", strlen(command), command, 0, false);
    } else if (strcmp(msg->topic, "room/get/switch") == 0) {
        printf("SWITCH: %s b'%s'\n", msg->topic, (char *)msg->payload);
    }
}

...
...

int main() {
    mosquitto_lib_init();
    struct mosquitto *mosq = mosquitto_new(NULL, true, NULL);

    mosquitto_connect_callback_set(mosq, on_connect);
    mosquitto_message_callback_set(mosq, on_message);
    mosquitto_subscribe_callback_set(mosq, on_subscribe);

...
...
  1. on_light_message와 on_switch_message에서 하나의 on_message로 통합
  2. 그 안에서 토픽을 구분하여 처리
profile
공부 기록

0개의 댓글