diff --git a/build.gradle b/build.gradle index 481d91a..8250fcb 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,9 @@ hipchatShareFile { hipchatSendNotification { String branch = project.hasProperty('branch') ? project.property('branch') : 'unknown' message = "Began executable deploy of SmartThingsPublic(${branch})." + if (branch == 'master') { + message += ' (dev shards)' + } color = branch == 'master' ? 'yellow' : 'red' notify = true } diff --git a/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy b/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy index d2f1660..bda1d20 100644 --- a/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy +++ b/devicetypes/smartthings/arrival-sensor-ha.src/arrival-sensor-ha.groovy @@ -11,6 +11,17 @@ * for the specific language governing permissions and limitations under the License. * */ + + /* + * Purpose: Arrival Sensor HA DTH File + * + * Filename: Arrival-Sensor-HA.src/Arrival-Sensor-HA.groovy + * + * Change History: + * 1. 20160115 TW - Update/Edit to support i18n translations + * 2. 20160121 TW - Update to V4 battery calcs, added pref's page title translations + */ + metadata { definition (name: "Arrival Sensor HA", namespace: "smartthings", author: "SmartThings") { capability "Tone" @@ -32,7 +43,7 @@ metadata { ]) } section { - input "checkInterval", "enum", title: "Presence timeout (minutes)", + input "checkInterval", "enum", title: "Presence timeout (minutes)", description: "Tap to set", defaultValue:"2", options: ["2", "3", "5"], displayDuringSetup: false } } @@ -82,7 +93,6 @@ def parse(String description) { private handleReportAttributeMessage(String description) { def descMap = zigbee.parseDescriptionAsMap(description) - if (descMap.clusterInt == 0x0001 && descMap.attrInt == 0x0020) { handleBatteryEvent(Integer.parseInt(descMap.value, 16)) } @@ -94,6 +104,7 @@ private handleReportAttributeMessage(String description) { * @param volts Battery voltage in .1V increments */ private handleBatteryEvent(volts) { + def descriptionText if (volts == 0 || volts == 255) { log.debug "Ignoring invalid value for voltage (${volts/10}V)" } @@ -107,15 +118,17 @@ private handleBatteryEvent(volts) { volts = minVolts else if (volts > maxVolts) volts = maxVolts - def pct = batteryMap[volts] - if (pct != null) { + def value = batteryMap[volts] + if (value != null) { def linkText = getLinkText(device) + descriptionText = '{{ linkText }} battery was {{ value }}' def eventMap = [ name: 'battery', - value: pct, - descriptionText: "${linkText} battery was ${pct}%" + value: value, + descriptionText: descriptionText, + translatable: true ] - log.debug "Creating battery event for voltage=${volts/10}V: ${eventMap}" + log.debug "Creating battery event for voltage=${volts/10}V: ${linkText} ${eventMap.name} is ${eventMap.value}%" sendEvent(eventMap) } } @@ -131,13 +144,19 @@ private handlePresenceEvent(present) { stopTimer() } def linkText = getLinkText(device) + def descriptionText + if ( present ) + descriptionText = "{{ linkText }} has arrived" + else + descriptionText = "{{ linkText }} has left" def eventMap = [ name: "presence", value: present ? "present" : "not present", linkText: linkText, - descriptionText: "${linkText} has ${present ? 'arrived' : 'left'}", + descriptionText: descriptionText, + translatable: true ] - log.debug "Creating presence event: ${eventMap}" + log.debug "Creating presence event: ${device.displayName} ${eventMap.name} is ${eventMap.value}" sendEvent(eventMap) } @@ -158,4 +177,4 @@ def checkPresenceCallback() { if (timeSinceLastCheckin >= theCheckInterval) { handlePresenceEvent(false) } -} +} \ No newline at end of file diff --git a/devicetypes/smartthings/arrival-sensor-ha.src/i18n/messages.properties b/devicetypes/smartthings/arrival-sensor-ha.src/i18n/messages.properties new file mode 100644 index 0000000..7bdabef --- /dev/null +++ b/devicetypes/smartthings/arrival-sensor-ha.src/i18n/messages.properties @@ -0,0 +1,35 @@ +#============================================================================== +# Copyright 2016 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. +#============================================================================== +# Purpose: Arrival Sensor HA i18n Translation File +# +# Filename: Arrival-Sensor-HA.src/i18n/messages.properties +# +# Change History: +# 1. 20160115 TW Initial release with informal Korean translation. +# 2. 20160121 TW Added def preference section titles. +#============================================================================== +# Korean (ko) +# Device Preferences +'''Give your device a name'''.ko=기기 이름 바꾸기 +'''Set Device Image'''.ko=기기 이미지 설정 +'''Presence timeout (minutes)'''.ko=시간 초과. 스마트폰 위치 정보 +'''Tap to set'''.ko=눌러서 설정 +'''Arrival Sensor'''.ko=도착알림 센서 +# Events / Notifications +'''{{ linkText }} battery was {{ value }}'''.ko={{ linkText }}남아있는 배터리는 {{ value }}입니다. +'''{{ linkText }} has arrived'''.ko={{ linkText }}집에 도착했습니다. +'''{{ linkText }} has left'''.ko={{ linkText }}집을 나갔습니다. +#============================================================================== diff --git a/devicetypes/smartthings/ecobee-sensor.src/ecobee-sensor.groovy b/devicetypes/smartthings/ecobee-sensor.src/ecobee-sensor.groovy index 6110a27..381f6fc 100644 --- a/devicetypes/smartthings/ecobee-sensor.src/ecobee-sensor.groovy +++ b/devicetypes/smartthings/ecobee-sensor.src/ecobee-sensor.groovy @@ -20,7 +20,6 @@ metadata { capability "Temperature Measurement" capability "Motion Sensor" capability "Refresh" - capability "Polling" } tiles { @@ -68,6 +67,6 @@ def refresh() { void poll() { log.debug "Executing 'poll' using parent SmartApp" - parent.pollChild(this) + parent.pollChild() } diff --git a/devicetypes/smartthings/ecobee-thermostat.src/ecobee-thermostat.groovy b/devicetypes/smartthings/ecobee-thermostat.src/ecobee-thermostat.groovy index eb245d6..7b08b14 100644 --- a/devicetypes/smartthings/ecobee-thermostat.src/ecobee-thermostat.groovy +++ b/devicetypes/smartthings/ecobee-thermostat.src/ecobee-thermostat.groovy @@ -20,7 +20,6 @@ metadata { capability "Actuator" capability "Thermostat" capability "Temperature Measurement" - capability "Polling" capability "Sensor" capability "Refresh" capability "Relative Humidity Measurement" @@ -134,9 +133,7 @@ def refresh() { void poll() { log.debug "Executing 'poll' using parent SmartApp" - - def results = parent.pollChild(this) - generateEvent(results) //parse received message from parent + parent.pollChild() } def generateEvent(Map results) { @@ -382,12 +379,16 @@ def getDataByName(String name) { state[name] ?: device.getDataValue(name) } -def setThermostatMode(String value) { - log.debug "setThermostatMode({$value})" +def setThermostatMode(String mode) { + log.debug "setThermostatMode($mode)" + mode = mode.toLowerCase() + switchToMode(mode) } -def setThermostatFanMode(String value) { - log.debug "setThermostatFanMode({$value})" +def setThermostatFanMode(String mode) { + log.debug "setThermostatFanMode($mode)" + mode = mode.toLowerCase() + switchToFanMode(mode) } def generateModeEvent(mode) { diff --git a/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy b/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy index f49ec95..a5d41ef 100644 --- a/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy +++ b/devicetypes/smartthings/hue-bulb.src/hue-bulb.groovy @@ -3,6 +3,7 @@ * * Author: SmartThings */ + // for the UI metadata { // Automatically generated. Make future change here. @@ -27,10 +28,10 @@ metadata { tiles (scale: 2){ multiAttributeTile(name:"rich-control", type: "lighting", width: 6, height: 4, canChangeIcon: true){ tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { - attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" + attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" + attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#C6C7CC", nextState:"turningOn" + attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff" + attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#C6C7CC", nextState:"turningOn" } tileAttribute ("device.level", key: "SLIDER_CONTROL") { attributeState "level", action:"switch level.setLevel", range:"(0..100)" @@ -43,16 +44,10 @@ metadata { } } - standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - state "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - } - controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") { state "colorTemperature", action:"color temperature.setColorTemperature" } + valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { state "colorTemperature", label: '${currentValue} K' } @@ -60,29 +55,12 @@ metadata { standardTile("reset", "device.reset", height: 2, width: 2, inactiveLabel: false, decoration: "flat") { state "default", label:"Reset Color", action:"reset", icon:"st.lights.philips.hue-single" } - standardTile("refresh", "device.switch", height: 2, width: 2, inactiveLabel: false, decoration: "flat") { + + standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") { state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" } - controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false, range:"(0..100)") { - state "level", action:"switch level.setLevel" - } - valueTile("level", "device.level", inactiveLabel: false, decoration: "flat") { - state "level", label: 'Level ${currentValue}%' - } - controlTile("saturationSliderControl", "device.saturation", "slider", height: 1, width: 2, inactiveLabel: false) { - state "saturation", action:"color control.setSaturation" - } - valueTile("saturation", "device.saturation", inactiveLabel: false, decoration: "flat") { - state "saturation", label: 'Sat ${currentValue} ' - } - controlTile("hueSliderControl", "device.hue", "slider", height: 1, width: 2, inactiveLabel: false) { - state "hue", action:"color control.setHue" - } - valueTile("hue", "device.hue", inactiveLabel: false, decoration: "flat") { - state "hue", label: 'Hue ${currentValue} ' - } - main(["switch"]) + main(["rich-control"]) details(["rich-control", "colorTempSliderControl", "colorTemp", "reset", "refresh"]) } } @@ -127,34 +105,34 @@ void nextLevel() { void setLevel(percent) { log.debug "Executing 'setLevel'" parent.setLevel(this, percent) - sendEvent(name: "level", value: percent) + sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%") } void setSaturation(percent) { log.debug "Executing 'setSaturation'" parent.setSaturation(this, percent) - sendEvent(name: "saturation", value: percent) + sendEvent(name: "saturation", value: percent, displayed: false) } void setHue(percent) { log.debug "Executing 'setHue'" parent.setHue(this, percent) - sendEvent(name: "hue", value: percent) + sendEvent(name: "hue", value: percent, displayed: false) } void setColor(value) { log.debug "setColor: ${value}, $this" parent.setColor(this, value) - if (value.hue) { sendEvent(name: "hue", value: value.hue)} - if (value.saturation) { sendEvent(name: "saturation", value: value.saturation)} + if (value.hue) { sendEvent(name: "hue", value: value.hue, displayed: false)} + if (value.saturation) { sendEvent(name: "saturation", value: value.saturation, displayed: false)} if (value.hex) { sendEvent(name: "color", value: value.hex)} - if (value.level) { sendEvent(name: "level", value: value.level)} - if (value.switch) { sendEvent(name: "switch", value: value.switch)} + if (value.level) { sendEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")} + sendEvent(name: "switch", value: "on") } void reset() { log.debug "Executing 'reset'" - def value = [level:100, hex:"#90C638", saturation:56, hue:23] + def value = [level:100, saturation:56, hue:23] setAdjustedColor(value) parent.poll() } diff --git a/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy b/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy index 49e7f2f..18affa4 100644 --- a/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy +++ b/devicetypes/smartthings/hue-lux-bulb.src/hue-lux-bulb.groovy @@ -36,13 +36,6 @@ metadata { } } - standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { - state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff" - state "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn" - } - controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false, range:"(0..100)") { state "level", action:"switch level.setLevel" } @@ -51,7 +44,7 @@ metadata { state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh" } - main(["switch"]) + main(["rich-control"]) details(["rich-control", "refresh"]) } } diff --git a/devicetypes/smartthings/mobile-presence.src/i18n/messages.properties b/devicetypes/smartthings/mobile-presence.src/i18n/messages.properties index bfe484e..3e4de71 100644 --- a/devicetypes/smartthings/mobile-presence.src/i18n/messages.properties +++ b/devicetypes/smartthings/mobile-presence.src/i18n/messages.properties @@ -19,13 +19,14 @@ # # Change History: # 1. 20160205 TW Initial release with informal Korean translation. +# 2. 20160224 TW Updated with formal Korean translation. #============================================================================== # Korean (ko) # Device Preferences '''Give your device a name'''.ko=기기 이름 바꾸기 -'''Set Device Image'''.ko=디바이스 이미지 설정 +'''Set Device Image'''.ko=기기 이미지 설정 # Events / Notifications -'''{{ linkText }} has left'''.ko={{ linkText }}님이 나갔습니다 -'''{{ linkText }} has arrived'''.ko={{ linkText }}님이 도착했습니다 +'''{{ linkText }} has left'''.ko={{ linkText }}집을 나갔습니다. +'''{{ linkText }} has arrived'''.ko={{ linkText }}집에 도착했습니다. '''present'''.ko=집안 -'''not present'''.ko=부재중 +'''not present'''.ko=외출 diff --git a/devicetypes/smartthings/mobile-presence.src/mobile-presence.groovy b/devicetypes/smartthings/mobile-presence.src/mobile-presence.groovy index 34bb78a..b0fa346 100644 --- a/devicetypes/smartthings/mobile-presence.src/mobile-presence.groovy +++ b/devicetypes/smartthings/mobile-presence.src/mobile-presence.groovy @@ -1,16 +1,28 @@ -/** - * Copyright 2015 SmartThings +/* +=============================================================================== + * Copyright 2016 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: + * 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. + * 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. +=============================================================================== + * Purpose: Mobile Presence DTH File * + * Filename: mobile-presence.src/mobile-presence.groovy + * + * Change History: + * 1. 20160205 TW - Update/Edit to support i18n translations +=============================================================================== */ + metadata { definition (name: "Mobile Presence", namespace: "smartthings", author: "SmartThings") { capability "Presence Sensor" @@ -41,6 +53,7 @@ def parse(String description) { def isStateChange = isStateChange(device, name, value) def results = [ + translatable: true, name: name, value: value, unit: null, @@ -72,8 +85,8 @@ private String parseValue(String description) { private parseDescriptionText(String linkText, String value, String description) { switch(value) { - case "present": return "$linkText has arrived" - case "not present": return "$linkText has left" + case "present": return "{{ linkText }} has arrived" + case "not present": return "{{ linkText }} has left" default: return value } } @@ -84,4 +97,4 @@ private getState(String value) { case "not present": return "left" default: return value } -} +} \ No newline at end of file diff --git a/devicetypes/smartthings/smartpower-outlet.src/i18n/messages.properties b/devicetypes/smartthings/smartpower-outlet.src/i18n/messages.properties new file mode 100644 index 0000000..49ce523 --- /dev/null +++ b/devicetypes/smartthings/smartpower-outlet.src/i18n/messages.properties @@ -0,0 +1,31 @@ +#============================================================================== +# Copyright 2016 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. +#============================================================================== +# Purpose: SmartPower Outlet i18n Translation File +# +# Filename: SmartPower-Outlet.src/i18n/messages.properties +# +# Change History: +# 1. 20160116 TW Initial release with informal Korean translation. +#============================================================================== +# Korean (ko) +# Device Preferences +'''Give your device a name'''.ko=기기 이름 바꾸기 +'''Outlet'''.ko=플러그 +# Events descriptionText +'''{{ device.displayName }} is On'''.ko={{ device.displayName }}켜졌습니다. +'''{{ device.displayName }} is Off'''.ko={{ device.displayName }}꺼졌습니다. +'''{{ device.displayName }} power is {{ value }} Watts'''.ko={{ device.displayName }} 전원은 {{ value }}와트입니다 +#============================================================================== diff --git a/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy b/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy index d6b3b76..0dea33e 100644 --- a/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy +++ b/devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy @@ -1,19 +1,26 @@ -/** - * Copyright 2015 SmartThings +/* +=============================================================================== + * Copyright 2016 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: + * 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. + * 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. +=============================================================================== + * Purpose: SmartPower Outlet DTH File * - * SmartPower Outlet (CentraLite) + * Filename: SmartPower-Outlet.src/SmartPower-Outlet.groovy * - * Author: SmartThings - * Date: 2015-08-23 + * Change History: + * 1. 20160117 TW - Update/Edit to support i18n translations +=============================================================================== */ metadata { // Automatically generated. Make future change here. @@ -91,22 +98,22 @@ def parse(String description) { finalResult = getPowerDescription(zigbee.parseDescriptionAsMap(description)) if (finalResult) { - log.info finalResult + log.info "final result = $finalResult" if (finalResult.type == "update") { log.info "$device updates: ${finalResult.value}" } else if (finalResult.type == "power") { def powerValue = (finalResult.value as Integer)/10 - sendEvent(name: "power", value: powerValue) + sendEvent(name: "power", value: powerValue, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true ) /* Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10 - power level is an integer. The exact power level with correct units needs to be handled in the device type to account for the different Divisor value (AttrId: 0302) and POWER Unit (AttrId: 0300). CLUSTER for simple metering is 0702 */ } else { - sendEvent(name: finalResult.type, value: finalResult.value) + def descriptionText = finalResult.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off' + sendEvent(name: finalResult.type, value: finalResult.value, descriptionText: descriptionText, translatable: true) } } else { diff --git a/devicetypes/smartthings/smartsense-moisture-sensor.src/i18n/messages.properties b/devicetypes/smartthings/smartsense-moisture-sensor.src/i18n/messages.properties index 307fbb8..c0a19a0 100644 --- a/devicetypes/smartthings/smartsense-moisture-sensor.src/i18n/messages.properties +++ b/devicetypes/smartthings/smartsense-moisture-sensor.src/i18n/messages.properties @@ -1,14 +1,41 @@ - -# Generated on Wed Feb 24 14:28:26 CST 2016 by dylan -'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오 -'''Degrees'''.ko=온도 -'''Temperature Offset'''.ko=온도 직접 설정 -'''This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.'''.ko=기준 온도를 원하는대로 몇 도 올리거나 내려서 설정할 수 있습니다. -'''battery'''.ko=배터리 +#============================================================================== +# Copyright 2016 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. +#============================================================================== +# Purpose: SmartSense Moisture Sensor i18n Translation File +# +# Filename: SmartSense-Moisture-Sensor.src/i18n/messages.properties +# +# Change History: +# 1. 20160116 TW Initial release with formal Korean translation. +#============================================================================== +# Korean (ko) +# Device Preferences '''dry'''.ko=건조 '''wet'''.ko=누수 -'''{{ device.displayName }} battery has too much power: (> 3.5) volts.'''.ko={{ device.displayName }} 배터리 전력이 너무 높습니다(3.5볼트 초과). -'''{{ device.displayName }} battery was {{ value }}'''.ko={{ device.displayName }} 배터리가 {{ value }}였습니다 -'''{{ device.displayName }} is {{ value | translate }}'''.ko={{ device.displayName }}이(가) {{ value | translate }}입니다 +'''battery'''.ko=배터리 +'''Temperature Offset'''.ko=온도 직접 설정 +'''This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.'''.ko=기준 온도를 원하는대로 몇 도 올리거나 내려서 설정할 수 있습니다. +'''Degrees'''.ko=온도 +'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오 +'''Give your device a name'''.ko=기기 이름 바꾸기 +'''Water Leak Sensor'''.ko=누수센서 +# Events descriptionText +'''{{ device.displayName }} is dry'''.ko={{ device.displayName }}가 건조 +'''{{ device.displayName }} is wet'''.ko={{ device.displayName }}누수 '''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}이(가) {{ value }}°C였습니다 '''{{ device.displayName }} was {{ value }}°F'''.ko={{ device.displayName }}이(가) {{ value }}°F였습니다 +'''{{ device.displayName }} battery has too much power: (> 3.5) volts.'''.ko={{ device.displayName }} 배터리 전력이 너무 높습니다(3.5볼트 초과). +'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리는 {{ value }}%입니다. +#============================================================================== diff --git a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy index 1c38e23..599ba97 100644 --- a/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy +++ b/devicetypes/smartthings/smartsense-moisture-sensor.src/smartsense-moisture-sensor.groovy @@ -1,18 +1,29 @@ -/** - * SmartSense Moisture Sensor +/* +=============================================================================== + * Copyright 2016 SmartThings * - * Copyright 2014 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: + * 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. + * 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. +=============================================================================== + * Purpose: SmartSense Moisture Sensor DTH File * + * Filename: SmartSense-Moisture-Sensor.src/SmartSense-Moisture-Sensor.groovy + * + * Change History: + * 1. 20160116 TW - Update/Edit to support i18n translations + * 2. 20160125 TW = Incorporated new battery mapping from TM +=============================================================================== */ + metadata { definition (name: "SmartSense Moisture Sensor",namespace: "smartthings", author: "SmartThings") { capability "Configuration" @@ -43,7 +54,7 @@ metadata { ]) } section { - input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph" + input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.", displayDuringSetup: false, type: "paragraph", element: "paragraph" input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false } } @@ -116,16 +127,16 @@ private Map parseCatchAllMessage(String description) { resultMap = getBatteryResult(cluster.data.last()) break - case 0x0402: - // temp is last 2 data values. reverse to swap endian - String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() - def value = getTemperature(temp) - resultMap = getTemperatureResult(value) - break - } - } + case 0x0402: + // temp is last 2 data values. reverse to swap endian + String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join() + def value = getTemperature(temp) + resultMap = getTemperatureResult(value) + break + } + } - return resultMap + return resultMap } private boolean shouldProcessMessage(cluster) { @@ -220,7 +231,8 @@ private Map getBatteryResult(rawValue) { def result = [ name: 'battery', - value: '--' + value: '--', + translatable: true ] def volts = rawValue / 10 @@ -228,7 +240,7 @@ private Map getBatteryResult(rawValue) { if (rawValue == 0 || rawValue == 255) {} else { if (volts > 3.5) { - result.descriptionText = "${linkText} battery has too much power (${volts} volts)." + result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts." } else { if (device.getDataValue("manufacturer") == "SmartThings") { @@ -245,7 +257,7 @@ private Map getBatteryResult(rawValue) { def pct = batteryMap[volts] if (pct != null) { result.value = pct - result.descriptionText = "${linkText} battery was ${result.value}%" + result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } else { @@ -253,7 +265,7 @@ private Map getBatteryResult(rawValue) { def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) result.value = Math.min(100, (int) pct * 100) - result.descriptionText = "${linkText} battery was ${result.value}%" + result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } } @@ -263,27 +275,37 @@ private Map getBatteryResult(rawValue) { private Map getTemperatureResult(value) { log.debug 'TEMP' - def linkText = getLinkText(device) if (tempOffset) { def offset = tempOffset as int def v = value as int value = v + offset } - def descriptionText = "${linkText} was ${value}°${temperatureScale}" + def descriptionText + if ( temperatureScale == 'C' ) + descriptionText = '{{ device.displayName }} was {{ value }}°C' + else + descriptionText = '{{ device.displayName }} was {{ value }}°F' + return [ name: 'temperature', value: value, - descriptionText: descriptionText + descriptionText: descriptionText, + translatable: true ] } private Map getMoistureResult(value) { - log.debug 'water' - String descriptionText = "${device.displayName} is ${value}" + log.debug "water" + def descriptionText + if ( value == "wet" ) + descriptionText = '{{ device.displayName }} is wet' + else + descriptionText = '{{ device.displayName }} is dry' return [ name: 'water', value: value, - descriptionText: descriptionText + descriptionText: descriptionText, + translatable: true ] } diff --git a/devicetypes/smartthings/smartsense-motion-sensor.src/i18n/messages.properties b/devicetypes/smartthings/smartsense-motion-sensor.src/i18n/messages.properties index f1b7c52..f06d5ad 100644 --- a/devicetypes/smartthings/smartsense-motion-sensor.src/i18n/messages.properties +++ b/devicetypes/smartthings/smartsense-motion-sensor.src/i18n/messages.properties @@ -1,13 +1,40 @@ - -# Generated on Wed Feb 24 14:28:26 CST 2016 by dylan -'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오 -'''Degrees'''.ko=온도 -'''Temperature Offset'''.ko=온도 직접 설정 -'''This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.'''.ko=기준 온도를 원하는대로 몇 도 올리거나 내려서 설정할 수 있습니다. +#============================================================================== +# Copyright 2016 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. +#============================================================================== +# Purpose: SmartSense Motion Sensor i18n Translation File +# +# Filename: SmartSense-Motion-Sensor.src/i18n/messages.properties +# +# Change History: +# 1. 20160116 TW Initial release with formal Korean translation. +# 2. 20160224 TW Updated formal Korean translations from Mike Stoller. +#============================================================================== +# Korean (ko) +# Device Preferences '''battery'''.ko=배터리 -'''{{ device.displayName }} battery has too much power: (> 3.5) volts.'''.ko={{ device.displayName }} 배터리 전력이 너무 높습니다(3.5볼트 초과). -'''{{ device.displayName }} battery was {{ value }}'''.ko={{ device.displayName }} 배터리가 {{ value }}였습니다 -'''{{ device.displayName }} detected motion'''.ko={{ device.displayName }}가 움직임을 감지하였습니다. -'''{{ device.displayName }} motion has stopped'''.ko={{ device.displayName }} 동작이 중단되었습니다 -'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}이(가) {{ value }}°C였습니다 +'''Temperature Offset'''.ko=온도 직접 설정 +'''This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.'''.ko=기준 온도를 원하는대로 몇 도 올리거나 내려서 설정할 수 있습니다. +'''Degrees'''.ko=온도 +'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오 +'''Give your device a name'''.ko=기기 이름 바꾸기 +'''Motion Sensor'''.ko=모션 센서 +# Events descriptionText +'''{{ device.displayName }} detected motion'''.ko={{ device.displayName }} 가 움직임을 감지하였습니다. +'''{{ device.displayName }} motion has stopped'''.ko={{ device.displayName }}움직임이 중단되었습니다 +'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}이(가){{ value }}°C였습니다. '''{{ device.displayName }} was {{ value }}°F'''.ko={{ device.displayName }}이(가) {{ value }}°F였습니다 +'''{{ device.displayName }} battery has too much power: (> 3.5) volts.'''.ko={{ device.displayName }} 배터리 전력이 너무 높습니다(3.5볼트 초과). +'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리는 {{ value }}%입니다. +#============================================================================== diff --git a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy index e787c24..a840d48 100644 --- a/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy +++ b/devicetypes/smartthings/smartsense-motion-sensor.src/smartsense-motion-sensor.groovy @@ -1,17 +1,27 @@ -/** - * SmartSense Motion/Temp Sensor +/* +=============================================================================== + * Copyright 2016 SmartThings * - * Copyright 2014 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: + * 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. + * 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. +=============================================================================== + * Purpose: SmartSense Motion Sensor DTH File * + * Filename: SmartSense-Motion-Sensor.src/SmartSense-Motion-Sensor.groovy + * + * Change History: + * 1. 20160116 TW - Update/Edit to support i18n translations + * 2. 20160125 TW = Incorporated new battery mapping from TM +=============================================================================== */ metadata { @@ -47,7 +57,7 @@ metadata { ]) } section { - input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph" + input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.", displayDuringSetup: false, type: "paragraph", element: "paragraph" input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false } } @@ -236,7 +246,8 @@ private Map getBatteryResult(rawValue) { def result = [ name: 'battery', - value: '--' + value: '--', + translatable: true ] def volts = rawValue / 10 @@ -244,7 +255,7 @@ private Map getBatteryResult(rawValue) { if (rawValue == 0 || rawValue == 255) {} else { if (volts > 3.5) { - result.descriptionText = "${linkText} battery has too much power (${volts} volts)." + result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts." } else { if (device.getDataValue("manufacturer") == "SmartThings") { @@ -261,7 +272,8 @@ private Map getBatteryResult(rawValue) { def pct = batteryMap[volts] if (pct != null) { result.value = pct - result.descriptionText = "${linkText} battery was ${result.value}%" + def value = pct + result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } else { @@ -269,7 +281,7 @@ private Map getBatteryResult(rawValue) { def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) result.value = Math.min(100, (int) pct * 100) - result.descriptionText = "${linkText} battery was ${result.value}%" + result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } } @@ -279,28 +291,33 @@ private Map getBatteryResult(rawValue) { private Map getTemperatureResult(value) { log.debug 'TEMP' - def linkText = getLinkText(device) if (tempOffset) { def offset = tempOffset as int def v = value as int value = v + offset } - def descriptionText = "${linkText} was ${value}°${temperatureScale}" + def descriptionText + if ( temperatureScale == 'C' ) + descriptionText = '{{ device.displayName }} was {{ value }}°C' + else + descriptionText = '{{ device.displayName }} was {{ value }}°F' + return [ name: 'temperature', value: value, - descriptionText: descriptionText + descriptionText: descriptionText, + translatable: true ] } private Map getMotionResult(value) { log.debug 'motion' - String linkText = getLinkText(device) - String descriptionText = value == 'active' ? "${linkText} detected motion" : "${linkText} motion has stopped" + String descriptionText = value == 'active' ? "{{ device.displayName }} detected motion" : "{{ device.displayName }} motion has stopped" return [ name: 'motion', value: value, - descriptionText: descriptionText + descriptionText: descriptionText, + translatable: true ] } diff --git a/devicetypes/smartthings/smartsense-multi-sensor.src/i18n/messages.properties b/devicetypes/smartthings/smartsense-multi-sensor.src/i18n/messages.properties index 2326d40..0f97e6c 100644 --- a/devicetypes/smartthings/smartsense-multi-sensor.src/i18n/messages.properties +++ b/devicetypes/smartthings/smartsense-multi-sensor.src/i18n/messages.properties @@ -1,20 +1,45 @@ - -# Generated on Wed Feb 24 14:28:26 CST 2016 by dylan -'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오 -'''Degrees'''.ko=온도 -'''Do you want to use this sensor on a garage door?'''.ko=차고 문의 센서 사용 설정하기 +#============================================================================== +# Copyright 2016 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. +#============================================================================== +# Purpose: SmartSense Multi Sensor i18n Translation File +# +# Filename: SmartSense-Multi-Sensor.src/i18n/messages.properties +# +# Change History: +# 1. 20160117 TW Initial release with informal Korean translation. +#============================================================================== +# Korean (ko) +# Device Preferences +'''Yes'''.ko=예 '''No'''.ko=아니요 -'''Tap to set'''.ko=눌러서 설정 +'''battery'''.ko=배터리 '''Temperature Offset'''.ko=온도 직접 설정 '''This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.'''.ko=기준 온도를 원하는대로 몇 도 올리거나 내려서 설정할 수 있습니다. +'''Degrees'''.ko=온도 +'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오 +'''Do you want to use this sensor on a garage door?'''.ko=차고 문의 센서 사용 설정하기 +'''Tap to set'''.ko=눌러서 설정 +'''Give your device a name'''.ko=기기 이름 바꾸기 +'''Multipurpose Sensor'''.ko=멀티 센서 +# Events descriptionText +'''{{ device.displayName }} was opened'''.ko={{ device.displayName }}열림을 감지하였습니다. +'''{{ device.displayName }} was closed'''.ko={{ device.displayName }}닫혔습니다. +'''{{ device.displayName }} was active'''.ko={{ device.displayName }}활성화되었습니다. +'''{{ device.displayName }} was inactive'''.ko={{ device.displayName }}비활성화되었습니다. +'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}이(가){{ value }}°C였습니다. +'''{{ device.displayName }} was {{ value }}°F'''.ko={{ device.displayName }}이(가) {{ value }}°F였습니다 +'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리는 {{ value }}%입니다. '''Updating device to garage sensor'''.ko=기기-차고 센서 업데이트 중 '''Updating device to open/close sensor'''.ko=기기-열림/닫힘 센서 업데이트 중 -'''Yes'''.ko=예 -'''{{ device.displayName }} status was closed'''.ko={{ device.displayName }}은(는) 닫힌 상태입니다 -'''{{ device.displayName }} status was opened'''.ko={{ device.displayName }}은(는) 열린 상태입니다 -'''{{ device.displayName }} was active'''.ko={{ device.displayName }}이(가) 활성화되었습니다 -'''{{ device.displayName }} was closed'''.ko={{ device.displayName }}이(가) 닫혔습니다 -'''{{ device.displayName }} was inactive'''.ko={{ device.displayName }}이(가) 비활성화되었습니다 -'''{{ device.displayName }} was opened'''.ko={{ device.displayName }}이(가) 열렸습니다 -'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}이(가) {{ value }}°C였습니다 -'''{{ device.displayName }} was {{ value }}°F'''.ko={{ device.displayName }}이(가) {{ value }}°F였습니다 diff --git a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy index 01df653..ab26143 100644 --- a/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy +++ b/devicetypes/smartthings/smartsense-multi-sensor.src/smartsense-multi-sensor.groovy @@ -1,17 +1,27 @@ -/** - * SmartSense Multi +/* +=============================================================================== + * Copyright 2016 SmartThings * - * Copyright 2015 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: + * 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. + * 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. +=============================================================================== + * Purpose: SmartSense Multi Sensor DTH File * + * Filename: SmartSense-Multi-Sensor.src/SmartSense-Multi-Sensor.groovy + * + * Change History: + * 1. 20160117 TW - Update/Edit to support i18n translations + * 2. 20160125 TW = Incorporated new battery mapping from TM +=============================================================================== */ metadata { @@ -62,11 +72,11 @@ metadata { ]) } section { - input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph" + input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.", displayDuringSetup: false, type: "paragraph", element: "paragraph" input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false } section { - input("garageSensor", "enum", title: "Do you want to use this sensor on a garage door?", options: ["Yes", "No"], defaultValue: "No", required: false, displayDuringSetup: false) + input("garageSensor", "enum", title: "Do you want to use this sensor on a garage door?", description: "Tap to set", options: ["Yes", "No"], defaultValue: "No", required: false, displayDuringSetup: false) } } @@ -273,19 +283,19 @@ def updated() { if (garageSensor == "Yes") { def descriptionText = "Updating device to garage sensor" if (device.latestValue("status") == "open") { - sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText) + sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText, translatable: true) } else if (device.latestValue("status") == "closed") { - sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText) + sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText, translatable: true) } } else { def descriptionText = "Updating device to open/close sensor" if (device.latestValue("status") == "garage-open") { - sendEvent(name: 'status', value: 'open', descriptionText: descriptionText) + sendEvent(name: 'status', value: 'open', descriptionText: descriptionText, translatable: true) } else if (device.latestValue("status") == "garage-closed") { - sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText) + sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText, translatable: true) } } } @@ -301,11 +311,11 @@ def getTemperature(value) { private Map getBatteryResult(rawValue) { log.debug "Battery rawValue = ${rawValue}" - def linkText = getLinkText(device) def result = [ name: 'battery', - value: '--' + value: '--', + translatable: true ] def volts = rawValue / 10 @@ -313,7 +323,7 @@ private Map getBatteryResult(rawValue) { if (rawValue == 0 || rawValue == 255) {} else { if (volts > 3.5) { - result.descriptionText = "${linkText} battery has too much power (${volts} volts)." + result.descriptionText = "{{ device.displayName }} battery has too much power: (> 3.5) volts." } else { if (device.getDataValue("manufacturer") == "SmartThings") { @@ -330,7 +340,7 @@ private Map getBatteryResult(rawValue) { def pct = batteryMap[volts] if (pct != null) { result.value = pct - result.descriptionText = "${linkText} battery was ${result.value}%" + result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } else { @@ -338,7 +348,7 @@ private Map getBatteryResult(rawValue) { def maxVolts = 3.0 def pct = (volts - minVolts) / (maxVolts - minVolts) result.value = Math.min(100, (int) pct * 100) - result.descriptionText = "${linkText} battery was ${result.value}%" + result.descriptionText = "{{ device.displayName }} battery was {{ value }}%" } } } @@ -348,40 +358,50 @@ private Map getBatteryResult(rawValue) { private Map getTemperatureResult(value) { log.debug "Temperature" - def linkText = getLinkText(device) if (tempOffset) { def offset = tempOffset as int def v = value as int value = v + offset } - def descriptionText = "${linkText} was ${value}°${temperatureScale}" + def descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C': + '{{ device.displayName }} was {{ value }}°F' + return [ name: 'temperature', value: value, - descriptionText: descriptionText + descriptionText: descriptionText, + translatable: true ] } private Map getContactResult(value) { - log.debug "Contact" - def linkText = getLinkText(device) - def descriptionText = "${linkText} was ${value == 'open' ? 'opened' : 'closed'}" - sendEvent(name: 'contact', value: value, descriptionText: descriptionText, displayed:false) - sendEvent(name: 'status', value: value, descriptionText: descriptionText) + log.debug "Contact: ${device.displayName} value = ${value}" + def descriptionText = value == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed' + sendEvent(name: 'contact', value: value, descriptionText: descriptionText, displayed: false, translatable: true) + sendEvent(name: 'status', value: value, descriptionText: descriptionText, translatable: true) } private getAccelerationResult(numValue) { log.debug "Acceleration" def name = "acceleration" - def value = numValue.endsWith("1") ? "active" : "inactive" - def linkText = getLinkText(device) - def descriptionText = "$linkText was $value" + def value + def descriptionText + + if ( numValue.endsWith("1") ) { + value = "active" + descriptionText = '{{ device.displayName }} was active' + } else { + value = "inactive" + descriptionText = '{{ device.displayName }} was inactive' + } + def isStateChange = isStateChange(device, name, value) - [ + return [ name: name, value: value, descriptionText: descriptionText, - isStateChange: isStateChange + isStateChange: isStateChange, + translatable: true ] } @@ -451,15 +471,15 @@ def configure() { "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", "zcl mfg-code ${manufacturerCode}", "delay 200", - "zcl global send-me-a-report 0xFC02 0x0012 0x29 1 3600 {01}", "delay 200", + "zcl global send-me-a-report 0xFC02 0x0012 0x29 1 3600 {0100}", "delay 200", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", "zcl mfg-code ${manufacturerCode}", "delay 200", - "zcl global send-me-a-report 0xFC02 0x0013 0x29 1 3600 {01}", "delay 200", + "zcl global send-me-a-report 0xFC02 0x0013 0x29 1 3600 {0100}", "delay 200", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500", "zcl mfg-code ${manufacturerCode}", "delay 200", - "zcl global send-me-a-report 0xFC02 0x0014 0x29 1 3600 {01}", "delay 200", + "zcl global send-me-a-report 0xFC02 0x0014 0x29 1 3600 {0100}", "delay 200", "send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500" ] @@ -528,10 +548,9 @@ def garageEvent(zValue) { garageValue = 'garage-open' } if (contactValue != null){ - def linkText = getLinkText(device) - def descriptionText = "${linkText} was ${contactValue == 'open' ? 'opened' : 'closed'}" - sendEvent(name: 'contact', value: contactValue, descriptionText: descriptionText, displayed:false) - sendEvent(name: 'status', value: garageValue, descriptionText: descriptionText) + def descriptionText = contactValue == 'open' ? '{{ device.displayName }} was opened' :'{{ device.displayName }} was closed' + sendEvent(name: 'contact', value: contactValue, descriptionText: descriptionText, displayed:false, translatable: true) + sendEvent(name: 'status', value: garageValue, descriptionText: descriptionText, translatable: true) } } diff --git a/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy b/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy index 5024e42..a27c41b 100644 --- a/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy +++ b/devicetypes/smartthings/smartsense-multi.src/smartsense-multi.groovy @@ -22,6 +22,8 @@ metadata { capability "Battery" fingerprint profileId: "FC01", deviceId: "0139" + + attribute "status", "string" } simulator { @@ -99,7 +101,7 @@ def parse(String description) { } -private Map parseSingleMessage(description) { +private List parseSingleMessage(description) { def name = parseName(description) def value = parseValue(description) @@ -108,8 +110,9 @@ private Map parseSingleMessage(description) { def handlerName = value == 'open' ? 'opened' : value def isStateChange = isStateChange(device, name, value) - def results = [ - name: name, + def results = [] + results << createEvent( + name: "contact", value: value, unit: null, linkText: linkText, @@ -117,8 +120,18 @@ private Map parseSingleMessage(description) { handlerName: handlerName, isStateChange: isStateChange, displayed: displayed(description, isStateChange) - ] - log.debug "Parse results for $device: $results" + ) + + results << createEvent( + name: "status", + value: value, + unit: null, + linkText: linkText, + descriptionText: descriptionText, + handlerName: handlerName, + isStateChange: isStateChange, + displayed: displayed(description, isStateChange) + ) results } @@ -269,7 +282,7 @@ private List parseRssiLqiMessage(String description) { results } -private getContactResult(part, description) { +private List getContactResult(part, description) { def name = "contact" def value = part.endsWith("1") ? "open" : "closed" def handlerName = value == 'open' ? 'opened' : value @@ -277,16 +290,30 @@ private getContactResult(part, description) { def descriptionText = "$linkText was $handlerName" def isStateChange = isStateChange(device, name, value) - [ - name: name, - value: value, - unit: null, - linkText: linkText, - descriptionText: descriptionText, - handlerName: handlerName, - isStateChange: isStateChange, - displayed: displayed(description, isStateChange) - ] + def results = [] + results << createEvent( + name: "contact", + value: value, + unit: null, + linkText: linkText, + descriptionText: descriptionText, + handlerName: handlerName, + isStateChange: isStateChange, + displayed:false + ) + + results << createEvent( + name: "status", + value: value, + unit: null, + linkText: linkText, + descriptionText: descriptionText, + handlerName: handlerName, + isStateChange: isStateChange, + displayed: displayed(description, isStateChange) + ) + + results } private getAccelerationResult(part, description) { @@ -449,6 +476,7 @@ private Boolean isOrientationMessage(String description) { description ==~ /x:.*y:.*z:.*rssi:.*lqi:.*/ } +//Note: Not using this method anymore private String parseName(String description) { if (isSupportedDescription(description)) { return "contact" diff --git a/smartapps/com-vinli-smartthings/vinli-home-connect.src/vinli-home-connect.groovy b/smartapps/com-vinli-smartthings/vinli-home-connect.src/vinli-home-connect.groovy index 31e2a06..3bd89fb 100644 --- a/smartapps/com-vinli-smartthings/vinli-home-connect.src/vinli-home-connect.groovy +++ b/smartapps/com-vinli-smartthings/vinli-home-connect.src/vinli-home-connect.groovy @@ -67,11 +67,11 @@ mappings { def listAllDevices() { def resp = [] switches.each { - resp << [name: it.name, label: it.label, value: it.currentValue("switch"), type: "switch", id: it.id, hub: it.hub.name] + resp << [name: it.name, label: it.label, value: it.currentValue("switch"), type: "switch", id: it.id, hub: it.hub?.name] } locks.each { - resp << [name: it.name, label: it.label, value: it.currentValue("lock"), type: "lock", id: it.id, hub: it.hub.name] + resp << [name: it.name, label: it.label, value: it.currentValue("lock"), type: "lock", id: it.id, hub: it.hub?.name] } return resp } diff --git a/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy b/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy index d66e7c0..848b7b7 100644 --- a/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy +++ b/smartapps/smartthings/ecobee-connect.src/ecobee-connect.groovy @@ -463,29 +463,32 @@ def pollChildren(child = null) { } // Poll Child is invoked from the Child Device itself as part of the Poll Capability -def pollChild(child){ +def pollChild(){ - if (pollChildren(child)){ - if (!child.device.deviceNetworkId.startsWith("ecobee_sensor")){ - if(atomicState.thermostats[child.device.deviceNetworkId] != null) { - def tData = atomicState.thermostats[child.device.deviceNetworkId] - log.info "pollChild(child)>> data for ${child.device.deviceNetworkId} : ${tData.data}" - child.generateEvent(tData.data) //parse received message from parent - } else if(atomicState.thermostats[child.device.deviceNetworkId] == null) { - log.error "ERROR: Device connection removed? no data for ${child.device.deviceNetworkId}" - return null + def devices = getChildDevices() + + if (pollChildren()){ + devices.each { child -> + if (!child.device.deviceNetworkId.startsWith("ecobee_sensor")){ + if(atomicState.thermostats[child.device.deviceNetworkId] != null) { + def tData = atomicState.thermostats[child.device.deviceNetworkId] + log.info "pollChild(child)>> data for ${child.device.deviceNetworkId} : ${tData.data}" + child.generateEvent(tData.data) //parse received message from parent + } else if(atomicState.thermostats[child.device.deviceNetworkId] == null) { + log.error "ERROR: Device connection removed? no data for ${child.device.deviceNetworkId}" + return null + } } } } else { - log.info "ERROR: pollChildren(child) for ${child.device.deviceNetworkId} after polling" + log.info "ERROR: pollChildren()" return null } } void poll() { - def devices = getChildDevices() - devices.each {pollChild(it)} + pollChild() } def availableModes(child) { diff --git a/smartapps/smartthings/hue-connect.src/hue-connect.groovy b/smartapps/smartthings/hue-connect.src/hue-connect.groovy index 93453ac..5b908d8 100644 --- a/smartapps/smartthings/hue-connect.src/hue-connect.groovy +++ b/smartapps/smartthings/hue-connect.src/hue-connect.groovy @@ -24,7 +24,7 @@ definition( category: "SmartThings Labs", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/hue.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/hue@2x.png", - //singleInstance: true + singleInstance: true ) preferences { @@ -643,21 +643,25 @@ def setColorTemperature(childDevice, huesettings) { def setColor(childDevice, huesettings) { log.debug "Executing 'setColor($huesettings)'" - def hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535) - def sat = Math.min(Math.round(huesettings.saturation * 255 / 100), 255) + def hue = null + def sat = null + def xy = null + if (huesettings.hex) { + xy = getHextoXY(huesettings.hex) + } else if (huesettings.hue && huesettings.saturation) { + hue = Math.min(Math.round(huesettings.hue * 65535 / 100), 65535) + sat = Math.min(Math.round(huesettings.saturation * 255 / 100), 255) + } def alert = huesettings.alert ? huesettings.alert : "none" def transition = huesettings.transition ? huesettings.transition : 4 - def value = [sat: sat, hue: hue, alert: alert, transitiontime: transition] + def value = [xy: xy, sat: sat, hue: hue, alert: alert, transitiontime: transition, on: true] + if (huesettings.level != null) { if (huesettings.level == 1) value.bri = 1 else value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255) value.on = value.bri > 0 } - if (huesettings.switch) { - value.on = huesettings.switch == "on" - } - log.debug "sending command $value" put("lights/${getId(childDevice)}/state", value) } @@ -743,6 +747,59 @@ private getBridgeIP() { return host } +private getHextoXY(String colorStr) { + // For the hue bulb the corners of the triangle are: + // -Red: 0.675, 0.322 + // -Green: 0.4091, 0.518 + // -Blue: 0.167, 0.04 + + def cred = Integer.valueOf( colorStr.substring( 1, 3 ), 16 ) + def cgreen = Integer.valueOf( colorStr.substring( 3, 5 ), 16 ) + def cblue = Integer.valueOf( colorStr.substring( 5, 7 ), 16 ) + + double[] normalizedToOne = new double[3]; + normalizedToOne[0] = (cred / 255); + normalizedToOne[1] = (cgreen / 255); + normalizedToOne[2] = (cblue / 255); + float red, green, blue; + + // Make red more vivid + if (normalizedToOne[0] > 0.04045) { + red = (float) Math.pow( + (normalizedToOne[0] + 0.055) / (1.0 + 0.055), 2.4); + } else { + red = (float) (normalizedToOne[0] / 12.92); + } + + // Make green more vivid + if (normalizedToOne[1] > 0.04045) { + green = (float) Math.pow((normalizedToOne[1] + 0.055) + / (1.0 + 0.055), 2.4); + } else { + green = (float) (normalizedToOne[1] / 12.92); + } + + // Make blue more vivid + if (normalizedToOne[2] > 0.04045) { + blue = (float) Math.pow((normalizedToOne[2] + 0.055) + / (1.0 + 0.055), 2.4); + } else { + blue = (float) (normalizedToOne[2] / 12.92); + } + + float X = (float) (red * 0.649926 + green * 0.103455 + blue * 0.197109); + float Y = (float) (red * 0.234327 + green * 0.743075 + blue * 0.022598); + float Z = (float) (red * 0.0000000 + green * 0.053077 + blue * 1.035763); + + float x = X / (X + Y + Z); + float y = Y / (X + Y + Z); + + double[] xy = new double[2]; + xy[0] = x; + xy[1] = y; + return xy; +} + private Integer convertHexToInt(hex) { Integer.parseInt(hex,16) } diff --git a/smartapps/smartthings/notify-me-when.src/i18n/messages.properties b/smartapps/smartthings/notify-me-when.src/i18n/messages.properties index a190968..f5d69d6 100644 --- a/smartapps/smartthings/notify-me-when.src/i18n/messages.properties +++ b/smartapps/smartthings/notify-me-when.src/i18n/messages.properties @@ -1,31 +1,31 @@ -'''Acceleration Detected'''.ko=가속화 감지됨 -'''Arrival Of'''.ko=도착 -'''Both Push and SMS?'''.ko=푸시 메시지와 SMS를 모두 사용하시겠습니까? -'''Button Pushed'''.ko=버튼이 눌렸습니다 -'''Contact Closes'''.ko=접점 닫힘 -'''Contact Opens'''.ko=접점 열림 -'''Departure Of'''.ko=출발 +'''Acceleration Detected'''.ko=가속이 감지되었을 때 +'''Arrival Of'''.ko=도착했을 때 +'''Both Push and SMS?'''.ko=푸시 알람과 SMS 모두 사용 +'''Button Pushed'''.ko=버튼이 눌렸을 때 +'''Contact Closes'''.ko=닫힘이 감지되었을 때 +'''Contact Opens'''.ko=열림이 감지되었을 때 +'''Departure Of'''.ko=출발할 때 '''Message Text'''.ko=문자 메시지 -'''Minutes'''.ko=분 -'''Motion Here'''.ko=동작 -'''Phone Number (for SMS, optional)'''.ko=휴대전화 번호(문자 메시지 - 옵션) +'''Minutes'''.ko=메시지 전송 간격(분) +'''Motion Here'''.ko=움직임이 감지되었을 때 +'''Phone Number (for SMS, optional)'''.ko=전화번호 (옵션) '''Receive notifications when anything happens in your home.'''.ko=집 안에 무슨 일이 일어나면 알림이 전송됩니다. -'''Smoke Detected'''.ko=연기가 감지되었습니다 -'''Switch Turned Off'''.ko=스위치 꺼짐 -'''Switch Turned On'''.ko=스위치 꺼짐 -'''Choose one or more, when...'''.ko=다음의 경우 하나 이상 선택 +'''Smoke Detected'''.ko=연기가 감지되었을 때 +'''Switch Turned Off'''.ko=스위치가 꺼졌을 때 +'''Switch Turned On'''.ko=스위치가 켜졌을 때 +'''Choose one or more, when...'''.ko=다음 상황 중 하나 이상 선택 '''Yes'''.ko=예 '''No'''.ko=아니요 -'''Send this message (optional, sends standard status message if not specified)'''.ko=이 메시지 전송(선택적, 지정되지 않은 경우 표준 상태 메시지를 보냅니다) -'''Via a push notification and/or an SMS message'''.ko=푸시 알림 및/또는 문자 메시지를 통해 -'''Set for specific mode(s)'''.ko=특정 모드 설정 +'''Send this message (optional, sends standard status message if not specified)'''.ko=메시지 작성 (작성하지 않을 경우 디폴트 메시지 전송) +'''Via a push notification and/or an SMS message'''.ko=푸시 알람 및 SMS 설정 +'''Set for specific mode(s)'''.ko=특정 상태 설정 '''Tap to set'''.ko=눌러서 설정 -'''Minimum time between messages (optional, defaults to every message)'''.ko=메시지작 간 최소 시간(선택 사항, 모든 메시지의 기본 설정) -'''If outside the US please make sure to enter the proper country code'''.ko=미국 이외 거주자는 적절한 국가 코드를 입력했는지 확인하십시오 -'''Water Sensor Wet'''.ko=Water Sensor에서 물이 감지되었습니다 +'''Minimum time between messages (optional, defaults to every message)'''.ko=메시지 전송 간격 설정 +'''If outside the US please make sure to enter the proper country code'''.ko=미국 이외 국가에 거주한다면 국가 코드와 함께 입력하여 주세요. +'''Water Sensor Wet'''.ko=누수가 감지되었을 때 '''{{ triggerEvent.linkText }} has arrived at the {{ location.name }}'''.ko={{ triggerEvent.linkText }}님이 {{ location.name }}에 도착했습니다 '''{{ triggerEvent.linkText }} has arrived at {{ location.name }}'''.ko={{ triggerEvent.linkText }}님이 {{ location.name }}에 도착했습니다 '''{{ triggerEvent.linkText }} has left the {{ location.name }}'''.ko={{ triggerEvent.linkText }}님이 {{ location.name }}을(를) 떠났습니다 '''{{ triggerEvent.linkText }} has left {{ location.name }}'''.ko={{ triggerEvent.linkText }}님이 {{ location.name }}을(를) 떠났습니다 -'''Assign a name'''.ko=이름 배정 -'''Choose Modes'''.ko=모드 선택 +'''Assign a name'''.ko=이름 설정 +'''Choose Modes'''.ko=상태 선택 diff --git a/smartapps/smartthings/wemo-connect.src/wemo-connect.groovy b/smartapps/smartthings/wemo-connect.src/wemo-connect.groovy index 6213f7b..af89807 100644 --- a/smartapps/smartthings/wemo-connect.src/wemo-connect.groovy +++ b/smartapps/smartthings/wemo-connect.src/wemo-connect.groovy @@ -234,7 +234,7 @@ def addSwitches() { def d if (selectedSwitch) { d = getChildDevices()?.find { - it.dni == selectedSwitch.value.mac || it.device.getDataValue("mac") == selectedSwitch.value.mac + it.deviceNetworkId == selectedSwitch.value.mac || it.device.getDataValue("mac") == selectedSwitch.value.mac } } @@ -265,7 +265,7 @@ def addMotions() { def d if (selectedMotion) { d = getChildDevices()?.find { - it.dni == selectedMotion.value.mac || it.device.getDataValue("mac") == selectedMotion.value.mac + it.deviceNetworkId == selectedMotion.value.mac || it.device.getDataValue("mac") == selectedMotion.value.mac } } @@ -296,7 +296,7 @@ def addLightSwitches() { def d if (selectedLightSwitch) { d = getChildDevices()?.find { - it.dni == selectedLightSwitch.value.mac || it.device.getDataValue("mac") == selectedLightSwitch.value.mac + it.deviceNetworkId == selectedLightSwitch.value.mac || it.device.getDataValue("mac") == selectedLightSwitch.value.mac } }