blueprint: name: Weather upload description: > Upload weather data from Home Assistant to WUnderground and/or WOW. Config: The wu_station_id and wu_station_key variable must be fetched from WUnderground and the wow_site_id and wow_site_auth_key variable must be fetchet from WOW. Data will be uploaded to WUnderground if the wu_station_id and wu_station_key are filled in and data will be uploaded to WOW if the wow_site_id and wow_site_auth_key variable are filled in. The sensor_* variables are the sensors whos data will be uploaded The trigger_entities variable specifies the entries to trigger state changes on (this could be a list) The curl_command_service variable specifies the CURL-service to execute. The refresh_frequency variable specifies the frequency the sensors update their data The dewpoint temperature can be calculated based on the outdoor temperature and the outdoor humidity. By default, it will be calculated, to disable this set calculate_dewpt to false. The CURL-service must exist in Home Assistant. This can be configured with the following YAML shell_command: curl_get: 'curl -X GET {{ url }}' Automation config example: automation: - id: weather_data_upload alias: Weather data upload use_blueprint: path: weather_upload.yaml input: wu_station_id: !secret wunderground_station_id wu_station_key: !secret wunderground_station_key sensor_baro: 'sensor.outdoor_pressure' sensor_temp: 'sensor.outdoor_temperature' sensor_humidity: 'sensor.outdoor_humidity' sensor_rain: 'sensor.outdoor_rain' sensor_dailyrain: 'sensor.outdoor_rain_today' refresh_frequency: 300 trigger_entities: - sensor.outdoor_temperature - sensor.outdoor_humidity - sensor.outdoor_rain - sensor.outdoor_rain_today curl_command_service: shell_command.curl_get domain: automation source_url: "https://github.com/dvandonkelaar/home-assistant-blueprints/raw/main/weather_upload.yaml" input: wu_station_id: name: WUnderground station ID default: '' wu_station_key: name: WUnderground station key default: '' wow_site_id: name: WOW site ID default: '' wow_site_auth_key: name: WOW site authentication key default: '' sensor_baro: name: Barometer sensor selector: entity: domain: sensor device_class: pressure default: '' sensor_temp: name: Temperature sensor selector: entity: domain: sensor device_class: temperature default: '' sensor_dewpt: name: Dew point sensor selector: entity: domain: sensor device_class: temperature default: '' calculate_dewpt: name: Calculate dewpoint description: Dewpoint calculation is only possible if the outdoor temperature and outdoor humidity sensor are available. selector: boolean: default: true sensor_humidity: name: Humidity sensor selector: entity: domain: sensor device_class: humidity default: '' sensor_windspeed: name: Wind speed sensor selector: entity: domain: sensor default: '' sensor_windgust: name: Wind gust sensor selector: entity: domain: sensor default: '' sensor_winddir: name: Wind direction sensor selector: entity: domain: sensor default: '' sensor_windgustdir: name: Wind Gust direction sensor selector: entity: domain: sensor default: '' sensor_rain: name: Rain sensor selector: entity: domain: sensor default: '' sensor_dailyrain: name: Daily rain sensor selector: entity: domain: sensor default: '' sensor_indoortemp: name: Indoor temperature sensor selector: entity: domain: sensor device_class: temperature default: '' sensor_indoorhumidity: name: Indoor humidity sensor selector: entity: domain: sensor device_class: humidity default: '' sensor_solarradiation: name: Solar Radiation sensor selector: entity: domain: sensor default: '' sensor_UV: name: UV Index sensor selector: entity: domain: sensor default: '' refresh_frequency: name: Refresh frequency (seconds) selector: number: min: 1 max: 10800 step: 1 unit_of_measurement: seconds trigger_entities: name: Trigger entities selector: entity: multiple: true filter: domain: sensor default: '' curl_command_service: name: CURL command service selector: text: default: '' delay: name: Delay after publishing results selector: number: min: 0 max: 10800 step: 1 unit_of_measurement: seconds default: 10 mode: single max_exceeded: silent trigger: - platform: state entity_id: !input trigger_entities variables: wu_station_id: !input wu_station_id wu_station_key: !input wu_station_key wow_site_id: !input wow_site_id wow_site_auth_key: !input wow_site_auth_key sensor_baro: !input sensor_baro sensor_temp: !input sensor_temp sensor_dewpt: !input sensor_dewpt calculate_dewpt: !input calculate_dewpt sensor_humidity: !input sensor_humidity sensor_windspeed: !input sensor_windspeed sensor_windgust: !input sensor_windgust sensor_winddir: !input sensor_winddir sensor_windgustdir: !input sensor_windgustdir sensor_rain: !input sensor_rain sensor_dailyrain: !input sensor_dailyrain sensor_indoortemp: !input sensor_indoortemp sensor_indoorhumidity: !input sensor_indoorhumidity sensor_solarradiation: !input sensor_solarradiation sensor_UV: !input sensor_UV rtfreq: !input refresh_frequency delay: !input delay baromin: > {% set unit_of_measurement = state_attr(sensor_baro, 'unit_of_measurement') %} {{ sensor_baro if sensor_baro == '' else (states(sensor_baro) | float(default=0)) if unit_of_measurement not in ['mbar', 'hPa'] else ((states(sensor_baro) | float(default=0)) / 33.8639) }} tempf: > {% set unit_of_measurement = state_attr(sensor_temp, 'unit_of_measurement') %} {{ sensor_temp if sensor_temp == '' else ((states(sensor_temp) | float(default=0)) if unit_of_measurement == '°F' else ((states(sensor_temp) | float(default=0)) * 1.8) + 32) }} humidity: > {{ sensor_humidity if sensor_humidity == '' else (states(sensor_humidity) | float(default=0)) }} windspeedmph: > {% set unit_of_measurement = state_attr(sensor_windspeed, 'unit_of_measurement') %} {{ sensor_windspeed if sensor_windspeed == '' else (states(sensor_windspeed) | float(default=0)) * (0.6213 if unit_of_measurement == 'km/h' else 1) }} windgustmph: > {% set unit_of_measurement = state_attr(sensor_windgust, 'unit_of_measurement') %} {{ sensor_windgust if sensor_windgust == '' else (states(sensor_windgust) | float(default=0)) * (0.6213 if unit_of_measurement == 'km/h' else 1) }} winddir: > {% set candidate_wind_direction = states(sensor_winddir) %} {% set wind_direction_float = candidate_wind_direction | float(default=-1) %} {% if wind_direction_float == -1 %} {% set directions_map16 = {'N': 0, 'NNE': 22.5, 'NE': 45, 'ENE': 67.5, 'E': 90, 'ESE': 112.5, 'SE': 135, 'SSE': 157.5, 'S': 180, 'SSW': 202.5, 'SW': 225, 'WSW': 247.5, 'W': 270, 'WNW': 292.5, 'NW': 315, 'NNW': 337.5} %} {% set candidate_wind_direction = candidate_wind_direction.upper() %} {{ directions_map16.get(candidate_wind_direction, '') | float(default=0) }} {%- else -%} {{ wind_direction_float }} {%- endif %} windgustdir: > {% set candidate_windgust_direction = states(sensor_windgustdir) %} {% set windgust_direction_float = candidate_windgust_direction | float(default=-1) %} {% if windgust_direction_float == -1 %} {% set directions_map16 = {'N': 0, 'NNE': 22.5, 'NE': 45, 'ENE': 67.5, 'E': 90, 'ESE': 112.5, 'SE': 135, 'SSE': 157.5, 'S': 180, 'SSW': 202.5, 'SW': 225, 'WSW': 247.5, 'W': 270, 'WNW': 292.5, 'NW': 315, 'NNW': 337.5} %} {% set candidate_windgust_direction = candidate_windgust_direction.upper() %} {{ directions_map16.get(candidate_windgust_direction, '') | float(default=0) }} {%- else -%} {{ windgust_direction_float }} {%- endif %} rainin: > {% set unit_of_measurement = state_attr(sensor_rain, 'unit_of_measurement') %} {{ sensor_rain if sensor_rain == '' else ((states(sensor_rain) | float(default=0)) / (25.4 if unit_of_measurement == 'mm' else 1)) }} dailyrainin: > {% set unit_of_measurement = state_attr(sensor_dailyrain, 'unit_of_measurement') %} {{ sensor_dailyrain if sensor_dailyrain == '' else ((states(sensor_dailyrain) | float(default=0)) / (25.4 if unit_of_measurement == 'mm' else 1)) }} indoortempf: > {% set unit_of_measurement = state_attr(sensor_indoortemp, 'unit_of_measurement') %} {{ sensor_indoortemp if sensor_indoortemp == '' else ((states(sensor_indoortemp) | float(default=0)) if unit_of_measurement == '°F' else ((states(sensor_indoortemp) | float(default=0)) * 1.8) + 32) }} indoorhumidity: > {{ sensor_indoorhumidity if sensor_indoorhumidity == '' else (states(sensor_indoorhumidity) | float(default=0)) }} solarradiation: > {% set unit_of_measurement = state_attr(sensor_solarradiation, 'unit_of_measurement') %} {{ sensor_solarradiation if sensor_solarradiation == '' else ((states(sensor_solarradiation) | float(default=0) / 126.7) ) if unit_of_measurement == 'lux' else (states(sensor_solarradiation) | float(default=0)) }} UV: > {{ sensor_UV if sensor_UV == '' else (states(sensor_UV) | int(default=0)) }} dewptf_calculated: > {% set unit_of_measurement = state_attr(sensor_temp, 'unit_of_measurement') %} {% set T = ((states(sensor_temp) | float(default=0)) if unit_of_measurement == '°C' else ((states(sensor_temp) | float(default=0)) - 32) / 1.8) %} {% set RH = humidity %} {% set dewpt = '' %} {% if sensor_temp != '' and sensor_humidity != '' %} {% set A = log(RH / 100, default=0.0) + (17.62 * T / (243.12 + T)) %} {% set dewpt = 243.12 * A / (17.62 - A) %} {% set dewpt = (dewpt * 1.8) + 32 %} {% endif %} {{ dewpt }} dewptf: > {% set unit_of_measurement = state_attr(sensor_dewpt, 'unit_of_measurement') %} {{ (dewptf_calculated if calculate_dewpt is true else sensor_dewpt) if sensor_dewpt == '' else ((states(sensor_dewpt) | float(default=0)) if unit_of_measurement == '°F' else ((states(sensor_dewpt) | float(default=0)) * 1.8) + 32) }} wu_payload: > {% set data = namespace(sensors=[]) %} {% for i in [['rtfreq', rtfreq] ,['baromin', baromin] ,['tempf', tempf] ,['dewptf', dewptf] ,['humidity', humidity] ,['windspeedmph', windspeedmph] ,['windgustmph', windgustmph] ,['winddir', winddir] ,['windgustdir', windgustdir] ,['rainin', rainin] ,['dailyrainin', dailyrainin] ,['indoortempf', indoortempf] ,['indoorhumidity', indoorhumidity] ,['solarradiation', solarradiation] ,['UV', UV] ]%} {% if i[1] != '' %} {% set data.sensors = data.sensors + ['{}={}'.format(i[0], (i[1] if i[0] == 'rtfreq' else (i[1] | round(3)) | string))] %} {% endif %} {% endfor %} {% set _payload = 'ID=' + wu_station_id %} {% set _payload = _payload + '&PASSWORD=' + wu_station_key %} {% set _payload = _payload + '&action=updateraww' %} {% set _payload = _payload + '&realtime=1' %} {% set _payload = _payload + '&dateutc=now' %} {% set _payload = _payload + '&' if data.sensors | length > 0 else '' %} {% set _payload = _payload + data.sensors | join('&') %} {{ _payload }} wow_payload: > {% set data = namespace(sensors=[]) %} {% for i in [['rtfreq', rtfreq] ,['baromin', baromin] ,['tempf', tempf] ,['dewptf', dewptf] ,['humidity', humidity] ,['windspeedmph', windspeedmph] ,['windgustmph', windgustmph] ,['winddir', winddir] ,['windgustdir', windgustdir] ,['rainin', rainin] ,['dailyrainin', dailyrainin] ]%} {% if i[1] != '' %} {% set data.sensors = data.sensors + ['{}={}'.format(i[0], (i[1] if i[0] == 'rtfreq' else (i[1] | round(3)) | string))] %} {% endif %} {% endfor %} {% set _payload = 'siteid=' + wow_site_id %} {% set _payload = _payload + '&siteAuthenticationKey=' + wow_site_auth_key %} {% set _payload = _payload + '&dateutc=now' %} {% set _payload = _payload + '&' if data.sensors | length > 0 else '' %} {% set _payload = _payload + data.sensors | join('&') %} {% set _payload = _payload + '&softwaretype=homeassistant' %} {{ _payload }} action: - alias: "Check if wu_station_id and wu_station_key exist" if: > {{ wu_station_id != '' and wu_station_key != '' }} then: - service: !input curl_command_service data: url: "https://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?{{ wu_payload }}" - alias: "Wait before next upload if both WU and WOW are configured" if: > {{ wu_station_id != '' and wu_station_key != '' and wow_site_id != '' and wow_site_auth_key != '' }} then: - delay: seconds: "{{ delay | int }}" - alias: "Check if wow_site_id and wow_site_auth_key exist" if: > {{ wow_site_id != '' and wow_site_auth_key != '' }} then: - service: !input curl_command_service data: url: "http://wow.metoffice.gov.uk/automaticreading?{{ wow_payload }}" - alias: "Wait to prevent multiple uploads" delay: seconds: "{{ delay | int }}"