EdgeX Foundry - MQTT 设备服务

# EdgeX Foundry

https://iothub.org.cn/docs/edgex/
https://iothub.org.cn/docs/edgex/device/service-mqtt/

一、MQTT 设备服务

1.概述

MQTT 设备服务使用 MQTT 协议将设备/传感器连接到 EdgeX。目标设备和此设备服务连接到同一 MQTT 代理并交换异步数据和设备命令的消息。
在这里插入图片描述

EdgeX 与 MQTT 设备通信
在这里插入图片描述

2.服务配置

MQTT 设备服务具有以下配置来实现 MQTT 协议。

ConfigurationDefault ValueDescription
MQTTBrokerInfo.SchematcpThe URL schema
MQTTBrokerInfo.HostlocalhostThe URL host
MQTTBrokerInfo.Port1883The URL port
MQTTBrokerInfo.Qos0Quality of Service 0 (At most once), 1 (At least once) or 2 (Exactly once)
MQTTBrokerInfo.KeepAlive3600Seconds between client ping when no active data flowing to avoid client being disconnected. Must be greater then 2
MQTTBrokerInfo.ClientIddevice-mqttClientId to connect to the broker with
MQTTBrokerInfo.CredentialsRetryTime120The retry times to get the credential
MQTTBrokerInfo.CredentialsRetryWait1The wait time(seconds) when retry to get the credential
MQTTBrokerInfo.ConnEstablishingRetry10The retry times to establish the MQTT connection
MQTTBrokerInfo.ConnRetryWaitTime5The wait time(seconds) when retry to establish the MQTT connection
MQTTBrokerInfo.AuthModenoneIndicates what to use when connecting to the broker. Must be one of “none” , “usernamepassword”
MQTTBrokerInfo.CredentialsPathcredentialsName of the path in secret provider to retrieve your secrets. Must be non-blank.
MQTTBrokerInfo.IncomingTopicincoming/data/#IncomingTopic is used to receive the async value
MQTTBrokerInfo.ResponseTopiccommand/response/#ResponseTopic is used to receive the command response from the device
MQTTBrokerInfo.Writable.ResponseFetchInterval500ResponseFetchInterval specifies the retry interval(milliseconds) to fetch the command response from the MQTT broker

使用环境变量覆盖

用户可以使用 compose 文件中的变量覆盖上述任何配置 environment: 以满足他们的要求,例如:

The user can override any of the above configurations using environment: variables in the compose file to meet their requirement, for example:

# docker-compose.override.yml

  version: '3.7'

  services:
    device-mqtt:
      environment:
        MQTTBROKERINFO_CLIENTID: "my-device-mqtt"
        MQTTBROKERINFO_CONNRETRYWAITTIME: "10"

3.协议属性

此服务为支持 2 路通信的每个已定义设备定义以下协议属性。这些属性位于每个设备定义部分的mqtt键下protocols

PropertyDescription
CommandTopic用于向设备发送命令的基本 MQTT 主题

在这里插入图片描述

4.多级 Topics

在多级 Topics 中,发布的有效载荷中的数据是读值数据。设备和源的名称嵌入到主题中。支持多级主题有两种方式——异步数据和命令。

4.1.异步数据

异步数据发布到主题,incoming/data/{device-name}/{source-name}其中:

  • device-name 是发送读值的设备的名称
  • source-name 是已发布数据的命令或资源名称
  • 当源名称与命令名称匹配时,发布的数据必须是 JSON 对象,并且命令中指定的资源名称为字段名称。

在这里插入图片描述

  • 当source-name 只匹配资源名称的情况下,发布的数据可以是资源的读取值,也可以是以资源名称作为字段名称的 JSON 对象。
    在这里插入图片描述
4.2.命令

发送到设备的命令将针对以下主题发送 command/{device-name}/{command-name}/{method}/{uuid}

  • device-name 是将接收命令的设备的名称

  • command-name 是发送到设备的命令的名称

  • method 是命令的类型,get或者set

  • uuid 是命令请求的唯一标识符

  • 设置命令

如果命令方法是 a set,则发布的有效负载包含一个 JSON 对象,其中包含资源名称和用于设置这些资源的值。作为响应,设备应在主题上发布空响应 command/response/{uuid},其中 uuid 与命令请求主题中发送的唯一标识符匹配。
在这里插入图片描述

  • 获取命令

如果命令方法是 a get,则发布的有效负载为空,并且设备预计将发布对主题“command/response/{uuid}”的响应,其中 uuid 是在命令请求主题中发送的唯一标识符。发布的有效负载包含一个 JSON 对象,其中包含指定命令的资源名称及其值。
在这里插入图片描述

二、连接 MQTT 设备

在这里插入图片描述

# 官方文档

https://docs.edgexfoundry.org/3.1/microservices/device/services/device-mqtt/Ch-ExamplesAddingMQTTDevice/

1.docker-comepse

# 1.克隆 edgex-compose
$ git clone git@github.com:edgexfoundry/edgex-compose.git 
$ git clone https://github.com/edgexfoundry/edgex-compose.git
$ cd edgex-compose 
$ git checkout v3.1


# 2.生成 docker-compose.yml 文件(注意这包括 mqtt-broker)
$ cd compose-builder
$ make gen ds-mqtt mqtt-broker no-secty


# 3.检查生成的文件
$ ls | grep 'docker-compose.yml'
docker-compose.yml
[root@edgex mqtt-device]# git clone https://github.com/edgexfoundry/edgex-compose.git
Cloning into 'edgex-compose'...
remote: Enumerating objects: 4779, done.
remote: Counting objects: 100% (2916/2916), done.
remote: Compressing objects: 100% (173/173), done.
remote: Total 4779 (delta 2831), reused 2804 (delta 2741), pack-reused 1863
Receiving objects: 100% (4779/4779), 1.22 MiB | 450.00 KiB/s, done.
Resolving deltas: 100% (4042/4042), done.


[root@edgex mqtt-device]# ll
total 4
drwxr-xr-x. 6 root root 4096 Feb  1 04:10 edgex-compose


[root@edgex mqtt-device]# cd edgex-compose/
[root@edgex edgex-compose]# git checkout v3.1
Note: checking out 'v3.1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 488a3fe... Merge pull request #424 from lenny-intel/device-mqtt-secure-mode-napa


[root@edgex edgex-compose]# cd compose-builder/

[root@edgex compose-builder]# make gen ds-mqtt mqtt-broker no-secty
echo MQTT_VERBOSE=
MQTT_VERBOSE=
docker compose  -p edgex -f docker-compose-base.yml -f add-device-mqtt.yml -f add-mqtt-broker-mosquitto.yml convert > docker-compose.yml
rm -rf ./gen_ext_compose


[root@edgex compose-builder]# ls | grep 'docker-compose.yml'
docker-compose.yml

2.设备配置文件

在本部分中,我们创建文件夹,其中包含部署自定义设备配置以与现有设备服务配合使用所需的文件:

- custom-config
  |- devices
     |- my.custom.device.config.yaml
  |- profiles
     |- my.custom.device.profile.yml
[root@edgex custom-config]# pwd
/edgex/mqtt-device-svc/custom-config

[root@edgex custom-config]# tree
.
├── devices
│   └── my.custom.device.config.yaml
└── profiles
    └── my.custom.device.profile.yml

2 directories, 2 files

1.设备配置

使用此配置文件来定义设备和调度作业。device-mqtt 在启动时生成一个相对实例。

创建设备配置文件,命名为my.custom.device.config.yaml,如下所示:

[root@edgex custom-config]# vim my.custom.device.config.yaml 

# Pre-define Devices
deviceList:
- name: "my-custom-device"
  profileName: "my-custom-device-profile"
  description: "MQTT device is created for test purpose"
  labels: [ "MQTT", "test" ]
  protocols:
    mqtt:
      CommandTopic: "command/my-custom-device"
  autoEvents:
    - interval: "30s"
      onChange: false
      sourceName: "message"

CommandTopic 用于发布GET或SET命令请求

2.设备配置文件

DeviceProfile定义了设备的值和操作方法,可以是 Read 或 Write。

创建名为 的设备配置文件 my.custom.device.profile.yml,其中包含以下内容:

[root@edgex custom-config]# vim my.custom.device.profile.yml 

name: "my-custom-device-profile"
manufacturer: "iot"
model: "MQTT-DEVICE"
description: "Test device profile"
labels:
  - "mqtt"
  - "test"
deviceResources:
  -
    name: randnum
    isHidden: true
    description: "device random number"
    properties:
      valueType: "Float32"
      readWrite: "R"
  -
    name: ping
    isHidden: true
    description: "device awake"
    properties:
      valueType: "String"
      readWrite: "R"
  -
    name: message
    isHidden: false
    description: "device message"
    properties:
      valueType: "String"
      readWrite: "RW"
  -
    name: json
    isHidden: false
    description: "JSON message"
    properties:
      valueType: "Object"
      readWrite: "RW"
      mediaType: "application/json"

deviceCommands:
  -
    name: values
    readWrite: "R"
    isHidden: false
    resourceOperations:
        - { deviceResource: "randnum" }
        - { deviceResource: "ping" }
        - { deviceResource: "message" }

3.安装自定义配置

创建一个 docker-compose 文件来扩展compose-builder 生成的docker-compose.override.yml compose 文件。在此文件中,我们添加卷路径和环境变量,如下所示:

 # docker-compose.override.yml

 version: '3.7'

 services:
     device-mqtt:
        environment:
          DEVICE_DEVICESDIR: /custom-config/devices
          DEVICE_PROFILESDIR: /custom-config/profiles
        volumes:
        - /path/to/custom-config:/custom-config

将示例中的替换/path/to/custom-config为正确的路径

[root@edgex custom-config]# vim docker-compose.override.yml 

 version: '3.7'

 services:
     device-mqtt:
        environment:
          DEVICE_DEVICESDIR: /custom-config/devices
          DEVICE_PROFILESDIR: /custom-config/profiles
        volumes:
        - /edgex/mqtt-device-svc/custom-config:/custom-config

4.启动 EdgeX Foundry

使用以下命令部署 EdgeX:

$ cd edgex-compose/compose-builder
$ docker compose pull
$ docker compose -f docker-compose.yml -f docker-compose.override.yml up -d


# 修改配置文件
替换IP地址 127.0.0.1 为 0.0.0.0
# docker compose pull

# docker compose -f docker-compose.yml -f docker-compose.override.yml up -d

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.创建 MQTT 设备模拟器

要实现模拟的自定义 MQTT 设备,请创建一个名为 的 javascript,mock-device.js其中包含以下内容:

function getRandomFloat(min, max) {
    return Math.random() * (max - min) + min;
}

const deviceName = "my-custom-device";
let message = "test-message";
let json = {"name" : "My JSON"};

// DataSender sends async value to MQTT broker every 15 seconds
schedule('*/15 * * * * *', ()=>{
    var data = {};
    data.randnum = getRandomFloat(25,29).toFixed(1);
    data.ping = "pong"
    data.message = "Hello World"

    publish( 'incoming/data/my-custom-device/values', JSON.stringify(data));
});

// CommandHandler receives commands and sends response to MQTT broker
// 1. Receive the reading request, then return the response
// 2. Receive the set request, then change the device value
subscribe( "command/my-custom-device/#" , (topic, val) => {
    const words = topic.split('/');
    var cmd = words[2];
    var method = words[3];
    var uuid = words[4];
    var response = {};
    var data = val;

    if (method == "set") {
        switch(cmd) {
            case "message":
                message = data[cmd];
                break;
            case "json":
                json = data[cmd];
                break;
        }
    }else{
        switch(cmd) {
            case "ping":
                response.ping = "pong";
                break;
            case "message":
                response.message = message;
                break;
            case "randnum":
                response.randnum = 12.123;
                break;
            case "json":
                response.json = json;
                break;
        }
    }
    var sendTopic ="command/response/"+ uuid;
    publish( sendTopic, JSON.stringify(response));
});

要运行设备模拟器,请输入下面所示的命令并进行以下更改:

$ mv mock-device.js /path/to/mqtt-scripts
$ docker run --rm --name=mqtt-scripts \
    -v /path/to/mqtt-scripts:/scripts  --network host \
    dersimn/mqtt-scripts --dir /scripts

/path/to/mqtt-scripts将示例中的 mv 命令替换为正确的路径

然后 mqtt-scripts 显示日志如下:

2022-08-12 09:52:42.086 <info>  mqtt-scripts 1.2.2 starting
2022-08-12 09:52:42.227 <info>  mqtt connected mqtt://127.0.0.1
2022-08-12 09:52:42.733 <info>  /scripts/mock-device.js loading
# mv mock-device.js /edgex/mqtt-device/mqtt-scripts

# docker run --rm --name=mqtt-scripts \
    -v /edgex/mqtt-device-svc/mqtt-scripts:/scripts  --network host \
    dersimn/mqtt-scripts --dir /scripts
    
    
# docker run -d --rm --name=mqtt-scripts \
    -v /edgex/mqtt-device-svc/mqtt-scripts:/scripts  --network host \
    dersimn/mqtt-scripts --dir /scripts
# 运行容器

[root@edgex mqtt-device-svc]# docker run -d --rm --name=mqtt-scripts \
>     -v /edgex/mqtt-device-svc/mqtt-scripts:/scripts  --network host \
>     dersimn/mqtt-scripts --dir /scripts
Unable to find image 'dersimn/mqtt-scripts:latest' locally
latest: Pulling from dersimn/mqtt-scripts
4297e0229558: Pull complete 
f75ab7205508: Pull complete 
04c94b0d1e73: Pull complete 
710dcd208222: Pull complete 
e4edbf62c3fd: Pull complete 
45c71e9674b9: Pull complete 
a756f71ae17a: Pull complete 
Digest: sha256:f554723bc1acff53483a4ad0102d617b9bbfa099bc129023c096318c6ddacf8e
Status: Downloaded newer image for dersimn/mqtt-scripts:latest
e810a3bffed5580efae6807cf1df986d152200ede5174908c48b2d10b17033c8

6.访问 UI

6.1. consul
# 访问地址
http://192.168.202.233:8500

在这里插入图片描述

6.2. EdgeX Console
# 访问地址
http://192.168.202.233:4000/

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

7.测试

7.1.命令

在这里插入图片描述

7.2.事件

在这里插入图片描述

{
	"apiVersion": "v3",
	"id": "af46944b-e7e0-4d8b-bb6d-18d42721399b",
	"deviceName": "my-custom-device",
	"profileName": "my-custom-device-profile",
	"sourceName": "message",
	"origin": 1708341080603620600,
	"readings": [{
		"id": "edb1630b-7d15-49b8-97e3-1662520f7799",
		"origin": 1708341080603617300,
		"deviceName": "my-custom-device",
		"resourceName": "message",
		"profileName": "my-custom-device-profile",
		"valueType": "String",
		"value": "1111111"
	}]
}


{
	"apiVersion": "v3",
	"id": "99809eb7-83b9-49e3-9a5b-d65adc38a522",
	"deviceName": "my-custom-device",
	"profileName": "my-custom-device-profile",
	"sourceName": "values",
	"origin": 1708341090003785700,
	"readings": [{
		"id": "668df4eb-1404-4267-b0ee-464f1296e50b",
		"origin": 1708341090003772400,
		"deviceName": "my-custom-device",
		"resourceName": "randnum",
		"profileName": "my-custom-device-profile",
		"valueType": "Float32",
		"value": "2.650000e+01"
	}, {
		"id": "65067425-d134-4fc3-922f-2337d228cf0f",
		"origin": 1708341090003773700,
		"deviceName": "my-custom-device",
		"resourceName": "ping",
		"profileName": "my-custom-device-profile",
		"valueType": "String",
		"value": "pong"
	}, {
		"id": "fffe8f12-536c-43d9-9989-9d450d3b0b7b",
		"origin": 1708341090003774200,
		"deviceName": "my-custom-device",
		"resourceName": "message",
		"profileName": "my-custom-device-profile",
		"valueType": "String",
		"value": "Hello World"
	}]
}
7.3.读值

在这里插入图片描述

{
	"id": "aa29ebc7-2d31-4a4d-b58a-a8d85ba7903e",
	"origin": 1708341330008859000,
	"deviceName": "my-custom-device",
	"resourceName": "message",
	"profileName": "my-custom-device-profile",
	"valueType": "String",
	"value": "Hello World"
}

{
	"id": "448591a3-d4d7-4188-9943-88a289f9f54a",
	"origin": 1708341345006348800,
	"deviceName": "my-custom-device",
	"resourceName": "randnum",
	"profileName": "my-custom-device-profile",
	"valueType": "Float32",
	"value": "2.530000e+01"
}

{
	"id": "4af98f08-888a-495d-a07e-4c87dc6d2b82",
	"origin": 1708341345006350000,
	"deviceName": "my-custom-device",
	"resourceName": "ping",
	"profileName": "my-custom-device-profile",
	"valueType": "String",
	"value": "pong"
}

{
	"id": "26600864-c850-4d45-bf42-835dcf966249",
	"origin": 1708341345006350600,
	"deviceName": "my-custom-device",
	"resourceName": "message",
	"profileName": "my-custom-device-profile",
	"valueType": "String",
	"value": "Hello World"
}

{
	"id": "d70a679e-3532-4f7d-a3d1-0e53c8ad5f08",
	"origin": 1708341315007203800,
	"deviceName": "my-custom-device",
	"resourceName": "message",
	"profileName": "my-custom-device-profile",
	"valueType": "String",
	"value": "Hello World"
}
# EdgeX Foundry

https://iothub.org.cn/docs/edgex/
https://iothub.org.cn/docs/edgex/device/service-mqtt/
  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IoTHub - 物联网开源技术社区

支持开源技术! 传播开源文化!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值