Code by Scott שאול בן ישוע
Verified Commit 1f58d69b authored by Sha'ul ben Yeshua's avatar Sha'ul ben Yeshua 🎗
Browse files

added HE device handler weeWX-driver.groovy

parent d4ba65f1
/**
* Please Note: This app is NOT released under any open-source license.
* Please be sure to read the license agreement before installing this code.
*
* Weewx Weather Driver for Hubitat Elevation
*
* Copyright © 2019 AScott Grayban
* Original code from Andrew Parker
*
* This software package is created and licensed by Scott Grayban.
*
* This software, along with associated elements, including but not limited to online and/or electronic documentation are
* protected by international laws and treaties governing intellectual property rights.
*
* This software has been licensed to you. All rights are reserved. You may use and/or modify the software.
* You may not sublicense or distribute this software or any modifications to third parties in any way.
*
* You may not distribute any part of this software without the author's express permission
*
* By downloading, installing, and/or executing this software you hereby agree to the terms and conditions set forth in the Software license agreement.
* This agreement can be found on-line at: https://sgrayban.github.io/Hubitat-Public/software_License_Agreement.txt
*
* Hubitat is the trademark and intellectual property of Hubitat Inc.
* Scott Grayban has no formal or informal affiliations or relationships with Hubitat.
*
* 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 Agreement
* for the specific language governing permissions and limitations under the License.
*
*-------------------------------------------------------------------------------------------------------------------
*
* This driver is specifically designed to be used with 'Weewx' and your own PWS and
* requires you to install my Weewx Skin at https://github.com/sgrayban/hubitat-weewx-driver/
*
*/
metadata {
definition (name: "Weewx Weather Driver", namespace: "sgrayban", author: "Scott Grayban") {
capability "Actuator"
capability "Sensor"
capability "Temperature Measurement"
capability "Illuminance Measurement"
capability "Relative Humidity Measurement"
capability "Polling"
command "PollStation"
command "poll"
// Base Info
attribute "Missing or No Data", "string"
attribute "WeewxUptime", "string"
attribute "WeewxLocation", "string"
attribute "Refresh-Weewx", "string"
attribute "WeatherDisplay", "string"
// Units
attribute "distanceUnit", "string"
attribute "pressureUnit", "string"
attribute "rainUnit", "string"
// Collected Local Station Data
attribute "solarradiation", "string"
attribute "dewpoint", "string"
attribute "inside_humidity", "string"
attribute "inside_temperature", "string"
attribute "pressure", "string"
attribute "pressure_trend", "string"
attribute "wind", "string"
attribute "wind_gust", "string"
attribute "maxwindGust", "string"
attribute "wind_dir", "string"
attribute "rain_rate", "string"
attribute "uv", "string"
attribute "uvHarm", "string"
attribute "feelsLike", "string"
attribute "LastUpdate-Weewx", "string"
attribute "precip_1hr", "string"
attribute "precip_today", "string"
attribute "localSunrise", "string"
attribute "localSunset", "string"
attribute "tempMaxToday", "string"
attribute "tempMinToday", "string"
attribute "tempMaxInsideToday", "string"
attribute "tempMinInsideToday", "string"
}
preferences() {
section("Query Inputs"){
input "ipaddress", "text", required: true, title: "weeWX Server IP/URI", defaultValue: "0.0.0.0"
input "weewxPort", "text", required: true, title: "Connection Port", defaultValue: "800"
input "weewxPath", "text", required: true, title: "path to file", defaultValue: "weewx/daily.json"
input "unitSet", "bool", title: "Display Data Units", required: true, defaultValue: false
input "logSet", "bool", title: "Log All Data", required: true, defaultValue: false
input "pollInterval", "enum", title: "weeWX Station Poll Interval", required: true, defaultValue: "5 Minutes", options: ["Manual Poll Only", "5 Minutes", "10 Minutes", "15 Minutes", "30 Minutes", "1 Hour", "3 Hours"]
input "pressureUnit", "enum", title: "Pressure Unit", required:true, defaultValue: "INHg", options: ["INHg", "MBAR"]
input "rainUnit", "enum", title: "Rain Unit", required:true, defaultValue: "IN", options: ["IN", "MM"]
input "speedUnit", "enum", title: "Distance & Speed Unit", required:true, defaultValue: "Miles (MPH)", options: ["Miles (MPH)", "Kilometers (KPH)"]
input "temperatureUnit", "enum", title: "Temperature Unit", required:true, defaultValue: "Fahrenheit (�F)", options: ["Fahrenheit (�F)", "Celsius (�C)"]
input "decimalUnit", "enum", title: "Max Decimal Places", required:true, defaultValue: "2", options: ["1", "2", "3", "4", "5"]
}
section(){
input "summaryDashboard", "bool", title: "Weather Dashboard Summary", required: true, defaultValue: false, submitOnChange: true
if(summaryDashboard == true){
input "fweight", "enum", title: "Font Weight", submitOnChange: true, defaultValue: "Normal", options: ["Normal", "Italic", "Bold"]
input "fcolour", "text", title: "Font Colour (Hex Value)", defaultValue:"000000", submitOnChange: true
// input "fsize", "enum", title: "Font Size", submitOnChange: true, defaultValue: "Normal", options: fontSize()
input "dashboardFormat", "bool", title: "Custom Weather Dashboard Summary", required: true, defaultValue: false, submitOnChange: true
if(dashboardFormat == true){
input "slot1", "enum", title: "Attribute For Line 1", options: checkInput(), submitOnChange: true
if(slot1 == "Free Text"){
input "slot1Text1", "text", title: "Text For Line 1", submitOnChange: true
}
input "slot2", "enum", title: "Attribute For Line 2", options: checkInput()
if(slot2 == "Free Text"){
input "slot2Text1", "text", title: "Text For Line 2", submitOnChange: true
}
input "slot3", "enum", title: "Attribute For Line 3", options: checkInput()
if(slot3 == "Free Text"){
input "slot3Text1", "text", title: "Text For Line 3", submitOnChange: true
}
input "slot4", "enum", title: "Attribute For Line 4", options: checkInput()
if(slot4 == "Free Text"){
input "slot4Text1", "text", title: "Text For Line 4", submitOnChange: true
}
input "slot5", "enum", title: "Attribute For Line 5", options: checkInput()
if(slot5 == "Free Text"){
input "slot5Text1", "text", title: "Text For Line 5", submitOnChange: true
}
input "slot6", "enum", title: "Attribute For Line 6", options: checkInput()
if(slot6 == "Free Text"){
input "slot6Text1", "text", title: "Text For Line 6", submitOnChange: true
}
input "slot7", "enum", title: "Attribute For Line 7", options: checkInput()
if(slot7 == "Free Text"){
input "slot7Text1", "text", title: "Text For Line 7", submitOnChange: true
}
input "slot8", "enum", title: "Attribute For Line 8", options: checkInput()
if(slot8 == "Free Text"){
input "slot8Text1", "text", title: "Text For Line 8", submitOnChange: true
}
}
}
}
}
}
def initialize(){
updated()
}
private dbCleanUp() {
unschedule()
state.remove("Missing or No Data")
// state.remove("icon")
// state.remove("Copyright")
// state.remove("author")
// state.remove("InternalName")
// state.remove("newUpdateDate")
// state.remove("Status")
// state.remove("UpdateInfo")
// state.remove("CobraAppCheck")
}
def updated() {
dbCleanUp()
sendEvent(name: "Missing or No Data", value: "---")
log.debug "Updated called"
logCheck()
units()
PollStation()
def pollIntervalCmd = (settings?.pollInterval ?: "3 Hours").replace(" ", "")
if(pollInterval == "Manual Poll Only"){LOGINFO( "MANUAL POLLING ONLY")}
else{ "runEvery${pollIntervalCmd}"(pollSchedule)}
}
def poll(){
log.info "Manual Poll"
PollStation()
if(summaryDashboard == true){
if(dashboardFormat == true){advancedDash()}
if(dashboardFormat == false){standardDash()}
}
if(summaryDashboard == false){sendEvent(name: "WeatherDisplay", value: "N/A ")}
}
def units(){
state.SRU = " watts"
state.IU = " watts"
state.HU = " %"
state.DecimalPlaces = decimalUnit.toInteger()
state.DisplayUnits = unitSet
}
def pollSchedule()
{
PollStation()
if(summaryDashboard == true){
if(dashboardFormat == true){advancedDash()}
if(dashboardFormat == false){standardDash()}
}
if(summaryDashboard == false){sendEvent(name: "WeatherDisplay", value: "N/A ")}
}
def parse(String description) {
}
def PollStation()
{
units()
LOGDEBUG("Weewx: ForcePoll called")
def params1 = [
uri: "http://${ipaddress}:${weewxPort}/${weewxPath}"
]
try {
httpGet(params1) { resp1 ->
resp1.headers.each {
LOGINFO( "Response1: ${it.name} : ${it.value}")
}
if(logSet == true){
LOGINFO( "params1: ${params1}")
LOGINFO( "response contentType: ${resp1.contentType}")
LOGINFO( "response data: ${resp1.data}")
}
if(logSet == false){
// log.info "Further Weewx detailed data logging disabled"
}
// Collect Data
// ************************ ILLUMINANCE **************************************************************************************
LOGINFO("Checking illuminance")
def illuminanceRaw = (resp1.data.stats.current.solarRadiation)
if(illuminanceRaw == null || illuminanceRaw.contains("N/A")){
state.Illuminance = '---'
}
else{
def illuminanceRaw1 = (resp1.data.stats.current.solarRadiation.replaceFirst(wmcode, ""))
state.Illuminance = illuminanceRaw1.toFloat()
}
// ************************* SOLAR RADIATION*****************************************************************************************
LOGINFO("Checking SolarRadiation")
def solarradiationRaw = (resp1.data.stats.current.solarRadiation)
if(solarradiationRaw == null || solarradiationRaw.contains("N/A")){
state.SolarRadiation = '---'
}
else{
def solarradiationRaw1 = (resp1.data.stats.current.solarRadiation.replaceFirst(wmcode, ""))
state.SolarRadiation = solarradiationRaw1.toFloat()
}
// ************************** HUMIDITY ***************************************************************************************
LOGINFO("Checking Humidity")
def humidityRaw = (resp1.data.stats.current.humidity)
if(humidityRaw == null || humidityRaw.contains("N/A")){
state.Humidity = '---'
}
else{
def humidityRaw1 = (resp1.data.stats.current.humidity.replaceFirst("%", ""))
state.Humidity = humidityRaw1
}
// ************************** INSIDE HUMIDITY ************************************************************************************
LOGINFO("Checking Inside Humidity")
def inHumidRaw1 = (resp1.data.stats.current.insideHumidity.replaceFirst("%", ""))
if(inHumidRaw1 ==null || inHumidRaw1.contains("N/A")){
state.InsideHumidity = '---'}
else{
state.InsideHumidity = inHumidRaw1
}
// ************************* DEWPOINT *****************************************************************************************
LOGINFO("Checking Dewpoint")
def dewpointRaw1 = (resp1.data.stats.current.dewpoint)
if(dewpointRaw1 == null || dewpointRaw1.contains("N/A")){
state.Dewpoint = '---'}
if (dewpointRaw1.contains("F")) {
dewpointRaw1 = dewpointRaw1.replace(fcode, "")
if(temperatureUnit == "Fahrenheit (�F)"){
state.TU = '°F'
state.Dewpoint = dewpointRaw1
LOGINFO("Dewpoint Input = F - Output = F -- No conversion required")
}
if(temperatureUnit == "Celsius (�C)"){
state.TU = '°C'
def dewpoint1 = convertFtoC(dewpointRaw1)
state.Dewpoint = dewpoint1
}
}
if (dewpointRaw1.contains("C")) {
dewpointRaw1 = dewpointRaw1.replace(ccode, "")
if(temperatureUnit == "Fahrenheit (�F)"){
state.TU = '°F'
def dewpoint1 = convertCtoF(dewpointRaw1)
state.Dewpoint = dewpoint1
}
if(temperatureUnit == "Celsius (�C)"){
state.TU = '°C'
state.Dewpoint = dewpointRaw1
LOGINFO("Dewpoint Input = C - Output = C -- No conversion required" )
}
}
// ************************** PRESSURE ****************************************************************************************
LOGINFO("Checking Pressure")
def pressureRaw1 = (resp1.data.stats.current.barometer)
if (insideTemperatureRaw1 == null || pressureRaw1.contains("N/A")){
state.Pressure = '---'}
if (pressureRaw1.contains("inHg")) {
pressureRaw1 = pressureRaw1.replace("inHg", "")
if(pressureUnit == "INHg"){
state.PU = 'inhg'
state.Pressure = pressureRaw1
LOGINFO("Pressure Input = INHg - Output = INHg -- No conversion required")
}
if(pressureUnit == "MBAR"){
state.PU = 'mbar'
def pressureTemp1 = convertINtoMB(pressureRaw1)
state.Pressure = pressureTemp1
}
}
if (pressureRaw1.contains("mbar")) {
pressureRaw1 = pressureRaw1.replace("mbar", "")
if(pressureUnit == "INHg"){
state.PU = 'inhg'
def pressureTemp1 = convertMBtoIN(pressureRaw1)
state.Pressure = pressureTemp1
}
if(pressureUnit == "MBAR"){
state.PU = 'mbar'
state.Pressure = pressureRaw1
LOGINFO( "Pressure Input = MBAR - Output = MBAR --No conversion required")
}
}
// ************************** WIND SPEED ****************************************************************************************
LOGINFO("Checking Wind speed")
def windSpeedRaw1 = (resp1.data.stats.current.windSpeed)
if(windSpeedRaw1 == null || windSpeedRaw1.contains("N/A")){
state.WindSpeed = '---'}
if (windSpeedRaw1.contains("mph")) {
windSpeedRaw1 = windSpeedRaw1.replace("mph", "")
if(speedUnit == "Miles (MPH)"){
state.SU = 'mph'
state.WindSpeed = windSpeedRaw1
LOGINFO("Wind Speed Input = MPH - Output = MPH -- No conversion required")
}
if(speedUnit == "Kilometers (KPH)"){
state.SU = 'kph'
def speedTemp1 = convertMPHtoKPH(windSpeedRaw1)
state.WindSpeed = speedTemp1
}
}
if (windSpeedRaw1.contains("km/h")) {
windSpeedRaw1 = windSpeedRaw1.replace("km/h", "")
if(speedUnit == "Miles (MPH)"){
state.SU = 'mph'
def speedTemp1 = convertKPHtoMPH(pressureRaw1)
state.WindSpeed = speedTemp1
}
if(speedUnit == "Kilometers (KPH)"){
state.SU = 'kph'
state.WindSpeed = windSpeedRaw1
LOGINFO("WindSpeed Input = KPH - Output = KPH --No conversion required")
}
}
// ************************** WIND GUST ****************************************************************************************
LOGINFO("Checking Wind Gust")
def windGustRaw1 = (resp1.data.stats.current.windGust)
if(windGustRaw1 == null || windGustRaw1.contains("N/A")){
state.WindGust = '---'}
if (windGustRaw1.contains("mph")) {
windGustRaw1 = windGustRaw1.replace("mph", "")
if(speedUnit == "Miles (MPH)"){
state.SU = 'mph'
state.WindGust = windGustRaw1
LOGINFO( "Wind Gust Speed Input = MPH - Output = MPH -- No conversion required")
}
if(speedUnit == "Kilometers (KPH)"){
state.SU = 'kph'
def speedTemp2 = convertMPHtoKPH(windGustRaw1)
state.WindGust = speedTemp2
}
}
if (windGustRaw1.contains("km/h")) {
windGustRaw1 = windGustRaw1.replace("km/h", "")
if(speedUnit == "Miles (MPH)"){
state.SU = 'mph'
def speedTemp2 = convertKPHtoMPH(windGustRaw1)
state.WindGust = speedTemp2
}
if(speedUnit == "Kilometers (KPH)"){
state.SU = 'kph'
state.WindGust = windGustRaw1
LOGINFO( "Wind Gust Speed Input = KPH - Output = KPH --No conversion required")
}
}
// ************************** INSIDE TEMP ****************************************************************************************
LOGINFO("Checking Inside Temperature")
def insideTemperatureRaw1 = (resp1.data.stats.current.insideTemp)
if (insideTemperatureRaw1 == null || insideTemperatureRaw1.contains("N/A")){
state.InsideTemp = '---'}
if (insideTemperatureRaw1.contains("F")) {
insideTemperatureRaw1 = insideTemperatureRaw1.replace(fcode, "")
if(temperatureUnit == "Fahrenheit (�F)"){
state.TU = '°F'
state.InsideTemp = insideTemperatureRaw1
LOGINFO("InsideTemperature Input = F - Output = F -- No conversion required")
}
if(temperatureUnit == "Celsius (�C)"){
state.TU = '°C'
def insideTemp1 = convertFtoC(insideTemperatureRaw1)
state.InsideTemp = insideTemp1
}
}
if (insideTemperatureRaw1.contains("C")) {
insideTemperatureRaw1 = insideTemperatureRaw1.replace(ccode, "")
if(temperatureUnit == "Fahrenheit (�F)"){
state.TU = '°F'
def insideTemp1 = convertCtoF(insideTemperatureRaw1)
state.InsideTemp = insideTemp1
}
if(temperatureUnit == "Celsius (�C)"){
state.TU = '°C'
state.InsideTemp = insideTemperatureRaw1
LOGINFO( "InsideTemperature Input = C - Output = C --No conversion required")
}
}
// ************************** RAIN RATE ****************************************************************************************
LOGINFO("Checking Rain Rate")
def rainRateRaw1 = (resp1.data.stats.current.rainRate)
if(rainRateRaw1 == null || rainRateRaw1.contains("N/A")){
state.Rainrate = '---'}
if(rainRateRaw1.contains("in/hr")){
rainRateRaw1 = rainRateRaw1.replace("in/hr", "")
if(rainUnit == "IN"){
state.RRU = " in/hr"
state.Rainrate = rainRateRaw1
LOGINFO( "Rainrate Input = in/hr - Output = in/hr --No conversion required")
}
if(rainUnit == "MM"){
state.RRU = "mm/hr"
rrTemp = convertINtoMM(rainRateRaw1)
state.Rainrate = rrTemp
}
}
if(rainRateRaw1.contains("mm/hr")){
rainRateRaw1 = rainRateRaw1.replace("mm/hr", "")
0.621371
if(rainUnit == "IN"){
state.RRU = "in/hr"
rrTemp = convertMMtoIN(rainRateRaw1)
state.Rainrate = rrTemp
}
if(rainUnit == "MM"){
state.RRU = " mm/hr"
state.Rainrate = rainRateRaw1
LOGINFO( "Rainrate Input = mm/hr - Output = mm/hr --No conversion required")
}
}
// ************************** RAIN TODAY ****************************************************************************************
LOGINFO("Checking Rain Today")
def rainTodayRaw1 = (resp1.data.stats.sinceMidnight.rainSum)
if(rainTodayRaw1 == null || rainTodayRaw1.contains("N/A")){
state.RainToday = '---'}
if(rainTodayRaw1.contains("in")){
rainTodayRaw1 = rainTodayRaw1.replace("in", "")
if(rainUnit == "IN"){
state.RU = "in"
state.RainToday = rainTodayRaw1
LOGINFO( "RainToday Input = in - Output = in --No conversion required")
}
if(rainUnit == "MM"){
state.RU = "mm"
rtTemp = convertINtoMM(rainTodayRaw1)
state.RainToday = rtTemp
}
}
if(rainTodayRaw1.contains("mm")){
rainTodayRaw1 = rainTodayRaw1.replace("mm", "")
if(rainUnit == "IN"){
state.RU = "in"
rtTemp = convertMMtoIN(rainTodayRaw1)
state.RainToday = rtTemp
}
if(rainUnit == "MM"){
state.RU = "mm"
state.RainToday = rainTodayRaw1
LOGINFO("RainToday Input = mm - Output = mm --No conversion required")
}
}
// ************************** TEMPERATURE ****************************************************************************************
LOGINFO("Checking Temperature")
def temperatureRaw1 = (resp1.data.stats.current.outTemp)
if(temperatureRaw1 ==null || temperatureRaw1.contains("N/A")){
state.Temperature = '---'}
if (temperatureRaw1.contains("F")) {
temperatureRaw1 = temperatureRaw1.replace(fcode, "")
if(temperatureUnit == "Fahrenheit (�F)"){
state.TU = '°F'
state.Temperature = temperatureRaw1
LOGINFO("Temperature Input = F - Output = F -- No conversion required")
}
if(temperatureUnit == "Celsius (�C)"){
state.TU = '°C'
def temp1 = convertFtoC(temperatureRaw1)
state.Temperature = temp1
}
}
if (temperatureRaw1.contains("C")) {
temperatureRaw1 = temperatureRaw1.replace(ccode, "")
if(temperatureUnit == "Fahrenheit (�F)"){
state.TU = '°F'
def temp1 = convertCtoF(temperatureRaw1)
state.Temperature = temp1
}
if(temperatureUnit == "Celsius (�C)"){
state.TU = '°C'
state.Temperature = temperatureRaw1
LOGINFO("Temperature Input = C - Output = C --No conversion required")
}
}