Skip to content

Commit ddd26d6

Browse files
authored
Merge pull request SmartThingsCommunity#4118 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2 parents 9579bfb + 15b77ca commit ddd26d6

File tree

12 files changed

+340
-54
lines changed

12 files changed

+340
-54
lines changed

devicetypes/smartthings/aeon-key-fob.src/aeon-key-fob.groovy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ def updated() {
183183
def initialize() {
184184

185185
def results = []
186+
def buttons = 1
186187

187188
if (zwaveInfo && zwaveInfo.mfr == "0086" && zwaveInfo.prod == "0001" && zwaveInfo.model == "0026") {
188189
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
@@ -191,7 +192,7 @@ def initialize() {
191192
} else {
192193
// Device only goes OFFLINE when Hub is off
193194
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zwave", scheme:"untracked"]), displayed: false)
194-
def buttons = 4 // Default for Key Fob
195+
buttons = 4 // Default for Key Fob
195196
}
196197

197198
sendEvent(name: "numberOfButtons", value: buttons)

devicetypes/smartthings/springs-window-fashions-remote.src/springs-window-fashions-remote.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ metadata {
4444
}
4545

4646
def installed() {
47-
if (zwaveInfo.zw && zwaveInfo.zw.cc?.contains("84")) {
47+
if (zwaveInfo.cc?.contains("84")) {
4848
response(zwave.wakeUpV1.wakeUpNoMoreInformation())
4949
}
5050
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ metadata {
4949
fingerprint profileId: "0104", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, FFFF, 1000", outClusters: "0019", manufacturer: "LDS", model: "ZBT-DIMLight-GLS0000", deviceJoinName: "A60 Dim Bulb"
5050
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0019", manufacturer: "LDS", model: "ZHA-DIMLight-GLS0000", deviceJoinName: "A60 Dim Bulb"
5151
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019", manufacturer: "LDS", model: "ZBT-DIMLight-GLS", deviceJoinName: "A60 Dim Bulb"
52-
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019", manufacturer: "LDS", model: "ZBT-DIMLight-GLS0044", deviceJoinName: "智能球泡灯(可调光版)"
52+
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019", manufacturer: "LDS", model: "ZBT-DIMLight-GLS0044", deviceJoinName: "A60 Dim Bulb"
5353
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0009", outClusters: "0019", manufacturer: "Aurora", model: "FWMPROZXBulb50AU", deviceJoinName: "Aurora MPro"
5454
fingerprint profileId: "0104", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, FFFF, 1000", outClusters: "0019", manufacturer: "Aurora", model: "FWBulb51AU", deviceJoinName: "Aurora Smart Dimmable"
5555
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0019", manufacturer: "Aurora", model: "FWStrip50AU", deviceJoinName: "Aurora Dimmable Strip Controller"
@@ -61,6 +61,7 @@ metadata {
6161
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-N13", deviceJoinName: "Sengled Element Classic"
6262
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-N14", deviceJoinName: "Sengled Element Classic"
6363
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05, 1000, FEDC", outClusters: "000A, 0019", manufacturer: "LDS", model: "ZBT-DIMLight-GLS0006", deviceJoinName: "Smart Bulb"
64+
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0019", manufacturer: "Aurora", model: "WallDimmerMaster", deviceJoinName: "Aurora Smart Rotary Dimmer"
6465
}
6566

6667
tiles(scale: 2) {

devicetypes/smartthings/zigbee-power-meter.src/zigbee-power-meter.groovy

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
*/
1414
metadata {
15-
definition (name: "Zigbee Power Meter", namespace: "smartthings", author: "SmartThings") {
15+
definition (name: "Zigbee Power Meter", namespace: "smartthings", author: "SmartThings", mnmn: "SmartThings", vid: "SmartThings-smartthings-Aeon_Home_Energy_Meter") {
1616
capability "Energy Meter"
1717
capability "Power Meter"
1818
capability "Refresh"
@@ -105,5 +105,3 @@ def configure() {
105105
zigbee.simpleMeteringPowerConfig() +
106106
zigbee.electricMeasurementPowerConfig()
107107
}
108-
109-

devicetypes/smartthings/zigbee-white-color-temperature-bulb.src/zigbee-white-color-temperature-bulb.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ metadata {
5151
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B05, FC01", outClusters: "0019", manufacturer: "LEDVANCE", model: "RT TW", deviceJoinName: "SYLVANIA Smart+ Adustable White RT5/6"
5252

5353
// Aurora/AOne
54-
fingerprint profileId: "0104", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, 0300, FFFF, FFFF, 1000", outClusters: "0019", manufacturer: "Aurora", model: "TWBulb51AU", deviceJoinName: "Aurora Smart Tunable White", mnmn: "SmartThings", vid: "generic-color-temperature-bulb-2200K-5000K"
54+
fingerprint profileId: "0104", inClusters: "0000, 0004, 0003, 0006, 0008, 0005, 0300, FFFF, FFFF, 1000", outClusters: "0019", manufacturer: "Aurora", model: "TWBulb51AU", deviceJoinName: "Aurora Smart Tuneable White", mnmn: "SmartThings", vid: "generic-color-temperature-bulb-2200K-5000K"
5555
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019", manufacturer: "Aurora", model: "TWMPROZXBulb50AU", deviceJoinName: "Aurora MPro Smart Tuneable LED", mnmn: "SmartThings", vid: "generic-color-temperature-bulb-2200K-5000K"
5656
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019", manufacturer: "Aurora", model: "TWStrip50AU", deviceJoinName: "Aurora Tunable Strip Controller", mnmn: "SmartThings", vid: "generic-color-temperature-bulb-2200K-5000K"
5757
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B05, 1000, FEDC", outClusters: "0019, 000A", manufacturer: "Aurora", model: "TWGU10Bulb50AU", deviceJoinName: "Aurora GU10 Tuneable Smart Lamp", mnmn: "SmartThings", vid: "generic-color-temperature-bulb-2200K-5000K"

devicetypes/smartthings/zwave-motion-sensor.src/zwave-motion-sensor.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ metadata {
3333
fingerprint mfr: "0063", prod: "4953", model: "3133", deviceJoinName: "GE Portable Smart Motion Sensor"
3434
fingerprint mfr: "0214", prod: "0003", model: "0002", deviceJoinName: "BeSense Motion Detector"
3535
fingerprint mfr: "027A", prod: "0001", model: "0005", deviceJoinName: "Zooz Outdoor Motion Sensor"
36-
fingerprint mfr: "027A", prod: "0301", model: "0012", deviceJoinName: "Zooz Motion Sensor"
36+
fingerprint mfr: "027A", prod: "0301", model: "0012", deviceJoinName: "Zooz Motion Sensor", mnmn: "SmartThings", vid: "generic-motion-2"
3737
}
3838

3939
simulator {
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/**
2+
* Z-Wave Multi Button
3+
*
4+
* Copyright 2019 SmartThings
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7+
* in compliance with the License. You may obtain a copy of the License at:
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
12+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
13+
* for the specific language governing permissions and limitations under the License.
14+
*
15+
*/
16+
17+
metadata {
18+
definition (name: "Z-Wave Multi Button", namespace: "smartthings", author: "SmartThings", mnmn: "SmartThings", vid: "generic-6-button") {
19+
capability "Button"
20+
capability "Battery"
21+
capability "Sensor"
22+
capability "Health Check"
23+
capability "Configuration"
24+
25+
/*
26+
fingerprint mfr: "010F", prod: "1001", model: "1000", deviceJoinName: "Fibaro KeyFob" //EU
27+
fingerprint mfr: "010F", prod: "1001", model: "2000", deviceJoinName: "Fibaro KeyFob" //US
28+
*/
29+
}
30+
31+
tiles(scale: 2) {
32+
multiAttributeTile(name: "button", type: "generic", width: 6, height: 4, canChangeIcon: true) {
33+
tileAttribute("device.button", key: "PRIMARY_CONTROL") {
34+
attributeState "default", label: ' ', icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
35+
}
36+
}
37+
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
38+
state "battery", label:'${currentValue}% battery', unit:""
39+
}
40+
41+
main "button"
42+
details(["button", "battery"])
43+
}
44+
}
45+
46+
def installed() {
47+
runIn(2, "initialize", [overwrite: true])
48+
sendEvent(name: "button", value: "pushed", isStateChange: true)
49+
}
50+
51+
def updated() {
52+
runIn(2, "initialize", [overwrite: true])
53+
}
54+
55+
56+
def initialize() {
57+
def numberOfButtons = prodNumberOfButtons[zwaveInfo.prod]
58+
sendEvent(name: "numberOfButtons", value: numberOfButtons, displayed: false)
59+
sendEvent(name: "checkInterval", value: 8 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
60+
if(!childDevices) {
61+
addChildButtons(numberOfButtons)
62+
}
63+
if(childDevices) {
64+
def event
65+
for(def endpoint : 2..prodNumberOfButtons[zwaveInfo.prod]) {
66+
event = createEvent(name: "button", value: "pushed", isStateChange: true)
67+
sendEventToChild(endpoint, event)
68+
}
69+
}
70+
response([
71+
secure(zwave.batteryV1.batteryGet()),
72+
"delay 2000",
73+
secure(zwave.wakeUpV1.wakeUpNoMoreInformation())
74+
])
75+
}
76+
77+
def configure() {
78+
def cmds = []
79+
for(def parameter : 21..26) {
80+
cmds += secure(zwave.configurationV1.configurationSet(parameterNumber: parameter, scaledConfigurationValue: 15)) //Makes Fibaro KeyFob buttons send all kind of supported events
81+
}
82+
cmds
83+
}
84+
85+
def parse(String description) {
86+
def result = []
87+
if (description.startsWith("Err")) {
88+
result = createEvent(descriptionText:description, isStateChange:true)
89+
} else {
90+
def cmd = zwave.parse(description)
91+
if (cmd) {
92+
result += zwaveEvent(cmd)
93+
}
94+
}
95+
log.debug "Parse returned: ${result}"
96+
result
97+
}
98+
99+
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
100+
def encapsulatedCommand = cmd.encapsulatedCommand()
101+
if (encapsulatedCommand) {
102+
zwaveEvent(encapsulatedCommand)
103+
} else {
104+
log.warn "Unable to extract encapsulated cmd from $cmd"
105+
createEvent(descriptionText: cmd.toString())
106+
}
107+
}
108+
109+
def zwaveEvent(physicalgraph.zwave.commands.centralscenev1.CentralSceneNotification cmd) {
110+
def value = eventsMap[(int) cmd.keyAttributes]
111+
def description = "Button no. ${cmd.sceneNumber} was ${value}"
112+
def event = createEvent(name: "button", value: value, descriptionText: description, data: [buttonNumber: cmd.sceneNumber], isStateChange: true)
113+
if(cmd.sceneNumber == 1) {
114+
return event
115+
} else {
116+
sendEventToChild(cmd.sceneNumber, event)
117+
return createEvent(descriptionText: description)
118+
}
119+
}
120+
121+
def sendEventToChild(buttonNumber, event) {
122+
String childDni = "${device.deviceNetworkId}:$buttonNumber"
123+
def child = childDevices.find { it.deviceNetworkId == childDni }
124+
child?.sendEvent(event)
125+
}
126+
127+
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
128+
def results = []
129+
results += createEvent(descriptionText: "$device.displayName woke up", isStateChange: false)
130+
results += response([
131+
secure(zwave.batteryV1.batteryGet()),
132+
"delay 2000",
133+
secure(zwave.wakeUpV1.wakeUpNoMoreInformation())
134+
])
135+
results
136+
}
137+
138+
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
139+
def map = [ name: "battery", unit: "%", isStateChange: true ]
140+
state.lastbatt = now()
141+
if (cmd.batteryLevel == 0xFF) {
142+
map.value = 1
143+
map.descriptionText = "$device.displayName battery is low!"
144+
} else {
145+
map.value = cmd.batteryLevel
146+
}
147+
createEvent(map)
148+
}
149+
150+
def zwaveEvent(physicalgraph.zwave.Command cmd) {
151+
log.warn "Unhandled command: ${cmd}"
152+
}
153+
154+
private secure(cmd) {
155+
if(zwaveInfo.zw.endsWith("s")) {
156+
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
157+
} else {
158+
cmd.format()
159+
}
160+
}
161+
162+
private addChildButtons(numberOfButtons) {
163+
for(def endpoint : 2..numberOfButtons) {
164+
try {
165+
String childDni = "${device.deviceNetworkId}:$endpoint"
166+
def componentLabel = (device.displayName.endsWith(' 1') ? device.displayName[0..-2] : (device.displayName + " ")) + "${endpoint}"
167+
addChildDevice("Child Button", childDni, device.getHub().getId(), [
168+
completedSetup: true,
169+
label : componentLabel,
170+
isComponent : true,
171+
componentName : "button$endpoint",
172+
componentLabel: "Button $endpoint"
173+
])
174+
} catch(Exception e) {
175+
log.debug "Exception: ${e}"
176+
}
177+
}
178+
}
179+
180+
private getEventsMap() {[
181+
0: "pushed",
182+
1: "held",
183+
//2: "down_hold",
184+
3: "double",
185+
//4: "pushed_3x"
186+
]}
187+
188+
private getProdNumberOfButtons() {[
189+
"1001" : 6
190+
]}

devicetypes/smartthings/zwave-siren.src/zwave-siren.groovy

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,13 @@ def handleSwitchValue(value) {
363363

364364
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
365365
def map = [name: "battery", unit: "%"]
366-
if (cmd.batteryLevel == 0xFF) {
366+
367+
// The Utilitech siren always sends low battery events (0xFF) below 20%,
368+
// so we will ignore 0% events that sometimes seem to come before valid events.
369+
if (cmd.batteryLevel == 0 && isUtilitech()) {
370+
log.debug "Ignoring battery 0%"
371+
return [:]
372+
} else if (cmd.batteryLevel == 0xFF) {
367373
map.value = 1
368374
map.descriptionText = "$device.displayName has a low battery"
369375
} else {
@@ -414,4 +420,8 @@ def isYale() {
414420

415421
def isZipato() {
416422
(zwaveInfo?.mfr == "0131" && zwaveInfo?.prod == "0003" && zwaveInfo?.model == "1083")
417-
}
423+
}
424+
425+
def isUtilitech() {
426+
(zwaveInfo?.mfr == "0060" && zwaveInfo?.prod == "000C" && zwaveInfo?.model == "0001")
427+
}

devicetypes/smartthings/zwave-water-valve.src/zwave-water-valve.groovy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ metadata {
2323
fingerprint deviceId: "0x1006", inClusters: "0x25"
2424
fingerprint mfr: "0173", prod: "0003", model: "0002", deviceJoinName: "Leak Intelligence Leak Gopher Water Shutoff Valve"
2525
fingerprint mfr: "021F", prod: "0003", model: "0002", deviceJoinName: "Dome Water Main Shut-off"
26+
fingerprint mfr: "0157", prod: "0003", model: "0002", deviceJoinName: "EcoNet Bulldog Valve Robot"
2627
}
2728

2829
// simulator metadata

devicetypes/stelpro/stelpro-ki-thermostat.src/stelpro-ki-thermostat.groovy

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,13 @@ metadata {
4949
simulator { }
5050

5151
preferences {
52-
input("heatdetails", "enum", title: "Do you want a detailed operating state notification?", options: ["No", "Yes"], defaultValue: "No", required: true, displayDuringSetup: true)
53-
input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "[Do not use space](Blank = No Forecast)")
52+
section {
53+
input("heatdetails", "enum", title: "Do you want a detailed operating state notification?", options: ["No", "Yes"], defaultValue: "No", required: true, displayDuringSetup: true)
54+
}
55+
section {
56+
input title: "Outdoor Temperature", description: "To get the current outdoor temperature to display on your thermostat enter your zip code or postal code below and make sure that your SmartThings location has a Geolocation configured (typically used for geofencing).", displayDuringSetup: false, type: "paragraph", element: "paragraph"
57+
input("zipcode", "text", title: "ZipCode (Outdoor Temperature)", description: "[Do not use space](Blank = No Forecast)")
58+
}
5459
}
5560

5661
tiles(scale : 2) {
@@ -161,6 +166,7 @@ def updated() {
161166

162167
unschedule(scheduledUpdateWeather)
163168
if (settings.zipcode) {
169+
state.invalidZip = false // Reset and validate the zip-code later
164170
runEvery1Hour(scheduledUpdateWeather)
165171
scheduledUpdateWeather()
166172
}
@@ -208,21 +214,42 @@ def updateWeather() {
208214
// If there is a zipcode defined, weather forecast will be sent. Otherwise, no weather forecast.
209215
if (settings.zipcode) {
210216
log.debug "ZipCode: ${settings.zipcode}"
211-
weather = getTwcConditions(settings.zipcode)
217+
try {
218+
// If we do not have a zip-code setting we've determined as invalid, try to use the zip-code defined.
219+
if (!state.invalidZip) {
220+
weather = getTwcConditions(settings.zipcode)
221+
}
222+
} catch (e) {
223+
log.debug "getTwcConditions exception: $e"
224+
// There was a problem obtaining the weather with this zip-code, so fall back to the hub's location and note this for future runs.
225+
state.invalidZip = true
226+
}
212227

213-
// Check if the variable is populated, otherwise return.
214228
if (!weather) {
215-
log.debug("Something went wrong, no data found.")
216-
return false
229+
try {
230+
// It is possible that a non-U.S. zip-code was used, so try with the location's lat/lon.
231+
if (location?.latitude && location?.longitude) {
232+
// Restrict to two decimal places for the API
233+
weather = getTwcConditions(sprintf("%.2f,%.2f", location.latitude, location.longitude))
234+
}
235+
} catch (e2) {
236+
log.debug "getTwcConditions exception: $e2"
237+
weather = null
238+
}
217239
}
218240

219-
def locationScale = getTemperatureScale()
220-
def tempToSend = weather.temperature
221-
log.debug("Outdoor Temperature: ${tempToSend} ${locationScale}")
222-
// Right now this can disrupt device health if the device is
223-
// currently offline -- it would be erroneously marked online.
224-
//sendEvent(name: 'outsideTemp', value: tempToSend)
225-
setOutdoorTemperature(tempToSend)
241+
// Either the location lat,lon was invalid or one was not defined for the location, on top of an error with the given zip-code
242+
if (!weather) {
243+
log.debug("Something went wrong, no data found.")
244+
} else {
245+
def locationScale = getTemperatureScale()
246+
def tempToSend = weather.temperature
247+
log.debug("Outdoor Temperature: ${tempToSend} ${locationScale}")
248+
// Right now this can disrupt device health if the device is
249+
// currently offline -- it would be erroneously marked online.
250+
//sendEvent( name: 'outsideTemp', value: tempToSend )
251+
setOutdoorTemperature(tempToSend)
252+
}
226253
}
227254
}
228255

@@ -387,6 +414,7 @@ def refresh() {
387414
def configure() {
388415
unschedule(scheduledUpdateWeather)
389416
if (settings.zipcode) {
417+
state.invalidZip = false // Reset and validate the zip-code later
390418
runEvery1Hour(scheduledUpdateWeather)
391419
}
392420
poll()

0 commit comments

Comments
 (0)