首頁 >後端開發 >Golang >透過 MQTT 代理程式發送 IoT 設備資料。

透過 MQTT 代理程式發送 IoT 設備資料。

Patricia Arquette
Patricia Arquette原創
2024-09-23 14:19:291027瀏覽

Sending IoT Device Data via MQTT broker.

在上一篇文章中,我們展示如何使用 MQTT 代理程式從 IoT 裝置發送和接收訊息。在這篇文章中,我們將把這個想法擴展到現實世界的例子。

假設您有一個物聯網設備,可以測量溫室中的溫度和濕度(使用 Raspberry Pi 或 Arduino 製作一個並不難)

我們希望從另一台電腦或中央日誌服務遠端監控溫室條件。在上一篇文章中,我們展示了發送訊息的程式碼的 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 解組為結構體即可。我們將使用與發送端類似的結構;但我們需要一種方法來解組為具體類型而不是 Message 中的 Device 介面。我們將在 Message 上新增一個自訂的 unmarshal 方法,以使程式碼更簡潔

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