From 6f27d8db681f3903896efdadfffabc7426989c6a Mon Sep 17 00:00:00 2001 From: Donald Kirker Date: Fri, 24 Jul 2020 07:16:23 -0700 Subject: [PATCH 1/5] CHAD-5315 Update SmartWeather Station Tile DTH --- .../smartweather-station-tile.groovy | 63 ++++++++++++------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy b/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy index 77c3dfbb558..2d93938c9cb 100644 --- a/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy +++ b/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy @@ -344,7 +344,7 @@ def pollUsingPwsId(String stationId) { send(name: "humidity", value: obs.humidity, unit: "%") send(name: "weather", value: "n/a") - send(name: "weatherIcon", value: null, displayed: false) + send(name: "weatherIcon", value: "", displayed: false) send(name: "wind", value: convertWindSpeed(obs[dataScale].windSpeed, dataScale, tempUnits), unit: windUnits) send(name: "windVector", value: "${obs.winddir}° ${convertWindSpeed(obs[dataScale].windSpeed, dataScale, tempUnits)} ${windUnits}") def cityValue = obs.neighborhood @@ -361,7 +361,7 @@ def pollUsingPwsId(String stationId) { // Forecast not supported send(name: "percentPrecip", value: "n/a", unit: "%") - send(name: "forecastIcon", value: null, displayed: false) + send(name: "forecastIcon", value: "", displayed: false) send(name: "forecastToday", value: "n/a") send(name: "forecastTonight", value: "n/a") send(name: "forecastTomorrow", value: "n/a") @@ -435,33 +435,50 @@ private localDate(timeZone) { // but also send a legacy custom event for any DM-backed SmartApps using them. private send(Map map) { def eventConversion = [ - "localSunrise": "stsmartweather.astronomicalData.localSunrise", - "localSunset": "stsmartweather.astronomicalData.localSunset", - "city": "stsmartweather.astronomicalData.city", - "timeZoneOffset": "stsmartweather.astronomicalData.timeZoneOffset", - "weather": "stsmartweather.weatherSummary.weather", - "wind": "stsmartweather.windSpeed.wind", - "windVector": "stsmartweather.windDirection.windVector", - "weatherIcon": "stsmartweather.weatherSummary.weatherIcon", - "forecastIcon": "stsmartweather.weatherForecast.forecastIcon", - "feelsLike": "stsmartweather.apparentTemperature.feelsLike", - "percentPrecip": "stsmartweather.precipitation.percentPrecip", - "alert": "stsmartweather.weatherAlert.alert", - "alertKeys": "stsmartweather.weatherAlert.alertKeys", - "sunriseDate": "stsmartweather.astronomicalData.sunriseDate", - "sunsetDate": "stsmartweather.astronomicalData.sunsetDate", - "lastUpdate": "stsmartweather.smartWeather.lastUpdate", - "uvDescription": "stsmartweather.ultravioletDescription.uvDescription", - "forecastToday": "stsmartweather.weatherForecast.forecastToday", - "forecastTonight": "stsmartweather.weatherForecast.forecastTonight", - "forecastTomorrow": "stsmartweather.weatherForecast.forecastTomorrow" + // Apparent Temperature + "feelsLike": ["name": "stsmartweather.apparentTemperature.feelsLike", "attrType": "number"], + // Astronomical Data + "localSunrise": ["name": "stsmartweather.astronomicalData.localSunrise", "attrType": "string"], + "localSunset": ["name": "stsmartweather.astronomicalData.localSunset", "attrType": "string"], + "sunriseDate": ["name": "stsmartweather.astronomicalData.sunriseDate", "attrType": "string"], + "sunsetDate": ["name": "stsmartweather.astronomicalData.sunsetDate", "attrType": "string"], + "city": ["name": "stsmartweather.astronomicalData.city", "attrType": "string"], + "timeZoneOffset": ["name": "stsmartweather.astronomicalData.timeZoneOffset", "attrType": "string"], + // Precipitation + "percentPrecip": ["name": "stsmartweather.precipitation.percentPrecip", "attrType": "integer"], + // Smart Weather + "lastUpdate": ["name": "stsmartweather.smartWeather.lastUpdate", "attrType": "string"], + // Ultraviolet Description + "uvDescription": ["name": "stsmartweather.ultravioletDescription.uvDescription", "attrType": "string"], + // Weather Alert + "alert": ["name": "stsmartweather.weatherAlert.alert", "attrType": "string"], + "alertKeys": ["name": "stsmartweather.weatherAlert.alertKeys", "attrType": "string"], + // Weather Forecast + "forecastIcon": ["name": "stsmartweather.weatherForecast.forecastIcon", "attrType": "string"], + "forecastToday": ["name": "stsmartweather.weatherForecast.forecastToday", "attrType": "string"], + "forecastTonight": ["name": "stsmartweather.weatherForecast.forecastTonight", "attrType": "string"], + "forecastTomorrow": ["name": "stsmartweather.weatherForecast.forecastTomorrow" "attrType": "string"], + // Weather Summary + "weather": ["name": "stsmartweather.weatherSummary.weather", "attrType": "string"], + "weatherIcon": ["name": "stsmartweather.weatherSummary.weatherIcon", "attrType": "string"], + // Wind Direction + "windVector": ["name": "stsmartweather.windDirection.windVector", "attrType": "string"], + // Wind Speed + "wind": ["name": "stsmartweather.windSpeed.wind", "attrType": "string"] ] //log.trace "WUSTATION: event: $map" sendEvent(map) if (map.name && eventConversion.containsKey(map.name)) { def newMap = map.clone() - newMap.name = eventConversion[map.name] + def converter = eventConversion[map.name] + + newMap.name = converter.name + if (map.value == "n/a" && converter.attrType != "string") { + newMap.value = null + } else if (map.value == null && converter.attrType == "string") { + newMap.value = "" + } //log.trace "WUSTATION: NEW event: $newMap" sendEvent(newMap) From 35f0984184b35c227dd006475c1f7e763c10b13c Mon Sep 17 00:00:00 2001 From: Donald Kirker Date: Thu, 22 Oct 2020 17:07:17 -0700 Subject: [PATCH 2/5] Update capabilities --- ...pability.stsmartweather.precipitation.json | 23 +++++++++++++++- .../capability.stsmartweather.windSpeed.json | 26 ++++++++++++++++--- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.precipitation.json b/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.precipitation.json index af66d52e047..9e32e2d95e2 100644 --- a/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.precipitation.json +++ b/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.precipitation.json @@ -2,13 +2,34 @@ "name": "Precipitation", "attributes": { "percentPrecip": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "string" + }, + "unit": { + "type": "string", + "enum": [ + "%" + ], + "default": "%" + } + }, + "additionalProperties": false, + "required": [ + "value" + ] + } + }, + "precipitation": { "schema": { "type": "object", "properties": { "value": { "title": "IntegerPercent", "type": "integer", - "minimum": 0, + "minimum": -1, "maximum": 100 }, "unit": { diff --git a/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.windSpeed.json b/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.windSpeed.json index 9994d651c48..8566379b144 100644 --- a/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.windSpeed.json +++ b/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.windSpeed.json @@ -10,14 +10,32 @@ }, "unit": { "type": "string", - "enum": ["KPH", "MPH"], - "default": "KPH" + "enum": ["KPH", "MPH"] } }, "additionalProperties": false, "required": [ - "value", - "unit" + "value" + ] + } + }, + "localWindSpeed": { + "schema": { + "type": "object", + "properties": { + "value": { + "title": "PositiveNumber", + "type": "number", + "minimum": -1 + }, + "unit": { + "type": "string", + "enum": ["KPH", "MPH"] + } + }, + "additionalProperties": false, + "required": [ + "value" ] } } From e801a64122f6b402997e30c1c4cf190664c40d6a Mon Sep 17 00:00:00 2001 From: Donald Kirker Date: Thu, 29 Oct 2020 01:29:50 -0700 Subject: [PATCH 3/5] General logic updates, and better support for PWS forecast and conditions --- ...pability.stsmartweather.precipitation.json | 23 +- .../capability.stsmartweather.windSpeed.json | 22 +- .../smartweather-station-tile.groovy | 202 ++++++++---------- 3 files changed, 91 insertions(+), 156 deletions(-) diff --git a/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.precipitation.json b/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.precipitation.json index 9e32e2d95e2..af66d52e047 100644 --- a/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.precipitation.json +++ b/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.precipitation.json @@ -2,34 +2,13 @@ "name": "Precipitation", "attributes": { "percentPrecip": { - "schema": { - "type": "object", - "properties": { - "value": { - "type": "string" - }, - "unit": { - "type": "string", - "enum": [ - "%" - ], - "default": "%" - } - }, - "additionalProperties": false, - "required": [ - "value" - ] - } - }, - "precipitation": { "schema": { "type": "object", "properties": { "value": { "title": "IntegerPercent", "type": "integer", - "minimum": -1, + "minimum": 0, "maximum": 100 }, "unit": { diff --git a/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.windSpeed.json b/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.windSpeed.json index 8566379b144..04ccc66da41 100644 --- a/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.windSpeed.json +++ b/devicetypes/smartthings/smartweather-station-tile.src/capability.stsmartweather.windSpeed.json @@ -2,31 +2,13 @@ "name": "Wind Speed", "attributes": { "wind": { - "schema": { - "type": "object", - "properties": { - "value": { - "type": "string" - }, - "unit": { - "type": "string", - "enum": ["KPH", "MPH"] - } - }, - "additionalProperties": false, - "required": [ - "value" - ] - } - }, - "localWindSpeed": { "schema": { "type": "object", "properties": { "value": { "title": "PositiveNumber", "type": "number", - "minimum": -1 + "minimum": 0 }, "unit": { "type": "string", @@ -35,7 +17,7 @@ }, "additionalProperties": false, "required": [ - "value" + "value", "unit" ] } } diff --git a/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy b/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy index 2d93938c9cb..21c773cc39b 100644 --- a/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy +++ b/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy @@ -22,8 +22,8 @@ metadata { capability "Temperature Measurement" capability "Relative Humidity Measurement" capability "Ultraviolet Index" - //capability "Wind Speed" // Not in production yet - capability "stsmartweather.windSpeed" // "Wind Speed" only supports m/s unit, however we want to create both events + capability "Wind Speed" + capability "stsmartweather.windSpeed" capability "stsmartweather.windDirection" capability "stsmartweather.apparentTemperature" capability "stsmartweather.astronomicalData" @@ -34,29 +34,6 @@ metadata { capability "stsmartweather.weatherSummary" capability "Sensor" capability "Refresh" - - // While we have created a custom capability for these attributes, - // they will remain to support any custom DataManagement based SmartApps using them. - attribute "localSunrise", "string" - attribute "localSunset", "string" - attribute "city", "string" - attribute "timeZoneOffset", "string" - attribute "weather", "string" - attribute "wind", "string" - attribute "windVector", "string" - attribute "weatherIcon", "string" - attribute "forecastIcon", "string" - attribute "feelsLike", "string" - attribute "percentPrecip", "string" - attribute "alert", "string" - attribute "alertKeys", "string" - attribute "sunriseDate", "string" - attribute "sunsetDate", "string" - attribute "lastUpdate", "string" - attribute "uvDescription", "string" - attribute "forecastToday", "string" - attribute "forecastTonight", "string" - attribute "forecastTomorrow", "string" } preferences { @@ -255,11 +232,14 @@ def pollUsingZipCode(String zipCode) { send(name: "humidity", value: obs.relativeHumidity, unit: "%") send(name: "weather", value: obs.wxPhraseShort) send(name: "weatherIcon", value: obs.iconCode, displayed: false) + send(name: "wind", value: obs.windSpeed, unit: windUnits) + send(name: "windspeed", value: new BigDecimal(convertWindSpeed(obs.windSpeed, tempUnits == "F" ? "imperial" : "metric", "metric") / 3.6).setScale(2, BigDecimal.ROUND_HALF_UP), unit: "m/s") send(name: "windVector", value: "${obs.windDirectionCardinal} ${obs.windSpeed} ${windUnits}") + log.trace "Getting location info" - def loc = getTwcLocation(zipCode).location - def cityValue = "${loc.city}, ${loc.adminDistrictCode} ${loc.countryCode}" + def loc = getTwcLocation(zipCode)?.location + def cityValue = "${loc?.city}, ${loc?.adminDistrictCode} ${loc?.countryCode}" if (cityValue != device.currentValue("city")) { send(name: "city", value: cityValue, isStateChange: true) } @@ -275,7 +255,7 @@ def pollUsingZipCode(String zipCode) { def sunsetDate = dtf.parse(obs.sunsetTimeLocal) def tf = new java.text.SimpleDateFormat("h:mm a") - tf.setTimeZone(TimeZone.getTimeZone(loc.ianaTimeZone)) + tf.setTimeZone(TimeZone.getTimeZone(loc?.ianaTimeZone)) def localSunrise = "${tf.format(sunriseDate)}" def localSunset = "${tf.format(sunsetDate)}" @@ -287,22 +267,26 @@ def pollUsingZipCode(String zipCode) { // Forecast def f = getTwcForecast(zipCode) if (f) { - def icon = f.daypart[0].iconCode[0] ?: f.daypart[0].iconCode[1] - def precip = f.daypart[0].precipChance[0] ?: f.daypart[0].precipChance[1] + def icon = f.daypart[0].iconCode[0] != null ? f.daypart[0].iconCode[0] : f.daypart[0].iconCode[1] + def precip = f.daypart[0].precipChance[0] != null ? f.daypart[0].precipChance[0] : f.daypart[0].precipChance[1] def narrative = f.daypart[0].narrative send(name: "percentPrecip", value: precip, unit: "%") send(name: "forecastIcon", value: icon, displayed: false) - send(name: "forecastToday", value: narrative[0] ?: "-") - send(name: "forecastTonight", value: narrative[1] ?: "-") - send(name: "forecastTomorrow", value: narrative[2] ?: "-") - } - else { + send(name: "forecastToday", value: narrative[0] ?: "n/a") + send(name: "forecastTonight", value: narrative[1] ?: "n/a") + send(name: "forecastTomorrow", value: narrative[2] ?: "n/a") + } else { log.warn "Forecast not found" + send(name: "percentPrecip", value: 0, unit: "%", descriptionText: "Chance of precipitation could not be found") + send(name: "forecastIcon", value: "", displayed: false) + send(name: "forecastToday", value: "n/a", descriptionText: "Today's forecast could not be found") + send(name: "forecastTonight", value: "n/a", descriptionText: "Tonight's forecast could not be found") + send(name: "forecastTomorrow", value: "n/a", descriptionText: "Tomorrow's forecast could not be found") } // Alerts - def alerts = getTwcAlerts("${loc.latitude},${loc.longitude}") + def alerts = getTwcAlerts("${loc?.latitude},${loc?.longitude}") if (alerts) { alerts.each {alert -> def msg = alert.headlineText @@ -314,12 +298,10 @@ def pollUsingZipCode(String zipCode) { } send(name: "alert", value: msg, descriptionText: msg) } - } - else { + } else { send(name: "alert", value: "No current alerts", descriptionText: msg) } - } - else { + } else { log.warn "No response from TWC API" } @@ -339,33 +321,77 @@ def pollUsingPwsId(String stationId) { if (obsWrapper && obsWrapper.observations && obsWrapper.observations.size()) { def obs = obsWrapper.observations[0] def dataScale = obs.imperial ? 'imperial' : 'metric' + send(name: "temperature", value: convertTemperature(obs[dataScale].temp, dataScale, tempUnits), unit: tempUnits) send(name: "feelsLike", value: convertTemperature(obs[dataScale].windChill, dataScale, tempUnits), unit: tempUnits) send(name: "humidity", value: obs.humidity, unit: "%") - send(name: "weather", value: "n/a") - send(name: "weatherIcon", value: "", displayed: false) - send(name: "wind", value: convertWindSpeed(obs[dataScale].windSpeed, dataScale, tempUnits), unit: windUnits) - send(name: "windVector", value: "${obs.winddir}° ${convertWindSpeed(obs[dataScale].windSpeed, dataScale, tempUnits)} ${windUnits}") + + def windSpeed = convertWindSpeed(obs[dataScale].windSpeed, dataScale, tempUnits) + send(name: "wind", value: windSpeed, unit: windUnits) + send(name: "windspeed", value: new BigDecimal(convertWindSpeed(obs[dataScale].windSpeed, dataScale, "metric") / 3.6).setScale(2, BigDecimal.ROUND_HALF_UP), unit: "m/s") + send(name: "windVector", value: "${obs.winddir}° ${windSpeed} ${windUnits}") + def cityValue = obs.neighborhood if (cityValue != device.currentValue("city")) { send(name: "city", value: cityValue, isStateChange: true) } send(name: "ultravioletIndex", value: obs.uv) - send(name: "uvDescription", value: "n/a") - send(name: "localSunrise", value: "n/a", descriptionText: "Sunrise is not supported when using PWS") - send(name: "localSunset", value: "n/a", descriptionText: "Sunset is not supported when using PWS") - send(name: "illuminance", value: null) + def cond = getTwcConditions("${obs.lat},${obs.lon}") + if (cond) { + def loc = getTwcLocation("${obs.lat},${obs.lon}")?.location + + send(name: "weather", value: cond.wxPhraseShort) + send(name: "weatherIcon", value: cond.iconCode, displayed: false) + send(name: "uvDescription", value: cond.uvDescription) + + def dtf = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") + def sunriseDate = dtf.parse(cond.sunriseTimeLocal) + log.debug "'${cond.sunriseTimeLocal}'" + + def sunsetDate = dtf.parse(cond.sunsetTimeLocal) + def tf = new java.text.SimpleDateFormat("h:mm a") + tf.setTimeZone(TimeZone.getTimeZone(loc?.ianaTimeZone)) + + def localSunrise = "${tf.format(sunriseDate)}" + def localSunset = "${tf.format(sunsetDate)}" + send(name: "localSunrise", value: localSunrise, descriptionText: "Sunrise today is at $localSunrise") + send(name: "localSunset", value: localSunset, descriptionText: "Sunset today at is $localSunset") + + send(name: "illuminance", value: estimateLux(cond, sunriseDate, sunsetDate)) + } else { + log.warn "Conditions not found" + send(name: "weather", value: "n/a", descriptionText: "Weather summary could not be found") + send(name: "weatherIcon", value: "", displayed: false) + send(name: "uvDescription", value: "n/a") + + send(name: "localSunrise", value: "n/a", descriptionText: "Sunrise time could not be found") + send(name: "localSunset", value: "n/a", descriptionText: "Sunset time could not be found") + send(name: "illuminance", value: 0, descriptionText: "Illuminance could not be found") + } + + // Forecast + def f = getTwcForecast("${obs.lat},${obs.lon}") + if (f) { + def icon = f.daypart[0].iconCode[0] != null ? f.daypart[0].iconCode[0] : f.daypart[0].iconCode[1] + def precip = f.daypart[0].precipChance[0] != null ? f.daypart[0].precipChance[0] : f.daypart[0].precipChance[1] + def narrative = f.daypart[0].narrative - // Forecast not supported - send(name: "percentPrecip", value: "n/a", unit: "%") - send(name: "forecastIcon", value: "", displayed: false) - send(name: "forecastToday", value: "n/a") - send(name: "forecastTonight", value: "n/a") - send(name: "forecastTomorrow", value: "n/a") - log.warn "Forecast not supported when using PWS" + send(name: "percentPrecip", value: precip, unit: "%") + send(name: "forecastIcon", value: icon, displayed: false) + send(name: "forecastToday", value: narrative[0] ?: "n/a") + send(name: "forecastTonight", value: narrative[1] ?: "n/a") + send(name: "forecastTomorrow", value: narrative[2] ?: "n/a") + } else { + log.warn "Forecast not found" + send(name: "percentPrecip", value: 0, unit: "%", descriptionText: "Chance of precipitation could not be found") + send(name: "forecastIcon", value: "", displayed: false) + send(name: "forecastToday", value: "n/a", descriptionText: "Today's forecast could not be found") + send(name: "forecastTonight", value: "n/a", descriptionText: "Tonight's forecast could not be found") + send(name: "forecastTomorrow", value: "n/a", descriptionText: "Tomorrow's forecast could not be found") + } // Alerts def alerts = getTwcAlerts("${obs.lat},${obs.lon}") @@ -380,12 +406,10 @@ def pollUsingPwsId(String stationId) { } send(name: "alert", value: msg, descriptionText: msg) } - } - else { + } else { send(name: "alert", value: "No current alerts", descriptionText: msg) } - } - else { + } else { log.warn "No response from TWC API" } @@ -431,66 +455,16 @@ private localDate(timeZone) { df.format(new Date()) } -// Create the new custom capability event if needed, -// but also send a legacy custom event for any DM-backed SmartApps using them. private send(Map map) { - def eventConversion = [ - // Apparent Temperature - "feelsLike": ["name": "stsmartweather.apparentTemperature.feelsLike", "attrType": "number"], - // Astronomical Data - "localSunrise": ["name": "stsmartweather.astronomicalData.localSunrise", "attrType": "string"], - "localSunset": ["name": "stsmartweather.astronomicalData.localSunset", "attrType": "string"], - "sunriseDate": ["name": "stsmartweather.astronomicalData.sunriseDate", "attrType": "string"], - "sunsetDate": ["name": "stsmartweather.astronomicalData.sunsetDate", "attrType": "string"], - "city": ["name": "stsmartweather.astronomicalData.city", "attrType": "string"], - "timeZoneOffset": ["name": "stsmartweather.astronomicalData.timeZoneOffset", "attrType": "string"], - // Precipitation - "percentPrecip": ["name": "stsmartweather.precipitation.percentPrecip", "attrType": "integer"], - // Smart Weather - "lastUpdate": ["name": "stsmartweather.smartWeather.lastUpdate", "attrType": "string"], - // Ultraviolet Description - "uvDescription": ["name": "stsmartweather.ultravioletDescription.uvDescription", "attrType": "string"], - // Weather Alert - "alert": ["name": "stsmartweather.weatherAlert.alert", "attrType": "string"], - "alertKeys": ["name": "stsmartweather.weatherAlert.alertKeys", "attrType": "string"], - // Weather Forecast - "forecastIcon": ["name": "stsmartweather.weatherForecast.forecastIcon", "attrType": "string"], - "forecastToday": ["name": "stsmartweather.weatherForecast.forecastToday", "attrType": "string"], - "forecastTonight": ["name": "stsmartweather.weatherForecast.forecastTonight", "attrType": "string"], - "forecastTomorrow": ["name": "stsmartweather.weatherForecast.forecastTomorrow" "attrType": "string"], - // Weather Summary - "weather": ["name": "stsmartweather.weatherSummary.weather", "attrType": "string"], - "weatherIcon": ["name": "stsmartweather.weatherSummary.weatherIcon", "attrType": "string"], - // Wind Direction - "windVector": ["name": "stsmartweather.windDirection.windVector", "attrType": "string"], - // Wind Speed - "wind": ["name": "stsmartweather.windSpeed.wind", "attrType": "string"] - ] - //log.trace "WUSTATION: event: $map" sendEvent(map) - if (map.name && eventConversion.containsKey(map.name)) { - def newMap = map.clone() - def converter = eventConversion[map.name] - - newMap.name = converter.name - if (map.value == "n/a" && converter.attrType != "string") { - newMap.value = null - } else if (map.value == null && converter.attrType == "string") { - newMap.value = "" - } - - //log.trace "WUSTATION: NEW event: $newMap" - sendEvent(newMap) - } } private estimateLux(obs, sunriseDate, sunsetDate) { def lux = 0 if (obs.dayOrNight == 'N') { lux = 10 - } - else { + } else { //day switch(obs.iconCode) { case 4: @@ -516,7 +490,7 @@ private estimateLux(obs, sunriseDate, sunsetDate) { def beforeSunset = sunsetDate.time - now def oneHour = 1000 * 60 * 60 - if(afterSunrise < oneHour) { + if (afterSunrise < oneHour) { //dawn lux = (long)(lux * (afterSunrise/oneHour)) } else if (beforeSunset < oneHour) { @@ -556,7 +530,7 @@ private convertWindSpeed(value, fromScale, toScale) { return value } if (ts == 'imperial') { - return value * 1.608 + return value / 1.609 } - return value / 1.608 -} + return value * 1.609 +} \ No newline at end of file From 891410e9c2936e70f580614c031e5f216db6ce20 Mon Sep 17 00:00:00 2001 From: Donald Kirker Date: Thu, 29 Oct 2020 02:29:41 -0700 Subject: [PATCH 4/5] Update city name logic to account for i18n --- .../smartweather-station-tile.groovy | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy b/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy index 21c773cc39b..7dee908b6ee 100644 --- a/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy +++ b/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy @@ -230,7 +230,7 @@ def pollUsingZipCode(String zipCode) { send(name: "feelsLike", value: obs.temperatureFeelsLike, unit: tempUnits) send(name: "humidity", value: obs.relativeHumidity, unit: "%") - send(name: "weather", value: obs.wxPhraseShort) + send(name: "weather", value: obs.wxPhraseLong) send(name: "weatherIcon", value: obs.iconCode, displayed: false) send(name: "wind", value: obs.windSpeed, unit: windUnits) @@ -239,7 +239,7 @@ def pollUsingZipCode(String zipCode) { log.trace "Getting location info" def loc = getTwcLocation(zipCode)?.location - def cityValue = "${loc?.city}, ${loc?.adminDistrictCode} ${loc?.countryCode}" + def cityValue = createCityName(loc) ?: zipCode // I don't think we'll ever hit a point where we can't build a city name... But just in case... if (cityValue != device.currentValue("city")) { send(name: "city", value: cityValue, isStateChange: true) } @@ -332,7 +332,8 @@ def pollUsingPwsId(String stationId) { send(name: "windspeed", value: new BigDecimal(convertWindSpeed(obs[dataScale].windSpeed, dataScale, "metric") / 3.6).setScale(2, BigDecimal.ROUND_HALF_UP), unit: "m/s") send(name: "windVector", value: "${obs.winddir}° ${windSpeed} ${windUnits}") - def cityValue = obs.neighborhood + def loc = getTwcLocation("${obs.lat},${obs.lon}")?.location + def cityValue = createCityName(loc) ?: "${obs.neighborhood}, ${obs.country}" if (cityValue != device.currentValue("city")) { send(name: "city", value: cityValue, isStateChange: true) } @@ -341,9 +342,7 @@ def pollUsingPwsId(String stationId) { def cond = getTwcConditions("${obs.lat},${obs.lon}") if (cond) { - def loc = getTwcLocation("${obs.lat},${obs.lon}")?.location - - send(name: "weather", value: cond.wxPhraseShort) + send(name: "weather", value: cond.wxPhraseLong) send(name: "weatherIcon", value: cond.iconCode, displayed: false) send(name: "uvDescription", value: cond.uvDescription) @@ -533,4 +532,22 @@ private convertWindSpeed(value, fromScale, toScale) { return value / 1.609 } return value * 1.609 -} \ No newline at end of file +} + +private createCityName(location) { + def cityName = null + + if (location) { + cityName = location.city + ", " + + if (location.adminDistrictCode) { + cityName += location.adminDistrictCode + cityName += " " + cityName += location.countryCode ?: location.country + } else { + cityName += location.country + } + } + + cityName +} From fc24aacffd1a1b4469afe08705a0bb70370decdb Mon Sep 17 00:00:00 2001 From: Donald Kirker Date: Fri, 30 Oct 2020 01:58:45 -0700 Subject: [PATCH 5/5] Update polling logic -- poll once every 3 hours, `update()` reschedules --- .../smartweather-station-tile.groovy | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy b/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy index 7dee908b6ee..427833743c1 100644 --- a/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy +++ b/devicetypes/smartthings/smartweather-station-tile.src/smartweather-station-tile.groovy @@ -186,12 +186,18 @@ def parse(String description) { } def installed() { + schedulePoll() poll() - runEvery30Minutes(poll) +} + +def schedulePoll() { + unschedule() + runEvery3Hours("poll") } def updated() { - poll + schedulePoll() + poll() } def uninstalled() {