Em uma postagem anterior, mostramos como enviar e receber mensagens de dispositivos IoT usando um corretor MQTT. Neste post vamos estender essa ideia para um exemplo do mundo real.
Suponha que você tenha um dispositivo IoT que mede temperatura e umidade em uma estufa (Não é difícil fazer um usando Raspberry Pi ou Arduino).
Queremos monitorar as condições do efeito estufa remotamente a partir de outro computador ou, talvez, de um serviço central de registro. No post anterior, mostramos uma implementação de código Go para enviar mensagens, então estenderemos esse exemplo.
Em vez de apenas enviar uma string dizendo "temperatura é x, umidade é y", vamos definir uma estrutura para a mensagem e o dispositivo. Considere que você tem (ou deseja adicionar no futuro) um dispositivo para monitorar umidade ou precipitação e deseja conectá-lo também.
Para deixar aberta a possibilidade de vários dispositivos e tipos, precisamos de um modelo de dados para lidar com isso.
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 }
A estrutura Message é o que será enviado ao broker MQTT. Criamos uma interface para lidar com os atributos comuns de nossos dispositivos IoT e abstrair os detalhes dos dispositivos específicos.
O TempRHDevice é nosso dispositivo que mede temperatura e umidade. Ele implementa a interface do dispositivo, para que possa ser usado em uma mensagem.
Em seguida, precisamos enviar a mensagem ao corretor. Empregaremos o formato JSON por sua simplicidade neste exemplo. Observe que em um sistema de grande escala com milhares ou mais dispositivos, podemos querer usar um formato mais compacto.
message := generateRandomMessage() payload, err := json.Marshal(message) if err != nil { panic(err) } token := client.Publish(topic, 0, false, payload)
Go torna a triagem em JSON muito fácil. Depois de empacotada, a mensagem json é enviada ao corretor.
O que mais gostaríamos de fazer com os dados quando os tivermos: armazená-los em um banco de dados, exibi-los em um painel, verificar os valores das condições de alarme. Precisaremos converter o json para torná-lo utilizável.
No lado do recebimento, só precisamos desempacotar o json em uma estrutura. Usaremos uma estrutura semelhante à usada no lado do envio; mas precisamos de uma maneira de desempacotar em um tipo concreto, em vez da interface Device em Message. Adicionaremos um método unmarshal personalizado em Message para tornar o código um pouco mais limpo também
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 :=É apropriado ressaltar aqui que esse método fica complicado quando mais tipos de dispositivos são adicionados. Por exemplo, como o método UnmarshalJSON saberá que tipo de dispositivo a mensagem contém. Poderíamos fazer uma lógica inteligente no UnmarshalJSON para detectar o tipo.
Para outra alternativa, lembre-se de que o MQTT pode ser usado para publicar em vários tópicos e é prática comum usar uma convenção de nomenclatura hierárquica para tópicos. Portanto, no caso de vários tipos de dispositivos no exemplo da estufa, a maneira recomendada é publicar diferentes tipos de dispositivos em diferentes tópicos. É assim que lidaremos com isso à medida que adicionarmos novos tipos de dispositivos.
No exemplo da estufa, os nomes dos tópicos poderiam ser estruturados como:
/greenhouse/temprh/deviceid /greenhouse/moisture/deviceidNo MQTT, podemos assinar tópicos usando um tópico curinga, como:
if token := client.Subscribe("/greenhouse/#", 0, nil); token.Wait() && token.Error() != nil { fmt.Println(token.Error()) os.Exit(1) }que corresponderá a todos os dispositivos no namespace da estufa. então precisaríamos apenas adicionar lógica a processMsg() para examinar o tópico da mensagem recebida e saber como desempacotá-la.
Agora que temos uma mensagem do dispositivo em um formato utilizável, o que deve ser feito com ela. No próximo post desta série, demonstraremos nossa abordagem para persistir a mensagem no PostGres.
Como de costume, o código-fonte completo do remetente pode ser encontrado aqui e o código do assinante pode ser encontrado aqui.
Deixe-me saber sua opinião nos comentários.
Obrigado!
Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.
Copyright© 2022 湘ICP备2022001581号-3