How do you detect iced windscreens?

Hi Everyone!

Problem:
I think everybody knows the problem. You get up in the cold season and when you leave the house you notice that the windscreen is iced up. Now you are desperately looking for an ice scraper to free the windshield from the ice and time is getting short. The next day we decide to get up 10 minutes earlier and then have to find out that the windows are not iced.

At the latest then you start to look for a solution that tells you in time if you have to get up earlier because the windscreens are iced. After a while of research you learn that you are not alone with the problem and that you are dealing with a not so trivial physical phenomenon. Whether or not the windscreen is iced up depends not only on the temperature but also on the humidity, cloud cover, location, etc.

So what to do?

Solution:
One option now is to use a lot of sensors and plunge into complicated physical formulas to determine the degree of icing. A second and for me the more elegant version, if you don’t want to become a physicist, is to use the web service www.eiswarnung.de. Using a REST API, a prediction for the respective location can be retrieved and then processed in openHAB.

First, the appropriate API key must be requested according to the instructions at www.eiswarnung.de/rest-api/. Until this comes, you can enter your location in the Paper UI (Configuration -> System -> Regional Settings).

With the API you can retrieve 50 forecasts every day, but this is usually not necessary. According to my observations the forecast for the next day is released at 12 noon and does not change then. In my system an update is done every three hours.

Below you find my items, sitemaps and rules for the query.

Items:

// SA_IN_IceWarning - Internet service Eiswarnung.de
    Group gSA_IN_IceWarning	"SA_IN: Eiswarnung.de" <it_internet> (gSA_Internet, gInformation)
        Number		SA_IN_IceWarning_CallsLeft
                    "SA_IN: Ice warning calls left [%d]"
                    <it_internet>
                    (gSA_IN_IceWarning)

        Number		SA_IN_IceWarning_CallsDailyLimit
                    "SA_IN: Ice warning daily calls limit [%d]"
                    <it_internet>
                    (gSA_IN_IceWarning)

        Number		SA_IN_IceWarning_CallsResetSeconds
                    "SA_IN: Ice warning calls reset in seconds [%d s]"
                    <it_internet>
                    (gSA_IN_IceWarning)

        DateTime	SA_IN_IceWarning_RequestDate
                    "SA_IN: Ice warning request date [%1$td.%1$tm.%1$ty %1$tH:%1$tM:%1$tS]"
                    <it_internet>
                    (gSA_IN_IceWarning)

        Number		SA_IN_IceWarning_ForecastId
                    "SA_IN: Ice warning forcast id [%d]"
                    <it_internet>
                    (gSA_IN_IceWarning, gUpdateTimeline)

        String		SA_IN_IceWarning_ForecastText
                    "SA_IN: Ice warning forecast text [%s]"
                    <it_internet>
                    (gSA_IN_IceWarning)

        String		SA_IN_IceWarning_ForecastCity
                    "SA_IN: Ice warning forecast city [%s]"
                    <it_internet>
                    (gSA_IN_IceWarning)

        DateTime	SA_IN_IceWarning_ForecastDate
                    "SA_IN: Ice warning forecast date [%1$td.%1$tm.%1$ty]"
                    <it_internet>
                    (gSA_IN_IceWarning)

Sitemap:

    Frame label="Warnungen & Alarme" {
        Text item=SA_IN_IceWarning_ForecastDate label="Warnung: Vereiste Scheiben am [%1$td.%1$tm.%1$ty]" icon="weather_snow_ice_warning" visibility=[SA_IN_IceWarning_ForecastId == 1]
        Text item=SA_IN_IceWarning_ForecastDate label="Warnung: Ggf. vereiste Scheiben am [%1$td.%1$tm.%1$ty]" icon="weather_snow_ice_warning" visibility=[SA_IN_IceWarning_ForecastId == 2]
    }

Rules:

from core.rules import rule
from core.triggers import when
from core.osgi import get_service
from core.actions import HTTP
import json

try:
    #python2
    from urllib import urlencode
except ImportError:
    #python3
    from urllib.parse import urlencode


@rule("Get windscreen ice forecast", description="Get ice warning forecast from eiswarnung.de", tags=["Rule", "Environment"])
@when("Time cron  35 42 0/3 ? * * *")
def get_windscreen_ice_forecast(event):
    
    get_windscreen_ice_forecast.log.info("Ice warning: Requesting current forecast information!")

    # Define some variables and constants
    URL = 'https://api.eiswarnung.de/'
    API_KEY = 'XXXXXXX'
    
    # Prepare url payload
    location_provider = get_service('org.eclipse.smarthome.core.i18n.LocationProvider')
    if location_provider.getLocation() != None:
        payload = {'key': API_KEY}
        payload['lat'] = location_provider.getLocation().getLatitude()
        payload['lng'] = location_provider.getLocation().getLongitude()
    else:
        get_windscreen_ice_forecast.log.error('Ice warning: No location is set in system config! Take corrective measures.')
        return

    # Request information from web service
    try:
        response = HTTP.sendHttpGetRequest(URL + '?' + urlencode(payload), 10000)
        answer = json.loads(response)
    except Exception as e: 
        get_windscreen_ice_forecast.log.error('Ice warning: Forecast request has thrown exception:' + str(e))
        return

    # Process answer from web service
    if answer['success'] == True:
        events.postUpdate('SA_IN_IceWarning_CallsLeft', str(answer['callsLeft']))
        events.postUpdate('SA_IN_IceWarning_CallsDailyLimit', str(answer['callsDailyLimit']))
        events.postUpdate('SA_IN_IceWarning_CallsResetSeconds', str(answer['callsResetInSeconds']))
        events.postUpdate('SA_IN_IceWarning_RequestDate',  answer['result']['requestDate'].replace(' ', 'T'))
        events.postUpdate('SA_IN_IceWarning_ForecastId', str(answer['result']['forecastId']))
        events.postUpdate('SA_IN_IceWarning_ForecastText', answer['result']['forecastText'])
        events.postUpdate('SA_IN_IceWarning_ForecastCity', answer['result']['forecastCity'])
        events.postUpdate('SA_IN_IceWarning_ForecastDate', answer['result']['forecastDate'].replace(' ', 'T'))
    else:
        api_status = {
            200: 'Call successful',
            300: 'Geocoordinates missing',
            400: 'API key missing',
            401: 'API key invalid',
            402: 'Daily call limit reached'
        }
        get_windscreen_ice_forecast.log.error('Ice warning: Forecast request failed with code: ' + answer['code'] + ': ' + api_status[answer['code']])
        return

    get_windscreen_ice_forecast.log.info('Ice warning: Forecast information request finished successfully!')


If one does not get up too late, so that the ice has already melted again, the service works very well.

Possible extensions would be:
- Create a Habpanel Widget
- Set the alarm clock automatically
- Automatically start the parking heater in the car
- Insert a note in the daily news
- ….

Feedback is always welcome …

Thomas

1 Like

Thanks for the API-Link. I’ll definately use this!

Reminded me of this topic:

Hi,
do you also use it in OpenHAB3? Currently I have problems there that he complains about the “from”:

did you install all relevant things for python rules?

This could work with the HTTP binding, right? The rule isn’t strictly needed in that case and JSONPATH could be used to extract each field.