MQTT

The following example shows how an MQTT device can be used with Edge Xpert to report data from a variety of digital sensors in Industrial Internet of Things (IIoT) applications.

The example uses the MQ-7255M Ethernet I/O device. This device supports MQTT and has 8-channel Digital Input (DI) and 8-channel Digital Output (DO) built-in.

Scenario

The MQ-7255M collects or sets data for the attached sensors. The following actuation requests can be sent to the device:

  • Set the digital input for an identified digital input channel

The MQ-7255M must be registered with Edge Xpert and is managed by the MQTT Device Service, which does the following:

  • Translates the actuation requests sent to the device into protocol requests that are understood by the device

  • Collects the data

  • Passes the data to the core data component in the Core Services layer. In this scenario, the data comprises the sensor readings collected by the device

    MQTT Connections

This use case covers the following:

This use case does not cover the physical connection or the communication process between the host and the device.

Defining the Device

To define the device, you must do the following:

Creating the Device Profile

The device profile defines the following for the device:

  • Characteristics
  • Data provided
  • Command formats

In the device profile for our use case, we must define the following:

  • The subscriber to the MQTT message (subTopic)
  • The put command (pubTopic)
  • The quality of service (qos)

To create the device profile, complete the following steps:

  1. Open your favourite text editor

  2. Enter the following:

    name: "MQ7255M-IO-Device"
    manufacturer: "ICPDAS"
    model: "MQ-7255M"
    labels:
      - "mqtt"
    description: "The MQ-7255M is an Ethernet I/O device equipped with 8-channel DI and 8-channel DO"
    deviceResources:
      - name: DO0
        description: "Digital output channel 0"
        attributes:
          {
            subTopic: "${deviceName}/GetValue/DO0",
            pubTopic: "${deviceName}/SetValue/DO0",
            qos: "0"
          }
        properties:
          value:
            { type: "String", size: "0", readWrite: "W" ,scale: "", offset: "", base: ""  }
          units:
            { type: "String", readWrite: "R", defaultValue: "" }
    
      - name: DO1
        description: "Digital output channel 1"
        attributes:
          {
            subTopic: "${deviceName}/GetValue/DO1",
            pubTopic: "${deviceName}/SetValue/DO1",
            qos: "0"
          }
        properties:
          value:
            { type: "String", size: "0", readWrite: "W" ,scale: "", offset: "", base: ""  }
          units:
            { type: "String", readWrite: "R", defaultValue: "" }
    
      - name: DI0
        description: "Digital input channel 0"
        attributes:
          {
            subTopic: "${deviceName}/GetValue/DI0",
            qos: "0"
          }
        properties:
          value:
            { type: "String", size: "0", readWrite: "W" ,scale: "", offset: "", base: ""  }
          units:
            { type: "String", readWrite: "R", defaultValue: "" }
    
      - name: DI1
        description: "Digital input channel 1"
        attributes:
          {
            subTopic: "${deviceName}/GetValue/DI1",
            qos: "0"
          }
        properties:
          value:
            { type: "String", size: "0", readWrite: "W" ,scale: "", offset: "", base: ""  }
          units:
            { type: "String", readWrite: "R", defaultValue: "" }
    
    deviceCommands:
    
      - name: DO
        get:
          - { index: "0", operation: "get", object: "DO0", parameter: "DO0" }
          - { index: "1", operation: "get", object: "DO1", parameter: "DO1" }
        set:
          - { index: "0", operation: "set", object: "DO0", parameter: "DO0" }
          - { index: "1", operation: "set", object: "DO1", parameter: "DO1" }
    
      - name: DI
        get:
          - { index: "0", operation: "get", object: "DI0", parameter: "DI0" }
          - { index: "1", operation: "get", object: "DI1", parameter: "DI1" }
    
    coreCommands:
      - name: DO
        put:
          path: "/api/v1/device/{deviceId}/DO"
          parameterNames: ["DO0","DO1"]
          responses:
            - code: "204"
              description: "set the digital output."
              expectedValues: []
            - code: "503"
              description: "service unavailable"
              expectedValues: []
    
  3. Save the file to <path to your custom-config>/MQ7255M.yml

Creating the Configuration TOML File

The configuration.toml defines the following for the device:

  • Service
  • Registry
  • Logging
  • Clients
  • Devices
  • Device configuration

In the configuration for our use case, we must define device name to match the Subscribe/Publish topic prefix defined in the device set-up as illustrated below:

Device Set-up

To create the device configuration, complete the following steps:

  1. Open your favourite text editor

  2. Enter the following:

    [Writable]
    LogLevel = 'DEBUG'
    
    [Service]
    Host = "edgex-device-mqtt"
    Port = 49982
    ConnectRetries = 3
    Labels = []
    OpenMsg = "device mqtt started"
    ReadMaxLimit = 256
    Timeout = 5000
    EnableAsyncReadings = true
    AsyncBufferSize = 16
    
    [Registry]
    Host = "edgex-core-consul"
    Port = 8500
    CheckInterval = "10s"
    FailLimit = 3
    FailWaitTime = 10
    Type = "consul"
    
    [Logging]
    EnableRemote = true
    File = "./device-mqtt.log"
    
    [Clients]
      [Clients.Data]
      Name = "edgex-core-data"
      Protocol = "http"
      Host = "edgex-core-data"
      Port = 48080
      Timeout = 50000
    
      [Clients.Metadata]
      Name = "edgex-core-metadata"
      Protocol = "http"
      Host = "edgex-core-metadata"
      Port = 48081
      Timeout = 50000
    
      [Clients.Logging]
      Name = "edgex-support-logging"
      Protocol = "http"
      Host ="edgex-support-logging"
      Port = 48061
    
    [Device]
      DataTransform = true
      InitCmd = ""
      InitCmdArgs = ""
      MaxCmdOps = 128
      MaxCmdValueLen = 256
      RemoveCmd = ""
      RemoveCmdArgs = ""
      ProfilesDir = "/custom-config"
    
    # Pre-define Devices
    [[DeviceList]]
      Name = "MQ_DEVICE"
      Profile = "MQ7255M-IO-Device"
      Description = "General IO device"
      Labels = [ "MQTT"]
      [DeviceList.Protocols]
        [DeviceList.Protocols.mqtt]
    
    # Driver configs
    [Driver]
    Schema = "tcp"
    Host = "mqtt-broker"
    Port = "1883"
    User = ""
    Password = ""
    KeepAlive = "30"
    ConnWaitTimeout = "5"
    GetCmdTimeout = "5"
    ConnPoolEnable = "false"
    ConnPoolInitialSize = "10"
    ConnPoolMaximumSize = "30"
    
  3. Save the file to <path to your custom-config>/configuration.toml

Adding the Device to the docker-compose File

You must add the device to the /etc/edgexpert/docker-compose.yml file and tell it where to find your custom configuration files. To do this, complete the following steps:

  1. Open your favourite text editor

  2. Enter the following:

    version: '3'
    volumes:
      ...
    services:
      ...
      device-mqtt:
        image: iotechsys/${EX_REPO}-device-mqtt:${EX_VER}
        container_name: edgex-device-mqtt
        hostname: edgex-device-mqtt
        entrypoint: /device-mqtt
        command: "--confdir=/custom-config ${EX_REG_ADDR}
          --setting=Logging/EnableRemote:${EX_REMOTE_LOGGING}"
        networks:
         - edgex-network
        ports:
          - "49982:49982"
        environment:
        - EDGEXPERT_LICENSE_PATH=/edgexpert/licenses/
        volumes:
          - type: volume
            source: license-data
            target: /edgexpert/licenses/
            read_only: true
          - /home/user/Desktop/mqtt:/custom-config
        depends_on:
          - core-metadata
          - core-data
          - core-command
          - mqtt-broker
        logging:
          driver: "json-file"
          options:
            max-size: "10mb"
            max-file: "20"
    
  3. Save the file to /etc/edgexpert/docker-compose.yml

Registering the Device Service

The Device Service must be registered with Edge Xpert. This is known as provisioning, and can be done in any of the following ways:

  • Using the Edge Xpert REST API directly from a script or executable client application
  • Using Edge Xpert Manager
  • Using the Device Service local TOML configuration file

For examples of each method, see the MQTT Device Service example.

Using Commands

The available commands are given in the device profile. You can find the available commands by opening a browser and navigating to either of the following:

Example PUT Command

You can set a value of 1 for DO channel 0 and a value of 0 for DO channel 1 on the device in the following way:

  1. Open a terminal

  2. Enter the following cURL command:

    curl http://host-ip:48082/api/v1/device/name/MQ_DEVICE/command/DO -H "Content-Type:application/json" -X PUT \ -d '{"DO0":"1","DO1":"0"}'
    

Example Manual GET Command

The device takes readings from the senors and sends the data to Edge Xpert, either at defined intervals, or in response to manual calls to the device. For information on setting up defined intervals, see Scheduled Reading from the Async Value.

To manually obtain readings from the sensors, complete the following steps:

  1. Open a browser

  2. Navigate to http://host-ip:48080/api/v1/event

  3. Enter the following cURL command:

    curl http://host-ip:48080/api/v1/event | json_pp
    

    The output will be similar to the following:

    % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                   Dload  Upload   Total   Spent    Left  Speed
    100  3726    0  3726    0     0   601k      0 --:--:-- --:--:-- --:--:--  606k
    [
       {
          "id" : "12e9ae4b-bf46-4fda-b5b0-13d3d734f37c",
          "created" : 1557731017356,
          "device" : "MQ_DEVICE",
          "readings" : [
             {
                "created" : 1557731017356,
                "device" : "MQ_DEVICE",
                "value" : "1",
                "name" : "DI1",
                "id" : "5a484521-50e6-4773-a729-62af667895b3",
                "origin" : 1557731017205
             }
          ],
          "origin" : 1557731017355
       },
       {
          "origin" : 1557731017361,
          "created" : 1557731017362,
          "id" : "2f97ba3f-4ae5-496b-ac1e-4d0f7cd2f3ba",
          "device" : "MQ_DEVICE",
          "readings" : [
             {
                "id" : "7f6e2466-8c77-477a-88a0-5754d2e7fee0",
                "origin" : 1557731017360,
                "value" : "0",
                "name" : "DI1",
                "created" : 1557731017362,
                "device" : "MQ_DEVICE"
             }
          ]
       },
    
    …
    

Scheduled Reading from the Async Value

The device takes readings from the senors and sends the data to Edge Xpert, either at defined intervals, or in response to manual calls to the device. An example of a manual call is given in Example Manual GET Command.

Intervals and Auto Events can be defined in the [[Devices]] section of the TOML configuration file, as follows:

[[DeviceList.AutoEvents]]
  Frequency = "30s"
  OnChange = false
  Resource = "DO0"
[[DeviceList.AutoEvents]]
  Frequency = "10s"
  OnChange = false
  Resource = "DO1"

This definition would automatically send readings to Edge Xpert as follows:

  • Data from DO channel 0 every 30 seconds
  • Data from DO channel 1 every 10 seconds

Exporting the Data

Now you need to analyze your count data, and/or send to your enterprise system or the Cloud. To do this, you must set up export clients. Export clients register their interest in a topic, and are sent the relevant data automatically.

The can be achieved using the Edge Xpert export wizard. For an example of setting up an MQTT export service, see the MQTT Export Service example.