/**
*
* Fibaro Dimmer 2 (US)
*
* github: Eric Maycock (erocm123)
* email: erocmail@gmail.com
* Date: 2016-07-31 8:03PM
* Copyright Eric Maycock
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
* added button to the current state so Hubitat apps can pick up the 3 buttons and added doubletap and releasable button: borristhecat 24/5/19
* added basicSet zwave event so physical button presses are handled by the hub. /eriktack 20190812
* added physical and digital send events. Split logging for info and debug. Added the ability to hide the configure settings. borristhecat 26/8/19
*/
metadata {
definition (name: "Fibaro Dimmer 2", namespace: "erocm123", author: "Eric Maycock", importUrl: "https://raw.githubusercontent.com/erocm123/Hubitat/master/Drivers/fibaro-dimmer-2.src/fibaro-dimmer-2.groovy") {
capability "Actuator"
capability "Switch"
capability "Switch Level"
capability "Refresh"
capability "Configuration"
capability "Sensor"
// capability "Polling"
capability "Energy Meter"
capability "Power Meter"
capability "PushableButton"
capability "HoldableButton"
capability "ReleasableButton"
capability "DoubleTapableButton"
capability "Health Check"
attribute "needUpdate", "string"
attribute "firmware", "String"
fingerprint mfr: "010F", prod: "0102", model: "2000", deviceJoinName: "Fibaro Dimmer 2"
fingerprint deviceId: "0x1101", inClusters: "0x72,0x86,0x70,0x85,0x8E,0x26,0x7A,0x27,0x73,0xEF,0x26,0x2B"
fingerprint deviceId: "0x1101", inClusters: "0x5E,0x20,0x86,0x72,0x26,0x5A,0x59,0x85,0x73,0x98,0x7A,0x56,0x70,0x31,0x32,0x8E,0x60,0x75,0x71,0x27"
}
preferences {
input name: "settingEnable", type: "bool", title: "Enable setting", defaultValue: false
input name: "enableDebugging", type: "bool", title: "Enable Debug Logging?", defaultValue: false
input name: "enableInfo", type: "bool", title: "Enable Info Logging?", defaultValue: true
if (settingEnable) input description: "Once you change values on this page, the corner of the \"configuration\" icon will change orange until all configuration parameters are updated.", title: "Settings", displayDuringSetup: false, type: "paragraph", element: "paragraph"
if (settingEnable) generate_preferences(configuration_model())
}
}
private getCommandClassVersions() {
[
0x20: 1, // Basic
0x25: 1, // Switch Binary
0x70: 1, // Configuration
0x98: 1, // Security
0x60: 3, // Multi Channel
0x8E: 2, // Multi Channel Association
0x26: 1, // Switch Multilevel
0x87: 1, // Indicator
0x72: 2, // Manufacturer Specific
0x5B: 1, // Central Scene
0x32: 3, // Meter
0x85: 2, // Association
0x86: 1, // Version
0x75: 2 // Protection
]
}
def parse(description) {
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent(descriptionText: description, isStateChange: true)
} else if (description != "updated") {
def cmd = zwave.parse(description, commandClassVersions)
if (cmd) {
result = zwaveEvent(cmd)
//log.debug("'$cmd' parsed to $result")
} else {
log.debug "Couldn't zwave.parse '$description'"
}
}
result
}
def zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) {
logging(cmd)
def request = update_needed_settings()
if(request != []){
return [response(commands(request))]
} else {
return null
}
}
def zwaveEvent(hubitat.zwave.commands.basicv1.BasicSet cmd, ep=null) {
logging("$cmd : Endpoint: $ep")
/*def event
if (!ep) {
event = [createEvent([name: "switch", value: cmd.value? "on":"off"])]
}
return event*/
}
def zwaveEvent(hubitat.zwave.commands.sceneactivationv1.SceneActivationSet cmd) {
logging(cmd)
logging("sceneId: $cmd.sceneId")
logging("dimmingDuration: $cmd.dimmingDuration")
logging("Configuration for preference \"Switch Type\" is set to ${settings."20"}")
if (settings."20" == "2") {
Info("Switch configured as Roller blinds")
switch (cmd.sceneId) {
// Roller blinds S1
case 10: // Turn On (1x click)
buttonEvent(1, "pushed")
break
case 13: // Release
buttonEvent(1, "released")
break
case 14: // 2x click
buttonEvent(1, "doubleTapped")
break
case 17: // Brightening
buttonEvent(1, "held")
break
// Roller blinds S2
case 11: // Turn Off
buttonEvent(2, "pushed")
break
case 13: // Release
buttonEvent(2, "released")
break
case 14: // 2x click
buttonEvent(2, "doubleTapped")
break
case 15: // 3x click
buttonEvent(3, "pushed")
break
case 18: // Dimming
buttonEvent(2, "held")
break
default:
logging("Unhandled SceneActivationSet: ${cmd}")
break
}
} else if (settings."20" == "1") {
Info("Switch configured as Toggle")
switch (cmd.sceneId) {
// Toggle S1
case 10: // Off to On
buttonEvent(1, "held")
break
case 11: // On to Off
buttonEvent(1, "released")
break
case 14: // 2x click
buttonEvent(1, "doubleTapped")
break
// Toggle S2
case 20: // Off to On
buttonEvent(2, "held")
break
case 21: // On to Off
buttonEvent(2, "released")
break
case 24: // 2x click
buttonEvent(2, "doubleTapped")
break
case 25: // 3x click
buttonEvent(3, "pushed")
break
default:
logging("Unhandled SceneActivationSet: ${cmd}")
break
}
} else {
if (settings."20" == "0") Info("Switch configured as Momentary") else logging("Switch type not configured")
switch (cmd.sceneId) {
// Momentary S1
case 16: // 1x click
buttonEvent(1, "pushed")
break
case 14: // 2x click
buttonEvent(1, "doubleTapped")
break
case 12: // held
buttonEvent(1, "held")
break
case 13: // release
buttonEvent(1, "released")
break
// Momentary S2
case 26: // 1x click
buttonEvent(2, "pushed")
break
case 24: // 2x click
buttonEvent(2, "doubleTapped")
break
case 25: // 3x click
buttonEvent(3, "pushed")
break
case 22: // held
buttonEvent(2, "held")
break
case 23: // release
buttonEvent(2, "released")
break
default:
logging("Unhandled SceneActivationSet: ${cmd}")
break
}
}
}
def buttonEvent(button, value) {
Info("buttonEvent() Button:$button, Value:$value")
sendEvent(name: value, value: button, isStateChange:true, type: "physical")
}
def zwaveEvent(hubitat.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) {
logging(cmd)
dimmerEvents(cmd, (!state.lastRan || now() <= state.lastRan + 2000)?"digital":"physical")
}
def dimmerEvents(hubitat.zwave.Command cmd, source = null) {
def result = []
def value = (cmd.value ? "on" : "off")
def switchEvent = createEvent(name: "switch", value: value, descriptionText: "$device.displayName was turned $value [${source?source:'physical'}]", type: source?source:"physical")
result << switchEvent
if (cmd.value) {
result << createEvent(name: "level", value: cmd.value, unit: "%", descriptionText: "$device.displayName was set to ${cmd.value}% [${source?source:'physical'}]", type: source?source:"physical")
}
if (switchEvent.isStateChange) {
result << response(["delay 3000", zwave.meterV2.meterGet(scale: 2).format()])
}
return result
}
def zwaveEvent(hubitat.zwave.commands.associationv2.AssociationReport cmd) {
logging(cmd)
state."association${cmd.groupingIdentifier}" = cmd.nodeId[0]
}
def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand(commandClassVersions)
if (encapsulatedCommand) {
state.sec = 1
def result = zwaveEvent(encapsulatedCommand)
result = result.collect {
if (it instanceof hubitat.device.HubAction && !it.toString().startsWith("9881")) {
response(cmd.CMD + "00" + it.toString())
} else {
it
}
}
result
}
}
def zwaveEvent(hubitat.zwave.commands.crc16encapv1.Crc16Encap cmd) {
def encapsulatedCommand = zwave.getCommand(cmd.commandClass, cmd.command, cmd.data,1)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract CRC16 command from ${cmd}"
}
}
def zwaveEvent(hubitat.zwave.Command cmd) {
logging("Unhandled Z-Wave Event: $cmd")
}
def zwaveEvent(hubitat.zwave.commands.meterv3.MeterReport cmd) {
logging(cmd)
if (cmd.meterType == 1) {
if (cmd.scale == 0) {
sendEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kWh", type: "digital")
} else if (cmd.scale == 1) {
sendEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kVAh", type: "digital")
} else if (cmd.scale == 2) {
sendEvent(name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W", type: "digital")
} else {
sendEvent(name: "electric", value: cmd.scaledMeterValue, unit: ["pulses", "V", "A", "R/Z", ""][cmd.scale - 3], type: "digital")
}
}
}
def zwaveEvent(hubitat.zwave.commands.sensormultilevelv1.SensorMultilevelReport cmd){
logging(cmd)
def map = [:]
switch (cmd.sensorType) {
case 4:
map.name = "power"
map.value = cmd.scaledSensorValue.toInteger().toString()
map.unit = cmd.scale == 1 ? "Btu/h" : "W"
break
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}
def on() {
state.lastRan = now()
commands([zwave.basicV1.basicSet(value: 0xFF), zwave.basicV1.basicGet()])
}
def off() {
state.lastRan = now()
commands([zwave.basicV1.basicSet(value: 0x00), zwave.basicV1.basicGet()])
}
def refresh() {
logging("$device.displayName refresh()")
def cmds = []
if (state.lastRefresh != null && now() - state.lastRefresh < 5000) {
logging("Refresh Double Press")
def configuration = new XmlSlurper().parseText(configuration_model())
configuration.Value.each
{
if ( "${it.@setting_type}" == "zwave" ) {
cmds << zwave.configurationV1.configurationGet(parameterNumber: "${it.@index}".toInteger())
}
}
cmds << zwave.firmwareUpdateMdV2.firmwareMdGet()
} else {
cmds << zwave.meterV2.meterGet(scale: 0)
cmds << zwave.meterV2.meterGet(scale: 2)
cmds << zwave.basicV1.basicGet()
}
state.lastRefresh = now()
commands(cmds)
}
def ping() {
logging("$device.displayName ping()")
def cmds = []
cmds << zwave.meterV2.meterGet(scale: 0)
cmds << zwave.meterV2.meterGet(scale: 2)
cmds << zwave.basicV1.basicGet()
commands(cmds)
}
def setLevel(level, duration) {
state.lastRan = now()
logging("setLevel value:$level, duration:$duration")
def dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
logging("dimmingDuration: $dimmingDuration")
commands([
zwave.switchMultilevelV2.switchMultilevelSet(value: level < 100 ? level : 99, dimmingDuration: dimmingDuration),
zwave.switchMultilevelV1.switchMultilevelGet()
])
}
def setLevel(level) {
state.lastRan = now()
logging("setLevel value:$level")
if(level > 99) level = 99
if(level < 1) level = 1
def cmds = []
cmds << zwave.basicV1.basicSet(value: level)
cmds << zwave.switchMultilevelV1.switchMultilevelGet()
commands(cmds)
}
def updated()
{
sendEvent(name: "numberOfButtons", value: 3)
state.enableDebugging = settings.enableDebugging
state.enableInfo = settings.enableInfo
logging("updated() is being called")
sendEvent(name: "checkInterval", value: 2 * 30 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
state.needfwUpdate = ""
def cmds = update_needed_settings()
sendEvent(name:"needUpdate", value: device.currentValue("needUpdate"), displayed:false, isStateChange: true)
commands(cmds)
}
def installed(){
log.warn "installed..."
sendEvent(name: "numberOfButtons", value: 3)
}
private command(hubitat.zwave.Command cmd) {
if (getDataValue("zwaveSecurePairingComplete") == "true") {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=1500) {
delayBetween(commands.collect{ command(it) }, delay)
}
def generate_preferences(configuration_model)
{
def configuration = new XmlSlurper().parseText(configuration_model)
configuration.Value.each
{
switch(it.@type)
{
case ["byte","short","four"]:
input "${it.@index}", "number",
title:"${it.@label}\n" + "${it.Help}",
range: "${it.@min}..${it.@max}",
defaultValue: "${it.@value}",
displayDuringSetup: "${it.@displayDuringSetup}"
break
case "list":
def items = []
it.Item.each { items << ["${it.@value}":"${it.@label}"] }
input "${it.@index}", "enum",
title:"${it.@label}\n" + "${it.Help}",
defaultValue: "${it.@value}",
displayDuringSetup: "${it.@displayDuringSetup}",
options: items
break
case "decimal":
input "${it.@index}", "decimal",
title:"${it.@label}\n" + "${it.Help}",
range: "${it.@min}..${it.@max}",
defaultValue: "${it.@value}",
displayDuringSetup: "${it.@displayDuringSetup}"
break
case "boolean":
input "${it.@index}", "bool",
title:"${it.@label}\n" + "${it.Help}",
defaultValue: "${it.@value}",
displayDuringSetup: "${it.@displayDuringSetup}"
break
}
}
}
def update_current_properties(cmd)
{
def currentProperties = state.currentProperties ?: [:]
currentProperties."${cmd.parameterNumber}" = cmd.configurationValue
if (settings."${cmd.parameterNumber}" != null)
{
if (settings."${cmd.parameterNumber}".toInteger() == convertParam("${cmd.parameterNumber}".toInteger(), cmd2Integer(cmd.configurationValue)))
{
sendEvent(name:"needUpdate", value:"NO", displayed:false, isStateChange: true)
}
else
{
sendEvent(name:"needUpdate", value:"YES", displayed:false, isStateChange: true)
}
}
state.currentProperties = currentProperties
}
def update_needed_settings()
{
def cmds = []
def currentProperties = state.currentProperties ?: [:]
def configuration = new XmlSlurper().parseText(configuration_model())
def isUpdateNeeded = "NO"
if(!state.needfwUpdate || state.needfwUpdate == ""){
logging("Requesting device firmware version")
cmds << zwave.versionV1.versionGet()
}
if(!state.association1 || state.association1 == "" || state.association1 == "1"){
logging("Setting association group 1")
cmds << zwave.associationV2.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId)
cmds << zwave.associationV2.associationGet(groupingIdentifier:1)
}
if(!state.association2 || state.association2 == "" || state.association1 == "2"){
logging("Setting association group 2")
cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
cmds << zwave.associationV2.associationGet(groupingIdentifier:2)
}
configuration.Value.each
{
if ("${it.@setting_type}" == "zwave"){
if (currentProperties."${it.@index}" == null)
{
if (device.currentValue("firmware") == null || it.@fw == "" || "${it.@fw}".indexOf(device.currentValue("firmware")) >= 0){
isUpdateNeeded = "YES"
logging("Current value of parameter ${it.@index} is unknown")
cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
}
}
else if (settings."${it.@index}" != null && convertParam(it.@index.toInteger(), cmd2Integer(currentProperties."${it.@index}")) != settings."${it.@index}".toInteger())
{
if (device.currentValue("firmware") == null || it.@fw == "" || "${it.@fw}".indexOf(device.currentValue("firmware")) >= 0){
isUpdateNeeded = "YES"
logging("Parameter ${it.@index} will be updated to " + settings."${it.@index}")
def convertedConfigurationValue = convertParam(it.@index.toInteger(), settings."${it.@index}".toInteger())
cmds << zwave.configurationV1.configurationSet(configurationValue: integer2Cmd(convertedConfigurationValue, it.@byteSize.toInteger()), parameterNumber: it.@index.toInteger(), size: it.@byteSize.toInteger())
cmds << zwave.configurationV1.configurationGet(parameterNumber: it.@index.toInteger())
}
}
}
}
sendEvent(name:"needUpdate", value: isUpdateNeeded, displayed:false, isStateChange: true)
return cmds
}
/**
* Convert 1 and 2 bytes values to integer
*/
def cmd2Integer(array) {
switch(array.size()) {
case 1:
array[0]
break
case 2:
((array[0] & 0xFF) << 8) | (array[1] & 0xFF)
break
case 3:
((array[0] & 0xFF) << 16) | ((array[1] & 0xFF) << 8) | (array[2] & 0xFF)
break
case 4:
((array[0] & 0xFF) << 24) | ((array[1] & 0xFF) << 16) | ((array[2] & 0xFF) << 8) | (array[3] & 0xFF)
break
}
}
def integer2Cmd(value, size) {
switch(size) {
case 1:
[value]
break
case 2:
def short value1 = value & 0xFF
def short value2 = (value >> 8) & 0xFF
[value2, value1]
break
case 3:
def short value1 = value & 0xFF
def short value2 = (value >> 8) & 0xFF
def short value3 = (value >> 16) & 0xFF
[value3, value2, value1]
break
case 4:
def short value1 = value & 0xFF
def short value2 = (value >> 8) & 0xFF
def short value3 = (value >> 16) & 0xFF
def short value4 = (value >> 24) & 0xFF
[value4, value3, value2, value1]
break
}
}
def zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
update_current_properties(cmd)
logging("${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '${cmd2Integer(cmd.configurationValue)}'")
return null
}
def zwaveEvent(hubitat.zwave.commands.firmwareupdatemdv2.FirmwareMdReport cmd){
logging("Firmware Report ${cmd.toString()}")
def firmwareVersion
switch(cmd.checksum){
case "3281":
firmwareVersion = "3.08"
break;
default:
firmwareVersion = cmd.checksum
}
state.needfwUpdate = "false"
updateDataValue("firmware", firmwareVersion.toString())
createEvent(name: "currentFirmware", value: firmwareVersion)
}
def zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd) {
logging("${device.label?device.label:device.name}: ${cmd}")
if(cmd.applicationVersion != null && cmd.applicationSubVersion != null) {
def firmware = "${cmd.applicationVersion}.${cmd.applicationSubVersion.toString().padLeft(2,'0')}"
logging("${device.label?device.label:device.name}: Firmware report received: ${firmware}")
state.needfwUpdate = "false"
createEvent(name: "firmware", value: "${firmware}")
} else if(cmd.firmware0Version != null && cmd.firmware0SubVersion != null) {
def firmware = "${cmd.firmware0Version}.${cmd.firmware0SubVersion.toString().padLeft(2,'0')}"
logging("${device.label?device.label:device.name}: Firmware report received: ${firmware}")
state.needfwUpdate = "false"
createEvent(name: "firmware", value: "${firmware}")
}
}
def configure() {
state.enableDebugging = settings.enableDebugging
state.enableInfo = settings.enableInfo
logging("Configuring Device For Hubitat Use")
def cmds = []
cmds = update_needed_settings()
if (cmds != []) commands(cmds)
}
def convertParam(number, value) {
switch (number){
case 201:
if (value < 0)
256 + value
else if (value > 100)
value - 256
else
value
break
case 202:
if (value < 0)
256 + value
else if (value > 100)
value - 256
else
value
break
case 203:
if (value < 0)
65536 + value
else if (value > 1000)
value - 65536
else
value
break
case 204:
if (value < 0)
256 + value
else if (value > 100)
value - 256
else
value
break
default:
value
break
}
}
private def logging(message) {
if (state.enableDebugging == null || state.enableDebugging == true) log.debug "$message"
}
private def Info(message) {
if (state.enableInfo == null || state.enableInfo == true) log.info "$message"
}
def configuration_model()
{
'''
(parameter is set automatically during the calibration process)
The parameter can be changed manually after the calibration.
Range: 1~98
Default: 1
(parameter is set automatically during the calibration process)
The parameter can be changed manually after the calibration.
Range: 2~99
Default: 99
This parameter defines the percentage value of dimming step during the automatic control.
Range: 1~99
Default: 1
This parameter defines the time of single dimming step set in parameter 5 during the automatic control.
Range: 0~255
Default: 1
This parameter defines the percentage value of dimming step during the manual control.
Range: 1~99
Default: 1
This parameter defines the time of single dimming step set in parameter 7 during the manual control.
Range: 0~255
Default: 5
The Dimmer 2 will return to the last state before power failure.
0 - the Dimmer 2 does not save the state before a power failure, it returns to the "off" position
1 - the Dimmer 2 restores its state before power failure
Range: 0~1
Default: 1
This parameter allows to automatically switch off the device after specified time (seconds) from switching on the light source.
Range: 1~32767
Default: 0
If the parameter is active, switching on the Dimmer 2 (S1 single click) will always set this brightness level.
Range: 0~99
Default: 0
Choose between momentary, toggle and roller blind switch.
Range: 0~2
Default: 0
By default each change of toggle switch position results in action of Dimmer 2 (switch on/off) regardless the physical connection of contacts.
0 - device changes status on switch status change
1 - device status is synchronized with switch status
Range: 0~1
Default: 0
set the brightness level to MAX
Range: 0~1
Default: 1
Switch no. 2 controls the Dimmer 2 additionally (in 3-way switch mode). Function disabled for parameter 20 set to 2 (roller blind switch).
Range: 0~1
Default: 0
SCENE ID depends on the switch type configurations.
Range: 0~1
Default: 0
This parameter allows for switching the role of keys connected to S1 and S2 without changes in connection.
Range: 0~1
Default: 0
This parameter determines the trigger of auto-calibration procedure, e.g. power on, load error, etc.
0 - No auto-calibration of the load after power on
1 - Auto-calibration performed after first power on
2 - Auto-calibration performed after each power on
3 - Auto-calibration performed after first power on or after each LOAD ERROR alarm (no load, load failure, burnt out bulb), if parameter 37 is set to 1 also after alarms: SURGE (Dimmer 2 output overvoltage) and OVERCURRENT (Dimmer 2 output overcurrent)
4 - Auto-calibration performed after each power on or after each LOAD ERROR alarm (no load, load failure, burnt out bulb), if parameter 37 is set to 1 also after alarms: SURGE (Dimmer 2 output overvoltage) and OVERCURRENT (Dimmer 2 output overcurrent)
Range: 0~4
Default: 1
This parameter defines the maximum load for a dimmer.
Range: 0~350
Default: 250
This parameter determines how the device will react to General Alarm frame.
Range: 0~3
Default: 3 (Flash)
This parameter determines how the device will react to Flood Alarm frame.
Range: 0~3
Default: 2 (OFF)
This parameter determines how the device will react to CO, CO2 or Smoke frame.
Range: 0~3
Default: 3 (Flash)
This parameter determines how the device will react to Heat Alarm frame.
Range: 0~3
Default: 1 (ON)
This parameter allows to set duration of flashing alarm mode.
Range: 1~32000 (1s-32000s)
Default: 600 (10 min)
The parameter defines the power level change that will result in a new power report being sent. The value is a percentage of the previous report.
Range: 0~100
Default: 10
Parameter 52 defines a time period between consecutive reports. Timer is reset and counted from zero after each report.
Range: 0~32767
Default: 3600
Energy level change which will result in sending a new energy report.
Range: 0~255
Default: 10
The Dimmer 2 may include active power and energy consumed by itself in reports sent to the main controller.
Range: 0~1
Default: 0
'''
//
//
//
//
}