UK Greenwave Smart Plug

Hi All,

I'm very new to Hubitat, and hoping to migrate all my devices from ST. I have some Greenwave smart plugs (10 of) which I'm trying to get working. I read up on the changes between the Groovy and altered the code accordingly, (generously created by codersaur for my Firmware on the plugs, which worked great on ST) I've managed to get the device code saved. The attributes are all there, yet executing any command fails with the error below.

The full code:

	metadata {
   definition (name: "GreenWave PowerNode (Single) Advanced", namespace: "codersaur", author: "David Lomas") {
	   capability "Actuator"
	   capability "Switch"
	   capability "Sensor"
	   capability "Energy Meter"
	   capability "Power Meter"
	   capability "Polling"
	   capability "Refresh"


	   // Standard Attributes:
	   attribute "switch", "enum", ["on", "off"]
	   attribute "power", "number"
	   attribute "energy", "number"

	   // Custom Attributes:
	   attribute "energyLastReset", "string"   // Last time Accumulated Engergy was reset.
	   attribute "fault", "string"             // Indicates if the device has any faults. 'clear' if no active faults.
	   attribute "localProtectionMode", "enum", ["unprotected","sequence","noControl"] // Physical protection mode.
	   attribute "rfProtectionMode", "enum", ["unprotected","noControl","noResponse"] // Wireless protection mode.
	   attribute "logMessage", "string"        // Important log messages.
	   attribute "syncPending", "number"       // Number of config items that need to be synced with the physical device.
	   attribute "wheelStatus", "enum", ["black","green","blue","red","yellow","violet","orange","aqua","pink","white"]

	   // Display Attributes:
	   // These are only required because the UI lacks number formatting and strips leading zeros.
	   attribute "dispEnergy", "string"
	   attribute "dispPower", "string"

	   // Custom Commands:
	   command "blink"                     // Causes the Circle LED to blink for ~20 seconds.
	   command "reset"                     // Alias for resetEnergy().
	   command "resetEnergy"               // Reset accumulated energy figure to 0.
	   command "resetFault"                // Reset fault alarm to 'clear'.
	   command "setLocalProtectionMode"    // Set physical protection mode.
	   command "toggleLocalProtectionMode" // Toggle physical protection mode.
	   command "setRfProtectionMode"       // Set wireless protection mode.
	   command "toggleRfProtectionMode"    // Toggle wireless protection mode.
	   command "sync"                      // Sync configuration with physical device.
	   command "test"                      // Test function.

	   // Fingerprints:
	   fingerprint mfr: "0153", prod: "0002", model: "0002"
	   fingerprint type: "1001", mfr: "0153", cc: "25,27,32,56,70,71,72,75,85,86,87"
	   fingerprint inClusters: "0x20,0x25,0x27,0x32,0x56,0x70,0x71,0x72,0x75,0x85,0x86,0x87"
   }

	   main(["switch"])
	   details([
		   "switch",
		   "instMode","power",
		   "wheelStatus",
		   "energyLastReset","energy",
		   "blink",
		   "localProtectionMode",
		   "rfProtectionMode",
		   "syncPending",
//            "refresh",
		   "fault"//,
		   //"test"
	   ])
   }

   preferences {

	   section { // GENERAL:
		   input (
			   type: "paragraph",
			   element: "paragraph",
			   title: "GENERAL:",
			   description: "General device handler settings."
		   )

		   input (
			   name: "configLoggingLevelIDE",
			   title: "IDE Live Logging Level:\nMessages with this level and higher will be logged to the IDE.",
			   type: "enum",
			   options: [
				   "0" : "None",
				   "1" : "Error",
				   "2" : "Warning",
				   "3" : "Info",
				   "4" : "Debug",
				   "5" : "Trace"
			   ],
			   defaultValue: "3",
			   required: false
		   )

		   input (
			   name: "configLoggingLevelDevice",
			   title: "Device Logging Level:\nMessages with this level and higher will be logged to the logMessage attribute.",
			   type: "enum",
			   options: [
				   "0" : "None",
				   "1" : "Error",
				   "2" : "Warning"
			   ],
			   defaultValue: "2",
			   required: false
		   )

		   input (
			   name: "configSyncAll",
			   title: "Force Full Sync:\nAll device settings will be re-sent to the device.",
			   type: "boolean",
			   defaultValue: false,
			   required: false
		   )

		   input (
			   name: "configAutoOffTime",
			   title: "Timer Function (Auto-off):\nAutomatically switch off the device after a specified time.\n" +
			   "Values:\n0 = Function Disabled\n1-86400 = time in seconds\nDefault Value: 0",
			   type: "number",
			   range: "0..86400",
			   defaultValue: 0,
			   required: false
		   )

		   input (
			   name: "configIgnoreCurrentLeakageAlarms",
			   title: "Ignore Current Leakage Alarms:\nDo not raise a fault on a current leakage alarm.",
			   type: "boolean",
			   defaultValue: false,
			   required: false
		   )

		   input (
			   name: "configSwitchAllMode",
			   title: "ALL ON/ALL OFF Function:\nResponse to SWITCH_ALL_SET commands.",
			   type: "enum",
			   options: [
				   "0" : "0: All ON not active, All OFF not active",
				   "1" : "1: All ON not active, All OFF active",
				   "2" : "2: All ON active, All OFF not active",
				   "255" : "255: All ON active, All OFF active"],
			   defaultValue: "255",
			   required: false
		   )

	   }

	   generatePrefsParams()

	   //generatePrefsAssocGroups() // All Assoc Groups are HubOnly for this device.

   }



/*****************************************************************************************************************
*  SmartThings System Commands:
*****************************************************************************************************************/

def installed() {
   log.trace "installed()"

   state.installedAt = now()
   state.energyLastReset = new Date().format("YYYY/MM/dd \n HH:mm:ss", location.timeZone)
   state.loggingLevelIDE     = 3
   state.loggingLevelDevice  = 2
   state.useSecurity = false
   state.useCrc16 = true
   state.fwVersion = 4.23 // Will be updated when versionReport is received.
   state.protectLocalTarget = 0
   state.protectRfTarget = 0
   state.autoOffTime = 0

   sendEvent(name: "fault", value: "clear", displayed: false)

   def cmds = []
   cmds << zwave.configurationV1.configurationSet(parameterNumber: 1, size: 1, scaledConfigurationValue: 255) // Set Keep-Alive to 255.
   cmds << zwave.configurationV1.configurationGet(parameterNumber: 2) // Wheel Status
   cmds << zwave.protectionV2.protectionGet()
   cmds << zwave.manufacturerSpecificV2.manufacturerSpecificGet()
   cmds << zwave.versionV1.versionGet()

   sendCommands(cmds)
}

def updated() {
   logger("updated()","trace")

   def cmds = []

   if (!state.updatedLastRanAt || now() >= state.updatedLastRanAt + 2000) {
	   state.updatedLastRanAt = now()

	   // Update internal state:
	   state.loggingLevelIDE     = (settings.configLoggingLevelIDE) ? settings.configLoggingLevelIDE.toInteger() : 3
	   state.loggingLevelDevice  = (settings.configLoggingLevelDevice) ? settings.configLoggingLevelDevice.toInteger(): 2
	   state.syncAll             = ("true" == settings.configSyncAll)
	   state.autoOffTime         = (settings.configAutoOffTime) ? settings.configAutoOffTime.toInteger() : 0
	   state.ignoreCurrentLeakageAlarms = ("true" == settings.configIgnoreCurrentLeakageAlarms)
	   state.switchAllModeTarget = (settings.configSwitchAllMode) ? settings.configSwitchAllMode.toInteger() : 255

	   // Update Parameter target values:
	   getParamsMd().findAll( { !it.readonly & (it.fwVersion <= state.fwVersion) } ).each { // Exclude readonly/newer parameters.
		   state."paramTarget${it.id}" = settings."configParam${it.id}"?.toInteger()
	   }

	   // Update Assoc Group target values:
	   getAssocGroupsMd().findAll( { !it.hubOnly } ).each {
		   state."assocGroupTarget${it.id}" = parseAssocGroupInput(settings."configAssocGroup${it.id}", it.maxNodes)
	   }
	   getAssocGroupsMd().findAll( { it.hubOnly } ).each {
		   state."assocGroupTarget${it.id}" = [ zwaveHubNodeId ]
	   }

	   // Sync configuration with phyiscal device:
	   sync(state.syncAll)

	   // Request device medadata (this just seems the best place to do it):
	   cmds << zwave.manufacturerSpecificV2.manufacturerSpecificGet()
	   cmds << zwave.versionV1.versionGet()

	   return sendCommands(cmds)
   }
   else {
	   logger("updated(): Ran within last 2 seconds so aborting.","debug")
   }
}

def parse(description) {
   logger("parse(): Parsing raw message: ${description}","trace")

   def result = []

   def cmd = zwave.parse(description, getCommandClassVersions())
   if (cmd) {
	   result += zwaveEvent(cmd)
   } else {
	   logger("parse(): Could not parse raw message: ${description}","error")
   }
   return result
}

/*****************************************************************************************************************
*  Z-wave Event Handlers.
*****************************************************************************************************************/

def zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) {
   logger("zwaveEvent(): Basic Report received: ${cmd}","trace")

   def result = []

   def switchValue = (cmd.value ? "on" : "off")
   def switchEvent = createEvent(name: "switch", value: switchValue)
   if (switchEvent.isStateChange) logger("Switch turned ${switchValue}.","info")
   result << switchEvent

   if ( switchEvent.isStateChange & (switchValue == "on") & (state.autoOffTime > 0) ) {
	   logger("Scheduling Auto-off in ${state.autoOffTime} seconds.","info")
	   runIn(state.autoOffTime,autoOff)
   }

   return result
}


def zwaveEvent(hubitat.zwave.commands.applicationstatusv1.ApplicationBusy cmd) {
   logger("zwaveEvent(): Application Busy received: ${cmd}","trace")

   switch(cmd.status) {
	   case 0:
	   logger("Device is busy. Try again later.","warn")
	   break
	   case 1:
	   logger("Device is busy. Retry in ${cmd.waitTime} seconds.","warn")
	   break
	   case 2:
	   logger("Device is busy. Request is queued.","warn")
	   break
   }
}


def zwaveEvent(hubitat.zwave.commands.applicationstatusv1.ApplicationRejectedRequest cmd) {
   //logger("zwaveEvent(): Application Rejected Request received: ${cmd}","trace")
   logger("A command was rejected. Most likely, RF Protection Mode is set to 'No Control'.","warn")
}

def zwaveEvent(hubitat.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
   logger("zwaveEvent(): Switch Binary Report received: ${cmd}","trace")

   def result = []

   def switchValue = (cmd.value ? "on" : "off")
   def switchEvent = createEvent(name: "switch", value: switchValue)
   if (switchEvent.isStateChange) logger("Switch turned ${switchValue}.","info")
   result << switchEvent

   if ( switchEvent.isStateChange & (switchValue == "on") & (state.autoOffTime > 0) ) {
	   logger("Scheduling Auto-off in ${state.autoOffTime} seconds.","info")
	   runIn(state.autoOffTime,autoOff)
   }

   return result
}

def zwaveEvent(hubitat.zwave.commands.switchallv1.SwitchAllReport cmd) {
   logger("zwaveEvent(): Switch All Report received: ${cmd}","trace")

   state.switchAllModeCache = cmd.mode

   def msg = ""
   switch (cmd.mode) {
		   case 0:
			   msg = "Device is excluded from the all on/all off functionality."
			   break

		   case 1:
			   msg = "Device is excluded from the all on functionality but not all off."
			   break

		   case 2:
			   msg = "Device is excluded from the all off functionality but not all on."
			   break

		   default:
			   msg = "Device is included in the all on/all off functionality."
			   break
   }
   logger("Switch All Mode: ${msg}","info")

   updateSyncPending()
}

def zwaveEvent(hubitat.zwave.commands.meterv3.MeterReport cmd) {
   logger("zwaveEvent(): Meter Report received: ${cmd}","trace")

   def result = []

   switch (cmd.meterType) {
	   case 1:  // Electric meter:
		   switch (cmd.scale) {
			   case 0:  // Accumulated Energy (kWh):
				   result << createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kWh", displayed: true)
				   result << createEvent(name: "dispEnergy", value: String.format("%.2f",cmd.scaledMeterValue as BigDecimal) + " kWh", displayed: false)
				   logger("New meter reading: Accumulated Energy: ${cmd.scaledMeterValue} kWh","info")
				   break

			   case 1:  // Accumulated Energy (kVAh):
				   result << createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kVAh", displayed: true)
				   result << createEvent(name: "dispEnergy", value: String.format("%.2f",cmd.scaledMeterValue as BigDecimal) + " kVAh", displayed: false)
				   logger("New meter reading: Accumulated Energy: ${cmd.scaledMeterValue} kVAh","info")
				   break

			   case 2:  // Instantaneous Power (Watts):
				   result << createEvent(name: "power", value: cmd.scaledMeterValue, unit: "W", displayed: true)
				   result << createEvent(name: "dispPower", value: String.format("%.1f",cmd.scaledMeterValue as BigDecimal) + " W", displayed: false)
				   logger("New meter reading: Instantaneous Power: ${cmd.scaledMeterValue} W","info")

				   // Request Switch Binary Report if power suggests switch state has changed:
				   def sw = (cmd.scaledMeterValue) ? "on" : "off"
				   if ( device.latestValue("switch") != sw) { result << prepCommands([zwave.switchBinaryV1.switchBinaryGet()]) }
				   break

			   case 3:  // Accumulated Pulse Count:
				   result << createEvent(name: "pulseCount", value: cmd.scaledMeterValue, unit: "", displayed: true)
				   logger("New meter reading: Accumulated Electricity Pulse Count: ${cmd.scaledMeterValue}","info")
				   break

			   case 4:  // Instantaneous Voltage (Volts):
				   result << createEvent(name: "voltage", value: cmd.scaledMeterValue, unit: "V", displayed: true)
				   result << createEvent(name: "dispVoltage", value: String.format("%.1f",cmd.scaledMeterValue as BigDecimal) + " V", displayed: false)
				   logger("New meter reading: Instantaneous Voltage: ${cmd.scaledMeterValue} V","info")
				   break

				case 5:  // Instantaneous Current (Amps):
				   result << createEvent(name: "current", value: cmd.scaledMeterValue, unit: "A", displayed: true)
				   result << createEvent(name: "dispCurrent", value: String.format("%.1f",cmd.scaledMeterValue as BigDecimal) + " V", displayed: false)
				   logger("New meter reading: Instantaneous Current: ${cmd.scaledMeterValue} A","info")
				   break

				case 6:  // Instantaneous Power Factor:
				   result << createEvent(name: "powerFactor", value: cmd.scaledMeterValue, unit: "", displayed: true)
				   result << createEvent(name: "dispPowerFactor", value: String.format("%.1f",cmd.scaledMeterValue as BigDecimal), displayed: false)
				   logger("New meter reading: Instantaneous Power Factor: ${cmd.scaledMeterValue}","info")
				   break

			   default:
				   logger("zwaveEvent(): Meter Report with unhandled scale: ${cmd}","warn")
				   break
		   }
		   break

	   default:
		   logger("zwaveEvent(): Meter Report with unhandled meterType: ${cmd}","warn")
		   break
   }

   return result
}


def zwaveEvent(hubitat.zwave.commands.crc16encapv1.Crc16Encap cmd) {
   logger("zwaveEvent(): CRC-16 Encapsulation Command received: ${cmd}","trace")

   def versions = getCommandClassVersions()
   def version = versions[cmd.commandClass as Integer]
   def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
   def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
   // TO DO: It should be possible to replace the lines above with this line soon...
   //def encapsulatedCommand = cmd.encapsulatedCommand(getCommandClassVersions())
   if (!encapsulatedCommand) {
	   logger("zwaveEvent(): Could not extract command from ${cmd}","error")
   } else {
	   return zwaveEvent(encapsulatedCommand)
   }
}

def zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
   logger("zwaveEvent(): Configuration Report received: ${cmd}","trace")

   def result = []

   def paramMd = getParamsMd().find( { it.id == cmd.parameterNumber })
   // Some values are treated as unsigned and some as signed, so we convert accordingly:
   def paramValue = (paramMd?.isSigned) ? cmd.scaledConfigurationValue : byteArrayToUInt(cmd.configurationValue)
   def signInfo = (paramMd?.isSigned) ? "SIGNED" : "UNSIGNED"

   state."paramCache${cmd.parameterNumber}" = paramValue
   logger("Parameter #${cmd.parameterNumber} [${paramMd?.name}] has value: ${paramValue} [${signInfo}]","info")
   updateSyncPending()

   // Update wheelStatus if parameter #2:
   if (cmd.parameterNumber == 2) {
	   def wheelStatus = getWheelColours()[paramValue]
	def wheelEvent = createEvent(name: "wheelStatus", value: wheelStatus)
	if (wheelEvent.isStateChange) logger("Room Colour Wheel changed to ${wheelStatus}.","info")
	result << wheelEvent
}

return result
}


def zwaveEvent(hubitat.zwave.commands.alarmv1.AlarmReport cmd) {
logger("zwaveEvent(): Alarm Report received: ${cmd}","trace")

def result = []

switch(cmd.alarmType) {
	case 1: // Current Leakage:
		if (!state.ignoreCurrentLeakageAlarms) { result << createEvent(name: "fault", value: "currentLeakage",
		  descriptionText: "Current Leakage detected!", displayed: true) }
		logger("Current Leakage detected!","warn")
		break

	// TO DO: Check other alarm codes.

	default: // Over-current:
		result << createEvent(name: "fault", value: "current", descriptionText: "Over-current detected!", displayed: true)
		logger("Over-current detected!","warn")
		break
}

return result
}


def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
logger("zwaveEvent(): Manufacturer-Specific Report received: ${cmd}","trace")

// Display as hex strings:
def manufacturerIdDisp = String.format("%04X",cmd.manufacturerId)
def productIdDisp = String.format("%04X",cmd.productId)
def productTypeIdDisp = String.format("%04X",cmd.productTypeId)

logger("Manufacturer-Specific Report: Manufacturer ID: ${manufacturerIdDisp}, Manufacturer Name: ${cmd.manufacturerName}" +
", Product Type ID: ${productTypeIdDisp}, Product ID: ${productIdDisp}","info")

if ( 153 != cmd.manufacturerId) logger("Device Manufacturer is not GreenWave Reality. " +
  "Using this device handler with a different device may damage your device!","warn")
if ( 2 != cmd.productId) logger("Product ID does not match GreenWave PowerNode (Single). " +
  "Using this device handler with a different device may damage you device!","warn")

updateDataValue("manufacturerName",cmd.manufacturerName)
updateDataValue("manufacturerId",manufacturerIdDisp)
updateDataValue("productId",productIdDisp)
updateDataValue("productTypeId",productTypeIdDisp)
}

/**
*  zwaveEvent( COMMAND_CLASS_PROTECTION_V2 (0x75) : PROTECTION_REPORT_V2 (0x03) )
*
*  The Protection Report is used to report the protection state of a device.
*  I.e. measures to prevent unintentional control (e.g. by a child).
*
*  Action: Cache values, update syncPending, and log an info message.
*
*  cmd attributes:
*    Short  localProtectionState  Local protection state (i.e. physical switches/buttons)
*    Short  rfProtectionState     RF protection state.
*
*  Example: ProtectionReport(localProtectionState: 0, reserved01: 0, reserved11: 0, rfProtectionState: 0)
**/
def zwaveEvent(hubitat.zwave.commands.protectionv2.ProtectionReport cmd) {
logger("zwaveEvent(): Protection Report received: ${cmd}","trace")

def result = []

state.protectLocalCache = cmd.localProtectionState
state.protectRfCache = cmd.rfProtectionState

def lpStates = ["unprotected","sequence","noControl"]
def lpValue = lpStates[cmd.localProtectionState]
def lpEvent = createEvent(name: "localProtectionMode", value: lpValue)
if (lpEvent.isStateChange) logger("Local Protection set to ${lpValue}.","info")
result << lpEvent

def rfpStates = ["unprotected","noControl","noResponse"]
def rfpValue = rfpStates[cmd.rfProtectionState]
def rfpEvent = createEvent(name: "rfProtectionMode", value: rfpValue)
if (rfpEvent.isStateChange) logger("RF Protection set to ${rfpValue}.","info")
result << rfpEvent

logger("Protection Report: Local Protection: ${lpValue}, RF Protection: ${rfpValue}","info")
updateSyncPending()

return result
}

/**
*  zwaveEvent( COMMAND_CLASS_ASSOCIATION_V2 (0x85) : ASSOCIATION_REPORT_V2 (0x03) )
*
*  The Association Report command is used to advertise the current destination nodes of a given association group.
*
*  Action: Cache value and log info message only.
*
*  Note: Ideally, we want to update the corresponding preference value shown on the Settings GUI, however this
*  is not possible due to security restrictions in the SmartThings platform.
*
*  Example: AssociationReport(groupingIdentifier: 1, maxNodesSupported: 1, nodeId: [1], reportsToFollow: 0)
**/
def zwaveEvent(hubitat.zwave.commands.associationv2.AssociationReport cmd) {
logger("zwaveEvent(): Association Report received: ${cmd}","trace")

state."assocGroupCache${cmd.groupingIdentifier}" = cmd.nodeId

// Display to user in hex format (same as IDE):
def hexArray  = []
cmd.nodeId.each { hexArray.add(String.format("%02X", it)) };
def assocGroupMd = getAssocGroupsMd().find( { it.id == cmd.groupingIdentifier })
logger("Association Group ${cmd.groupingIdentifier} [${assocGroupMd?.name}] contains nodes: ${hexArray} (hexadecimal format)","info")

updateSyncPending()
}

/**
*  zwaveEvent( COMMAND_CLASS_VERSION (0x86) : VERSION_REPORT (0x12) )
*
*  The Version Report Command is used to advertise the library type, protocol version, and application version.
*
*  Action: Publish values as device 'data' and log an info message.
*          Store fwVersion as state.fwVersion.
*
*  cmd attributes:
*    Short  applicationSubVersion
*    Short  applicationVersion
*    Short  zWaveLibraryType
*    Short  zWaveProtocolSubVersion
*    Short  zWaveProtocolVersion
*
*  Example: VersionReport(applicationSubVersion: 4, applicationVersion: 3, zWaveLibraryType: 3,
*   zWaveProtocolSubVersion: 5, zWaveProtocolVersion: 4)
**/
def zwaveEvent(hubitat.zwave.commands.versionv1.VersionReport cmd) {
logger("zwaveEvent(): Version Report received: ${cmd}","trace")

def zWaveLibraryTypeDisp  = String.format("%02X",cmd.zWaveLibraryType)
def zWaveLibraryTypeDesc  = ""
switch(cmd.zWaveLibraryType) {
	case 1:
		zWaveLibraryTypeDesc = "Static Controller"
		break

	case 2:
		zWaveLibraryTypeDesc = "Controller"
		break

	case 3:
		zWaveLibraryTypeDesc = "Enhanced Slave"
		break

	case 4:
		zWaveLibraryTypeDesc = "Slave"
		break

	case 5:
		zWaveLibraryTypeDesc = "Installer"
		break

	case 6:
		zWaveLibraryTypeDesc = "Routing Slave"
		break

	case 7:
		zWaveLibraryTypeDesc = "Bridge Controller"
		break

	case 8:
		zWaveLibraryTypeDesc = "Device Under Test (DUT)"
		break

	case 0x0A:
		zWaveLibraryTypeDesc = "AV Remote"
		break

	case 0x0B:
		zWaveLibraryTypeDesc = "AV Device"
		break

	default:
		zWaveLibraryTypeDesc = "N/A"
}

def applicationVersionDisp = String.format("%d.%02d",cmd.applicationVersion,cmd.applicationSubVersion)
def zWaveProtocolVersionDisp = String.format("%d.%02d",cmd.zWaveProtocolVersion,cmd.zWaveProtocolSubVersion)

state.fwVersion = new BigDecimal(applicationVersionDisp)

logger("Version Report: Application Version: ${applicationVersionDisp}, " +
	   "Z-Wave Protocol Version: ${zWaveProtocolVersionDisp}, " +
	   "Z-Wave Library Type: ${zWaveLibraryTypeDisp} (${zWaveLibraryTypeDesc})","info")

updateDataValue("applicationVersion","${cmd.applicationVersion}")
updateDataValue("applicationSubVersion","${cmd.applicationSubVersion}")
updateDataValue("zWaveLibraryType","${zWaveLibraryTypeDisp}")
updateDataValue("zWaveProtocolVersion","${cmd.zWaveProtocolVersion}")
updateDataValue("zWaveProtocolSubVersion","${cmd.zWaveProtocolSubVersion}")
}

/**
*  zwaveEvent( COMMAND_CLASS_INDICATOR (0x87) : INDICATOR_REPORT (0x03) )
*
*  The Indicator Report command is used to advertise the state of an indicator.
*
*  Action: Do nothing. It doesn't tell us anything useful.
*
*  cmd attributes:
*    Short value  Indicator status.
*      0x00       = Off/Disabled
*      0x01..0x63 = Indicator Range.
*      0xFF       = On/Enabled.
*
*  Example: IndicatorReport(value: 0)
**/
def zwaveEvent(hubitat.zwave.commands.indicatorv1.IndicatorReport cmd) {
logger("zwaveEvent(): Indicator Report received: ${cmd}","trace")
}

/**
*  zwaveEvent( DEFAULT CATCHALL )
*
*  Called for all commands that aren't handled above.
**/
def zwaveEvent(hubitat.zwave.Command cmd) {
logger("zwaveEvent(): No handler for command: ${cmd}","error")
}

/*****************************************************************************************************************
*  Capability-related Commands:
*****************************************************************************************************************/

/**
*  on()                        [Capability: Switch]
*
*  Turn the switch on.
**/
def on() {
logger("on(): Turning switch on.","info")
	sendCommands([
	zwave.basicV1.basicSet(value: 0xFF).format(),
	zwave.switchBinaryV1.switchBinaryGet().format(),
	"delay 3000",
	zwave.meterV2.meterGet(scale: 2).format()
])
}

/**
*  off()                       [Capability: Switch]
*
*  Turn the switch off.
**/
def off() {
logger("off(): Turning switch off.","info")
sendCommands([
	zwave.basicV1.basicSet(value: 0x00).format(),
	zwave.switchBinaryV1.switchBinaryGet().format(),
	"delay 3000",
	zwave.meterV2.meterGet(scale: 2).format()
])
}

/**
*  poll()                      [Capability: Polling]
*
*  Calls refresh().
**/
def poll() {
logger("poll()","trace")
refresh()
}

/**
*  refresh()                   [Capability: Refresh]
*
*  Action: Request switchBinary, energy, and power reports. Plus, get wheel status.
*  Trigger a sync too.
**/
def refresh() {
logger("refresh()","trace")
sendCommands([
	zwave.switchBinaryV1.switchBinaryGet().format(),
	zwave.meterV2.meterGet(scale: 0).format(),
	zwave.meterV2.meterGet(scale: 2).format(),
	zwave.configurationV1.configurationGet(parameterNumber: 2) // Wheel Status
])
sync()
}

/*****************************************************************************************************************
*  Custom Commands:
*****************************************************************************************************************/

/**
*  blink()
*
*  Causes the Circle LED to blink for ~20 seconds.
**/
def blink() {
logger("blink(): Blinking Circle LED","info")
sendCommands([zwave.indicatorV1.indicatorSet(value: 255)])
}

/**
*  autoOff()
*
*  Calls off(), but with additional log message.
**/
def autoOff() {
logger("autoOff(): Automatically turning off the device.","info")
off()
}

/**
*  reset()
*
*  Alias for resetEnergy().
*
*  Note: this used to be part of the official 'Energy Meter' capability, but isn't anymore.
**/
def reset() {
logger("reset()","trace")
resetEnergy()
}

/**
*  resetEnergy()
*
*  Reset the Accumulated Energy figure held in the device.
**/
def resetEnergy() {
logger("resetEnergy(): Resetting Accumulated Energy","info")

state.energyLastReset = new Date().format("YYYY/MM/dd \n HH:mm:ss", location.timeZone)
sendEvent(name: "energyLastReset", value: state.energyLastReset, descriptionText: "Accumulated Energy Reset")

sendCommands([
	zwave.meterV3.meterReset(),
	zwave.meterV3.meterGet(scale: 0)
],400)
}

/**
*  resetFault()
*
*  Reset fault alarm to 'clear'.
**/
def resetFault() {
logger("resetFault(): Resetting fault alarm.","info")
sendEvent(name: "fault", value: "clear", descriptionText: "Fault alarm cleared", displayed: true)
}

/**
*  setLocalProtectionMode(localProtectionMode)
*
*  Set local (physical) protection mode.
*
*  Note: GreenWave PowerNode supports "unprotected" and "noControl" modes only.
*
*  localProtectionMode values:
*   "unprotected"  Physical switches are operational.
*   "sequence"     Special sequence required to operate.
*   "noControl"    Physical switches are disabled.
**/
def setLocalProtectionMode(localProtectionMode) {
logger("setLocalProtectionMode(${localProtectionMode})","trace")

switch(localProtectionMode.toLowerCase()) {
	case "unprotected":
		state.protectLocalTarget = 0
		break
	case "sequence":
		logger("setLocalProtectionMode(): Protection by sequence is not supported by this device.","warn")
		state.protectLocalTarget = 2
		break
	case "nocontrol":
		state.protectLocalTarget = 2
		break
	default:
		logger("setLocalProtectionMode(): Unknown protection mode: ${localProtectionMode}.","warn")
}
sync()
}

/**
*  toggleLocalProtectionMode()
*
*  Toggle local (physical) protection mode between "unprotected" and "noControl" modes.
**/
def toggleLocalProtectionMode() {
logger("toggleLocalProtectionMode()","trace")

if (device.latestValue("localProtectionMode") != "unprotected") {
	setLocalProtectionMode("unprotected")
}
else {
	setLocalProtectionMode("noControl")
}
}

/**
*  setRfProtectionMode(rfProtectionMode)
*
*  Set RF (wireless) protection mode.
*
*  Note: GreenWave PowerNode supports "unprotected" and "noControl" modes only.
*
*  rfProtectionMode values:
*   "unprotected"   Device responds to wireless commands.
*   "noControl"     Device ignores wireless commands (sends ApplicationRejectedRequest).
*   "noResponse"    Device ignores wireless commands.
**/
def setRfProtectionMode(rfProtectionMode) {
logger("setRfProtectionMode(${rfProtectionMode})","trace")

switch(rfProtectionMode.toLowerCase()) {
	case "unprotected":
		state.protectRfTarget = 0
		break
	case "nocontrol":
		state.protectRfTarget = 1
		break
	case "noresponse":
		logger("setRfProtectionMode(): NoResponse mode is not supported by this device.","warn")
		state.protectRfTarget = 1
		break
	default:
		logger("setRfProtectionMode(): Unknown protection mode: ${rfProtectionMode}.","warn")
}
sync()
}

/**
*  toggleRfProtectionMode()
*
*  Toggle RF (wireless) protection mode between "unprotected" and "noControl" modes.
**/
def toggleRfProtectionMode() {
logger("toggleRfProtectionMode()","trace")

if (device.latestValue("rfProtectionMode") != "unprotected") {
	setRfProtectionMode("unprotected")
}
else {
	setRfProtectionMode("noControl")
}
}


/*****************************************************************************************************************
*  Private Helper Functions:
*****************************************************************************************************************/

/**
*  encapCommand(cmd)
*
*  Applies security or CRC16 encapsulation to a command as needed.
*  Returns a hubitat.zwave.Command.
**/
private encapCommand(hubitat.zwave.Command cmd) {
if (state.useSecurity) {
	return zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd)
}
else if (state.useCrc16) {
	return zwave.crc16EncapV1.crc16Encap().encapsulate(cmd)
}
else {
	return cmd
}
}

/**
*  prepCommands(cmds, delay=200)
*
*  Converts a list of commands (and delays) into a HubMultiAction object, suitable for returning via parse().
*  Uses encapCommand() to apply security or CRC16 encapsulation as needed.
**/
private prepCommands(cmds, delay=200) {
return response(delayBetween(cmds.collect{ (it instanceof hubitat.zwave.Command ) ? encapCommand(it).format() : it },delay))
}

/**
*  sendCommands(cmds, delay=200)
*
*  Sends a list of commands directly to the device using sendHubCommand.
*  Uses encapCommand() to apply security or CRC16 encapsulation as needed.
**/
private sendCommands(cmds, delay=200) {
sendHubCommand(hubitat.device.HubAction)( cmds.collect{ (it instanceof hubitat.zwave.Command ) ? response(encapCommand(it)) : response(it) }, delay)
}

/**
*  logger()
*
*  Wrapper function for all logging:
*    Logs messages to the IDE (Live Logging), and also keeps a historical log of critical error and warning
*    messages by sending events for the device's logMessage attribute.
*    Configured using configLoggingLevelIDE and configLoggingLevelDevice preferences.
**/
private logger(msg, level = "debug") {

switch(level) {
	case "error":
		if (state.loggingLevelIDE >= 1) log.error msg
		if (state.loggingLevelDevice >= 1) sendEvent(name: "logMessage", value: "ERROR: ${msg}", displayed: false, isStateChange: true)
		break

	case "warn":
		if (state.loggingLevelIDE >= 2) log.warn msg
		if (state.loggingLevelDevice >= 2) sendEvent(name: "logMessage", value: "WARNING: ${msg}", displayed: false, isStateChange: true)
		break

	case "info":
		if (state.loggingLevelIDE >= 3) log.info msg
		break

	case "debug":
		if (state.loggingLevelIDE >= 4) log.debug msg
		break

	case "trace":
		if (state.loggingLevelIDE >= 5) log.trace msg
		break

	default:
		log.debug msg
		break
}
}

/**
*  sync()
*
*  Manages synchronisation of parameters, association groups, etc. with the physical device.
*  The syncPending attribute advertises remaining number of sync operations.
*
*  Does not return a list of commands, it sends them immediately using sendCommands(), which means sync() can be
*  triggered by schedule().
*
*  Parameters:
*   forceAll    Force all items to be synced, otherwise only changed items will be synced.
**/
private sync(forceAll = false) {
logger("sync(): Syncing configuration with the physical device.","info")

def cmds = []
def syncPending = 0

if (forceAll) { // Clear all cached values.
	getParamsMd().findAll( {!it.readonly} ).each { state."paramCache${it.id}" = null }
	getAssocGroupsMd().each { state."assocGroupCache${it.id}" = null }
	state.protectLocalCache = null
	state.protectRfCache = null
	state.switchAllModeCache = null
}

getParamsMd().findAll( { !it.readonly & (it.fwVersion <= state.fwVersion) } ).each { // Exclude readonly/newer parameters.
	if ( (state."paramTarget${it.id}" != null) & (state."paramCache${it.id}" != state."paramTarget${it.id}") ) {
		cmds << zwave.configurationV1.configurationSet(parameterNumber: it.id, size: it.size, scaledConfigurationValue: state."paramTarget${it.id}".toInteger())
		cmds << zwave.configurationV1.configurationGet(parameterNumber: it.id)
		logger("sync(): Syncing parameter #${it.id} [${it.name}]: New Value: " + state."paramTarget${it.id}","info")
		syncPending++
		}
}

getAssocGroupsMd().each {
	def cachedNodes = state."assocGroupCache${it.id}"
	def targetNodes = state."assocGroupTarget${it.id}"

	if ( cachedNodes != targetNodes ) {
		// Display to user in hex format (same as IDE):
		def targetNodesHex  = []
		targetNodes.each { targetNodesHex.add(String.format("%02X", it)) }
		logger("sync(): Syncing Association Group #${it.id} [${it.name}]: Destinations: ${targetNodesHex}","info")
		if (it.multiChannel) {
			cmds << zwave.multiChannelAssociationV2.multiChannelAssociationRemove(groupingIdentifier: it.id, nodeId: []) // Remove All
			cmds << zwave.multiChannelAssociationV2.multiChannelAssociationSet(groupingIdentifier: it.id, nodeId: targetNodes)
			cmds << zwave.multiChannelAssociationV2.multiChannelAssociationGet(groupingIdentifier: it.id)
		}
		else {
			cmds << zwave.associationV2.associationRemove(groupingIdentifier: it.id, nodeId: []) // Remove All
			cmds << zwave.associationV2.associationSet(groupingIdentifier: it.id, nodeId:[zwaveHubNodeId])
			cmds << zwave.associationV2.associationGet(groupingIdentifier: it.id)
		}
		syncPending++
	}
}

if ( (state.protectLocalTarget != null) & (state.protectRfTarget != null)
  & ( (state.protectLocalCache != state.protectLocalTarget) || (state.protectRfCache != state.protectRfTarget) ) ) {

	logger("sync(): Syncing Protection State: Local Protection: ${state.protectLocalTarget}, RF Protection: ${state.protectRfTarget}","info")
	cmds << zwave.protectionV2.protectionSet(localProtectionState : state.protectLocalTarget, rfProtectionState: state.protectRfTarget)
	cmds << zwave.protectionV2.protectionGet()
	syncPending++
}

if ( (state.switchAllModeTarget != null) & (state.switchAllModeCache != state.switchAllModeTarget) ) {
	logger("sync(): Syncing SwitchAll Mode: ${state.switchAllModeTarget}","info")
	cmds << zwave.switchAllV1.switchAllSet(mode: state.switchAllModeTarget)
	cmds << zwave.switchAllV1.switchAllGet()
	syncPending++
}

sendEvent(name: "syncPending", value: syncPending, displayed: false)
sendCommands(cmds,800)
}

/**
*  updateSyncPending()
*
*  Updates syncPending attribute, which advertises remaining number of sync operations.
**/
private updateSyncPending() {

def syncPending = 0

getParamsMd().findAll( { !it.readonly & (it.fwVersion <= state.fwVersion) } ).each { // Exclude readonly/newer parameters.
	if ( (state."paramTarget${it.id}" != null) & (state."paramCache${it.id}" != state."paramTarget${it.id}") ) {
		syncPending++
	}
}

getAssocGroupsMd().each {
	def cachedNodes = state."assocGroupCache${it.id}"
	def targetNodes = state."assocGroupTarget${it.id}"

	if ( cachedNodes != targetNodes ) {
		syncPending++
	}
}

if ( (state.protectLocalCache == null) || (state.protectRfCache == null) ||
	 (state.protectLocalCache != state.protectLocalTarget) || (state.protectRfCache != state.protectRfTarget) ) {
	syncPending++
}

if ( (state.switchAllModeTarget != null) & (state.switchAllModeCache != state.switchAllModeTarget) ) {
	syncPending++
}

logger("updateSyncPending(): syncPending: ${syncPending}", "debug")
if ((syncPending == 0) & (device.latestValue("syncPending") > 0)) logger("Sync Complete.", "info")
sendEvent(name: "syncPending", value: syncPending, displayed: false)
}

/**
*  generatePrefsParams()
*
*  Generates preferences (settings) for device parameters.
**/
private generatePrefsParams() {
	section {
		input (
			type: "paragraph",
			element: "paragraph",
			title: "DEVICE PARAMETERS:",
			description: "Device parameters are used to customise the physical device. " +
						 "Refer to the product documentation for a full description of each parameter."
		)

getParamsMd().findAll( {!it.readonly} ).each { // Exclude readonly parameters.

	def lb = (it.description.length() > 0) ? "\n" : ""

	switch(it.type) {
		case "number":
		input (
			name: "configParam${it.id}",
			title: "#${it.id}: ${it.name}: \n" + it.description + lb +"Default Value: ${it.defaultValue}",
			type: it.type,
			range: it.range,
//                defaultValue: it.defaultValue, // iPhone users can uncomment these lines!
			required: it.required
		)
		break

		case "enum":
		input (
			name: "configParam${it.id}",
			title: "#${it.id}: ${it.name}: \n" + it.description + lb + "Default Value: ${it.defaultValue}",
			type: it.type,
			options: it.options,
//                defaultValue: it.defaultValue, // iPhone users can uncomment these lines!
			required: it.required
		)
		break
	}
}
	} // section
}

/**
*  generatePrefsAssocGroups()
*
*  Generates preferences (settings) for Association Groups.
*  Excludes any groups that are hubOnly.
**/
private generatePrefsAssocGroups() {
	section {
		input (
			type: "paragraph",
			element: "paragraph",
			title: "ASSOCIATION GROUPS:",
			description: "Association groups enable the device to control other Z-Wave devices directly, " +
						 "without participation of the main controller.\n" +
						 "Enter a comma-delimited list of destinations (node IDs and/or endpoint IDs) for " +
						 "each association group. All IDs must be in hexadecimal format. E.g.:\n" +
						 "Node destinations: '11, 0F'\n" +
						 "Endpoint destinations: '1C:1, 1C:2'"
		)

getAssocGroupsMd().findAll( { !it.hubOnly } ).each {
		input (
			name: "configAssocGroup${it.id}",
			title: "Association Group #${it.id}: ${it.name}: \n" + it.description + " \n[MAX NODES: ${it.maxNodes}]",
			type: "text",
//                defaultValue: "", // iPhone users can uncomment these lines!
			required: false
		)
	}
}
}

/**
*  byteArrayToUInt(byteArray)
*
*  Converts a byte array to an UNSIGNED int.
**/
private byteArrayToUInt(byteArray) {
// return java.nio.ByteBuffer.wrap(byteArray as byte[]).getInt()
def i = 0
byteArray.reverse().eachWithIndex { b, ix -> i += b * (0x100 ** ix) }
return i
}

/**
*  test()
*
*  Called from 'test' tile.
**/
private test() {
logger("test()","trace")

def cmds = []

sendCommands(cmds, 500)
}

/*****************************************************************************************************************
*  Static Matadata Functions:
*
*  These functions encapsulate metadata about the device. Mostly obtained from:
*   Z-wave Alliance Reference: http://products.z-wavealliance.org/products/1036
*****************************************************************************************************************/

/**
*  getCommandClassVersions()
*
*  Returns a map of the command class versions supported by the device. Used by parse() and zwaveEvent() to
*  extract encapsulated commands from MultiChannelCmdEncap, MultiInstanceCmdEncap, SecurityMessageEncapsulation,
*  and Crc16Encap messages.
*
*  Reference: http://products.z-wavealliance.org/products/629/classes
**/
private getCommandClassVersions() {
return [
	0x20: 1, // Basic V1
	0x22: 1, // Application Status V1 (Not advertised but still sent)
	0x25: 1, // Switch Binary V1
	0x27: 1, // Switch All V1
	0x32: 3, // Meter V3
	0x56: 1, // CRC16 Encapsulation V1
	0x70: 1, // Configuration V1
	0x71: 1, // Alarm (Notification) V1
	0x72: 2, // Manufacturer Specific V2
	0x75: 2, // Protection V2
	0x85: 2, // Association V2
	0x86: 1, // Version V1
	0x87: 1 // Indicator V1
]
}

/**
*  getParamsMd()
*
*  Returns device parameters metadata. Used by sync(), updateSyncPending(), and generatePrefsParams().
*
*  List attributes:
*   id/size/type/range/defaultValue/required/name/description/options    These directly correspond to input attributes.
*   readonly     If the parameter is readonly, then it will not be displayed by generatePrefsParams() or synced.
*   isSigned     Indicates if the raw byte value represents a signed or unsigned number.
*   fwVersion    The minimum firmware version that supports the parameter. Parameters with a higher fwVersion than the
*                device instance will not be displayed by generatePrefsParams() or synced.
**/
private getParamsMd() {
return [
	// Firmware v4.22 onwards:
	[id:  0, size: 1, type: "number", range: "1..100", defaultValue: 10, required: false, readonly: false,
	 isSigned: true, fwVersion: 4.22,
	 name: "Power Report Threshold",
	 description : "Power level change that will result in a new power report being sent.\n" +
	 "Values: 1-100 = % change from previous report"],
	[id:  1, size: 1, type: "number", range: "0..255", defaultValue: 255, required: false, readonly: false, // Real default is 2.
	 isSigned: false, fwVersion: 4.22,
	 name: "Keep-Alive Time",
	 description : "Time after which the LED indicator will flash if there has been no communication from the hub.\n" +
	 "Values: 1-255 = time in minutes"],
	[id: 2, size: 1, type: "number", defaultValue: 0, required: false, readonly: true, // READ-ONLY!
	 isSigned: false, fwVersion: 4.22,
	 name: "Wheel Status",
	 description : "Indicates the position of the Room Colour Selector wheel."],
	// Firmware v4.28 onwards:
	[id: 3, size: 1, type: "enum", defaultValue: "2", required: false, readonly: false,
	 isSigned: true, fwVersion: 4.28,
	 name: "State After Power Failure",
	 description : "Switch state to restore after a power failure. [Firmware 4.28+ Only]",
	 options: ["0" : "0: Off",
			   "1" : "1: Restore Previous State",
			   "2" : "2: On"] ],
	[id: 4, size: 1, type: "enum", defaultValue: "1", required: false, readonly: false,
	 isSigned: true, fwVersion: 4.28,
	 name: "LED for Network Error",
	 description : "LED indicates network error. [Firmware 4.28+ Only]",
	 options: ["0" : "0: DISABLED",
			   "1" : "1: ENABLED"] ]
]
}

/**
*  getAssocGroupsMd()
*
*  Returns association groups metadata. Used by sync(), updateSyncPending(), and generatePrefsAssocGroups().
*
*  List attributes:
*   id            Association group ID (groupingIdentifier).
*   maxNodes      Maximum nodes supported.
*   name          Name, shown on device settings screen and logs.
*   hubOnly       Group should only contain the SmartThings hub (not shown on settings screen).
*   multiChannel  Group supports multiChannelAssociation.
*   description   Description, shown on device settings screen.
**/
private getAssocGroupsMd() {
return [
	[id: 1, maxNodes: 1, name: "Wheel Status", hubOnly: true, multiChannel: false,
	 description : "Reports wheel status using CONFIGURATION_REPORT commands."],
	[id: 2, maxNodes: 1, name: "Relay Health", hubOnly: true, multiChannel: false,
	 description : "Sends ALARM commands when current leakage is detected."],
	[id: 3, maxNodes: 1, name: "Power Level", hubOnly: true, multiChannel: false,
	 description : "Reports instantaneous power using METER_REPORT commands (configured using parameter #0)."],
	[id: 4, maxNodes: 1, name: "Overcurrent Protection", hubOnly: true, multiChannel: false,
	 description : "Sends ALARM commands when overcurrent is detected."]
]
}

/**
*  getWheelColours()
*
*  Returns a map of wheel colours.
**/
private getWheelColours() {
return [
	0x80 : "black",
	0x81 : "green",
	0x82 : "blue",
	0x83 : "red",
	0x84 : "yellow",
	0x85 : "violet",
	0x86 : "orange",
	0x87 : "aqua",
	0x88 : "pink",
	0x89 : "white"
]
}

This is the line the error is reporting on.

private sendCommands(cmds, delay=200) {
sendHubCommand(hubitat.device.HubAction)( cmds.collect{ (it instanceof hubitat.zwave.Command ) ? response(encapCommand(it)) : response(it) }, delay)
}

If anyone could help or provide some tips, that would be great. Original documentation here

Many thanks

the sendHubCommand doesn't look correct.
Can you try replacing sendHubCommand(hubitat.device.HubAction)( cmds.collect{ (it instanceof hubitat.zwave.Command ) ? response(encapCommand(it)) : response(it) }, delay)

with: sendHubCommand( cmds.collect{ (it instanceof hubitat.zwave.Command ) ? response(encapCommand(it)) : response(it) }, delay)

Thanks for the reply Mike. I've updated and now see these errors.

I can get them to turn on/off using the Generic Z-wave Smart Switch (albeit without power measuring, I'm not too bothered about that). However, these plugs are kind of weird. If they don't receive any coms from the hub within 2 mins, they have a light which starts flashing. If I perform a Refresh manually, it stops, for another 2 mins.

So I started on a workaround for that, just sending a refresh every 90 secs as a start, but cant get that accomplished via a Piston, despite the piston firing fine.

Edit: Refresh now working as a workaround, so at least the cats can sleep without disco lights :slight_smile:

Hi! This is actually my last device zwave device on smart things.

I'm keen to get the power metering working for my use case. Just wandering if you got the device handler working. Mine is tucked away, so I don't mind the disco lights ! :slight_smile: but have they worked reliably?

I'm just trying with the generic zwave driver for now..

Cheers!

No power monitoring at all sadly. Just using as a simple on/off. The refresh works ok to kill the light but I’d rather not have to do that.

I tried the driver again but to no avail, and sadly don’t know enough to get it working :cry:

BTW they do work fine with the Generic driver (sorry hadn't answered that part). Just a shame we cant get the full functionality of them.

I hope that the support comes, because it is very important for me. My wife has agreed that she will get word when the washing machine is ready. (Fair the power consumption)

Everything needed is in the driver above. Sadly I just don’t have the knowledge to make this work in HE. We just need someone who can help alter the code.

Did you ever get these working?
I have some of these plugs I want to move over from ST as ST is too unreliable to use anymore!

Hi Phil,

They will work as a “generic z-wave switch”. I’ve still had no luck at porting the ST driver as yet. They won’t show power usage, and the light still might flash. My workaround for that is a RM rule that performs a refresh every two mins.

Cheers
Roy

Cheers Roy.

Have you had any luck with any power monitoring with another zwave switch?

Current uses I have (in ST) are:

  1. Change Location Mode based on power draw from a plug - i.e Night mode when both phones are on charge in bedroom etc....

  2. Turn off an Harmony Activity when Power drops below 0 - this one will probably be trickier I think due to lack of full Harmony integration

The only device I have that now shows power is my ST plug. :disappointed_relieved:

Which method are you using for Harmony? Pretty sure it can be achieved. I’m using this one.

I haven't yet tried Harmony, I just read up whilst waiting for my Hub that is doesnt offer full integration like ST.

The driver you shared looks like it will do some of what i want. My two uses currently for Harmony / ST are to turn on a switch when an activity has started and also to turn off the activity and the switch when power draw is zero. I use a laptop as my HTPC that is set to turn on when power is detected, and i then have it set to shut down after 30 mins of no activity and turn the switch off. This is all done using the Greenwave plugs currently (well it was until ST stopped working for me!)

I guess what I could possibly do if the driver allows me is to turn off the plug and then turn on the plug when an activity is started as by default it would most likely still be on from previously if i cannot turn it off based on power draw.

1 Like

Yeah, pretty sure you could achieve this with RM. I find the Harmony much faster than on ST, as its all local. :+1:

I'm struggling to get any of the greenwave's I have working with ST using the generic switch or smart switch drivers... Which one have you got them working with?

This is one on HE.

Cheers for the image, mine aren't playing ball. Also got a number of TKB switches that aren't pairing too.
Will keep trying :slight_smile:

So they aren't pairing at all, or just not working once paired?

I can get one of them paired but then it doesnt turn on or off...

Very odd. Sorry more questions...

Are they removed from ST, presuming ST may still be on.
Did you hit the "Configure" option after pairing?
Whats the plugs Status in the Device Information of the plug?

This is my Details in the device, just wondering if they may be different on yours, which could maybe point to a different firmware (There are around 3 FW for these from memory).