VSCode Problem-Messages in Py-Scripts

Hardware: RPi 3b (Test-Machine for jsr223 tinkering)
Software: Openhabian-Distro, OH-Version 2.5.2 stable. NGRE, jsr223, Mail-Binding, MQTT,OpenWeatherMap, SystemOInfo
Some Py.Scripts are running (Hello World, OWM)
No Errors in logs.

I try to write some scripts(to learn more about Scripted Automation), which are running (more or less), but I always see the below Problem-Messages in my VSCode-Editor.
vsc

My settings.json is:

{
    "openhab.host": "192.168.x.y",
    "openhab.port": 8080,
    "openhab.remoteLspEnabled": true,
    "openhab.remoteLspPort": 5007,
    "openhab.sitemapPreviewUI": "basicui",
    "openhab.useRestApi": true,
    "python.linting.ignorePatterns": [
        "**/automation/**/python/core/**/*.py",
        "**/automation/**/python/community/**/*.py"
    ]

}

and my .env is

PYTHONPATH="./automation/lib/python"

in the openhab-conf-directory:
grafik

What else do I have to do to get rid of these errors ?

Thanks in advance for any help and hints

Hi Scott,
thx for answering. After installing the .pylintrc File

[MESSAGES CONTROL]
disable=
    missing-docstring,
    unused-variable,
    line-too-long,
    logging-format-interpolation,
    bare-except,
    broad-except,
    pointless-string-statement,
    undefined-variable,
    unused-argument,
    wrong-import-position,
    anomalous-unicode-escape-in-string,
    global-statement

ignored-modules=
    org.joda.time,
    java,
    core,
    core.jsr223,
    core.actions,
    community,
    personal,
    configuration,
    events

[DESIGN]
# Maximum number of parents for a class (see R0901).
max-parents=15

most of the errors where gone :+1:, but others came up :cry:

The reason for “doesn’t conform snake_case naming style” I understand. But I won’t change in the case of e.g. “owmThingUID”, as it’s your script and I like this way of declaring variables.

Any hints to solve or suppress those messages ?

After applying the pylintrc, any warnings and errors that are left should be corrected. But that is up to you. I have an update that will correct everything in the helper libraries, so no need to fix those.

Thx for answering and sorry for my late reply, but I was a bit ill with fever, the cough and sore throat.
As I do not quite understand what you meant, I have to ask one more time.

I installed the .pylintrc File as above shown or do you mean that one ?

Next question: What’s about the update you have to correct everything in the helpers library ? And where can I get it ?

And another question: I made the installation of “Scripted Automation” as described here in January.
If there is a new helpers-library in the meantime, how can I see, if so ? And if so, how can I install it ?

Sorry for my silly questions, but you know that I’m a fool :crazy_face: and always need a helping hand, but I have to say that my NGRE/Jython Setup is running quite fine using the installation guide, even with the warnings of VSC.
But learning from professionals will help a lot.

Cheers - Peter

Also, make sure that you have selected the Python 2.7 interpreter in VS Code.

1 Like

Thx for your hint. On my Windows machine only Python 3.8.2 was installed. After installing 2.7.16 nearly all errors/messages where gone. But it’s a bit weird now, I have installed python on my Windows-machine and on my RPi. :thinking:

@mjcumming @5iver

Sorry to say, but after restarting my Windows-machine today and running VSC a lot of errors/ messages came back :cry:.
Some examples:

{
	"resource": "/x:/automation/jsr223/python/personal/owm_test.py",
	"owner": "python",
	"code": "deprecated-lambda",
	"severity": 4,
	"message": "map/filter on lambda could be replaced by comprehension",
	"source": "pylint",
	"startLineNumber": 228,
	"startColumn": 35,
	"endLineNumber": 228,
	"endColumn": 35
}
{
	"resource": "/x:/automation/jsr223/python/personal/owm_test.py",
	"owner": "python",
	"code": "import-error",
	"severity": 8,
	"message": "Unable to import 'javax.measure.quantity'",
	"source": "pylint",
	"startLineNumber": 28,
	"startColumn": 5,
	"endLineNumber": 28,
	"endColumn": 5
}
{
	"resource": "/X:/automation/jsr223/python/personal/presence_detection.py",
	"owner": "python",
	"code": "invalid-encoded-data",
	"severity": 4,
	"message": "Cannot decode using encoding \"ascii\", unexpected byte at position 62",
	"source": "pylint",
	"startLineNumber": 8,
	"startColumn": 1,
	"endLineNumber": 8,
	"endColumn": 1
}
{
	"resource": "/x:/automation/jsr223/python/personal/my_firstrule.py",
	"owner": "python",
	"code": "invalid-name",
	"severity": 2,
	"message": "Variable name \"lastReading\" doesn't conform to snake_case naming style",
	"source": "pylint",
	"startLineNumber": 23,
	"startColumn": 5,
	"endLineNumber": 23,
	"endColumn": 5
}

and a screenshot of it:

Any further hints ?

What is in your script? These warnings may be legitimate.

The script is just this:

from core.log import logging, LOG_PREFIX, log_traceback

@log_traceback
def removeOWMItems():
    removeOWMItems.log = logging.getLogger("{}.removeOWMItems".format(LOG_PREFIX))
    from core.items import remove_item

    for item in ir.getItemsByTag("OpenWeatherMap"):
        removeOWMItems.log.debug("removeOWMItems: [{}]".format(item))
        remove_item(item)
    '''
    # use this as a last resort, but make sure it's not removing any Items not
    created by this script

    for item in ir.getAll():
        if "Forecast_" in item.name or "Current_" in item.name:
            removeOWMItems.log.debug("removeOWMItems: [{}]".format(item))
            remove_item(item)
    '''
#removeOWMItems()

def addOWMItems():
    addOWMItems.log = logging.getLogger("{}.addOWMItems".format(LOG_PREFIX))

    # create OWM Items and groups, if they do not exist
    scriptExtension.importPreset("RuleSupport")

    from javax.measure.quantity import Dimensionless, Temperature, Length, Speed, Pressure#, Angle

    try:
        from org.openhab.core.thing import ThingTypeUID
        from org.openhab.core.thing import ChannelUID
    except:
        from org.eclipse.smarthome.core.thing import ThingTypeUID
        from org.eclipse.smarthome.core.thing import ChannelUID

    try:
        from org.eclipse.smarthome.core.library.types import QuantityTypeArithmeticGroupFunction
    except:
        from org.openhab.core.library.types import QuantityTypeArithmeticGroupFunction

    from core.items import add_item
    from core.links import add_link

    try:
        owmThingUID = None
        for thing in things.getAll():
            if thing.getThingTypeUID() == ThingTypeUID("openweathermap:weather-and-forecast"):
                if str(thing.statusInfo) == "ONLINE":
                    thingConfiguration = thing.getConfiguration()
                    forecastHours = thingConfiguration.get("forecastHours")
                    if str(forecastHours) == "120":
                        forecastDays = thingConfiguration.get("forecastDays")
                        if str(forecastDays) == "0":
                            owmThingUID = str(thing.getUID())
                            break
                        else:
                            addOWMItems.log.warn("Thing found, but forecastDays is not set to [0]: forecastDays=[{}]".format(forecastDays))
                    else:
                        addOWMItems.log.warn("Thing found, but forecastHours is not set to [120]: forecastHours=[{}]".format(forecastHours))
                else:
                    addOWMItems.log.warn("Thing found, but statusInfo was not [ONLINE]: statusInfo=[{}]".format(thing.statusInfo))
        if owmThingUID is None:
            addOWMItems.log.warn("No Thing found with ThingTypeUID 'openweathermap:weather-and-forecast', or it was not ONLINE, or it was improperly configured for the free API. Exiting script.")
        else:
            addOWMItems.log.debug("owmThingUID set to [{}]".format(owmThingUID))

            # install Scale transformation service, if not already
            from org.eclipse.smarthome.model.script.actions.Exec import executeCommandLine
            import json

            scaleCheckResult = json.loads(executeCommandLine("/bin/sh@@-c@@/usr/bin/curl -s --connect-timeout 10 -m 10 -X GET -H \"Accept: application/json\" \"http://localhost:8080/rest/extensions/transformation-scale\"", 15000))['installed']
            if not scaleCheckResult:
                installScaleResult = executeCommandLine("/bin/sh@@-c@@/usr/bin/curl -o /dev/null -s -w \"%{http_code}\" --connect-timeout 10 -m 10 -X POST -H \"Content-Type: application/json\" -H \"Accept: application/json\" \"http://localhost:8080/rest/extensions/transformation-scale/install\"",15000)
                if installScaleResult != "200":
                    addOWMItems.log.debug("Scale transformation service installation failed")
                    return
                else:
                    addOWMItems.log.debug("Scale transformation service has been installed")
            else:
                addOWMItems.log.debug("Scale transformation service is already installed")

            # create Current group and Items
            if ir.getItems("gOpenWeatherMap") == []:
                add_item("gOpenWeatherMap", item_type="Group", groups=["gWeather"], label="OpenWeatherMap", tags=["OpenWeatherMap"])
            if ir.getItems("gCurrent") == []:
                add_item("gCurrent", item_type="Group", groups=["gOpenWeatherMap"], label="Current", tags=["OpenWeatherMap"])
            if ir.getItems("Current_Timestamp") == []:
                add_item("Current_Timestamp", item_type="DateTime", groups=["gCurrent", "gForecast_Timestamp_1"], label="Current: Timestamp [%1$tY-%1$tm-%1$td %1$tI:%1$tM%1$tp]", category="Time", tags=["OpenWeatherMap"])
                add_link("Current_Timestamp", ChannelUID(owmThingUID + ":current#time-stamp"))
            if ir.getItems("Current_Condition") == []:
                add_item("Current_Condition", item_type="String", groups=["gCurrent", "gForecast_Condition_1"], label="Current: Condition [%s]", category="Sun_Clouds", tags=["OpenWeatherMap"])
                add_link("Current_Condition", ChannelUID(owmThingUID + ":current#condition"))
            if ir.getItems("Current_ConditionID") == []:
                add_item("Current_ConditionID", item_type="String", groups=["gCurrent", "gForecast_ConditionID_1"], label="Current: Condition ID [%s]", tags=["OpenWeatherMap"])
                add_link("Current_ConditionID", ChannelUID(owmThingUID + ":current#condition-id"))
            if ir.getItems("Current_IconID") == []:
                add_item("Current_IconID", item_type="String", groups=["gCurrent", "gForecast_IconID_1"], label="Current: Icon ID [%s]", tags=["OpenWeatherMap"])
                add_link("Current_IconID", ChannelUID(owmThingUID + ":current#icon-id"))
            if ir.getItems("Current_Icon") == []:
                add_item("Current_Icon", item_type="Image", groups=["gCurrent", "gForecast_Icon_1"], label="Current: Icon", tags=["OpenWeatherMap"])
                add_link("Current_Icon", ChannelUID(owmThingUID + ":current#icon"))
            if ir.getItems("Current_Temperature") == []:
                add_item("Current_Temperature", item_type="Number:Temperature", groups=["gCurrent", "gForecast_Temperature_High_1", "gForecast_Temperature_Low_1"], label="Current: Temperature [%.0f %unit%]", category="Temperature", tags=["OpenWeatherMap"])
                add_link("Current_Temperature", ChannelUID(owmThingUID + ":current#temperature"))
            if ir.getItems("Current_Pressure") == []:
                add_item("Current_Pressure", item_type="Number:Pressure", groups=["gCurrent", "gForecast_Pressure_1"], label="Current: Pressure [%.1f %unit%]", category="Pressure", tags=["OpenWeatherMap"])
                add_link("Current_Pressure", ChannelUID(owmThingUID + ":current#pressure"))
            if ir.getItems("Current_Humidity") == []:
                add_item("Current_Humidity", item_type="Number:Dimensionless", groups=["gCurrent", "gForecast_Humidity_1"], label="Current: Humidity [%d %%]", category="Humidity", tags=["OpenWeatherMap"])
                add_link("Current_Humidity", ChannelUID(owmThingUID + ":current#humidity"))
            if ir.getItems("Current_WindSpeed") == []:
                add_item("Current_WindSpeed", item_type="Number:Speed", groups=["gCurrent", "gForecast_WindSpeed_1"], label="Current: Wind speed [%.0f %unit%]", category="Wind", tags=["OpenWeatherMap"])
                add_link("Current_WindSpeed", ChannelUID(owmThingUID + ":current#wind-speed"))
            if ir.getItems("Current_GustSpeed") == []:
                add_item("Current_GustSpeed", item_type="Number:Speed", groups=["gCurrent", "gForecast_GustSpeed_1"], label="Current: Gust speed [%.0f %unit%]", category="Wind", tags=["OpenWeatherMap"])
                add_link("Current_GustSpeed", ChannelUID(owmThingUID + ":current#gust-speed"))
            if ir.getItems("Current_WindDirection") == []:
                add_item("Current_WindDirection", item_type="Number:Angle", groups=["gCurrent", "gForecast_WindDirection_1"], label="Current: Wind direction [SCALE(windDirection.scale):%s]", category="Wind", tags=["OpenWeatherMap"])
                add_link("Current_WindDirection", ChannelUID(owmThingUID + ":current#wind-direction"))
            if ir.getItems("Current_Cloudiness") == []:
                add_item("Current_Cloudiness", item_type="Number:Dimensionless", groups=["gCurrent", "gForecast_Cloudiness_1"], label="Current: Cloudiness [%d %%]", category="Sun_Clouds", tags=["OpenWeatherMap"])
                add_link("Current_Cloudiness", ChannelUID(owmThingUID + ":current#cloudiness"))
            if ir.getItems("Current_RainVolume") == []:
                add_item("Current_RainVolume", item_type="Number:Length", groups=["gCurrent", "gForecast_RainVolume_1"], label="Current: Rain volume [%.1f %unit%]", category="Rain", tags=["OpenWeatherMap"])
                add_link("Current_RainVolume", ChannelUID(owmThingUID + ":current#rain"))
            if ir.getItems("Current_SnowVolume") == []:
                add_item("Current_SnowVolume", item_type="Number:Length", groups=["gCurrent", "gForecast_SnowVolume_1"], label="Current: Snow volume [%.1f %unit%]", category="Snow", tags=["OpenWeatherMap"])
                add_link("Current_SnowVolume", ChannelUID(owmThingUID + ":current#snow"))

            # create Forecast groups
            import calendar
            from org.joda.time import DateTime
            lastReading = DateTime(str(items["Current_Timestamp"])).getDayOfWeek() - 1
            for index in range(1, 6):
                dayOfWeek = "Today" if index == 1 else calendar.day_name[(lastReading + index - 1) % 7]
                if ir.getItems("gForecast_" + str(index)) == []:
                    add_item("gForecast_" + str(index), item_type="Group", groups=["gOpenWeatherMap"], label=dayOfWeek, tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_Timestamp_" + str(index)) == []:
                    add_item("gForecast_Timestamp_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Timestamp [%1$tY-%1$tm-%1$td %1$tI:%1$tM%1$tp]", category="Time", tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_Condition_" + str(index)) == []:
                    add_item("gForecast_Condition_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Condition [%s]", gi_base_type="String", category="Sun_Clouds", tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_ConditionID_" + str(index)) == []:
                    add_item("gForecast_ConditionID_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Condition ID [%s]", gi_base_type="String", tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_IconID_" + str(index)) == []:
                    add_item("gForecast_IconID_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Icon ID [%s]", gi_base_type="String", tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_Icon_" + str(index)) == []:
                    add_item("gForecast_Icon_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Icon", gi_base_type="Image", tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_Temperature_High_" + str(index)) == []:
                    add_item("gForecast_Temperature_High_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Temperature (high) [%.0f %unit%]", category="Temperature_Hot", gi_base_type="Number:Temperature", group_function=QuantityTypeArithmeticGroupFunction.Max(Temperature), tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_Temperature_Low_" + str(index)) == []:
                    add_item("gForecast_Temperature_Low_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Temperature (low) [%.0f %unit%]", category="Temperature_Cold", gi_base_type="Number:Temperature", group_function=QuantityTypeArithmeticGroupFunction.Min(Temperature), tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_Pressure_" + str(index)) == []:
                    add_item("gForecast_Pressure_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Pressure [%.1f %unit%]", category="Pressure", gi_base_type="Number:Pressure", group_function=QuantityTypeArithmeticGroupFunction.Max(Pressure), tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_Humidity_" + str(index)) == []:
                    add_item("gForecast_Humidity_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Humidity [%d %%]", category="Humidity", gi_base_type="Number:Dimensionless", group_function=QuantityTypeArithmeticGroupFunction.Max(Dimensionless), tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_WindSpeed_" + str(index)) == []:
                    add_item("gForecast_WindSpeed_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Wind Speed [%.0f %unit%]", category="Wind", gi_base_type="Number:Speed", group_function=QuantityTypeArithmeticGroupFunction.Max(Speed), tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_GustSpeed_" + str(index)) == []:
                    add_item("gForecast_GustSpeed_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Gust Speed [%.0f %unit%]", category="Wind", gi_base_type="Number:Speed", group_function=QuantityTypeArithmeticGroupFunction.Max(Speed), tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_WindDirection_" + str(index)) == []:
                    #add_item("gForecast_WindDirection_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Wind direction [SCALE(windDirection.scale):%s]", category="Wind", gi_base_type="Number:Angle", group_function=QuantityTypeArithmeticGroupFunction.Avg(Angle), tags=["OpenWeatherMap"])# this doesn't work properly yet
                    add_item("gForecast_WindDirection_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Wind direction [SCALE(windDirection.scale):%s]", category="Wind", gi_base_type="Number:Angle", tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_Cloudiness_" + str(index)) == []:
                    add_item("gForecast_Cloudiness_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Cloudiness [%d %%]", category="Sun_Clouds", gi_base_type="Number:Dimensionless", group_function=QuantityTypeArithmeticGroupFunction.Max(Dimensionless), tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_RainVolume_" + str(index)) == []:
                    add_item("gForecast_RainVolume_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Rain Volume [%.1f %unit%]", category="Rain", gi_base_type="Number:Length", group_function=QuantityTypeArithmeticGroupFunction.Sum(Length), tags=["OpenWeatherMap"])
                if ir.getItems("gForecast_SnowVolume_" + str(index)) == []:
                    add_item("gForecast_SnowVolume_" + str(index), item_type="Group", groups=["gForecast_" + str(index)], label=dayOfWeek + ": Snow Volume [%.1f %unit%]", category="Snow", gi_base_type="Number:Length", group_function=QuantityTypeArithmeticGroupFunction.Sum(Length), tags=["OpenWeatherMap"])

            # create Forecast Items
            for index in range(1, 41):
                if ir.getItems("Forecast_Timestamp_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_Timestamp_{:02d}".format(3 * index), item_type="DateTime", label="Forecast ({:02d}): Timestamp [%1$tY-%1$tm-%1$td %1$tI:%1$tM%1$tp]".format(3 * index), category="Time", tags=["OpenWeatherMap"])
                    add_link("Forecast_Timestamp_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#time-stamp".format(3 * index)))
                if ir.getItems("Forecast_Condition_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_Condition_{:02d}".format(3 * index), item_type="String", label="Forecast ({:02d}): Condition [%s]".format(3 * index), category="Sun_Clouds", tags=["OpenWeatherMap"])
                    add_link("Forecast_Condition_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#condition".format(3 * index)))
                if ir.getItems("Forecast_ConditionID_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_ConditionID_{:02d}".format(3 * index), item_type="String", label="Forecast ({:02d}): Condition ID [%s]".format(3 * index), tags=["OpenWeatherMap"])
                    add_link("Forecast_ConditionID_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#condition-id".format(3 * index)))
                if ir.getItems("Forecast_IconID_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_IconID_{:02d}".format(3 * index), item_type="String", label="Forecast ({:02d}): Icon ID [%s]".format(3 * index), tags=["OpenWeatherMap"])
                    add_link("Forecast_IconID_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#icon-id".format(3 * index)))
                if ir.getItems("Forecast_Icon_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_Icon_{:02d}".format(3 * index), item_type="Image", label="Forecast ({:02d}): Icon".format(3 * index), tags=["OpenWeatherMap"])
                    add_link("Forecast_Icon_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#icon".format(3 * index)))
                if ir.getItems("Forecast_Temperature_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_Temperature_{:02d}".format(3 * index), item_type="Number:Temperature", label="Forecast ({:02d}): Temperature [%.0f %unit%]".format(3 * index), category="Temperature", tags=["OpenWeatherMap"])
                    add_link("Forecast_Temperature_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#temperature".format(3 * index)))
                if ir.getItems("Forecast_Pressure_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_Pressure_{:02d}".format(3 * index), item_type="Number:Pressure", label="Forecast ({:02d}): Pressure [%.1f %unit%]".format(3 * index), category="Pressure", tags=["OpenWeatherMap"])
                    add_link("Forecast_Pressure_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#pressure".format(3 * index)))
                if ir.getItems("Forecast_Humidity_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_Humidity_{:02d}".format(3 * index), item_type="Number:Dimensionless", label="Forecast ({:02d}): Humidity [%d %%]".format(3 * index), category="Humidity", tags=["OpenWeatherMap"])
                    add_link("Forecast_Humidity_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#humidity".format(3 * index)))
                if ir.getItems("Forecast_WindSpeed_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_WindSpeed_{:02d}".format(3 * index), item_type="Number:Speed", label="Forecast ({:02d}): Wind speed [%.0f %unit%]".format(3 * index), category="Wind", tags=["OpenWeatherMap"])
                    add_link("Forecast_WindSpeed_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#wind-speed".format(3 * index)))
                if ir.getItems("Forecast_GustSpeed_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_GustSpeed_{:02d}".format(3 * index), item_type="Number:Speed", label="Forecast ({:02d}): Gust speed [%.0f %unit%]".format(3 * index), category="Wind", tags=["OpenWeatherMap"])
                    add_link("Forecast_GustSpeed_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#gust-speed".format(3 * index)))
                if ir.getItems("Forecast_WindDirection_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_WindDirection_{:02d}".format(3 * index), item_type="Number:Angle", label="Forecast ({:02d}): Wind direction [SCALE(windDirection.scale):%s]".format(3 * index), category="Wind", tags=["OpenWeatherMap"])
                    add_link("Forecast_WindDirection_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#wind-direction".format(3 * index)))
                if ir.getItems("Forecast_Cloudiness_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_Cloudiness_{:02d}".format(3 * index), item_type="Number:Dimensionless", label="Forecast ({:02d}): Cloudiness [%d %%]".format(3 * index), category="Sun_Clouds", tags=["OpenWeatherMap"])
                    add_link("Forecast_Cloudiness_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#cloudiness".format(3 * index)))
                if ir.getItems("Forecast_RainVolume_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_RainVolume_{:02d}".format(3 * index), item_type="Number:Length", label="Forecast ({:02d}): Rain volume [%.1f %unit%]".format(3 * index), category="Rain", tags=["OpenWeatherMap"])
                    add_link("Forecast_RainVolume_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#rain".format(3 * index)))
                if ir.getItems("Forecast_SnowVolume_{:02d}".format(3 * index)) == []:
                    add_item("Forecast_SnowVolume_{:02d}".format(3 * index), item_type="Number:Length", label="Forecast ({:02d}): Snow volume [%.1f %unit%]".format(3 * index), category="Snow", tags=["OpenWeatherMap"])
                    add_link("Forecast_SnowVolume_{:02d}".format(3 * index), ChannelUID(owmThingUID + ":forecastHours{:02d}#snow".format(3 * index)))

            from core.rules import rule
            from core.triggers import when

            @rule("Add OpenWeatherMap Items to daily forecast groups")
            @when("Item Current_Timestamp changed")
            def addOWMItemsToGroups(event):
                # remove hourly forecast Items from groups
                for groupIndex in range(1, 6):
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_Timestamp_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_Timestamp_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_Condition_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_Condition_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_ConditionID_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_ConditionID_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_IconID_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_IconID_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_Icon_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_Icon_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_Temperature_High_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_Temperature_High_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_Temperature_Low_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_Temperature_Low_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_Pressure_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_Pressure_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_Humidity_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_Humidity_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_WindSpeed_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_WindSpeed_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_GustSpeed_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_GustSpeed_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_WindDirection_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_WindDirection_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_Cloudiness_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_Cloudiness_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_RainVolume_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_RainVolume_{}".format(groupIndex)).removeMember(member)
                    for member in filter(lambda item: "Current" not in item.name, ir.getItem("gForecast_SnowVolume_{}".format(groupIndex)).getMembers()):
                        ir.getItem("gForecast_SnowVolume_{}".format(groupIndex)).removeMember(member)

                # update group labels to reflect week day
                from org.joda.time import DateTime
                import calendar
                lastReading = DateTime(str(items["Current_Timestamp"])).getDayOfWeek() - 1
                for index in range(1, 6):
                    dayOfWeek = "Today" if index == 1 else calendar.day_name[(lastReading + index - 1) % 7]
                    ir.getItem("gForecast_" + str(index)).setLabel(dayOfWeek)
                    ir.getItem("gForecast_Timestamp_" + str(index)).setLabel(dayOfWeek + ": Timestamp")
                    ir.getItem("gForecast_Condition_" + str(index)).setLabel(dayOfWeek + ": Condition [%s]")
                    ir.getItem("gForecast_ConditionID_" + str(index)).setLabel(dayOfWeek + ": Condition ID [%s]")
                    ir.getItem("gForecast_IconID_" + str(index)).setLabel(dayOfWeek + ": Icon ID [%s]")
                    ir.getItem("gForecast_Icon_" + str(index)).setLabel(dayOfWeek + ": Icon")
                    ir.getItem("gForecast_Temperature_High_" + str(index)).setLabel(dayOfWeek + ": Temperature (high) [%.0f %unit%]")
                    ir.getItem("gForecast_Temperature_Low_" + str(index)).setLabel(dayOfWeek + ": Temperature (low) [%.0f %unit%]")
                    ir.getItem("gForecast_Pressure_" + str(index)).setLabel(dayOfWeek + ": Pressure [%.1f %unit%]")
                    ir.getItem("gForecast_Humidity_" + str(index)).setLabel(dayOfWeek + ": Humidity [%d %%]")
                    ir.getItem("gForecast_WindSpeed_" + str(index)).setLabel(dayOfWeek + ": Wind Speed [%.0f %unit%]")
                    ir.getItem("gForecast_GustSpeed_" + str(index)).setLabel(dayOfWeek + ": Gust Speed [%.0f %unit%]")
                    ir.getItem("gForecast_WindDirection_" + str(index)).setLabel(dayOfWeek + ": Wind direction [SCALE(windDirection.scale):%s]")
                    ir.getItem("gForecast_Cloudiness_" + str(index)).setLabel(dayOfWeek + ": Cloudiness [%d %%]")
                    ir.getItem("gForecast_RainVolume_" + str(index)).setLabel(dayOfWeek + ": Rain Volume [%.1f %unit%]")
                    ir.getItem("gForecast_SnowVolume_" + str(index)).setLabel(dayOfWeek + ": Snow Volume [%.1f %unit%]")

                # add Forecast Items to groups, and update the labels to reflect time
                groupIndex = 1
                for index in range(1, 41):
                    if DateTime(str(items["Forecast_Timestamp_{:02}".format(3 * index)])).getDayOfWeek() - 1 != (DateTime.now().getDayOfWeek() + groupIndex - 2) % 7:
                        if groupIndex == 5:
                            break# we're at the end of the forecasts that fit into 5 days
                        else:
                            groupIndex += 1
                    labelTime = items["Forecast_Timestamp_{:02}".format(3 * index)].format("%1$tl:%1$tM%1$tp")

                    ir.getItem("gForecast_Timestamp_{}".format(groupIndex)).addMember(ir.getItem("Forecast_Timestamp_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_Timestamp_{:02d}".format(3 * index)).setLabel("Forecast ({}): Timestamp [%1$tY-%1$tm-%1$td %1$tI:%1$tM%1$tp]".format(labelTime))

                    ir.getItem("gForecast_Condition_{}".format(groupIndex)).addMember(ir.getItem("Forecast_Condition_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_Condition_{:02d}".format(3 * index)).setLabel("Forecast ({}): Condition [%s]".format(labelTime))

                    ir.getItem("gForecast_ConditionID_{}".format(groupIndex)).addMember(ir.getItem("Forecast_ConditionID_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_ConditionID_{:02d}".format(3 * index)).setLabel("Forecast ({}): Condition ID [%s]".format(labelTime))

                    ir.getItem("gForecast_IconID_{}".format(groupIndex)).addMember(ir.getItem("Forecast_IconID_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_IconID_{:02d}".format(3 * index)).setLabel("Forecast ({}): Icon ID [%s]".format(labelTime))

                    ir.getItem("gForecast_Icon_{}".format(groupIndex)).addMember(ir.getItem("Forecast_Icon_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_Icon_{:02d}".format(3 * index)).setLabel("Forecast ({}): Icon".format(labelTime))

                    ir.getItem("gForecast_Temperature_High_{}".format(groupIndex)).addMember(ir.getItem("Forecast_Temperature_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_Temperature_{:02d}".format(3 * index)).setLabel("Forecast ({}): Temperature [%.0f %unit%]".format(labelTime))

                    ir.getItem("gForecast_Temperature_Low_{}".format(groupIndex)).addMember(ir.getItem("Forecast_Temperature_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_Temperature_{:02d}".format(3 * index)).setLabel("Forecast ({}): Temperature [%.0f %unit%]".format(labelTime))

                    ir.getItem("gForecast_Pressure_{}".format(groupIndex)).addMember(ir.getItem("Forecast_Pressure_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_Pressure_{:02d}".format(3 * index)).setLabel("Forecast ({}): Pressure [%.1f %unit%]".format(labelTime))

                    ir.getItem("gForecast_Humidity_{}".format(groupIndex)).addMember(ir.getItem("Forecast_Humidity_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_Humidity_{:02d}".format(3 * index)).setLabel("Forecast ({}): Humidity [%d %%]".format(labelTime))

                    ir.getItem("gForecast_WindSpeed_{}".format(groupIndex)).addMember(ir.getItem("Forecast_WindSpeed_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_WindSpeed_{:02d}".format(3 * index)).setLabel("Forecast ({}): Wind speed [%.0f %unit%]".format(labelTime))

                    ir.getItem("gForecast_GustSpeed_{}".format(groupIndex)).addMember(ir.getItem("Forecast_GustSpeed_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_GustSpeed_{:02d}".format(3 * index)).setLabel("Forecast ({}): Gust speed [%.0f %unit%]".format(labelTime))

                    ir.getItem("gForecast_WindDirection_{}".format(groupIndex)).addMember(ir.getItem("Forecast_WindDirection_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_WindDirection_{:02d}".format(3 * index)).setLabel("Forecast ({}): Wind direction [SCALE(windDirection.scale):%s]".format(labelTime))

                    ir.getItem("gForecast_Cloudiness_{}".format(groupIndex)).addMember(ir.getItem("Forecast_Cloudiness_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_Cloudiness_{:02d}".format(3 * index)).setLabel("Forecast ({}): Cloudiness [%d %%]".format(labelTime))

                    ir.getItem("gForecast_RainVolume_{}".format(groupIndex)).addMember(ir.getItem("Forecast_RainVolume_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_RainVolume_{:02d}".format(3 * index)).setLabel("Forecast ({}): Rain volume [%.1f %unit%]".format(labelTime))

                    ir.getItem("gForecast_SnowVolume_{}".format(groupIndex)).addMember(ir.getItem("Forecast_SnowVolume_{:02d}".format(3 * index)))
                    ir.getItem("Forecast_SnowVolume_{:02d}".format(3 * index)).setLabel("Forecast ({}): Snow volume [%.1f %unit%]".format(labelTime))

                # set Condition, Icon and WindDirection group values
                for index in range(1, 6):
                    for group in [600, 200, 500, 300, 700, 800]:# the Conditions are organized into groups (https://openweathermap.org/weather-conditions), which I have prioritized
                        forecastItems = filter(lambda item: int(item.state.toString()) in range(group, group + 100), ir.getItem("gForecast_ConditionID_" + str(index)).getMembers())
                        if len(forecastItems) > 0:
                            sortedItems = sorted(forecastItems, key = lambda item: int(item.state.toString()))
                            selectedItem = sortedItems.pop()# this will provide the highest value in the sorted list of Items, which is usually the most severe condition
                            events.postUpdate("gForecast_ConditionID_" + str(index), selectedItem.state.toString())
                            events.postUpdate("gForecast_Condition_" + str(index), items[selectedItem.name.replace("ID", "")].toString())
                            events.postUpdate("gForecast_IconID_" + str(index), items[selectedItem.name.replace("Condition", "Icon")].toString())
                            events.postUpdate(ir.getItem("gForecast_Icon_" + str(index)), items[selectedItem.name.replace("ConditionID", "Icon")])
                            break
                    # this can be removed when QuantityTypeArithmeticGroupFunction.Avg() is fixed for Number:Angle
                    windDirectionItemStates = map(lambda item: item.state.intValue(), filter(lambda member: member.state != NULL and member.state != UNDEF, ir.getItem("gForecast_WindDirection_" + str(index)).getMembers()))
                    if len(windDirectionItemStates) > 0:
                        windDirectionAvg = reduce(lambda x, y: (((x + y) / 2) if y - x < 180 else (x + y + 360) / 2) % 360, windDirectionItemStates)
                        events.postUpdate("gForecast_WindDirection_" + str(index), str(windDirectionAvg))

                addOWMItemsToGroups.log.debug("Updated groups and Items")

            addOWMItemsToGroups(None)
    except:
        import traceback
        addOWMItems.log.error(traceback.format_exc())

def scriptLoaded(id):
    addOWMItems()

and it works quite fine( it’s Original Scott :wink:). So I’m wondering if my VSC-Settings for Python are correct?!

.env is:

PYTHONPATH="./automation/lib/python"

.pylintrc is:

[MESSAGES CONTROL]
disable=
    missing-docstring,
    unused-variable,
    line-too-long,
    logging-format-interpolation,
    bare-except,
    broad-except,
    pointless-string-statement,
    undefined-variable,
    unused-argument,
    wrong-import-position,
    anomalous-unicode-escape-in-string,
    global-statement

ignored-modules=
    org.joda.time,
    java,
    core,
    core.jsr223,
    core.actions,
    community,
    personal,
    configuration,
    events

[DESIGN]
# Maximum number of parents for a class (see R0901).
max-parents=15

and .vsc(settings.json) is:

{
    "openhab.host": "192.168.x.yyy",
    "openhab.port": 8080,
    "openhab.remoteLspEnabled": true,
    "openhab.remoteLspPort": 5007,
    "openhab.sitemapPreviewUI": "basicui",
    "openhab.useRestApi": true,
    "python.linting.ignorePatterns": [
        "**/automation/**/python/core/**/*.py",
        "**/automation/**/python/community/**/*.py"
    ],
    "python.linting.enabled": true,
    "python.linting.pylintEnabled": true,
    "python.pythonPath": "D:\\Programme-Peter\\Python\\Python27\\python.exe"

}

OK… these are not extraneous but legitimate warnings from pylint. I could have cleared this up a while ago, if you had been more specific about what script you were seeing the warnings in :slightly_smiling_face:.

A few months ago, I updated all of the Jython core and community helper libraries and scripts, so that pylint no longer returns any errors or warnings for them. Once I get the PRs merged and you update, you will no longer see these warnings.

That sounds good, but where can I get actual setup ?
I installed what I found in the forum. Can you give me some hints and help to upgrade ?

I’m working on getting the PRs together. You’ll need to be patient. The warnings you are receiving are superficial, so there’s no urgency.

In case there is confusion… the OpenWeatherMap script needs updating.

1 Like

No worries, mate. I can live with the current SetUp, when I know that it’s only temporarily and superficial.
With your answers I will go on now to learn more about JSR223/Scripted Automation and don’t think anymore about the side-effects of my VSC-SetUp for the Python-Extension.
Thx for answering and help. Hope to hear from you, when new PRs are online.

Cheers - Peter

1 Like