Skip to content

Commit 3a4ec6c

Browse files
authored
Merge pull request SmartThingsCommunity#3105 from SmartThingsCommunity/staging
Rolling up staging to production
2 parents ecff3c8 + 1a8dda8 commit 3a4ec6c

Some content is hidden

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

59 files changed

+315
-94
lines changed

devicetypes/smartthings/cree-bulb.src/cree-bulb.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
metadata {
18-
definition (name: "Cree Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light") {
18+
definition (name: "Cree Bulb", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.light", runLocally: true, executeCommandsLocally: true, minHubCoreVersion: "000.022.0004") {
1919

2020
capability "Actuator"
2121
capability "Configuration"

devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* under the License.
1515
*/
1616
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
17-
17+
import physicalgraph.zigbee.zcl.DataType
1818

1919
metadata {
2020
definition(name: "SmartSense Moisture Sensor", namespace: "smartthings", author: "SmartThings", runLocally: true, minHubCoreVersion: '000.017.0012', executeCommandsLocally: false, mnmn: "SmartThings", vid: "generic-leak") {
@@ -86,6 +86,18 @@ metadata {
8686
}
8787
}
8888

89+
private List<Map> collectAttributes(Map descMap) {
90+
List<Map> descMaps = new ArrayList<Map>()
91+
92+
descMaps.add(descMap)
93+
94+
if (descMap.additionalAttrs) {
95+
descMaps.addAll(descMap.additionalAttrs)
96+
}
97+
98+
return descMaps
99+
}
100+
89101
def parse(String description) {
90102
log.debug "description: $description"
91103

@@ -96,8 +108,23 @@ def parse(String description) {
96108
map = parseIasMessage(description)
97109
} else {
98110
Map descMap = zigbee.parseDescriptionAsMap(description)
99-
if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) {
100-
map = getBatteryResult(Integer.parseInt(descMap.value, 16))
111+
112+
if (descMap?.clusterInt == zigbee.POWER_CONFIGURATION_CLUSTER && descMap.commandInt != 0x07 && descMap.value) {
113+
List<Map> descMaps = collectAttributes(descMap)
114+
115+
if (device.getDataValue("manufacturer") == "Samjin") {
116+
def battMap = descMaps.find { it.attrInt == 0x0021 }
117+
118+
if (battMap) {
119+
map = getBatteryPercentageResult(Integer.parseInt(battMap.value, 16))
120+
}
121+
} else {
122+
def battMap = descMaps.find { it.attrInt == 0x0020 }
123+
124+
if (battMap) {
125+
map = getBatteryResult(Integer.parseInt(battMap.value, 16))
126+
}
127+
}
101128
} else if (descMap?.clusterInt == 0x0500 && descMap.attrInt == 0x0002) {
102129
def zs = new ZoneStatus(zigbee.convertToInt(descMap.value, 16))
103130
map = translateZoneStatus(zs)
@@ -181,6 +208,20 @@ private Map getBatteryResult(rawValue) {
181208
return result
182209
}
183210

211+
private Map getBatteryPercentageResult(rawValue) {
212+
log.debug "Battery Percentage rawValue = ${rawValue} -> ${rawValue / 2}%"
213+
def result = [:]
214+
215+
if (0 <= rawValue && rawValue <= 200) {
216+
result.name = 'battery'
217+
result.translatable = true
218+
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
219+
result.value = Math.round(rawValue / 2)
220+
}
221+
222+
return result
223+
}
224+
184225
private Map getMoistureResult(value) {
185226
log.debug "water"
186227
def descriptionText
@@ -204,20 +245,37 @@ def ping() {
204245
}
205246

206247
def refresh() {
207-
log.debug "Refreshing Temperature and Battery"
208-
def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
209-
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) +
210-
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS)
248+
log.debug "Refreshing Values"
249+
def refreshCmds = []
250+
251+
if (device.getDataValue("manufacturer") == "Samjin") {
252+
refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021)
253+
} else {
254+
refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020)
255+
}
256+
refreshCmds += zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
257+
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) +
258+
zigbee.enrollResponse()
211259

212-
return refreshCmds + zigbee.enrollResponse()
260+
return refreshCmds
213261
}
214262

215263
def configure() {
216264
// Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time)
217265
// enrolls with default periodic reporting until newer 5 min interval is confirmed
218266
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
219267

268+
log.debug "Configuring Reporting"
269+
def configCmds = []
270+
220271
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
221272
// battery minReport 30 seconds, maxReportTime 6 hrs by default
222-
return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config
273+
if (device.getDataValue("manufacturer") == "Samjin") {
274+
configCmds += zigbee.configureReporting(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021, DataType.UINT8, 30, 21600, 0x10)
275+
} else {
276+
configCmds += zigbee.batteryConfig()
277+
}
278+
configCmds += zigbee.temperatureConfig(30, 300)
279+
280+
return refresh() + configCmds // send refresh cmds as part of config
223281
}

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

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* under the License.
1515
*/
1616
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
17-
17+
import physicalgraph.zigbee.zcl.DataType
1818

1919
metadata {
2020
definition(name: "SmartSense Motion Sensor", namespace: "smartthings", author: "SmartThings", runLocally: true, minHubCoreVersion: '000.017.0012', executeCommandsLocally: false, mnmn: "SmartThings", vid: "generic-motion") {
@@ -93,6 +93,18 @@ metadata {
9393
}
9494
}
9595

96+
private List<Map> collectAttributes(Map descMap) {
97+
List<Map> descMaps = new ArrayList<Map>()
98+
99+
descMaps.add(descMap)
100+
101+
if (descMap.additionalAttrs) {
102+
descMaps.addAll(descMap.additionalAttrs)
103+
}
104+
105+
return descMaps
106+
}
107+
96108
def parse(String description) {
97109
log.debug "description: $description"
98110
Map map = zigbee.getEvent(description)
@@ -101,9 +113,24 @@ def parse(String description) {
101113
map = parseIasMessage(description)
102114
} else {
103115
Map descMap = zigbee.parseDescriptionAsMap(description)
104-
if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) {
116+
117+
if (descMap?.clusterInt == zigbee.POWER_CONFIGURATION_CLUSTER && descMap.commandInt != 0x07 && descMap.value) {
105118
log.info "BATT METRICS - attr: ${descMap?.attrInt}, value: ${descMap?.value}, decValue: ${Integer.parseInt(descMap.value, 16)}, currPercent: ${device.currentState("battery")?.value}, device: ${device.getDataValue("manufacturer")} ${device.getDataValue("model")}"
106-
map = getBatteryResult(Integer.parseInt(descMap.value, 16))
119+
List<Map> descMaps = collectAttributes(descMap)
120+
121+
if (device.getDataValue("manufacturer") == "Samjin") {
122+
def battMap = descMaps.find { it.attrInt == 0x0021 }
123+
124+
if (battMap) {
125+
map = getBatteryPercentageResult(Integer.parseInt(battMap.value, 16))
126+
}
127+
} else {
128+
def battMap = descMaps.find { it.attrInt == 0x0020 }
129+
130+
if (battMap) {
131+
map = getBatteryResult(Integer.parseInt(battMap.value, 16))
132+
}
133+
}
107134
} else if (descMap?.clusterInt == 0x0500 && descMap.attrInt == 0x0002) {
108135
def zs = new ZoneStatus(zigbee.convertToInt(descMap.value, 16))
109136
map = translateZoneStatus(zs)
@@ -215,6 +242,20 @@ private Map getBatteryResult(rawValue) {
215242
return result
216243
}
217244

245+
private Map getBatteryPercentageResult(rawValue) {
246+
log.debug "Battery Percentage rawValue = ${rawValue} -> ${rawValue / 2}%"
247+
def result = [:]
248+
249+
if (0 <= rawValue && rawValue <= 200) {
250+
result.name = 'battery'
251+
result.translatable = true
252+
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
253+
result.value = Math.round(rawValue / 2)
254+
}
255+
256+
return result
257+
}
258+
218259
private Map getMotionResult(value) {
219260
log.debug 'motion'
220261
String descriptionText = value == 'active' ? "{{ device.displayName }} detected motion" : "{{ device.displayName }} motion has stopped"
@@ -234,23 +275,39 @@ def ping() {
234275
}
235276

236277
def refresh() {
237-
log.debug "refresh called"
278+
log.debug "Refreshing Values"
279+
def refreshCmds = []
238280

239-
def refreshCmds = zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) +
240-
zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
241-
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS)
281+
if (device.getDataValue("manufacturer") == "Samjin") {
282+
refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021)
283+
} else {
284+
refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020)
285+
}
286+
refreshCmds += zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
287+
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) +
288+
zigbee.enrollResponse()
242289

243-
return refreshCmds + zigbee.enrollResponse()
290+
return refreshCmds
244291
}
245292

246293
def configure() {
247294
// Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time)
248295
// enrolls with default periodic reporting until newer 5 min interval is confirmed
249296
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
250297

298+
log.debug "Configuring Reporting"
299+
def configCmds = []
300+
251301
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
252302
// battery minReport 30 seconds, maxReportTime 6 hrs by default
253-
return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config
303+
if (device.getDataValue("manufacturer") == "Samjin") {
304+
configCmds += zigbee.configureReporting(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021, DataType.UINT8, 30, 21600, 0x10)
305+
} else {
306+
configCmds += zigbee.batteryConfig()
307+
}
308+
configCmds += zigbee.temperatureConfig(30, 300)
309+
310+
return refresh() + configCmds // send refresh cmds as part of config
254311
}
255312

256313
private shouldUseOldBatteryReporting() {

devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,18 @@ metadata {
117117
}
118118
}
119119

120+
private List<Map> collectAttributes(Map descMap) {
121+
List<Map> descMaps = new ArrayList<Map>()
122+
123+
descMaps.add(descMap)
124+
125+
if (descMap.additionalAttrs) {
126+
descMaps.addAll(descMap.additionalAttrs)
127+
}
128+
129+
return descMaps
130+
}
131+
120132
def parse(String description) {
121133
def maps = []
122134
maps << zigbee.getEvent(description)
@@ -126,8 +138,23 @@ def parse(String description) {
126138
maps += parseIasMessage(description)
127139
} else {
128140
Map descMap = zigbee.parseDescriptionAsMap(description)
129-
if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) {
130-
maps << getBatteryResult(Integer.parseInt(descMap.value, 16))
141+
142+
if (descMap?.clusterInt == zigbee.POWER_CONFIGURATION_CLUSTER && descMap.commandInt != 0x07 && descMap.value) {
143+
List<Map> descMaps = collectAttributes(descMap)
144+
145+
if (device.getDataValue("manufacturer") == "Samjin") {
146+
def battMap = descMaps.find { it.attrInt == 0x0021 }
147+
148+
if (battMap) {
149+
maps += getBatteryPercentageResult(Integer.parseInt(battMap.value, 16))
150+
}
151+
} else {
152+
def battMap = descMaps.find { it.attrInt == 0x0020 }
153+
154+
if (battMap) {
155+
maps += getBatteryResult(Integer.parseInt(battMap.value, 16))
156+
}
157+
}
131158
} else if (descMap?.clusterInt == 0x0500 && descMap.attrInt == 0x0002) {
132159
def zs = new ZoneStatus(zigbee.convertToInt(descMap.value, 16))
133160
maps += translateZoneStatus(zs)
@@ -263,6 +290,7 @@ private Map getBatteryResult(rawValue) {
263290
result.name = 'battery'
264291
result.translatable = true
265292
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
293+
266294
if (device.getDataValue("manufacturer") == "SmartThings") {
267295
volts = rawValue // For the batteryMap to work the key needs to be an int
268296
def batteryMap = [28: 100, 27: 100, 26: 100, 25: 90, 24: 90, 23: 70,
@@ -309,6 +337,20 @@ private Map getBatteryResult(rawValue) {
309337
return result
310338
}
311339

340+
private Map getBatteryPercentageResult(rawValue) {
341+
log.debug "Battery Percentage rawValue = ${rawValue} -> ${rawValue / 2}%"
342+
def result = [:]
343+
344+
if (0 <= rawValue && rawValue <= 200) {
345+
result.name = 'battery'
346+
result.translatable = true
347+
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
348+
result.value = Math.round(rawValue / 2)
349+
}
350+
351+
return result
352+
}
353+
312354
List<Map> garageEvent(zValue) {
313355
List<Map> results = []
314356
def absValue = zValue.abs()
@@ -338,11 +380,17 @@ def ping() {
338380

339381
def refresh() {
340382
log.debug "Refreshing Values "
383+
def refreshCmds = []
341384

342-
def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
343-
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) +
344-
zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode]) +
345-
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + zigbee.enrollResponse()
385+
if (device.getDataValue("manufacturer") == "Samjin") {
386+
refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021)
387+
} else {
388+
refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020)
389+
}
390+
refreshCmds += zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
391+
zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode]) +
392+
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) +
393+
zigbee.enrollResponse()
346394

347395
return refreshCmds
348396
}
@@ -377,7 +425,7 @@ def configure() {
377425
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
378426
// battery minReport 30 seconds, maxReportTime 6 hrs by default
379427
if (device.getDataValue("manufacturer") == "Samjin") {
380-
configCmds += zigbee.batteryConfig() +
428+
configCmds += zigbee.configureReporting(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021, DataType.UINT8, 30, 21600, 0x10) +
381429
zigbee.temperatureConfig(30, 300) +
382430
zigbee.configureReporting(0xFC02, 0x0010, DataType.BITMAP8, 0, 3600, 0x01, [mfgCode: manufacturerCode]) +
383431
zigbee.configureReporting(0xFC02, 0x0012, DataType.INT16, 0, 3600, 0x0001, [mfgCode: manufacturerCode]) +

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
146146
{
147147
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
148148

149-
if (state.MSR == "011A-0601-0901" && device.currentState('motion') == null) { // Enerwave motion doesn't always get the associationSet that the hub sends on join
149+
if (isEnerwave() && device.currentState('motion') == null) { // Enerwave motion doesn't always get the associationSet that the hub sends on join
150150
result << response(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
151151
}
152152
if (!state.lastbat || (new Date().time) - state.lastbat > 53*60*60*1000) {
@@ -250,6 +250,9 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
250250

251251
def initialPoll() {
252252
def request = []
253+
if (isEnerwave()) { // Enerwave motion doesn't always get the associationSet that the hub sends on join
254+
request << zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId)
255+
}
253256
request << zwave.batteryV1.batteryGet()
254257
request << zwave.sensorBinaryV2.sensorBinaryGet(sensorType: 0x0C) //motion
255258
commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
@@ -269,3 +272,7 @@ private command(physicalgraph.zwave.Command cmd) {
269272
cmd.format()
270273
}
271274
}
275+
276+
private isEnerwave() {
277+
zwaveInfo?.mfr?.equals("011A") && zwaveInfo?.prod?.equals("0601") && zwaveInfo?.model?.equals("0901")
278+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
*/
1414
metadata {
15-
definition(name: "Z-Wave Water Valve", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.watervalve") {
15+
definition(name: "Z-Wave Water Valve", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "oic.d.watervalve", runLocally: true, executeCommandsLocally: true, minHubCoreVersion: "000.022.0004") {
1616
capability "Actuator"
1717
capability "Health Check"
1818
capability "Valve"

smartapps/michaelstruck/color-coordinator.src/i18n/bg-BG.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@
2727
'''Next page'''=Следваща страница
2828
'''Text'''=Текст
2929
'''Number'''=Номер
30+
'''This application will allow you to control the settings of multiple colored lights with one control. Simply choose a master control light, and then choose the lights that will follow the settings of the master, including on/off conditions, hue, saturation, level and color temperature. Also includes a random color feature.'''=Това приложение ще позволи да управлявате настройките на много цветни лампи с една контрола. Просто изберете основна контролна лампа, след което изберете лампите, които ще следват настройките на основната лампа, включително състоянието на включване/изключване, нюанса, наситеността, нивото и цветната температура. Също така включва и функция за произволен цвят.

0 commit comments

Comments
 (0)