>  기사  >  백엔드 개발  >  MQTT 브로커를 통해 IoT 장치 데이터를 전송합니다.

MQTT 브로커를 통해 IoT 장치 데이터를 전송합니다.

Patricia Arquette
Patricia Arquette원래의
2024-09-23 14:19:29985검색

Sending IoT Device Data via MQTT broker.

이전 게시물에서는 MQTT 브로커를 사용하여 IoT 기기와 메시지를 주고받는 방법을 보여드렸습니다. 이 게시물에서는 해당 아이디어를 실제 사례로 확장해 보겠습니다.

온실의 온도와 습도를 측정하는 IoT 기기가 있다고 가정해보세요(라즈베리파이나 아두이노를 이용해서 만드는 것은 어렵지 않습니다).

우리는 다른 컴퓨터나 중앙 로깅 서비스를 통해 원격으로 온실 상태를 모니터링하고 싶습니다. 이전 게시물에서 메시지를 보내는 코드의 Go 구현을 보여주었으므로 해당 예제를 확장해 보겠습니다.

단순히 "온도는 x, 습도는 y"라는 문자열을 보내는 대신 메시지와 장치의 구조를 정의해 보겠습니다. 습기나 강수량을 모니터링하는 장치가 있고(또는 향후 추가할 예정) 해당 장치에도 연결하고 싶다고 가정해 보세요.

여러 장치와 유형의 가능성을 열어두려면 이를 처리할 데이터 모델이 필요합니다.

type Message struct {
    Time   time.Time `json:"time"`
    Device Device    `json:"device"`
}

type Device interface {
    ID() string
    Name() string
}

type TempRHDevice struct {
    Id         string  `json:"id"`
    DeviceName string  `json:"name,omitempty"`
    Temp       float32 `json:"temp,omitempty"`
    Rh         float32 `json:"rh,omitempty"`
}

func (t TempRHDevice) ID() string {
    return t.Id
}

func (t TempRHDevice) Name() string {
    return t.DeviceName
}

Message 구조체는 MQTT 브로커로 전송됩니다. 우리는 IoT 장치의 공통 속성을 처리하고 특정 장치의 세부 정보를 추상화하는 인터페이스를 만들었습니다.

TempRHDevice는 온도와 습도를 측정하는 장치입니다. Device 인터페이스를 구현하여 메시지에서 사용할 수 있습니다.

다음으로 브로커에게 메시지를 보내야 합니다. 이 예에서는 단순성을 위해 JSON 형식을 사용합니다. 수천 개 이상의 장치가 포함된 대규모 시스템에서는 보다 컴팩트한 형식을 사용하는 것이 좋습니다.

message := generateRandomMessage()
payload, err := json.Marshal(message)
if err != nil {
    panic(err)
}
token := client.Publish(topic, 0, false, payload)

Go를 사용하면 JSON으로 마샬링하는 것이 매우 쉽습니다. 마샬링되면 json 메시지가 브로커로 전송됩니다.

데이터가 확보되면 그 외에 무엇을 하고 싶습니까? 데이터베이스에 저장하고, 대시보드에 표시하고, 경보 조건에 대한 값을 확인합니다. json을 사용할 수 있도록 변환해야 합니다.

수신 측에서는 json을 구조체로 역정렬화하기만 하면 됩니다. 우리는 송신 측에서 사용된 것과 유사한 구조를 사용할 것입니다. 하지만 메시지의 Device 인터페이스 대신 구체적인 유형으로 역마샬링하는 방법이 필요합니다. 코드를 좀 더 깔끔하게 만들기 위해 Message에 사용자 정의 역마샬링 메서드를 추가하겠습니다

type rawMessage struct {
    Time   time.Time `json:"time"`
    Device TempRHDevice    `json:"device"`
}
func (m *Message) UnmarshalJSON(data []byte) error {
    var raw rawMessage
    if err := json.Unmarshal(data, &raw); err != nil {
        return err
    }
    m.Time = raw.Time
    m.Device = &raw.Device
    return nil
}

...

func processMsg(ctx context.Context, ....

...

    case msg, ok := <-input:
    if !ok {
        return
    }
    logger.Info().Msg(fmt.Sprintf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic()))
    var iotMsg Message
    err := json.Unmarshal(msg.Payload(), &iotMsg)
    if err != nil {
        logger.Error().Err(err).Msg("Error unmarshalling Message")
    } else {
        out <- iotMsg
    }

...

더 많은 장치 유형이 추가되면 이 방법이 복잡해진다는 점을 여기서 지적하는 것이 적절합니다. 예를 들어 UnmarshalJSON 메서드는 메시지에 포함된 장치 유형을 어떻게 알 수 있습니까? 유형을 감지하기 위해 UnmarshalJSON에서 몇 가지 영리한 논리를 수행할 수 있습니다.

또 다른 대안으로 MQTT를 사용하여 여러 주제에 게시할 수 있으며 주제에 대해 계층적 명명 규칙을 사용하는 것이 일반적인 관행이라는 점을 기억하세요. 따라서 온실 예에서 여러 장치 유형이 있는 경우 권장되는 방법은 서로 다른 장치 유형이 서로 다른 주제에 게시되도록 하는 것입니다. 앞으로 새로운 장치 유형을 추가할 때 이러한 방식으로 처리할 것입니다.

온실 예에서 주제 이름은 다음과 같이 구성될 수 있습니다.

/greenhouse/temprh/deviceid
/greenhouse/moisture/deviceid

MQTT에서는 다음과 같은 와일드카드 주제를 사용하여 주제를 구독할 수 있습니다.

if token := client.Subscribe("/greenhouse/#", 0, nil); token.Wait() && token.Error() != nil {
        fmt.Println(token.Error())
        os.Exit(1)
    }

온실 네임스페이스의 모든 장치와 일치합니다. 그런 다음 들어오는 메시지의 주제를 살펴보고 이를 역마샬링하는 방법을 알기 위해 processMsg()에 논리를 추가하면 됩니다.

이제 사용 가능한 형식의 장치 메시지가 생겼으니 어떻게 해야 할까요? 이 시리즈의 다음 게시물에서는 PostGres에서 메시지를 유지하는 접근 방식을 보여드리겠습니다.

평소와 같이 발신자의 전체 소스 코드는 여기에서 찾을 수 있으며 구독자 코드는 여기에서 찾을 수 있습니다.

댓글로 여러분의 생각을 알려주세요.

감사합니다!

위 내용은 MQTT 브로커를 통해 IoT 장치 데이터를 전송합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.