diff --git a/devicetypes/smartthings/testing/simulated-refrigerator-door.src/simulated-refrigerator-door.groovy b/devicetypes/smartthings/testing/simulated-refrigerator-door.src/simulated-refrigerator-door.groovy new file mode 100644 index 0000000..cf7f3ef --- /dev/null +++ b/devicetypes/smartthings/testing/simulated-refrigerator-door.src/simulated-refrigerator-door.groovy @@ -0,0 +1,57 @@ +/** + * Copyright 2017 SmartThings + * + * 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. + * + */ +metadata { + definition (name: "Simulated Refrigerator Door", namespace: "smartthings/testing", author: "SmartThings") { + capability "Contact Sensor" + capability "Sensor" + + command "open" + command "close" + } + + tiles { + standardTile("contact", "device.contact", width: 2, height: 2) { + state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821", action: "open") + state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e", action: "close") + } + standardTile("freezerDoor", "device.contact", width: 2, height: 2, decoration: "flat") { + state("closed", label:'Freezer', icon:"st.contact.contact.closed", backgroundColor:"#79b821") + state("open", label:'Freezer', icon:"st.contact.contact.open", backgroundColor:"#ffa81e") + } + standardTile("mainDoor", "device.contact", width: 2, height: 2, decoration: "flat") { + state("closed", label:'Fridge', icon:"st.contact.contact.closed", backgroundColor:"#79b821") + state("open", label:'Fridge', icon:"st.contact.contact.open", backgroundColor:"#ffa81e") + } + standardTile("control", "device.contact", width: 1, height: 1, decoration: "flat") { + state("closed", label:'${name}', icon:"st.contact.contact.closed", action: "open") + state("open", label:'${name}', icon:"st.contact.contact.open", action: "close") + } + main "contact" + details "contact" + } +} + +def installed() { + sendEvent(name: "contact", value: "closed") +} + +def open() { + sendEvent(name: "contact", value: "open") + parent.doorOpen(device.deviceNetworkId) +} + +def close() { + sendEvent(name: "contact", value: "closed") + parent.doorClosed(device.deviceNetworkId) +} diff --git a/devicetypes/smartthings/testing/simulated-refrigerator-temperature-control.src/simulated-refrigerator-temperature-control.groovy b/devicetypes/smartthings/testing/simulated-refrigerator-temperature-control.src/simulated-refrigerator-temperature-control.groovy new file mode 100644 index 0000000..972641e --- /dev/null +++ b/devicetypes/smartthings/testing/simulated-refrigerator-temperature-control.src/simulated-refrigerator-temperature-control.groovy @@ -0,0 +1,94 @@ +/** + * Simulated Refrigerator Temperature Control + * + * Copyright 2017 SmartThings + * + * 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. + * + */ +metadata { + definition (name: "Simulated Refrigerator Temperature Control", namespace: "smartthings/testing", author: "SmartThings") { + capability "Temperature Measurement" + capability "Thermostat Cooling Setpoint" + + command "tempUp" + command "tempDown" + command "setpointUp" + command "setpointDown" + } + + tiles { + valueTile("refrigerator", "device.temperature", width: 2, height: 2, canChangeBackground: true) { + state("temperature", label:'${currentValue}°', unit:"F", + backgroundColors:[ + [value: 0, color: "#153591"], + [value: 40, color: "#1e9cbb"], + [value: 45, color: "#f1d801"] + ] + ) + } + valueTile("freezer", "device.temperature", width: 2, height: 2, canChangeBackground: true) { + state("temperature", label:'${currentValue}°', unit:"F", + backgroundColors:[ + [value: 0, color: "#153591"], + [value: 5, color: "#1e9cbb"], + [value: 15, color: "#f1d801"] + ] + ) + } + valueTile("freezerSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") { + state "setpoint", label:'Freezer Set: ${currentValue}°', unit:"F" + } + valueTile("refrigeratorSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") { + state "heat", label:'Fridge Set: ${currentValue}°', unit:"F" + } + standardTile("tempUp", "device.temperature", inactiveLabel: false, decoration: "flat") { + state "default", action:"tempUp", icon:"st.thermostat.thermostat-up" + } + standardTile("tempDown", "device.temperature", inactiveLabel: false, decoration: "flat") { + state "default", action:"tempDown", icon:"st.thermostat.thermostat-down" + } + standardTile("setpointUp", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") { + state "default", action:"setpointUp", icon:"st.thermostat.thermostat-up" + } + standardTile("setpointDown", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") { + state "default", action:"setpointDown", icon:"st.thermostat.thermostat-down" + } + } +} + +def installed() { + sendEvent(name: "temperature", value: device.componentName == "freezer" ? 2 : 40) + sendEvent(name: "coolingSetpoint", value: device.componentName == "freezer" ? 2 : 40) +} + +def updated() { + installed() +} + +void tempUp() { + def value = device.currentValue("temperature") as Integer + sendEvent(name: "temperature", value: value + 1) +} + +void tempDown() { + def value = device.currentValue("temperature") as Integer + sendEvent(name: "temperature", value: value - 1) +} + +void setpointUp() { + def value = device.currentValue("coolingSetpoint") as Integer + sendEvent(name: "coolingSetpoint", value: value + 1) +} + +void setpointDown() { + def value = device.currentValue("coolingSetpoint") as Integer + sendEvent(name: "coolingSetpoint", value: value - 1) +} diff --git a/devicetypes/smartthings/testing/simulated-refrigerator.src/simulated-refrigerator.groovy b/devicetypes/smartthings/testing/simulated-refrigerator.src/simulated-refrigerator.groovy new file mode 100644 index 0000000..ba5fbfe --- /dev/null +++ b/devicetypes/smartthings/testing/simulated-refrigerator.src/simulated-refrigerator.groovy @@ -0,0 +1,91 @@ +/** + * Simulated Refrigerator + * + * Example composite device handler that simulates a refrigerator with a freezer compartment and a main compartment. + * Each of these compartments has its own door, temperature, and temperature setpoint. Each compartment modeled + * as a child device of the main refrigerator device so that temperature-based SmartApps can be used with each + * compartment + * + * Copyright 2017 SmartThings + * + * 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. + * + */ +metadata { + definition (name: "Simulated Refrigerator", namespace: "smartthings/testing", author: "SmartThings") { + capability "Contact Sensor" + } + + tiles(scale: 2) { + standardTile("contact", "device.contact", width: 4, height: 4) { + state("closed", label:'${name}', icon:"st.fridge.fridge-closed", backgroundColor:"#79b821") + state("open", label:'${name}', icon:"st.fridge.fridge-open", backgroundColor:"#ffa81e") + } + childDeviceTile("freezerDoor", "freezerDoor", height: 2, width: 2, childTileName: "freezerDoor") + childDeviceTile("mainDoor", "mainDoor", height: 2, width: 2, childTileName: "mainDoor") + childDeviceTile("freezer", "freezer", height: 2, width: 2, childTileName: "freezer") + childDeviceTile("refrigerator", "refrigerator", height: 2, width: 2, childTileName: "refrigerator") + childDeviceTile("freezerSetpoint", "freezer", height: 1, width: 2, childTileName: "freezerSetpoint") + childDeviceTile("refrigeratorSetpoint", "refrigerator", height: 1, width: 2, childTileName: "refrigeratorSetpoint") + + // for simulator + childDeviceTile("freezerUp", "freezer", height: 1, width: 1, childTileName: "tempUp") + childDeviceTile("freezerDown", "freezer", height: 1, width: 1, childTileName: "tempDown") + childDeviceTile("refrigeratorUp", "refrigerator", height: 1, width: 1, childTileName: "tempUp") + childDeviceTile("refrigeratorDown", "refrigerator", height: 1, width: 1, childTileName: "tempDown") + childDeviceTile("freezerDoorControl", "freezerDoor", height: 1, width: 1, childTileName: "control") + childDeviceTile("mainDoorControl", "mainDoor", height: 1, width: 1, childTileName: "control") + childDeviceTile("freezerSetpointUp", "freezer", height: 1, width: 1, childTileName: "setpointUp") + childDeviceTile("freezerSetpointDown", "freezer", height: 1, width: 1, childTileName: "setpointDown") + childDeviceTile("refrigeratorSetpointUp", "refrigerator", height: 1, width: 1, childTileName: "setpointUp") + childDeviceTile("refrigeratorSetpointDown", "refrigerator", height: 1, width: 1, childTileName: "setpointDown") + } +} + +def installed() { + state.counter = state.counter ? state.counter + 1 : 1 + if (state.counter == 1) { + addChildDevice( + "Simulated Refrigerator Door", + "${device.deviceNetworkId}.1", + null, + [completedSetup: true, label: "${device.label} (Freezer Door)", componentName: "freezerDoor", componentLabel: "Freezer Door"]) + + addChildDevice( + "Simulated Refrigerator Door", + "${device.deviceNetworkId}.2", + null, + [completedSetup: true, label: "${device.label} (Main Door)", componentName: "mainDoor", componentLabel: "Main Door"]) + + addChildDevice( + "Simulated Refrigerator Temperature Control", + "${device.deviceNetworkId}.3", + null, + [completedSetup: true, label: "${device.label} (Freezer)", componentName: "freezer", componentLabel: "Freezer"]) + + addChildDevice( + "Simulated Refrigerator Temperature Control", + "${device.deviceNetworkId}.3", + null, + [completedSetup: true, label: "${device.label} (Fridge)", componentName: "refrigerator", componentLabel: "Fridge"]) + } +} + +def doorOpen(dni) { + // If any door opens, then the refrigerator is considered to be open + sendEvent(name: "contact", value: "open") +} + +def doorClosed(dni) { + // Both doors must be closed for the refrigerator to be considered closed + if (!childDevices.find{it.deviceNetworkId != dni && it.currentValue("contact") == "open"}) { + sendEvent(name: "contact", value: "closed") + } +} \ No newline at end of file