/* * Minoston MP22ZP Outdoor Plug * * Description: * This Hubitat driver is designed for use with the following device(s): * Minoston MP22ZP * * Features List: * Ability to turn on/off the switch * Ability to report the current power usage * Ability to check a website (mine) if there is a newer version of the driver available * * Licensing: * Copyright 2022 David Snell * 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. * * Version Control: * 0.1.2 - Ignore power meter data if Power Monitoring is disabled and rework of configuration * 0.1.1 - Fingerprinting for MP22ZP, added indicator status, added power metering, more commands, & more preferences * 0.1.0 - Initial attempt at driver * * Thank you(s): * I would like to thank @Cobra his contributions to the community. Parts based on Cobra's driver update code * have been included at the bottom of the driver and are noted as such. */ // Returns the driver name def DriverName(){ return "Minoston MP22ZP" } // Returns the driver version def DriverVersion(){ return "0.1.2" } metadata{ definition( name: "Minoston MP22ZP", namespace: "Snell", author: "David Snell", importUrl: "https://www.drdsnell.com/projects/hubitat/drivers/Minoston MP22ZP.groovy" ){ capability "Actuator" capability "Refresh" capability "Outlet" capability "Switch" capability "PowerMeter" capability "Sensor" capability "Polling" capability "VoltageMeasurement" capability "CurrentMeter" capability "Configuration" //capability "HealthCheck" //capability "Indicator" command "ParameterGet", [ [ name:"Parameter", type:"NUMBER", description:"Parameter Number (blank gets all)", constraints:[ "NUMBER" ] ] ] command "ParameterSet",[ [ name:"Parameter", type:"NUMBER", description:"Parameter Number", constraints:[ "NUMBER" ] ], [ name:"Size", type:"NUMBER", description:"Size", constraints:[ "NUMBER" ] ], [ name:"Value", type:"NUMBER", description:"Value", constraints:[ "NUMBER" ] ] ] command "ResetEnergyMeter" //command "DoSomething" // Attributes about the driver only attribute "Driver Name", "string" // Identifies the driver's name attribute "Driver Status", "string" // Identifies the driver's update status attribute "Driver Version", "string" // Identifies the driver's version number attribute "Configured", "string" // Have preferences been configured on the device yet // Attributes being built into the device attribute "Hardware Version", "string" attribute "Firmware Version", "string" attribute "Z-Wave Version", "string" attribute "switch", "ENUM", [ "on", "off" ] // Just reference for the switch state attribute "power", "number" attribute "Radio Power", "string" // attribute "Indicator", "ENUM", [ "on", "off" ] // Just reference for the indicator state attribute "indicatorStatus", "ENUM", [ "never", "when on", "when off", "always on", "always off" ] attribute "AutoOff", "number" attribute "AutoOn", "number" attribute "PowerReportMinutes", "number" attribute "PowerReportWattage", "number" attribute "PowerReportCurrent", "number" attribute "PowerReportKWH", "number" attribute "energy", "number" attribute "power", "number" // Reference, power in watts attribute "voltage", "number" attribute "amperage", "number" fingerprint deviceId: "65295", deviceType: "65280", inClusters: "0x5E,0x55,0x9F,0x6C", outClusters: "", manufacturer: "786", model: "MP22ZP", deviceJoinName: "Minoston MP22ZP" } preferences{ section{ if( ShowAllPreferences || ShowAllPreferences == null ){ // Show the preferences options input( type: "enum", name: "LogType", title: "Enable Logging?", required: true, multiple: false, options: [ "None", "Info", "Debug", "Trace" ], defaultValue: "Info" ) input( type: "enum", name: "IndicatorSetting", title: "Indicator Setting", required: false, multiple: false, options: [ "Always On", "Always Off", "When On", "When Off" ], defaultValue: "When On" ) input( type: "enum", name: "RestoreSetting", title: "Restore After Power Failure", required: false, multiple: false, options: [ "Last setting", "Off", "On" ], defaultValue: "Last setting" ) //input( type: "enum", name: "AutoOff", title: "Automatically Turn Off After X Minutes?", required: false, multiple: false, options: [ "0", "15", "60", "120", "240", "480", "1440" ], defaultValue: "0" ) //input( type: "enum", name: "AutoOn", title: "Automatically Turn On After X Minutes?", required: false, multiple: false, options: [ "0", "15", "60", "120", "240", "480", "1440" ], defaultValue: "0" ) input( type: "bool", name: "PowerMonitoring", title: "Enable Power Monitoring?", defaultValue: false ) if( PowerMonitoring || PowerMonitoring == null ){ // Show the power-related preferences input( type: "enum", name: "PowerReportMinutes", title: "Report Power Every X Minutes", required: false, multiple: false, options: [ "1", "5", "10", "15", "30", "60", "240", "480", "1440" ], defaultValue: "5" ) input( type: "enum", name: "PowerReportWattage", title: "Report Power Every X Watts", required: false, multiple: false, options: [ "5", "10", "15", "20", "25", "30", "35", "40", "45", "50" ], defaultValue: "5" ) input( type: "enum", name: "PowerReportCurrent", title: "Minimum Current Change to Report (Amps)", required: false, multiple: false, options: [ "0.1", "0.2", "0.3", "1" ], defaultValue: "0.1" ) input( type: "enum", name: "PowerReportKWH", title: "Minimum kWh Change to Report", required: false, multiple: false, options: [ "0.01", "0.02", "0.03", "1" ], defaultValue: "0.01" ) } input( type: "bool", name: "ShowAllPreferences", title: "Show All Preferences?", defaultValue: true ) } else { input( type: "bool", name: "ShowAllPreferences", title: "Show All Preferences?", defaultValue: true ) } } } } // Testing function, should be disabled prior to publishing def DoSomething(){ ZWaveCommands([ hubitat.zwave.notificationV8.notificationGet() ] ) } // Sets some basic values of the driver def updated(){ // Clear State Variables state.clear() // Set the basic driver info known at this moment ProcessEvent( "Driver Name", DriverName() ) ProcessEvent( "Driver Version", DriverVersion() ) // Schedule the daily driver version check schedule( new Date(), CheckForUpdate ) Logging( "Updated", 2 ) ProcessState( "Configured", "false" ) configure() } // Used by switches and outlets for on def on() { ZWaveCommands([ zwave.basicV1.basicSet( value: 0xFF ), //zwave.switchBinaryV1.switchBinaryGet(), //zwave.basicV1.basicGet() ]) } // Used by switches and outlets for off def off() { ZWaveCommands([ zwave.basicV1.basicSet( value: 0x00 ), //zwave.switchBinaryV1.switchBinaryGet(), //zwave.basicV1.basicGet() ]) } // ping just calls for a refresh to be performed def ping(){ refresh() } // poll just calls for a refresh to be performed def poll(){ refresh() } // Refreshes the device information by clearing states and tamper def refresh(){ if( PowerMonitoring == true ){ ZWaveCommands( [ zwave.switchBinaryV1.switchBinaryGet(), zwave.basicV1.basicGet(), zwave.powerlevelV1.powerlevelGet(), zwave.powerlevelV1.powerlevelTestNodeGet(), zwave.meterV5.meterGet(scale: 0), // kWh zwave.meterV5.meterGet(scale: 2), // Watts zwave.meterV5.meterGet(scale: 4), // Voltage zwave.meterV5.meterGet(scale: 5), // Current zwave.indicatorV3.indicatorGet() ] ) } else { ZWaveCommands( [ zwave.switchBinaryV1.switchBinaryGet(), zwave.basicV1.basicGet(), zwave.powerlevelV1.powerlevelGet() ] ) } } // Reset the energy meter def ResetEnergyMeter(){ ZWaveCommands( [ zwave.meterV5.meterReset() ] ) } def getCommandClassVersions(){ [ 0x10: 1, // Generic - Binary Switch 0x5E: 2, // Z-Wave Plus Info 0x25: 2, // Binary Switch 0x70: 4, // Configuration 0x85: 3, // Association 0x8E: 4, // Multi-channel Association 0x59: 3, // Association Group 0x71: 8, // Notification 0x32: 5, // Meter 0x55: 2, // Transport Service 0x86: 2, // Version 0x72: 2, // Manufacturer Specific 0x5A: 1, // Device Reset Locally 0x87: 3, // Indicator 0x73: 1, // Power Level 0x9F: 1, // Security 2 0x6C: 1, // Supervision 0x7A: 5, // Firmware Update 0x20: 1, // Basic ] } // parse handles splitting up the z-wave reports and making sure the commands are handled def parse( String description ){ def Split = description.split() def CommandClass = Split[ 4 ].take( 2 ) def Data = zwave.parse( description, commandClassVersions ) if( description.startsWith( "Err" ) ){ Logging( "Parse Error: ${ description }", 3 ) } else { zwaveEvent( Data ) //ClassRouting( CommandClass, Data ) } } def ClassRouting( CommandClass, Data ){ switch( CommandClass ){ case "20": // Basic HandleBasic( Data ) break case "73": // COMMAND_CLASS_POWERLEVEL HandlePowerLevel( Data ) break case "25": // COMMAND_CLASS_SWITCH_BINARY_V2 HandleSwitch( Data ) break case "70": // CONFIGURATION_V4 HandleConfiguration( Data ) break case "84": // WakeUp HandleWakeUp( Data ) break case "86": // COMMAND_CLASS_VERSION_V2 HandleVersion( Data ) break case "87": // COMMAND_CLASS_INDICATOR_V3 HandleIndicator( Data ) break case "32": // COMMAND_CLASS_METER_V5 HandleMeter( Data ) break case "72": // COMMAND_CLASS_MANUFACTURER_SPECIFIC_V2 HandleManufacturerSpecific( Data ) break case "5E": // COMMAND_CLASS_ZWAVEPLUS_INFO_V2 HandleZWavePlusInfo( Data ) break case "6C": // COMMAND_CLASS_SUPERVISION HandleSupervision( Data ) break // Class(es) that will likely not have anything done unless something useful crops up case "10": // GENERIC_TYPE GENERIC_TYPE_SWITCH_BINARY case "85": // COMMAND_CLASS_ASSOCIATION_V3 case "8E": // COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION_V4 case "59": // COMMAND_CLASS_ASSOCIATION_GRP_INFO_V3 case "71": // COMMAND_CLASS_NOTIFICATION_V8 case "55": // COMMAND_CLASS_TRANSPORT_SERVICE_V2 case "5A": // COMMAND_CLASS_DEVICE_RESET_LOCALLY case "9F": // COMMAND_CLASS_SECURITY_2 case "7A": // COMMAND_CLASS_FIRMWARE_UPDATE_MD_V5 Logging( "Checking Z-Wave Data: ${ Data }", 4 ) break // Not doing anything with these class(es) // Unknown/unexpected clases, pop info in debug to determine how they should be handled default: Logging( "Unknown Z-Wave Data for ${ CommandClass }: ${ Data }", 4 ) break } } def zwaveEvent( hubitat.zwave.Command Data ){ Logging( "Unknown Z-Wave Data: ${ Data }", 4 ) } // Handle basic events from Z-Wave //def HandleBasic( Data ){ def zwaveEvent( hubitat.zwave.commands.basicv1.BasicReport Data ){ Logging( "Basic Data: ${ Data }", 4 ) if( Data.value == 0 ){ ProcessEvent( "switch", "off", null, true ) Logging( "switch: off", 1 ) } else if( Data.value == 255 ){ ProcessEvent( "switch", "on", null, true ) Logging( "switch: on", 1 ) } } // Handle switch events from Z-Wave //def HandleSwitch( Data ){ def zwaveEvent( hubitat.zwave.commands.switchbinaryv1.SwitchBinaryReport Data ){ Logging( "Switch Data: ${ Data }", 4 ) if( Data.value == 0 ){ ProcessEvent( "switch", "off", null, true ) Logging( "switch: off", 1 ) } else if( Data.value == 255 ){ ProcessEvent( "switch", "on", null, true ) Logging( "switch: on", 1 ) } } def zwaveEvent( hubitat.zwave.commands.switchmultilevelv3.SwitchMultilevelReport Data ){ Logging( "Switch Data: ${ Data }", 4 ) if( Data.value == 0 ){ ProcessEvent( "switch", "off", null, true ) Logging( "switch: off", 1 ) } else if( Data.value == 255 ){ ProcessEvent( "switch", "on", null, true ) Logging( "switch: on", 1 ) } } // Handle radio power level events from Z-Wave def HandlePowerLevel( Data ){ //def zwaveEvent( hubitat.zwave.commands.powerlevelV1.powerLevelReport Data ){ Logging( "Radio Power Data: ${ Data }", 4 ) if( Data.powerLevel == 0 ){ ProcessEvent( "Radio Power", "Normal" ) } else if( Data.powerLevel == 255 ){ ProcessEvent( "Radio Power", "-${ TypeInt } dB" ) } } // Handle configuration events from Z-Wave //def HandleConfiguration( Data ){ def zwaveEvent( hubitat.zwave.commands.configurationv4.ConfigurationReport Data ){ Logging( "Configuration Data: ${ Data }", 4 ) if( Data.parameterNumber != null ){ switch( Data.parameterNumber ){ case "1": // Indicator switch( Data.scaledConfigurationValue ){ case "0": ProcessEvent( "indicatorStatus", "when on" ) break case "1": ProcessEvent( "indicatorStatus", "when off" ) break case "2": ProcessEvent( "indicatorStatus", "always off" ) break case "3": ProcessEvent( "indicatorStatus", "always on" ) break } break case "2": // Auto Off ProcessEvent( "AutoOff", Data.scaledConfigurationValue as int ) break case "3": // Auto On ProcessEvent( "AutoOn", Data.scaledConfigurationValue as int ) break case "4": // Restore after Power Failure switch( Data.scaledConfigurationValue ){ case "0": ProcessEvent( "indicatorStatus", "when on" ) break case "1": ProcessEvent( "indicatorStatus", "when off" ) break case "2": ProcessEvent( "indicatorStatus", "always off" ) break } break case "5": // Power Report Wattage ProcessEvent( "PowerReportWattage", Data.scaledConfigurationValue as int ) break case "6": // Power Report Minutes ProcessEvent( "PowerReportMinutes", Data.scaledConfigurationValue as int ) break case "7": // Power Report Current switch( Data.scaledConfigurationValue ){ case "1": ProcessEvent( "PowerReportCurrent", "0.1" ) break case "2": ProcessEvent( "PowerReportCurrent", "0.2" ) break case "3": ProcessEvent( "PowerReportCurrent", "0.3" ) break case "10": ProcessEvent( "PowerReportCurrent", "1" ) break } break case "8": // Power Report KWH switch( Data.scaledConfigurationValue ){ case "1": ProcessEvent( "PowerReportKWH", "0.01" ) break case "2": ProcessEvent( "PowerReportKWH", "0.02" ) break case "3": ProcessEvent( "PowerReportKWH", "0.03" ) break case "100": ProcessEvent( "PowerReportKWH", "1" ) break } break } } } // Handle version events from Z-Wave // Sample = VersionReport(zWaveLibraryType:3, zWaveProtocolVersion:7, zWaveProtocolSubVersion:13, firmware0Version:1, firmware0SubVersion:0, hardwareVersion:1, firmwareTargets:0, targetVersions:[]) def HandleVersion( Data ){ Logging( "Version Data: ${ Data }", 4 ) ProcessEvent( "Hardware Version", "${ Data.hardwareVersion }" ) ProcessEvent( "Firmware Version", "${ Data.firmware0Version }.${ Data.firmware0SubVersion }" ) ProcessEvent( "Z-Wave Version", "${ Data.zWaveProtocolVersion }.${ Data.zWaveProtocolSubVersion }" ) } // Handle manufacturer specific events from Z-Wave // Sample = ManufacturerSpecificReport(manufacturerId:786, productId:65295, productTypeId:65280) def HandleManufacturerSpecific( Data ){ Logging( "ManufacturerSpecific Data: ${ Data }", 4 ) } // Handle ZWave Plus Info events from Z-Wave // Sample = def HandleZWavePlusInfo( Data ){ Logging( "ZWavePlusInfo Data: ${ Data }", 4 ) } // Handle Supervision class events // Sample = void zwaveEvent( hubitat.zwave.commands.supervisionv1.SupervisionGet Data ){ hubitat.zwave.Command encapCmd = Data.encapsulatedCommand( commandClassVersions ) if( encapCmd ){ zwaveEvent( encapCmd ) } sendHubCommand( new hubitat.device.HubAction( zwaveSecureEncap( zwave.supervisionV1.supervisionReport( sessionID: Data.sessionID, reserved: 0, moreStatusUpdates: false, status: 0xFF, duration: 0 ).format() ), hubitat.device.Protocol.ZWAVE ) ) } // Handle indicator events from Z-Wave def HandleIndicator( Data ){ Logging( "Indicator Data: ${ Data }", 4 ) if( Data.value == 0 ){ //ProcessEvent( "Indicator", "off" ) } else if( Data.value == 1 ){ //ProcessEvent( "Indicator", "on" ) } } // Handle meter events from Z-Wave //def HandleMeter( Data ){ def zwaveEvent( hubitat.zwave.commands.meterv1.MeterReport Data ){ if( PowerMonitoring == true ){ Logging( "Meter Data: ${ Data }", 4 ) if( Data.meterType == 1 ){ if( Data.scale == 0 ){ def Energy = ( HexToInt( Data.meterValue, 4 ) / 100 ) as float ProcessEvent( "energy", Energy, "kWh", false ) } else if( Data.scale == 1 ){ ProcessEvent( "energy", Data.meterValue, "kVAh", false ) as float } else if( Data.scale == 2 ){ def Watts = ( HexToInt( Data.meterValue, 2 ) / 10 ) as float ProcessEvent( "power", Watts, "W", false ) } else if( Data.scale == 4 ){ def Volts = ( HexToInt( Data.meterValue, 2 ) / 100 ) as float ProcessEvent( "voltage", Volts, "V", false ) } else if( Data.scale == 5 ){ def Amps = ( HexToInt( Data.meterValue, 2 ) / 100 ) as float ProcessEvent( "amperage", Amps, "Amps", false ) } } } } def zwaveEvent( hubitat.zwave.commands.meterv3.MeterReport Data ){ if( PowerMonitoring == true ){ Logging( "Meter Data: ${ Data }", 4 ) if( Data.meterType == 1 ){ if( Data.scale == 0 ){ def Energy = ( HexToInt( Data.meterValue, 4 ) / 100 ) as float ProcessEvent( "energy", Energy, "kWh", false ) } else if( Data.scale == 1 ){ ProcessEvent( "energy", Data.meterValue, "kVAh", false ) as float } else if( Data.scale == 2 ){ def Watts = ( HexToInt( Data.meterValue, 2 ) / 10 ) as float ProcessEvent( "power", Watts, "W", false ) } else if( Data.scale == 4 ){ def Volts = ( HexToInt( Data.meterValue, 2 ) / 100 ) as float ProcessEvent( "voltage", Volts, "V", false ) } else if( Data.scale == 5 ){ def Amps = ( HexToInt( Data.meterValue, 2 ) / 100 ) as float ProcessEvent( "amperage", Amps, "Amps", false ) } } } } // Handle the Wake Up events from Z-Wave //def HandleWakeUp( Data ){ def zwaveEvent( hubitat.zwave.commands.wakeupv2.WakeUpNotification Data ){ Logging( "WakeUp Data: ${ Data }", 4 ) } // Set a parameter, based on Hubitat examples List ParameterSet( Parameter, Size, Value ){ if( Parameter == null ){ Logging( "Missing required setting: Parameter", 5 ) } else if( Size == null ){ Logging( "Missing required setting: Size", 5 ) } else if( Value == null ){ Logging( "Missing required setting: Value", 5 ) } else { Logging( "Setting Parameter ${ Parameter } to ${ Value }", 4 ) ZWaveCommands( [ zwave.configurationV4.configurationSet( scaledConfigurationValue: Value, parameterNumber: Parameter, size: Size ), zwave.configurationV4.configurationGet( parameterNumber: Parameter ) ] ) } } // Get information on a parameter, based on Hubitat examples List ParameterGet( Parameter ){ if( Parameter != null ){ Logging( "Getting Parameter ${ Parameter }", 4 ) ZWaveCommands( [ zwave.configurationV4.configurationGet( parameterNumber: Parameter ) ] ) } } // Handle Z-Wave commands to send private ZWaveCommand( hubitat.zwave.Command Command ){ /* if( getDataValue( "zwaveSecurePairingComplete" ) == "true" && getDataValue( "S2" ) == null ){ zwave.securityV1.securityMessageEncapsulation().encapsulate( Command ).format() } else { Command.format() } */ if( getDataValue( "zwaveSecurePairingComplete" ) == "true" && getDataValue( "S2" ) != null ){ //zwave.securityV1.securityMessageEncapsulation().encapsulate( Command ).format() zwaveSecureEncap( Command ) } else { Command.format() } } // Put multiple Z-Wave commands together with a delay between them private ZWaveCommands( Commands, Delay = 500 ){ Logging( "Processing ZWave Commands: ${ Commands }", 4 ) delayBetween( Commands.collect{ ZWaveCommand( it ) }, Delay ) } private HexToInt( Hex, Size ){ switch( Size ){ case "4": return ( ( Hex[ 0 ] * 0x1000000 ) + ( Hex[ 1 ] * 0x10000 ) + ( Hex[ 2 ] * 0x100 ) + Hex[ 3 ] ) break case "3": return ( ( Hex[ 0 ] * 0x10000 ) + ( Hex[ 1 ] * 0x100 ) + Hex[ 2 ] ) break case "2": return ( ( Hex[ 0 ] * 0x100 ) + Hex[ 1 ] ) break case "1": return Hex[ 0 ] break } } // Configures the device, typically at install or when preferences are saved def configure(){ Logging( "Configuring device...", 2 ) // Set various parameters based on preferences def Indicator = 0 switch( IndicatorSetting ){ case "When Off": Indicator = 1 break case "Always Off": Indicator = 2 break case "Always On": Indicator = 3 break case "When On": // default setting default: Indicator = 0 break } def Restore = 0 switch( RestoreSetting ){ case "Off": Restore = 1 break case "On": Restore = 2 break case "Last setting": // default setting default: Restore = 0 break } def Commands = [] ZWaveCommands( [ zwave.zwaveplusInfoV2.zwaveplusInfoGet(), zwave.versionV2.versionGet(), zwave.manufacturerSpecificV2.manufacturerSpecificGet() ], 1000 ) if( PowerMonitoring == true ){ Logging( "Configuring with Power Monitoring", 4 ) ParameterSet( 1, 1, Indicator ) ParameterSet( 2, 4, AutoOff as int ) ParameterSet( 3, 4, AutoOn as int ) ParameterSet( 4, 4, Restore ) ParameterSet( 5, 1, PowerReportWattage as int ) ParameterSet( 6, 4, PowerReportMinutes as int ) ParameterSet( 7, 1, ( ( PowerReportCurrent as float ) * 10 ) as int ) ParameterSet( 8, 1, ( ( PowerReportKWH as float ) * 100 ) as int ) /* ZWaveCommands( [ zwave.configurationV4.configurationSet( scaledConfigurationValue: Indicator, parameterNumber: 1, size: 1 ), zwave.configurationV4.configurationGet( parameterNumber: 1 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: AutoOff as int, parameterNumber: 2, size: 4 ), zwave.configurationV4.configurationGet( parameterNumber: 2 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: AutoOn as int, parameterNumber: 3, size: 4 ), zwave.configurationV4.configurationGet( parameterNumber: 3 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: Restore, parameterNumber: 4, size: 4 ), zwave.configurationV4.configurationGet( parameterNumber: 4 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: PowerReportWattage as int, parameterNumber: 5, size: 1 ), zwave.configurationV4.configurationGet( parameterNumber: 5 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: PowerReportMinutes as int, parameterNumber: 6, size: 4 ), zwave.configurationV4.configurationGet( parameterNumber: 6 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: ( ( PowerReportCurrent as float ) * 10 ) as int, parameterNumber: 7, size: 1 ), zwave.configurationV4.configurationGet( parameterNumber: 7 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: ( ( PowerReportKWH as float ) * 100 ) as int, parameterNumber: 8, size: 1 ), zwave.configurationV4.configurationGet( parameterNumber: 8 ) ], 1000 ) */ } else { Logging( "Configuring without Power Monitoring", 4 ) ParameterSet( 1, 1, Indicator ) ParameterSet( 2, 4, AutoOff as int ) ParameterSet( 3, 4, AutoOn as int ) ParameterSet( 4, 4, Restore ) /* ZWaveCommands( [ zwave.configurationV4.configurationSet( scaledConfigurationValue: Indicator, parameterNumber: 1, size: 1 ), zwave.configurationV4.configurationGet( parameterNumber: 1 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: AutoOff as int, parameterNumber: 2, size: 4 ), zwave.configurationV4.configurationGet( parameterNumber: 2 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: AutoOn as int , parameterNumber: 3, size: 4 ), zwave.configurationV4.configurationGet( parameterNumber: 3 ), zwave.configurationV4.configurationSet( scaledConfigurationValue: Restore, parameterNumber: 4, size: 4 ), zwave.configurationV4.configurationGet( parameterNumber: 4 ) ], 1000 ) */ } ProcessState( "Configured", "true" ) } // installed is called when the device is installed, all it really does is run updated def installed(){ Logging( "Installed", 2 ) updated() } // initialize is called when the device is initialized, all it really does is run updated def initialize(){ Logging( "Initialized", 2 ) updated() } // Process data to check against current state value and then send an event if it has changed def ProcessEvent( Variable, Value, Unit = null, ForceEvent = false ){ if( ( state."${ Variable }" != Value ) || ( ForceEvent == true ) ){ state."${ Variable }" = Value if( Unit != null ){ Logging( "Event: ${ Variable } = ${ Value }${ Unit }", 4 ) sendEvent( name: "${ Variable }", value: Value, unit: Unit, isStateChanged: true ) } else { Logging( "Event: ${ Variable } = ${ Value }", 4 ) sendEvent( name: "${ Variable }", value: Value, isStateChanged: true ) } } } // Process data to check against current state value and then send an event if it has changed def ProcessState( Variable, Value ){ if( state."${ Variable }" != Value ){ Logging( "State: ${ Variable } = ${ Value }", 4 ) state."${ Variable }" = Value } } // Handles whether logging is enabled and thus what to put there. def Logging( LogMessage, LogLevel ){ // Add all messages as info logging if( ( LogLevel == 2 ) && ( LogType != "None" ) ){ log.info( "${ device.displayName } - ${ LogMessage }" ) } else if( ( LogLevel == 3 ) && ( ( LogType == "Debug" ) || ( LogType == "Trace" ) ) ){ log.debug( "${ device.displayName } - ${ LogMessage }" ) } else if( ( LogLevel == 4 ) && ( LogType == "Trace" ) ){ log.trace( "${ device.displayName } - ${ LogMessage }" ) } else if( LogLevel == 5 ){ log.error( "${ device.displayName } - ${ LogMessage }" ) } } // Checks drdsnell.com for the latest version of the driver // Original inspiration from @cobra's version checking def CheckForUpdate(){ ProcessEvent( "Driver Name", DriverName() ) ProcessEvent( "Driver Version", DriverVersion() ) httpGet( uri: "https://www.drdsnell.com/projects/hubitat/drivers/versions.json", contentType: "application/json" ){ resp -> switch( resp.status ){ case 200: if( resp.data."${ DriverName() }" ){ CurrentVersion = DriverVersion().split( /\./ ) if( resp.data."${ DriverName() }".version == "REPLACED" ){ ProcessEvent( "Driver Status", "Driver replaced, please use ${ resp.data."${ state.'Driver Name' }".file }" ) } else if( resp.data."${ DriverName() }".version == "REMOVED" ){ ProcessEvent( "Driver Status", "Driver removed and no longer supported." ) } else { SiteVersion = resp.data."${ DriverName() }".version.split( /\./ ) if( CurrentVersion == SiteVersion ){ Logging( "Driver version up to date", 3 ) ProcessEvent( "Driver Status", "Up to date" ) } else if( ( CurrentVersion[ 0 ] as int ) > ( SiteVersion [ 0 ] as int ) ){ Logging( "Major development ${ CurrentVersion[ 0 ] }.${ CurrentVersion[ 1 ] }.${ CurrentVersion[ 2 ] } version", 3 ) ProcessEvent( "Driver Status", "Major development ${ CurrentVersion[ 0 ] }.${ CurrentVersion[ 1 ] }.${ CurrentVersion[ 2 ] } version" ) } else if( ( CurrentVersion[ 1 ] as int ) > ( SiteVersion [ 1 ] as int ) ){ Logging( "Minor development ${ CurrentVersion[ 0 ] }.${ CurrentVersion[ 1 ] }.${ CurrentVersion[ 2 ] } version", 3 ) ProcessEvent( "Driver Status", "Minor development ${ CurrentVersion[ 0 ] }.${ CurrentVersion[ 1 ] }.${ CurrentVersion[ 2 ] } version" ) } else if( ( CurrentVersion[ 2 ] as int ) > ( SiteVersion [ 2 ] as int ) ){ Logging( "Patch development ${ CurrentVersion[ 0 ] }.${ CurrentVersion[ 1 ] }.${ CurrentVersion[ 2 ] } version", 3 ) ProcessEvent( "Driver Status", "Patch development ${ CurrentVersion[ 0 ] }.${ CurrentVersion[ 1 ] }.${ CurrentVersion[ 2 ] } version" ) } else if( ( SiteVersion[ 0 ] as int ) > ( CurrentVersion[ 0 ] as int ) ){ Logging( "New major release ${ SiteVersion[ 0 ] }.${ SiteVersion[ 1 ] }.${ SiteVersion[ 2 ] } available", 2 ) ProcessEvent( "Driver Status", "New major release ${ SiteVersion[ 0 ] }.${ SiteVersion[ 1 ] }.${ SiteVersion[ 2 ] } available" ) } else if( ( SiteVersion[ 1 ] as int ) > ( CurrentVersion[ 1 ] as int ) ){ Logging( "New minor release ${ SiteVersion[ 0 ] }.${ SiteVersion[ 1 ] }.${ SiteVersion[ 2 ] } available", 2 ) ProcessEvent( "Driver Status", "New minor release ${ SiteVersion[ 0 ] }.${ SiteVersion[ 1 ] }.${ SiteVersion[ 2 ] } available" ) } else if( ( SiteVersion[ 2 ] as int ) > ( CurrentVersion[ 2 ] as int ) ){ Logging( "New patch ${ SiteVersion[ 0 ] }.${ SiteVersion[ 1 ] }.${ SiteVersion[ 2 ] } available", 2 ) ProcessEvent( "Driver Status", "New patch ${ SiteVersion[ 0 ] }.${ SiteVersion[ 1 ] }.${ SiteVersion[ 2 ] } available" ) } } } else { Logging( "${ DriverName() } is not published on drdsnell.com", 2 ) ProcessEvent( "Driver Status", "${ DriverName() } is not published on drdsnell.com" ) } break default: Logging( "Unable to check drdsnell.com for ${ DriverName() } driver updates.", 2 ) break } } }