[DEPRECATED THREAD: visit community.webcore.co for assistance] WebCoRE - Example Pistons

Anyone else unable to delete a category, or is it just me? The X is clickable, it just doesn’t do anything.

Deleting categories not yet implemented

Oh the OCD… :stuck_out_tongue:

In case anyone was interested, I have updated my welcome home piston (also edited the main post at the start ignoring his thread) that triggers a greeting to be played out of a Sonos speaker depending on who has come home:

3 Likes

Another example. Chance of rain report spoken from a connected speaker (in my case a Sonos player) and using the Nest weather device:

My SHM Manager piston. Designed to run when me or the wife come home individually or together and disarm SHM and put in the right mode depending on the time. And to also turn off all lights and Automation switches. And enable when someone gets home:

Have you listened to this speak your text? Or read it out loud?

How are you doing the door icon? It seems to be a character in an unknown font… I’m programming smoke and motion detectors and I’d like to change the icon.

Here’s My 1st contribution. If you have a Harmony Hub and a Sonos speaker, this will reset the volume level back to 35%. I find that useful so that if you turned off the TV after watching a loud movie, or listening to music at a loud volume, you or your family wont be surprised by a loud speaker later. The 60 second pause is just to keep it from reseting if you accidentally turned off an activity.

You are on a roll… :wink:

Is there a way to use stacked Font Awesome icons? I tried messing around with it but wasn’t able to make anything work.

Examples: Font Awesome

1 Like

I know it’s apart of FA but I haven’t been able to get them to stack in tests.

1 Like

No luck here either when I tried before… I got some wierd combos :smiley:

I don’t even know where to begin. I want to make a piston that turns a couple lights on each night and then off but vary the time by a few minutes. Basically vacation lighting. The on and off at a set time is easy, but the varying the time stumps me.

Here is one that I use.
There are some virtual switchs that I use for testing and other things that can be left out.
You can leave the set piston state out as well.

I know what you’re saying.
This simulates my wife going to the en suite 50 times a night. :wink:
This one doesn’t.

2 Likes

This is an autolock for any of my three zwave locks. This changes the TCP to cancel on piston only. This seems to work for the scenario where one lock unlocks, another lock unlocks, the original lock locks and then unlocks again, all within the lock timer (three minutes in my example). I noticed my piston was getting cancelled if multiple locks opened, and I assumed there could be a situation where if you locked the lock and unlocked it again the original 3 minute timer would lock it early. The async if/while and cancel on piston only seem to account for this.

This piston was created with the help of @bangali who set up the Piston State messages and provides an example of a complex piston state setup. The concept of the piston is to turn devices (in my case, a wall heater and a water heater) on a specified time before the time for which your Wake-Up alarm is set. If the device is not turned on by the piston, the reason why the device was not turned on (i.e. the condition which had not been met), is displayed in the webCore Dashboard. A few examples of the piston state in the Dashboard:

The piston (Important: For the piston state to be set correctly, Condition traversal optimization has to be turned off. (In Edit mode, click on Settings > Gear Icon > Look for CTO and turn it off):

The Alarm (Piston) is Turned On or Off and the Wake-up time of the piston is set with this device handler, which is an adaptation of a DTH was originally created by @Arnqvist:

/**
 * This is copied directly from the Z-wave switch with power metering from SmartThings, i added a Image Capture
 * capability just to be able to send a string to webcore, the string is the departure time which represent
 * when you are leaving your home so the switch turns on a couple of hours before if you have plugged in
 * your engine heater cable. All rules are set in webcore though. This just provides an easy way of setting
 * a departure time.
 */
metadata {
	definition (name: "Z-Wave Metering Switch With Timer", namespace: "arnqvist", author: "Petter Arnqvist Eriksson", ocfDeviceType: "oic.d.switch") {
		capability "Energy Meter"
		capability "Actuator"
		capability "Switch"
		capability "Power Meter"
		capability "Polling"
		capability "Refresh"
		capability "Configuration"
		capability "Sensor"
		capability "Light"
		capability "Health Check"
        capability "Image Capture"
       
        attribute "departure", "string"

		command "reset"

		fingerprint inClusters: "0x25,0x32"
		fingerprint mfr:"0086", prod:"0003", model:"0012", deviceJoinName: "Aeon Labs Micro Smart Switch"
	}
    
    preferences {
    input name: "timer", type: "time", title: "Tid för avresa:", description: "Ange tid", required: false
	}

	// simulator metadata
	simulator {
		status "on":  "command: 2003, payload: FF"
		status "off": "command: 2003, payload: 00"

		for (int i = 0; i <= 10000; i += 1000) {
			status "power  ${i} W": new physicalgraph.zwave.Zwave().meterV1.meterReport(
				scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
		}
		for (int i = 0; i <= 100; i += 10) {
			status "energy  ${i} kWh": new physicalgraph.zwave.Zwave().meterV1.meterReport(
				scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
		}

		// reply messages
		reply "2001FF,delay 100,2502": "command: 2503, payload: FF"
		reply "200100,delay 100,2502": "command: 2503, payload: 00"

	}

	// tile definitions
	tiles {
		standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true, decoration: "flat") {
			state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
			state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
		}
		valueTile("power", "device.power") {
			state "default", label:'${currentValue} W'
		}
		valueTile("energy", "device.energy") {
			state "default", label:'${currentValue} kWh'
		}
        valueTile("departure", "device.departure") {
			state "default", label:'Avresa: ${currentValue}'
		}
		standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat") {
			state "default", label:'reset kWh', action:"reset"
		}
		standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}

		main(["switch","power","energy","departure"])
		details(["switch","power","energy","departure","refresh","reset"])
	}
}

def installed() {
	// Device-Watch simply pings if no device events received for 32min(checkInterval)
	sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
}

def updated() {
	// Device-Watch simply pings if no device events received for 32min(checkInterval)
	sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
	try {
		if (!state.MSR) {
			response(zwave.manufacturerSpecificV2.manufacturerSpecificGet().format())
		}
	} catch (e) { log.debug e }
    
       def time = timer.substring(11,16)
        def tz = location.timeZone
		def schedTime = timeToday(timer, tz)
		//*def time = schedTime.format("H",tz)
		//def min = schedTime.format("m",tz
       // def time = schedTime.format('yyyy-MM-dd HH:mm:ss', tz).toString()

    if(timer) {
    		log.debug "Departure time set to: $timer"
    		sendEvent("name":"image", "value":timer)
            sendEvent("name":"departure", "value":time)
    } else {
    		log.debug "No departure time is set"
    		}
}

def getCommandClassVersions() {
	[
		0x20: 1,  // Basic
		0x32: 1,  // SwitchMultilevel
		0x56: 1,  // Crc16Encap
		0x72: 2,  // ManufacturerSpecific
	]
}

def parse(String description) {
	def result = null
	if(description == "updated") return
	def cmd = zwave.parse(description, commandClassVersions)
	if (cmd) {
		result = zwaveEvent(cmd)
	}
	return result
}

def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
	if (cmd.scale == 0) {
		createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kWh")
	} else if (cmd.scale == 1) {
		createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kVAh")
	} else if (cmd.scale == 2) {
		createEvent(name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W")
	}
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
	def evt = createEvent(name: "switch", value: cmd.value ? "on" : "off", type: "physical")
	if (evt.isStateChange) {
		[evt, response(["delay 3000", zwave.meterV2.meterGet(scale: 2).format()])]
	} else {
		evt
	}
}

def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
	createEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital")
}

def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
	def result = []

	def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
	log.debug "msr: $msr"
	updateDataValue("MSR", msr)

	// retypeBasedOnMSR()

	result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)

	if (msr.startsWith("0086") && !state.aeonconfig) {  // Aeon Labs meter
		state.aeonconfig = 1
		result << response(delayBetween([
			zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 4).format(),   // report power in watts
			zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 300).format(), // every 5 min
			zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 8).format(),   // report energy in kWh
			zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 300).format(), // every 5 min
			zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0).format(),    // no third report
			//zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 300).format(), // every 5 min
			zwave.meterV2.meterGet(scale: 0).format(),
			zwave.meterV2.meterGet(scale: 2).format(),
		]))
	} else {
		result << response(delayBetween([
			zwave.meterV2.meterGet(scale: 0).format(),
			zwave.meterV2.meterGet(scale: 2).format(),
		]))
	}

	result
}

def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) {
	def versions = commandClassVersions
	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)
	if (encapsulatedCommand) {
		zwaveEvent(encapsulatedCommand)
	}
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
	log.debug "$device.displayName: Unhandled: $cmd"
	[:]
}

def on() {
	[
		zwave.basicV1.basicSet(value: 0xFF).format(),
		zwave.switchBinaryV1.switchBinaryGet().format(),
		"delay 3000",
		zwave.meterV2.meterGet(scale: 2).format()
	]
}

def off() {
	[
		zwave.basicV1.basicSet(value: 0x00).format(),
		zwave.switchBinaryV1.switchBinaryGet().format(),
		"delay 3000",
		zwave.meterV2.meterGet(scale: 2).format()
	]
}

def poll() {
	delayBetween([
		zwave.switchBinaryV1.switchBinaryGet().format(),
		zwave.meterV2.meterGet(scale: 0).format(),
		zwave.meterV2.meterGet(scale: 2).format()
	])
}

/**
 * PING is used by Device-Watch in attempt to reach the Device
 * */
def ping() {
	log.debug "ping() called"
	refresh()
}

def refresh() {
	delayBetween([
		zwave.switchBinaryV1.switchBinaryGet().format(),
		zwave.meterV2.meterGet(scale: 0).format(),
		zwave.meterV2.meterGet(scale: 2).format()
	])
    
}

def configure() {
	zwave.manufacturerSpecificV2.manufacturerSpecificGet().format()
}

def reset() {
	return [
		zwave.meterV2.meterReset().format(),
		zwave.meterV2.meterGet(scale: 0).format()
	]
} 

I use the above piston in conjunction with this one. This one handles stuff like turning the bedroom lights and TV on in the morning. It also warns you if the Wake-Up alarm is turned off.

Both pistons are controlled by the same DTH provided above:

2 Likes

My first contribution to this thread.

Here’s a piston that will display tiles for two Nest thermostats as well as a piston state.

The tiles will show blue when cooling, orange when heating (hopefully, I am NOT testing that in this heat right now, LOL) and black when idle. The main temp value on the tile is the setpoint. The temp in the footer is the actual temp.

Temps in the piston state will show different colours based on the temps but you may not see much change as it’s likely your temps will remain in a tight zone.

I am pretty sure this can be accomplished in a much cleaner fashion by using variables because as it stands there are lot of edits a user needs to do to make it theirs. I will have a go at that next. For now this was just a learning experience for me to get all the conditions in the expressions working.

EDIT: Hold up folks. I just noticed some errors in the logs even though things are working generally okay. I need to figure out what the issue is.

SECOND EDIT: Errors fixed.

4 Likes

This sends a notification if any exterior doors are open while away or asleep.

(modified the battery notification example piston)