Dans un article précédent, nous avons montré comment envoyer et recevoir des messages à partir d'appareils IoT à l'aide d'un courtier MQTT. Dans cet article, nous étendrons cette idée à un exemple concret.
Supposons que vous ayez un appareil IoT qui mesure la température et l'humidité dans une serre (Pas difficile d'en fabriquer un avec Raspberry Pi ou Arduino).
Nous souhaitons surveiller les conditions de la serre à distance depuis un autre ordinateur ou, peut-être, un service d'enregistrement central. Dans l'article précédent, nous avons montré une implémentation Go de code pour envoyer des messages, nous allons donc étendre cet exemple.
Au lieu de simplement envoyer une chaîne disant "la température est x, l'humidité est y", définissons une structure pour le message et l'appareil. Considérez que vous disposez (ou souhaitez ajouter à l’avenir) un appareil pour surveiller l’humidité ou les précipitations et que vous souhaitez également le connecter.
Pour laisser ouverte la possibilité de plusieurs appareils et types, nous avons besoin d'un modèle de données pour gérer cela.
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 }
La structure Message est ce qui sera envoyé au courtier MQTT. Nous avons créé une interface pour gérer les attributs communs de nos appareils IoT et résumer les détails des appareils spécifiques.
Le TempRHDevice est notre appareil qui mesure la température et l'humidité. Il implémente l'interface Device, il peut donc être utilisé dans un message.
Ensuite, nous devons envoyer le message au courtier. Nous utiliserons le format JSON pour sa simplicité dans cet exemple. Notez que dans un système à grande échelle comprenant des milliers d'appareils ou plus, nous souhaiterons peut-être utiliser un format plus compact.
message := generateRandomMessage() payload, err := json.Marshal(message) if err != nil { panic(err) } token := client.Publish(topic, 0, false, payload)
Go facilite le marshalling en JSON. Une fois marshalé, le message json est envoyé au courtier.
Que voudrions-nous faire d'autre avec les données une fois que nous les avons : les stocker dans une base de données, les afficher sur un tableau de bord, vérifier les valeurs des conditions d'alarme. Nous devrons convertir le json pour le rendre utilisable.
Du côté de la réception, il nous suffit de désorganiser le json dans une structure. Nous utiliserons une structure similaire à celle utilisée du côté expéditeur ; mais nous avons besoin d'un moyen de transformer en un type concret plutôt que l'interface Device dans Message. Nous ajouterons une méthode de démarshal personnalisée sur Message pour rendre le code un peu plus propre également
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 } ...
Il convient de souligner ici que cette méthode se complique lorsque d'autres types d'appareils sont ajoutés. Par exemple, comment la méthode UnmarshalJSON saura-t-elle quel type de périphérique contient le message. Nous pourrions faire une logique intelligente dans UnmarshalJSON pour détecter le type.
Pour une autre alternative, n'oubliez pas que MQTT peut être utilisé pour publier sur plusieurs sujets et qu'il est courant d'utiliser une convention de dénomination hiérarchique pour les sujets. Ainsi, dans le cas de plusieurs types d'appareils dans l'exemple de serre, la méthode recommandée consiste à publier différents types d'appareils sur différents sujets. C’est ainsi que nous procéderons à l’avenir à mesure que nous ajouterons de nouveaux types d’appareils.
Dans l'exemple de la serre, les noms des sujets pourraient être structurés comme :
/greenhouse/temprh/deviceid /greenhouse/moisture/deviceid
Dans MQTT, nous pouvons nous abonner à des sujets en utilisant un sujet générique, tel que :
if token := client.Subscribe("/greenhouse/#", 0, nil); token.Wait() && token.Error() != nil { fmt.Println(token.Error()) os.Exit(1) }
qui correspondra à tous les appareils de l'espace de noms de la serre. il nous suffirait alors d'ajouter une logique à processMsg() pour examiner le sujet du message entrant afin de savoir comment le désorganiser.
Maintenant que nous avons un message sur l'appareil sous une forme utilisable, que faut-il en faire ? Dans le prochain article de cette série, nous démontrerons notre approche pour conserver le message dans PostGres.
Comme d'habitude, le code source complet de l'expéditeur peut être trouvé ici et le code d'abonné peut être trouvé ici.
Faites-moi part de vos commentaires dans les commentaires.
Merci !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!