Difference between revisions of "MQTT-flex"

From wiki.netio-products.com
Jump to navigation Jump to search
(Broker)
(přidány/aktualizovaány délky proměnných dle http://gitlab.int.netio.eu/netio/Cobra/-/issues/1198#note_21816)
Line 147: Line 147:
 
| style="background-color:#efefef;" | mandatory
 
| style="background-color:#efefef;" | mandatory
 
| style="background-color:#efefef;" | regexp+len
 
| style="background-color:#efefef;" | regexp+len
| style="background-color:#efefef;" | Credentials for MQTT broker
+
| style="background-color:#efefef;" | Credentials for MQTT broker. Max. 128 characters (since FW 3.2.4).
 
| style="background-color:#efefef;" | "username":"freedom"
 
| style="background-color:#efefef;" | "username":"freedom"
 
|-
 
|-
Line 153: Line 153:
 
| style="background-color:#efefef;" | mandatory
 
| style="background-color:#efefef;" | mandatory
 
| style="background-color:#efefef;" | regexp+len
 
| style="background-color:#efefef;" | regexp+len
| style="background-color:#efefef;" | Credentials for MQTT broker
+
| style="background-color:#efefef;" | Credentials for MQTT broker. Max. 256 characters (since FW 3.2.4).
 
| style="background-color:#efefef;" | "password":"peace|LOVE|empathy4ALL"
 
| style="background-color:#efefef;" | "password":"peace|LOVE|empathy4ALL"
 
|-
 
|-
Line 159: Line 159:
 
| style="background-color:#efefef;" | optional
 
| style="background-color:#efefef;" | optional
 
| style="background-color:#efefef;" | regexp+len
 
| style="background-color:#efefef;" | regexp+len
| style="background-color:#efefef;" | MQTT clientid. Max. 32 characters. Variables ${DEVICE_MAC} or ${DEVICE_NAME} can be used
+
| style="background-color:#efefef;" | MQTT clientid. Max. 128 characters (since FW 3.2.4). Variables ${DEVICE_MAC} or ${DEVICE_NAME} can be used
 
| style="background-color:#efefef;" | "clientid":"myEcoTable01"
 
| style="background-color:#efefef;" | "clientid":"myEcoTable01"
 
|-
 
|-
Line 197: Line 197:
 
| style="background-color:#efefef;" | mandatory
 
| style="background-color:#efefef;" | mandatory
 
| style="background-color:#efefef;" | see table below
 
| style="background-color:#efefef;" | see table below
| style="background-color:#efefef;" | specification of the topic, which MQTT-flex device listens from broker and act accordingly
+
| style="background-color:#efefef;" | specification of the topic, which MQTT-flex device listens from broker and act accordingly. Max. 32 characters.
 
| style="background-color:#efefef;" | "topic":"netio/${DEVICE_NAME}/output/1/action"
 
| style="background-color:#efefef;" | "topic":"netio/${DEVICE_NAME}/output/1/action"
 
|-
 
|-

Revision as of 12:44, 31 March 2022

The MQTT-flex version of the MQTT protocol can be configured in detail thanks to the “flex” extension.

https://www.netio-products.com/en/glossary/mqtt-flex

Why MQTT-flex
There is a lot of approaches in integration of MQTT in devices and systems. One vendor prefer one topic with structured data payload, the another one prefer tree topic structure with simple value in data payload. MQTT-flex is a standard MQTT with specific configuration approach. The goal of MQTT-flex is to give a user opportunity to integrate NETIO device with any system with different data approach.

Configuration of MQTT in devices supporting MQTT flex is done by JSON (JavaScript Object Notation). With MQTT-flex you can easily define the MQTT topics, payloads and device behaviour via text configuration in JSON object format. Since there is then lot of possibilities with such freestyle flexibility allowed, you can find bellow full set of all implemented attributes.

Contents

Supported devices:

  • PowerCable MQTT 101x
  • PowerPDU 4PS
  • PowerDIN 4PZ
  • PowerBOX 3Px
  • PowerBOX 4Kx

FW version:
>2.2.1

Not supported NETIO devices:

  • PowerPDU 4C
  • NETIO 4
  • NETIO 4All

Simple MQTT-flex configuration + explanation

We strongly recommend to create and test MQTT-flex configuration on "local" device what can be easily restarted. The validation of config before saving is not 100% and for example some specific typos can cause a freeze of a device - the solution is to restart a device (unplug/plug input power cable). If the configuration is saved and device is working then there are no known failure case so it is safe to use this configuration on the "remote" devices.

{
     "config":{
        "broker":{
            "url":"broker.hivemq.com",
            "protocol":"mqtt",
            "port":1883,
            "ssl":false,
            "type":"generic",
            "username":"freedom",
            "password":"peace|LOVE|empathy4ALL"
        },
        "subscribe":[{
               "topic":"netio/${DEVICE_NAME}/output/1/action",
               "qos":0,
               "target":"OUTPUTS/1/ACTION",
               "action":"${payload}"
           }
       ],
       "publish":[{
               "topic":"netio/${DEVICE_NAME}/output/1/state",
               "qos":0,
               "retain":false,
               "payload":"${OUTPUTS/1/STATE}",
               "events":[
                   {
                       "type":"timer",
                       "period":"1000"
                   }
               ]
           }
       ]
   }
}

Client Configuration (broker section)

Put here MQTT client connection setup

This configuration example set NETIO device to connect to broker.hivemq.com with mqtt protocol, no ssl connection with credetials freedom/peace|love|empathy4ALL.

        "broker":{
            "url":"broker.hivemq.com",
            "protocol":"mqtt",
            "port":1883,
            "ssl":false,
            "type":"generic",
            "username":"freedom",
            "password":"peace|LOVE|empathy4ALL"
        },

Device Control (subscribe section)

Put here array of topics where to subscribe

Device output 1 is controlled with action received by subscription to netio/${DEVICE_NAME}/output/1/action topic with QOS 0

        "subscribe":[{
               "topic":"netio/${DEVICE_NAME}/output/1/action",
               "qos":0,
               "target":"OUTPUTS/1/ACTION",
               "action":"${payload}"
           }
       ],

Output State monitoring (publish section)

Put here array of topics where to publish.

Device send every 1000 s message to topic with QOS 0, retain true information with output 1 state

       "publish":[{
               "topic":"netio/${DEVICE_NAME}/output/1/state",
               "qos":0,
               "retain":true,
               "payload":"${OUTPUTS/1/STATE}",
               "events":[
                   {
                       "type":"timer",
                       "period":"1000"
                   }
               ]
           }
       ]

Config sections

Broker

here you have to define URL or IP address of machine hosting MQTT broker, level of security used for protocol, auth data and optionally some specific MQTT attributes, which are in the spec, but not mandatory required

Attributes table overview

Item Presence Possible Values Description JSON Config Usage
url mandatory MQTT broker URL "url":"broker.hivemq.com"
port mandatory 1 - 65535 MQTT broker port "port":1883
ssl mandatory true, false Use SSL crypted communication selector "ssl":false
type mandatory generic Communication/setup type option "type":"generic"
username mandatory regexp+len Credentials for MQTT broker. Max. 128 characters (since FW 3.2.4). "username":"freedom"
password mandatory regexp+len Credentials for MQTT broker. Max. 256 characters (since FW 3.2.4). "password":"peace|LOVE|empathy4ALL"
clientid optional regexp+len MQTT clientid. Max. 128 characters (since FW 3.2.4). Variables ${DEVICE_MAC} or ${DEVICE_NAME} can be used "clientid":"myEcoTable01"
keepalive optional 1 - 65535 MQTT keep alive period in seconds "keepalive":90

Note: clientid attribute is mandatory for MQTT(s) communication. When not configured, random ID will be generated.

Examples

Standard setup

Security (SSL / TLS) secured setup

You can enable MQTTs by using the encrypted port 8883 + "ssl":true.

Variables used setup

Subscribe

Hints to usage

When receive message in topic do action on target.

actiondef: When message in topic match actiondef payload do action on target.

Attributes table overview

Item Presence Possible Values Description JSON Config Usage
topic mandatory see table below specification of the topic, which MQTT-flex device listens from broker and act accordingly. Max. 32 characters. "topic":"netio/${DEVICE_NAME}/output/1/action"
qos mandatory 0, 1 or 2 MQTT's Quality of Sevice - definition {here|http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180912} "qos":0
target mandatory internal definition of action, which can be performed above the specified output "target":"OUTPUTS/1/ACTION"
action mandatory a payload or a value the action attribute needs to have passed to "action":"${payload}"
actiondefNot supported yet optional
jsonNot supported yet optional

Examples

Toggle output with standard payload

Toggle output with custom payload

Subscribe to more than one topic

Subscribe topic payload values specification for control of the output:

netio/<DEVICE_NAME>/output/1/action with payload for output control : (0 – off, 1 – on, 2 – short off, 3 – short on, 4 – toggle, 5 – no change)

Publish

when you need to send some data from device towards the broker, you have to specify it in the publish section - you can send measurement data as they are implemented, or you can use translation tables to send some pre-defined strings or even send JSON object. these attributes can be send periodicaly every time the timer reached specified value in seconds or based on value change (something like delta principle, but using only value differrence within defined period)

Hints to usage

When event send message with payload to topic.

Attributes table overview

Item Presence Possible Values Description JSON Config Usage
topic mandatory see table below definition of the topic, how it is registered towards MQTT broker "topic":"netio/${DEVICE_NAME}/output/1/load"
qos mandatory see table below MQTT's Quality of Sevice - definition {here|http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180912}
retain mandatory boolean: true or false MQTT's attribute to specify to broker how to store last received information - section 3.3.1.3 of {MQTT doc|http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180841} "retain":true
payload mandatory see table below definition of the topic, how it is registered towards MQTT broker "topic":"netio/${DEVICE_NAME}/output/1/load"
events mandatory see table below definition of events used for triggering sending of data via mqtt (change, delta, timer)
type
source
delta
period
payloaddefNot supported yet

Examples

Publish energy periodically (event timer)

Publish current on change (delta)

Publish output state

Publish to more than one topic with different events

Target / Source

In MQTT-flex we use targets and sources specify where to apply some change or get value. Practically it means addressing of INPUTS/OUTPUTS and adding command or variable.

  • source - specifies from where the value will be read (specifies the source of data for payload, change detection, delta calculation)
  • target - specifies where the data should be sent or command applied (e.g. specifies the target for ACTION)

INPUT / OUTPUT (Target) selection

NETIO Devices can have inputs and outputs which can be different type. When you want to work with some variable you have to specify on which I/O. For doing that in MQTT-flex is implemented structured addressing with "/" separator. See the steps below how to compose source or target.

  1. At first specify if requested variable is from/for INPUT or OUTPUT using keywords "OUTPUTS" or "INPUTS" .
  2. Add "/" separator
  3. Specify the number of INPUT/OUTPUT to 1(or TOTAL for summary statistics if available)
  4. Add "/" separator
  5. Specify requested variable or command

Note: Not all of OUTPUTS/INPUTS support all variables. Available variables are closely connected with the device functions and I/O features.

Note2: INPUTS available only on NETIO PowerDIN 4PZ

Examples:

adressing controll of output 3

OUTPUTS/3/ACTION

getting voltage on output 1

OUTPUTS/1/VOLTAGE

getting state of input 1

INPUTS/1/STATE

Commands

Variables

In some parameters is nescessary to use variables to get current state and measurements. Variables are separated in two categories:

  • Target/Source variables
  • Payload Topic variables

Target Source Variables

The list of available variables for each

OUTPUTS variables

VOLTAGE

Unit: V

Type: integer

Allowed in: "payload" "source"

Example 1: "payload":"Present RMS voltage on output 1 is ${OUTPUTS/1/VOLTAGE}"

Example 2: "source":"${OUTPUTS/1/VOLTAGE}"

CURRENT

Unit: mA

Type: integer

Allowed in: "payload" "source"

Example 1: "payload":"Present RMS current on output 1 is ${OUTPUTS/1/CURRENT}"

Example 2: "source":"${OUTPUTS/1/CURRENT}"

POWER_FACTOR

Unit: [-]

Type: float (2 decimals)

Allowed in: "payload" "source"

Example 1: "payload":"True Power Factor on output 1 is ${OUTPUTS/1/POWER_FACTOR}"

Example 2: "source":"${OUTPUTS/1/POWER_FACTOR}"

LOAD

Unit: W

Type: integer

Allowed in: "payload" "source"

Example 1: "payload":"Present load on output 1 is ${OUTPUTS/1/LOAD}W"

Example 2: "payload":"Device's load connected to output 1 is ${OUTPUTS/1/LOAD}W"

Example 3: "source":"${OUTPUTS/1/LOAD}"

STATE

Type: bool(integer) - 0 or 1

Allowed in: "payload" "source"

Example 1: "payload":"Present output 1 state is ${OUTPUTS/1/STATE}"

Example 2: "source":"${OUTPUTS/1/STATE}"

ACTION

Type: integer

Possible actions:

  • 0 - set state OFF
  • 1 - set state ON
  • 2 - short OFF (restart)
  • 3 - short ON
  • 4 - toggle (switch)
  • 5 - no change

Allowed in: "target"

Example: "target":"OUTPUTS/1/ACTION"

DELAY [ms]

NAME

FREQUENCY

Unit: Hz

Type: integer

Allowed in: "payload" "source"

Example: "payload":"Frequency in power grid is ${OUTPUTS/1/ENERGY}Hz"

ENERGY

Energy consumed by an device connected to NETIO device output.

Unit: Wh

Type: integer

Allowed in: "payload" "source"

Example 1: "payload":"Consumed energy on output 1 is ${OUTPUTS/1/ENERGY}Wh"

Example 2: "source":"${OUTPUTS/1/ENERGY}"

REVERSE_ENERGY

Energy delivered back to grid. For example from solar system connected to NETIO device output.

Unit: Wh

Type: integer

Allowed in: "payload" "source"

Example 1: "payload":"Delivered energy on output 1 is ${OUTPUTS/1/REVERSE_ENERGY}Wh"

Example 2: "source":"${OUTPUTS/1/REVERSE_ENERGY}"


ENERGY_START

Date when the counters ENERGY and REVERSE_ENERGY have been resetted by user.

Unit: unix timestamp

Type: integer

Allowed in: "payload"

Example 1: "payload":"Energy measured since ${OUTPUTS/1/ENERGY_START} unix time"

Example 2: "payload":"${OUTPUTS/1/ENERGY_START}" is output payload 1567654639

ENERGY_START_FMT

Date when the counters ENERGY and REVERSE_ENERGY have been resetted by user.

Unit: fmt date format

Type: string

Allowed in: "payload"

Example 1: "payload":"Energy measured since ${OUTPUTS/1/ENERGY_START}"

Example 2: "payload":"${OUTPUTS/1/ENERGY_START_FMT}" is output payload 2019-09-05T03:37:19+00:00

ENERGY_NR

Non-resettable counter of Energy consumed by an device connected to NETIO device output.

Unit: Wh

Type: integer

Allowed in: "payload" "source"

Example 1: "payload":"Consumed energy on output 1 is ${OUTPUTS/1/ENERGY_NR}Wh"

Example 2: "source":"${OUTPUTS/1/ENERGY_NR}"

REVERSE_ENERGY_NR

Non-resettable counter of Energy delivered back to grid. For example from solar system connected to NETIO device output.

Unit: Wh

Type: integer

Allowed in: "payload" "source"

Example 1: "payload":"Delivered energy on output 1 is ${OUTPUTS/1/REVERSE_ENERGY_NR}Wh"

Example 2: "source":"${OUTPUTS/1/REVERSE_ENERGY_NR}"


TOTALs - for use with devices having more than 1 measured output

  • OUTPUTS/TOTAL/ENERGY
  • OUTPUTS/TOTAL/LOAD
  • OUTPUTS/TOTAL/CURRENT
  • OUTPUTS/TOTAL/VOLTAGE
  • OUTPUTS/TOTAL/POWER_FACTOR
  • OUTPUTS/TOTAL/FREQUENCY
  • OUTPUTS/TOTAL/PHASE
  • OUTPUTS/TOTAL/REVERSE_ENERGY
  • OUTPUTS/TOTAL/ENERGY_NR
  • OUTPUTS/TOTAL/REVERSE_ENERGY_NR
  • OUTPUTS/TOTAL/ENERGY_START
  • OUTPUTS/TOTAL/ENERGY_START_FMT


REST_JSON

Allow use of NETIO JSON structure to control outputs.

Type: string / JSON

Allowed in: "target" for Subscribe section

Example: "target": "REST_JSON"

The payload is JSON structure identical to NETIO JSON API M2M Protocol (documentation available at https://www.netio-products.com/files/NETIO-M2M-API-Protocol-JSON.pdf). You can control one or multiple outputs.

Payload example 1 - Toggle output 1: {"Outputs":[{"ID": 1,"Action": 4}]}

Payload example 2 - Turn output 1 OFF and output 3 ON: {"Outputs":[{"ID":1,"Action":0},{"ID":3,"Action":1}]}

INPUT variables

STATE

Type: bool(integer) - 0 or 1

Allowed in: "payload" "source"

Example 1: "payload":"Present input 1 state is ${INPUTS/1/STATE}"

Example 2: "source":"${INPUTS/1/STATE}"

S0

S0 Counter value Unit: -

Type: integer

Allowed in: "payload" "source"

Example 1: "payload":"Input 1 S0 Counter value is ${INPUTS/1/S0}impulses"

Example 2: "source":"${INPUTS/1/S0}"

Payload/topic variables

DEVICE_NAME

Can be used in: "payload", "topic"

Example 1: "payload":"${DEVICE_NAME}"

Example 2: "topic":"netio/${DEVICE_NAME}/output/1/action"

DEVICE_MAC

UPTIME Not yet implemented

PAYLOAD

Can be used in: "action"

Example: "action":"${PAYLOAD}"

OUTPUT_ID Not yet implemented

WIFI_SIGNALNot yet implemented

OUTPUTS_STATUS

Provide complete outputs status and measurement if supported.

Type: string / JSON

Allowed in: "payload" for Publish section

Example: "payload":"${OUTPUTS_STATUS}"

Payload example: { "GlobalMeasure":{"Voltage":236,"TotalCurrent":72,"TotalLoad":11,"TotalEnergy":167,"OverallPowerFactor":0.64,"Frequency":50.07,"Phase":-36.86,"EnergyStart":"2020-06-30T17:04:48+01:00"}, "Outputs":[ {"ID":1,"Name":"Power output 1","State":1,"Action":6,"Delay":2020,"Current":72,"PowerFactor":0.64,"Phase":-36.86,"Energy":139,"ReverseEnergy":0,"Load":11}, {"ID":2,"Name":"Power output 2","State":1,"Action":6,"Delay":2020,"Current":0,"PowerFactor":1.00,"Phase":0.00,"Energy":27,"ReverseEnergy":0,"Load":0}, {"ID":3,"Name":"Free Contact 3","State":1,"Action":6,"Delay":2020}, {"ID":4,"Name":"Free Contact 4","State":1,"Action":6,"Delay":2020} ]}

INPUTS_STATUS

Provide complete inputs status if supported. Since FW 3.0.0

Type: string / JSON

Allowed in: "payload" for Publish section

Example: "payload":"${INPUTS_STATUS}"

Payload example: { "Inputs":[ {"ID":1,"Name":"Input 1","State":0,"S0Counter":0}, {"ID":2,"Name":"Input 2","State":0,"S0Counter":0} ]}

INOUT_STATUS

Provide complete inputs and output status and measurement if supported. Since FW 3.0.0

Type: string / JSON

Allowed in: "payload" for Publish section

Example: "payload":"${INOUT_STATUS}"

Payload example: { "GlobalMeasure":{"Voltage":238,"TotalCurrent":105,"TotalLoad":17,"TotalEnergy":1451,"OverallPowerFactor":0.67,"Frequency":50.03,"Phase":-33.67,"EnergyStart":"2020-06-30T17:04:48+01:00"}, "Outputs":[ {"ID":1,"Name":"Power output 1","State":0,"Action":6,"Delay":5000,"Current":0,"PowerFactor":1.00,"Phase":0.00,"Energy":701,"ReverseEnergy":0,"Load":0}, {"ID":2,"Name":"Power output 2","State":1,"Action":6,"Delay":5000,"Current":105,"PowerFactor":0.65,"Phase":-33.67,"Energy":750,"ReverseEnergy":0,"Load":17}, {"ID":3,"Name":"Free Contact 3","State":1,"Action":6,"Delay":5000}, {"ID":4,"Name":"Free Contact 4","State":0,"Action":6,"Delay":5000} ], "Inputs":[ {"ID":1,"Name":"Input 1","State":0,"S0Counter":0}, {"ID":2,"Name":"Input 2","State":0,"S0Counter":0} ]}

Extended MQTT flex JSON config examples

Default NETIO MQTT-flex configuration

This example demonstrates setup for connection to public broker.hivemq.com, measurement reporting and output control.

The device cabe be controlled via netio/${DEVICE_NAME}/output/1/action topic by sending standard NETIO action values:

  • 0 - OFF
  • 1 - ON
  • 2 - SHORT OFF
  • 3 - SHORT ON
  • 4 - TOGGLE
  • 5 - NO ACTION.

The device report measurements:

  • Output state - every 15 minutes or by change
  • Voltage [V]- every 5 minutes or by change of 1 V
  • Current [mA]- every 5 minutes or by change of 50 mA
  • Load(Power) [W]- every 5 minutes or by change of 10 W
  • Energy(Consumption) [Wh]- every 15 minutes or by change of 1Wh
  • True Power Factor (TPF) [-]- every 5 minutes or by change of 0.02
  • Frequency [Hz]- every 1 hour or by change of 0.1 Hz

For register all values, you can use wildcard netio/${DEVICE_NAME}/output/1/#

{
  "config":{
     "broker":{
        "url":"broker.hivemq.com",
        "protocol":"mqtt",
        "port":1883,
        "ssl":false,
        "type":"generic",
        "username":"",
        "password":"",
        "clientid":"moje${DEVICE_NAME}${DEVICE_MAC}",
        "keepalive":30
     },
     "subscribe":[
        {
           "topic":"netio/${DEVICE_NAME}/output/1/action",
           "qos":0,
           "target":"OUTPUTS/1/ACTION",
           "action":"${payload}"
        },
        {
           "topic":"netio/${DEVICE_NAME}/output/1/switch",
           "qos":0,
           "target":"OUTPUTS/1/ACTION",
           "action":4
        }
     ],
     "publish":[
        {
           "topic":"netio/${DEVICE_MAC}/output/1/state",
           "qos":0,
           "retain":true,
           "payload":"${OUTPUTS/1/STATE}",
           "events":[
              {
                 "type":"change",
                 "source":"OUTPUTS/1/STATE"
              },
              {
                 "type":"timer",
                 "period":900
              }
           ]
        },
        {
           "topic":"netio/${DEVICE_NAME}/output/1/voltage",
           "qos":0,
           "retain":false,
           "payload":"${OUTPUTS/1/VOLTAGE}",
           "events":[
              {
                 "type":"timer",
                 "period":300
              },
              {
                 "type":"delta",
                 "source":"OUTPUTS/1/VOLTAGE",
                 "delta":1
              }
           ]
        },
        {
           "topic":"netio/${DEVICE_NAME}/output/1/current",
           "qos":0,
           "retain":false,
           "payload":"${OUTPUTS/1/CURRENT}",
           "events":[
              {
                 "type":"timer",
                 "period":300
              },
              {
                 "type":"delta",
                 "source":"OUTPUTS/1/CURRENT",
                 "delta":50
              }
           ]
        },
        {
           "topic":"netio/${DEVICE_NAME}/output/1/load",
           "qos":0,
           "retain":false,
           "payload":"${OUTPUTS/1/LOAD}",
           "events":[
              {
                 "type":"timer",
                 "period":300
              },
              {
                 "type":"delta",
                 "source":"OUTPUTS/1/LOAD",
                 "delta":10
              }
           ]
        },
        {
           "topic":"netio/${DEVICE_NAME}/output/1/energy",
           "qos":0,
           "retain":false,
           "payload":"${OUTPUTS/1/ENERGY}",
           "events":[
              {
                 "type":"timer",
                 "period":900
              },
              {
                 "type":"delta",
                 "source":"OUTPUTS/1/ENERGY",
                 "delta":1
              }
           ]
        },
        {
           "topic":"netio/${DEVICE_NAME}/output/1/tpf",
           "qos":0,
           "retain":false,
           "payload":"${OUTPUTS/1/POWER_FACTOR}",
           "events":[
              {
                 "type":"timer",
                 "period":900
              },
              {
                 "type":"delta",
                 "source":"OUTPUTS/1/POWER_FACTOR",
                 "delta":0.02
              }
           ]
        },
        {
           "topic":"netio/${DEVICE_NAME}/output/1/frequency",
           "qos":0,
           "retain":false,
           "payload":"${OUTPUTS/1/FREQUENCY}",
           "events":[
              {
                 "type":"timer",
                 "period":3600
              },
              {
                 "type":"delta",
                 "source":"OUTPUTS/1/FREQUENCY",
                 "delta":0.1
              }
           ]
        }
     ]
  }
}