”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 通过 MQTT 代理发送 IoT 设备数据。

通过 MQTT 代理发送 IoT 设备数据。

发布于2024-11-08
浏览:269

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 := 



这里需要指出的是,当添加更多设备类型时,此方法会变得复杂。例如,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 中保存消息的方法。

像往常一样,发送者的完整源代码可以在这里找到,订阅者代码可以在这里找到。

请在评论中告诉我您的想法。

谢谢!

版本声明 本文转载于:https://dev.to/johnscode/sending-iot-device-data-via-mqtt-broker-3ji6?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 语言 API,允许您添加您的母语。
    语言 API,允许您添加您的母语。
    早在 2016 年 4 月,我就有了为一个我非常喜欢的部落“Igede Language”创建一个字典项目的想法,我决定将其称为“Igede Dictionary”,尽管我不是“ t 是母语人士。 这促使我将 5,000 多个单词从 Igede 语言编写并翻译成英语。毫无疑问,这是我曾经研究过或拥...
    编程 发布于2024-11-08
  • 使用 Playwright、TypeScript 和 JavaScript 进行自动化
    使用 Playwright、TypeScript 和 JavaScript 进行自动化
    剧作家与 TypeScript | JavaScript 安装 Playwright 是 Microsoft 与 Puppeteer 团队合作推出的基于 Web 的现代 API 自动化工具,Puppeteer 是一个 JavaScript 库,它提供高级 API 来通过 DevTools 协议或 W...
    编程 发布于2024-11-08
  • 为什么使用 Z-Index 时我的伪元素出现在标题元素上方?
    为什么使用 Z-Index 时我的伪元素出现在标题元素上方?
    Z-Index 和伪元素:案例研究在 CSS 中,z-index 属性指定元素的堆叠顺序页面,确定哪些元素出现在其他元素“前面”或“后面”。然而,当涉及到伪元素时,例如 ::before 或 ::after,它们与 z-index 的交互有时可能不那么简单。考虑一个场景,我们使用::before 伪...
    编程 发布于2024-11-08
  • 如何在剥离标签之前删除顽固的 HTML 特殊字符?
    如何在剥离标签之前删除顽固的 HTML 特殊字符?
    去除顽固的 HTML 特殊字符strip_tags 函数虽然擅长删除 HTML 标签,但无法处理讨厌的 HTML 特殊字符,例如用于不间断空格或 © 用于版权符号。这可能是创建干净 RSS 源的绊脚石。要解决此问题,请考虑使用以下策略之一:HTML 实体解码:在字符串经过 strip_tags 之前...
    编程 发布于2024-11-08
  • 如何在 Go 中解密 AES ECB 模式加密?
    如何在 Go 中解密 AES ECB 模式加密?
    Go 中的 AES ECB 加密AES ECB 模式加密,其中每个明文块都独立加密,是一种简单但可能不安全的加密方法。在Go中,可以使用以下代码执行AES ECB解密:package main import ( "crypto/aes" "fmt&quo...
    编程 发布于2024-11-08
  • PHP 会话管理中的 session_unset() 和 session_destroy() 有什么区别?
    PHP 会话管理中的 session_unset() 和 session_destroy() 有什么区别?
    揭示 PHP 中 session_unset() 和 session_destroy() 的独特作用在 PHP 会话管理领域,出现了两个关键函数:session_unset() 和 session_destroy()。虽然它们似乎都围绕会话数据操作,但它们的功能和效果却显着不同。1。理解差异根据 P...
    编程 发布于2024-11-08
  • 以下是一些标题选项,请记住问题格式和文章的重点是控制选择框选项宽度:

**选项 1(更多技术性):**
* **如何控制Sele的宽度
    以下是一些标题选项,请记住问题格式和文章的重点是控制选择框选项宽度: **选项 1(更多技术性):** * **如何控制Sele的宽度
    如何控制选择框选项的宽度当选择框中的选项超出框的宽度时,可能会造成混乱以及笨拙的外观。为了解决这个问题,我们可以同时使用 CSS 和 JavaScript 来自定义选项的宽度并截断任何多余的文本。CSS 方法:虽然单独使用 CSS 是不行的足以设置选项的宽度,我们可以利用它来固定选择框本身的宽度。通...
    编程 发布于2024-11-08
  • C++ 异常说明符值得这么麻烦吗?
    C++ 异常说明符值得这么麻烦吗?
    C 中的异常说明符:你应该使用它们吗?C 中的异常说明符允许您指示函数是否可能抛出特定的异常类型。然而,由于担心 Visual Studio .NET 中的编译器执行、程序终止和非标准行为,人们对其实际用途产生了疑问。为什么不使用异常说明符:有限执行:编译器不严格执行异常说明符,从而减少了它们提供的...
    编程 发布于2024-11-08
  • 使用 .EJS 模板配置 Express
    使用 .EJS 模板配置 Express
    通常,我使用经典的入门版。 Expressjs.com const express = require('express') const app = express() const port = 3000 app.set('view engine', 'ejs') app.use(express.u...
    编程 发布于2024-11-08
  • 如何将自定义字体添加到 Tailwind - 对于网络和本地下载的字体
    如何将自定义字体添加到 Tailwind - 对于网络和本地下载的字体
    创建 Web 应用程序时,包含您喜欢的字体就像锦上添花。字体增强文本效果,使网站更具吸引力,并提供更好的用户体验。设计师和开发人员对某些字体又爱又恨,使用默认字体可能会限制他们的创造力。添加自定义字体使开发人员可以自由地将外部字体添加到他们的应用程序中。 先决条件 在本教程中,我强烈...
    编程 发布于2024-11-08
  • JavaScript 中柯里化的详细讨论
    JavaScript 中柯里化的详细讨论
    Currying হলো একটি ফাংশনাল প্রোগ্রামিং কৌশল যেখানে একটি ফাংশন একাধিক আর্গুমেন্ট নেওয়ার পরিবর্তে একটি একক আর্গুমেন্ট গ্রহণ করে এবং একটি নতুন ফাংশন রিটা...
    编程 发布于2024-11-08
  • 了解 Python 装饰器:深入探讨
    了解 Python 装饰器:深入探讨
    Python 装饰器是强大的工具,允许我们修改或增强函数或方法的行为。常见用例包括日志记录、授权等。 然而,当被要求定义一个装饰器时,许多人可能会说, 它是函数的包装器。 虽然这在技术上是正确的,但幕后还发生了更多事情。 剖析一个简单的装饰器 让我们探讨一个简单的例子: def my_decora...
    编程 发布于2024-11-08
  • 课程计划:年级学生 Python 基础知识(初级)
    课程计划:年级学生 Python 基础知识(初级)
    客观的: 在本课程结束时,学生将对 Python 编程有基本的了解,包括变量、基本数据类型、循环和函数。他们将使用 Python 创建简单的程序,运用逻辑思维和解决问题的技能。 持续时间:6 节课 第 1 课:Python 简介和设置 目标:让学生熟...
    编程 发布于2024-11-08
  • 如何在 Java 中正确复制二维数组以保留修改?
    如何在 Java 中正确复制二维数组以保留修改?
    通过复制保留二维数组修改在 Java 中,创建对象副本时,了解引用分配行为至关重要。在给定的场景中,定义了两个名为 current 和 old 的二维数组,以及复制内容的方法。old() 方法将 current 数组分配给 old 。然而,这只是将引用传输到内存中的同一数组。当对 current 进...
    编程 发布于2024-11-08
  • 如何在不依赖扩展名的情况下确定文件类型?
    如何在不依赖扩展名的情况下确定文件类型?
    如何在不依赖扩展名的情况下检测文件类型除了检查文件的扩展名之外,确定文件是 mp3 还是图像格式是很有价值的编程中的任务。这是一个不依赖扩展的全面解决方案:PHP >= 5.3:$mimetype = finfo_fopen(fopen($filename, 'r'), FILEINFO_MIME_...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3