본문 바로가기
기록해보기

MQTT를 사용한 프로젝트 진행해보기 2

by titlejjk 2023. 8. 28.

다음으로 센서 데이터를 전송하기 위해 데이터를 생성하는 로직을 만들어보려고 한다.

모의 프로젝트라 센서 데이터를 생성 할 수가 없어서 가상의 센서 데이터를 생성하는 로직을 추가하는 방법을 택했다.

이렇게 생성된 가상의 센서데이터는 MQTT브로커로 전송이 된다.

특정 간격으로 온도 데이터를 생성하고 브로커로 전송하는 기능을 가지게 했다.

@Service
public class MqttPublisher {

    @Autowired
    private MqttClient mqttClient;

    private int temperature = 0;  // 초기 온도 설정

    // 클라이언트의 요청에 따라 온도를 증가시키는 메서드
    public void startTemperatureIncrease() {
        try {
            temperature += 1;  // 온도 1도 증가

            MqttMessage message = new MqttMessage();
            message.setPayload(String.valueOf(temperature).getBytes());

            mqttClient.publish("sensor/temperature", message);

            // 온도가 100도에 도달했다면 클라이언트에 알림을 보냄
            if (temperature >= 100) {
                // 클라이언트에 알림을 보내는 로직 (예: WebSocket, HTTP 등)
            }
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    // "완료" 버튼을 누를 경우 온도를 초기화하는 메서드
    public void resetTemperature() {
        temperature = 0;  // 온도 초기화
    }
}

temperature변수를 0으로 초기값을 주고 5초마다 1도씩 증가하도록 설정해두었다.

온도가 100도에 도달하면("sensor/alert")로 MQTT에 추가적으로 메세지를 보낸다.

 

위 처럼 메서드를 설계한 이유는 아래와 같다.

가장 기본적인 설정은 클라이언트에게 선택권을 주려고 설계한 것인데.

반려동물 요리에 관한 프로젝트이기 때문에 사용하기 위한 클라이언트에 의해 해당 메서드가 실행이 되고 클라이언트가 원할때 해당 메서드를 종료할 수 있게끔 설계해 작성해 보았다.

 

즉 온도 증가는 클라이언트의 요청에 따라 시작이 되며 온도가 100도에 도달했을 때 클라이언트에게 알림을 보내며 "완료" 버튼을 누르면 온도를 다시 0으로 초기화 시키는 메서드이다.

 

다음은 MQTT메세지를 구독하고 처리하는 로직을 추가해볼 것이다.

Spring Boot 애플리케이션에서 MQTT메세지를 구독하는 코드는 아래와 같다.

package com.project.mqtt;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class MqttSubscriber {

    //MqttConfig에 있는 MqttPahoMessageDrivenChannelAdapter의존성 주입
    private final MqttPahoMessageDrivenChannelAdapter messageDrivenChannelAdapter;

    @ServiceActivator(inputChannel = "mqttInputChannel")
    public void receiveMessage(String payload){
        //payload처리
        System.out.println("Received message : " + payload);
    }
}

우선 @Service어노테이션으로 위 클래스를 Spring이 관리하게끔 설정해주었으며 MQTT메세지를 받도록 설정해두었다.

여기서 "mqttInputChannel"은 MQTT메세지를 수신할 때 사용되는 채널의 이름이다.

receiveMessage메서드는 실제로 MQTT메세지의 payload를 받아 처리하는 메서드이다.

지금 당장은 콘솔에 출력하도록 설정해 두었다.

 

여기까지 백엔드에서의 준비는 끝이 났다.

프론트엔드와의 통신에 앞서 먼저 테스트코드를 작성해보는 것이 좋을 것 같다.

 

MQTT메세지 발행과 구독을 테스트하는 간단한 테스트코드를 작성해보겠다.

package com.project;

import com.project.mqtt.MqttPublisher;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

public class MqttMessageHandlingTest {

    //테스트할 MqttPublisher Class
    @InjectMocks
    private MqttPublisher mqttPublisher;

    //MQTT 클라이언트 Mock 객체
    @Mock
    private MqttClient mqttClient;

    //Mock 객체를 초기화하기 위한 메서드
    @BeforeEach
    public void setup(){
        MockitoAnnotations.openMocks(this);
    }

    //메세지 발행 테스트
    @Test
    @DisplayName("MQTT pub/sub간의 메세지 발행 테스트")
    public void testPublishMessage() throws Exception{

        //Given
        MqttMessage message = new MqttMessage();
        message.setPayload("Test Message : ".getBytes());

        //When
        mqttPublisher.startTemperatureIncrease();//메서드 실행

        //Then
        verify(mqttClient, times(1)).publish(eq("sensor/temperature"), any(MqttMessage.class));
    }
}

단순 테스트 코드이다.

성공적으로 테스트 된것같다.

다음에는 프론트엔드랑 연결하는 부분을 작성해보겠다.

'기록해보기' 카테고리의 다른 글

E-mail인증 처리2  (0) 2023.09.08
E-mail인증 처리  (0) 2023.09.08
MQTT를 사용한 프로젝트 진행해보기 1  (0) 2023.08.28
메서드 분리와 DRY의 원칙  (0) 2023.08.27
Follow 기능 구현  (0) 2023.08.24

댓글