Skip to content

Commit 4c256a7

Browse files
committed
2 parents e77dadd + d69abb6 commit 4c256a7

File tree

65 files changed

+3629
-2080
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+3629
-2080
lines changed
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/**
2+
* PlantLink
3+
*
4+
* This device type takes sensor data and converts it into a json packet to send to myplantlink.com
5+
* where its values will be computed for soil and plant type to show user readable values of how your
6+
* specific plant is doing.
7+
*
8+
*
9+
* Copyright 2015 Oso Technologies
10+
*
11+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
12+
* in compliance with the License. You may obtain a copy of the License at:
13+
*
14+
* http://www.apache.org/licenses/LICENSE-2.0
15+
*
16+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
17+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
18+
* for the specific language governing permissions and limitations under the License.
19+
*
20+
*/
21+
22+
import groovy.json.JsonBuilder
23+
24+
metadata {
25+
definition (name: "PlantLink", namespace: "OsoTech", author: "Oso Technologies") {
26+
capability "Sensor"
27+
28+
command "setStatusIcon"
29+
command "setPlantFuelLevel"
30+
command "setBatteryLevel"
31+
command "setInstallSmartApp"
32+
33+
attribute "plantStatus","string"
34+
attribute "plantFuelLevel","number"
35+
attribute "linkBatteryLevel","string"
36+
attribute "installSmartApp","string"
37+
38+
fingerprint profileId: "0104", inClusters: "0000,0001,0B04"
39+
}
40+
41+
simulator {
42+
status "battery": "read attr - raw: C0720100010A000021340A, dni: C072, endpoint: 01, cluster: 0001, size: 0A, attrId: 0000, encoding: 21, value: 0a34"
43+
status "moisture": "read attr - raw: C072010B040A0001290000, dni: C072, endpoint: 01, cluster: 0B04, size: 0A, attrId: 0100, encoding: 29, value: 0000"
44+
}
45+
46+
tiles {
47+
standardTile("Title", "device.label") {
48+
state("label", label:'PlantLink ${device.label}')
49+
}
50+
51+
valueTile("plantMoistureTile", "device.plantFuelLevel", width: 1, height: 1) {
52+
state("plantMoisture", label: '${currentValue}% Moisture')
53+
}
54+
55+
valueTile("plantStatusTextTile", "device.plantStatus", decoration: "flat", width: 2, height: 2) {
56+
state("plantStatusTextTile", label:'${currentValue}')
57+
}
58+
59+
valueTile("battery", "device.linkBatteryLevel" ) {
60+
state("battery", label:'${currentValue}% battery')
61+
}
62+
63+
valueTile("installSmartApp","device.installSmartApp", decoration: "flat", width: 3, height: 1) {
64+
state "needSmartApp", label:'Please install SmartApp "Required PlantLink Connector"', defaultState:true
65+
state "connectedToSmartApp", label:'Connected to myplantlink.com'
66+
}
67+
68+
main "plantStatusTextTile"
69+
details(['plantStatusTextTile', "plantMoistureTile", "battery", "installSmartApp"])
70+
}
71+
}
72+
73+
def setStatusIcon(value){
74+
def status = ''
75+
switch (value) {
76+
case '0':
77+
status = 'Needs Water'
78+
break
79+
case '1':
80+
status = 'Dry'
81+
break
82+
case '2':
83+
case '3':
84+
status = 'Good'
85+
break
86+
case '4':
87+
status = 'Too Wet'
88+
break
89+
case 'No Soil':
90+
status = 'Too Dry'
91+
setPlantFuelLevel(0)
92+
break
93+
case 'Recently Watered':
94+
status = 'Watered'
95+
setPlantFuelLevel(100)
96+
break
97+
case 'Low Battery':
98+
status = 'Low Battery'
99+
break
100+
case 'Waiting on First Measurement':
101+
status = 'Calibrating'
102+
break
103+
default:
104+
status = "?"
105+
break
106+
}
107+
sendEvent("name":"plantStatus", "value":status, "description":statusText, displayed: true, isStateChange: true)
108+
}
109+
110+
def setPlantFuelLevel(value){
111+
sendEvent("name":"plantFuelLevel", "value":value, "description":statusText, displayed: true, isStateChange: true)
112+
}
113+
114+
def setBatteryLevel(value){
115+
sendEvent("name":"linkBatteryLevel", "value":value, "description":statusText, displayed: true, isStateChange: true)
116+
}
117+
118+
def setInstallSmartApp(value){
119+
sendEvent("name":"installSmartApp", "value":value)
120+
}
121+
122+
def parse(String description) {
123+
124+
def description_map = parseDescriptionAsMap(description)
125+
def event_name = ""
126+
def measurement_map = [
127+
type: "link",
128+
signal: "0x00",
129+
zigbeedeviceid: device.zigbeeId,
130+
created: new Date().time /1000 as int
131+
]
132+
if (description_map.cluster == "0000"){
133+
/* version number, not used */
134+
135+
} else if (description_map.cluster == "0001"){
136+
/* battery voltage in mV (device needs minimium 2.1v to run) */
137+
log.debug "PlantLink - id ${device.zigbeeId} battery ${description_map.value}"
138+
event_name = "battery_status"
139+
measurement_map["battery"] = "0x${description_map.value}"
140+
141+
} else if (description_map.cluster == "0B04"){
142+
/* raw moisture reading (needs to be sent to plantlink for soil/plant type conversion) */
143+
log.debug "PlantLink - id ${device.zigbeeId} raw moisture ${description_map.value}"
144+
measurement_map["moisture"] = "0x${description_map.value}"
145+
event_name = "moisture_status"
146+
147+
} else{
148+
log.debug "PlantLink - id ${device.zigbeeId} Unknown '${description}'"
149+
return
150+
}
151+
152+
def json_builder = new JsonBuilder(measurement_map)
153+
def result = createEvent(name: event_name, value: json_builder.toString())
154+
return result
155+
}
156+
157+
158+
def parseDescriptionAsMap(description) {
159+
(description - "read attr - ").split(",").inject([:]) { map, param ->
160+
def nameAndValue = param.split(":")
161+
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
162+
}
163+
}
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/**
2+
* Copyright 2016 SmartThings
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5+
* in compliance with the License. You may obtain a copy of the License at:
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
10+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
11+
* for the specific language governing permissions and limitations under the License.
12+
*
13+
*/
14+
metadata {
15+
definition (name: "Arrival Sensor HA", namespace: "smartthings", author: "SmartThings") {
16+
capability "Tone"
17+
capability "Actuator"
18+
capability "Presence Sensor"
19+
capability "Sensor"
20+
capability "Battery"
21+
capability "Configuration"
22+
23+
fingerprint inClusters: "0000,0001,0003,000F,0020", outClusters: "0003,0019",
24+
manufacturer: "SmartThings", model: "tagv4", deviceJoinName: "Arrival Sensor"
25+
}
26+
27+
preferences {
28+
section {
29+
image(name: 'educationalcontent', multiple: true, images: [
30+
"http://cdn.device-gse.smartthings.com/Arrival/Arrival1.png",
31+
"http://cdn.device-gse.smartthings.com/Arrival/Arrival2.png"
32+
])
33+
}
34+
section {
35+
input "checkInterval", "enum", title: "Presence timeout (minutes)",
36+
defaultValue:"2", options: ["2", "3", "5"], displayDuringSetup: false
37+
}
38+
}
39+
40+
tiles {
41+
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
42+
state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0"
43+
state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff"
44+
}
45+
standardTile("beep", "device.beep", decoration: "flat") {
46+
state "beep", label:'', action:"tone.beep", icon:"st.secondary.beep", backgroundColor:"#ffffff"
47+
}
48+
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {
49+
state "battery", label:'${currentValue}% battery', unit:""
50+
}
51+
52+
main "presence"
53+
details(["presence", "beep", "battery"])
54+
}
55+
}
56+
57+
def updated() {
58+
startTimer()
59+
}
60+
61+
def configure() {
62+
def cmds = zigbee.configureReporting(0x0001, 0x0020, 0x20, 20, 20, 0x01)
63+
log.debug "configure -- cmds: ${cmds}"
64+
return cmds
65+
}
66+
67+
def beep() {
68+
log.debug "Sending Identify command to beep the sensor for 5 seconds"
69+
return zigbee.command(0x0003, 0x00, "0500")
70+
}
71+
72+
def parse(String description) {
73+
state.lastCheckin = now()
74+
handlePresenceEvent(true)
75+
76+
if (description?.startsWith('read attr -')) {
77+
handleReportAttributeMessage(description)
78+
}
79+
}
80+
81+
private handleReportAttributeMessage(String description) {
82+
def descMap = zigbee.parseDescriptionAsMap(description)
83+
84+
if (descMap.clusterInt == 0x0001 && descMap.attrInt == 0x0020) {
85+
handleBatteryEvent(Integer.parseInt(descMap.value, 16))
86+
}
87+
}
88+
89+
private handleBatteryEvent(rawValue) {
90+
def linkText = getLinkText(device)
91+
92+
def eventMap = [
93+
name: 'battery',
94+
value: '--'
95+
]
96+
97+
def volts = rawValue / 10
98+
if (volts > 0){
99+
def minVolts = 2.0
100+
def maxVolts = 2.8
101+
102+
if (volts < minVolts)
103+
volts = minVolts
104+
else if (volts > maxVolts)
105+
volts = maxVolts
106+
def pct = (volts - minVolts) / (maxVolts - minVolts)
107+
108+
eventMap.value = Math.round(pct * 100)
109+
eventMap.descriptionText = "${linkText} battery was ${eventMap.value}%"
110+
}
111+
112+
log.debug "Creating battery event: ${eventMap}"
113+
sendEvent(eventMap)
114+
}
115+
116+
private handlePresenceEvent(present) {
117+
def wasPresent = device.currentState("presence")?.value == "present"
118+
if (!wasPresent && present) {
119+
log.debug "Sensor is present"
120+
startTimer()
121+
} else if (!present) {
122+
log.debug "Sensor is not present"
123+
stopTimer()
124+
}
125+
def linkText = getLinkText(device)
126+
def eventMap = [
127+
name: "presence",
128+
value: present ? "present" : "not present",
129+
linkText: linkText,
130+
descriptionText: "${linkText} has ${present ? 'arrived' : 'left'}",
131+
]
132+
log.debug "Creating presence event: ${eventMap}"
133+
sendEvent(eventMap)
134+
}
135+
136+
private startTimer() {
137+
log.debug "Scheduling periodic timer"
138+
schedule("0 * * * * ?", checkPresenceCallback)
139+
}
140+
141+
private stopTimer() {
142+
log.debug "Stopping periodic timer"
143+
unschedule()
144+
}
145+
146+
def checkPresenceCallback() {
147+
def timeSinceLastCheckin = (now() - state.lastCheckin) / 1000
148+
def theCheckInterval = (checkInterval ? checkInterval as int : 2) * 60
149+
log.debug "Sensor checked in ${timeSinceLastCheckin} seconds ago"
150+
if (timeSinceLastCheckin >= theCheckInterval) {
151+
handlePresenceEvent(false)
152+
}
153+
}

devicetypes/smartthings/centralite-dimmer.src/centralite-dimmer.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* Author: SmartThings
1616
* Date: 2013-12-04
1717
*/
18+
//DEPRECATED - Using the generic DTH for this device. Users need to be moved before deleting this DTH
1819
metadata {
1920
definition (name: "CentraLite Dimmer", namespace: "smartthings", author: "SmartThings") {
2021
capability "Switch Level"
@@ -25,7 +26,6 @@ metadata {
2526
capability "Refresh"
2627
capability "Sensor"
2728

28-
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0B04,0B05", outClusters: "0019"
2929
}
3030

3131
// simulator metadata

0 commit comments

Comments
 (0)