In einem früheren Beitrag haben wir gezeigt, wie man mithilfe eines MQTT-Brokers Nachrichten von IoT-Geräten sendet und empfängt. In diesem Beitrag erweitern wir diese Idee auf ein Beispiel aus der Praxis.
Angenommen, Sie haben ein IoT-Gerät, das Temperatur und Luftfeuchtigkeit in einem Gewächshaus misst (Es ist nicht schwer, eines mit Raspberry Pi oder Arduino herzustellen).
Wir möchten die Gewächshausbedingungen von einem anderen Computer oder vielleicht von einem zentralen Protokollierungsdienst aus fernüberwachen. Im vorherigen Beitrag haben wir eine Go-Implementierung des Codes zum Senden von Nachrichten gezeigt, daher werden wir dieses Beispiel erweitern.
Anstatt nur eine Zeichenfolge mit der Aufschrift „Temperatur ist x, Luftfeuchtigkeit ist y“ zu senden, definieren wir eine Struktur für die Nachricht und das Gerät. Bedenken Sie, dass Sie ein Gerät zur Überwachung von Feuchtigkeit oder Niederschlag haben (oder in Zukunft hinzufügen möchten) und dieses auch anschließen möchten.
Um die Möglichkeit mehrerer Geräte und Typen offen zu lassen, benötigen wir ein Datenmodell, um damit umzugehen.
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 }
Die Nachrichtenstruktur ist das, was an den MQTT-Broker gesendet wird. Wir haben eine Schnittstelle erstellt, um die gemeinsamen Attribute unserer IoT-Geräte zu verarbeiten und die Details der spezifischen Geräte zu abstrahieren.
Das TempRHDevice ist unser Gerät, das Temperatur und Luftfeuchtigkeit misst. Es implementiert die Geräteschnittstelle und kann daher in einer Nachricht verwendet werden.
Als nächstes müssen wir die Nachricht an den Broker senden. Der Einfachheit halber verwenden wir in diesem Beispiel das JSON-Format. Beachten Sie, dass wir in einem großen System mit Tausenden oder mehr Geräten möglicherweise ein kompakteres Format verwenden möchten.
message := generateRandomMessage() payload, err := json.Marshal(message) if err != nil { panic(err) } token := client.Publish(topic, 0, false, payload)
Go macht das Marshalling in JSON ziemlich einfach. Nach dem Marshalling wird die JSON-Nachricht an den Broker gesendet.
Was möchten wir sonst noch mit den Daten machen, wenn wir sie haben: Sie in einer Datenbank speichern, auf einem Dashboard anzeigen, die Werte auf Alarmbedingungen überprüfen. Wir müssen den JSON konvertieren, um ihn nutzbar zu machen.
Auf der Empfangsseite müssen wir nur den JSON in eine Struktur entmarshalieren. Wir verwenden eine ähnliche Struktur wie auf der Absenderseite. Wir brauchen jedoch eine Möglichkeit zum Unmarshalieren in einen konkreten Typ und nicht in die Geräteschnittstelle in Message. Wir werden Message eine benutzerdefinierte Unmarshal-Methode hinzufügen, um den Code ebenfalls etwas sauberer zu machen
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 } ...
An dieser Stelle sei darauf hingewiesen, dass diese Methode komplizierter wird, wenn weitere Gerätetypen hinzugefügt werden. Wie erkennt die UnmarshalJSON-Methode beispielsweise, welchen Gerätetyp die Nachricht enthält? Wir könnten in UnmarshalJSON eine clevere Logik verwenden, um den Typ zu erkennen.
Bedenken Sie als weitere Alternative, dass MQTT zum Veröffentlichen in mehreren Themen verwendet werden kann und es gängige Praxis ist, eine hierarchische Namenskonvention für Themen zu verwenden. Im Falle mehrerer Gerätetypen im Gewächshausbeispiel besteht die empfohlene Vorgehensweise darin, unterschiedliche Gerätetypen zu unterschiedlichen Themen veröffentlichen zu lassen. So werden wir künftig vorgehen, wenn wir neue Gerätetypen hinzufügen.
Im Gewächshaus-Beispiel könnten die Themennamen wie folgt aufgebaut sein:
/greenhouse/temprh/deviceid /greenhouse/moisture/deviceid
In MQTT können wir Themen mit einem Platzhalterthema abonnieren, wie zum Beispiel:
if token := client.Subscribe("/greenhouse/#", 0, nil); token.Wait() && token.Error() != nil { fmt.Println(token.Error()) os.Exit(1) }
was mit allen Geräten im Gewächshaus-Namespace übereinstimmt. Dann müssten wir nur noch Logik zu „processMsg()“ hinzufügen, um uns das Thema der eingehenden Nachricht anzusehen und zu wissen, wie man sie entmarshallt.
Da wir nun eine Gerätemeldung in verwendbarer Form haben, fragen wir uns, was damit geschehen soll. Im nächsten Beitrag dieser Reihe demonstrieren wir unseren Ansatz, die Nachricht in PostGres beizubehalten.
Wie üblich finden Sie hier den vollständigen Quellcode des Absenders und hier den Abonnentencode.
Teilen Sie mir Ihre Gedanken in den Kommentaren mit.
Danke!
Das obige ist der detaillierte Inhalt vonSenden von IoT-Gerätedaten über einen MQTT-Broker.. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!