Over the past weeks I have succeded in installing (easy: openHabian) HABApp, configuring a development environment (VS Code on my macos: hard - took me days to understand virtualenvironments, pyenv etc), and even a rule to shut off my espresso machine after being unused for 1,5 hours.
I also got my screens working (auto up and down based on sun_azimuth and elevation).
However, while making the rule smarter I also introduced errors. Up until now I have been able to correct these myself. This time I am stuck however.
Help would be appreciated to get me going again.
This is my script:
import HABApp
from HABApp.core.events import ValueUpdateEventFilter, ValueUpdateEvent
from HABApp.core.items import Item
from HABApp.openhab.items import SwitchItem, NumberItem, GroupItem
import statistics
import logging
log = logging.getLogger("RuleLog")
class ScreenAutomation(HABApp.Rule):
def __init__(self):
super().__init__()
self.sceneScreensZdicht=SwitchItem.get_item('Zuidscreens_preset_0_omlaag_Scene')
self.sceneScreensZopen=SwitchItem.get_item('Zone_Zuidscreens_Group_gray_Scene_preset_2_Scene')
self.sceneScreensWdicht=SwitchItem.get_item('Zone_Westscreens_Group_preset_0_Scene')
self.sceneScreensWopen=SwitchItem.get_item('Zone_Westscreens_Group_gray_Scene_preset_2_Scene')
self.bewolking0H=NumberItem.get_item('One_Call_API_Bewolking_plus_0H').value
self.bewolking1H=NumberItem.get_item('One_Call_API_Bewolking_plus_1H').value
self.bewolking2H=NumberItem.get_item('One_Call_API_Bewolking_plus_2H').value
self.bewolking3H=NumberItem.get_item('One_Call_API_Bewolking_plus_3H').value
self.gem_bewolking=statistics.mean([self.bewolking0H, self.bewolking1H, self.bewolking2H, self.bewolking3H])
self.buienhoeveelheid=GroupItem.get_item('Buienradar_eerste_kwartier')
self.buien=(GroupItem.get_item('Buienradar_komende_2_uur'))
self.run.at(self.run.trigger.sun_azimuth(90),self.screensSouthDown)
self.run.at(self.run.trigger.sun_azimuth(140),self.screensWestDown)
self.run.at(self.run.trigger.sun_azimuth(250),self.screensSouthUp)
self.run.at(self.run.trigger.sun_elevation(15,'setting'),self.screensWestUp)
self.buienhoeveelheid.listen_event(self.alleScreensOmhoog,ValueUpdateEventFilter())
def screensSouthDown(self) -> None:
log.info('Tijd om de screens in het zuiden te sluiten.')
if self.gem_bewolking<45:
log.debug(f'"Verwacht bewolkingspercentage: "{self.gem_bewolking}". Boven 45% gaan screens niet dicht."')
if self.buien.value<1:
log.debug(f'Verwachte buienhoeveelheid komende twee uur: {self.buien.value}. Boven 1mm gaan screens niet dicht.')
if self.sceneScreensZdicht.is_off():
log.debug(f'"Status van screen scene "dicht": "{self.sceneScreensZopen}')
self.sceneScreensZdicht.on()
log.info('Commando "DICHT" gegeven.')
log.info(f'{self.sceneScreensZdicht.name}", "{self.sceneScreensZdicht.command_value}')
else:
log.info('Geen actie: de screens zijn al dicht.')
log.debug(f'{self.sceneScreensZdicht.name}", "{self.sceneScreensZdicht.command_value}')
else:
log.info(f'"Buienkans is meer dan "{self.buien.value}" mm in de komende 2 uur, screens dichtlaten."')
else:
log.info(f'"De bewolking is meer dan "{self.gem_bewolking}" %. Geen screens nodig."')
def screensSouthUp(self):
log.info('Tijd om de screens in het zuiden te openen')
if self.sceneScreensZopen.is_off():
self.sceneScreensZopen.on()
log.info('Commando "OPEN" gegeven.')
log.info(f'{self.sceneScreensZopen.name}", "{self.sceneScreensZopen.command_value}')
else:
log.info('Geen actie: de screens staan al omhoog.')
def screensWestDown(self):
log.info('Tijd om de screens in het westen te sluiten.')
if self.gem_bewolking.value<45:
log.debug(f'"Verwacht bewolkingspercentage: "{self.gem_bewolking}". Boven 45% gaan screens niet dicht."')
if self.buien.value<1:
log.debug(f'"Verwachte buienhoeveelheid komende twee uur: "{self.buien.value}". Boven 1mm gaan screens niet dicht."')
if self.sceneScreensWdicht.is_off():
self.sceneScreensWdicht.on()
log.info('Commando "DICHT" gegeven.')
log.info(f'{self.sceneScreensWdicht.name}", "{self.sceneScreensWdicht.command_value}')
else:
log.info('Geen actie: de screens zijn al dicht.')
log.debug(f'{self.sceneScreensZdicht.name}", "{self.sceneScreensZdicht.command_value}')
else:
log.info(f'"Buienkans is meer dan "{self.buien.value}" mm in de komende 2 uur, screens dichtlaten"')
else:
log.info(f'"De gem_bewolking is meer dan "{self.gem_bewolking}"%. Geen screens nodig."')
def screensWestUp(self):
log.info('Tijd om de screens in het westen te openen')
if self.sceneScreensWopen.is_off():
self.sceneScreensWopen.on()
log.info('Commando "OPEN" gegeven.')
log.info(f'{self.sceneScreensWopen.name}", "{self.sceneScreensWopen.command_value}')
else:
log.info('Geen actie: de screens staan al omhoog.')
def alleScreensOmhoog(self, event: ValueUpdateEvent):
if self.buienhoeveelheid.value>0.0:
if self.buienhoeveelheid.value <0.5 and (self.sceneScreensZdicht.is_on or self.sceneScreensWdicht.is_on):
log.info(f'"De hoeveelheid regen de komende 15 minuten valt mee: "{self.buienhoeveelheid.value}" mm, de screens kunnen omlaag blijven."')
elif self.sceneScreensWopen.is_off:
log.info('Regen in de komende 15 minuten: screens op het westen omhoog.')
self.sceneScreensWopen.on
elif self.sceneScreensZopen.is_off:
log.info('Regen in de komende 15 minuten: screens op het zuiden omhoog.')
self.sceneScreensZopen.on
ScreenAutomation()
What am I trying to do?
- Bring down the sunscreens as soon as the sun is going to shine into the windows (sun_azimuth).
- Do not bring the screens down if cloudiness is going to be more than 45% or if there is a chance of rain of more than 1 mm/hr.
- Bring up the screens as soon as the sun goes beyond a certain azimuth (does not shine on window) or if it is so far down (elevation) it’s ray’s stop having enough power to warm up the window.
- Bring up the screens if there is a chance of rain > 1.5 mm in the coming quarter of an hour.
The error seems to be from this code:
self.gem_bewolking=statistics.mean([self.bewolking0H, self.bewolking1H, self.bewolking2H, self.bewolking3H])
In stead of using the value of an avaraged group in openhab I thought I would calculate the avarage cloudiness (bewolking) for the coming 4 hours.
The cloudiness items are One_Call_API dimensionless numbered channels (openweather). Somehow python wants a unit (but does not see one)? But from documentation I understand that statistics.mean() only expects numbers.
Websearches at this point fail to help me with usefull hits. I think I need hints from knowledgable Python programmers.
System used:
RPi 5 , 16GB
openhabian
openhab 4.3.5
habapp 25.5.0
This is the traceback from my HABApp.log:
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.run.trigger = <class 'eascheduler.builder.triggers.TriggerBuilder'>
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - [self.bewolking0H, self.bewolking1H, self.bewolking2H, self.bewolking3H] = [100, 100, 100, 100]
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self = <ScreenAutomation>
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.bewolking0H = 100
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.bewolking1H = 100
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.bewolking2H = 100
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.bewolking3H = 100
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.run = <HABApp.rule.scheduler.job_builder.HABAppJobBuilder object at 0x7fff3289b790>
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.sceneScreensWdicht = <SwitchItem name: Zone_Westscreens_Group_preset_0_Scene, value: OFF, last_change: InstantView(2025-06-01T16:43:02.378733221+02:00), last_update: InstantView(2025-06-01T16:43:02.378733221+02:00)>
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.sceneScreensWopen = <SwitchItem name: Zone_Westscreens_Group_gray_Scene_preset_2_Scene, value: ON, last_change: InstantView(2025-06-01T16:43:02.378279089+02:00), last_update: InstantView(2025-06-01T16:43:02.378279089+02:00)>
2025-06-01 16:43:03.791 [ERROR] [HABApp.Rules ] - self.sceneScreensZdicht = <SwitchItem name: Zuidscreens_preset_0_omlaag_Scene, value: OFF, last_change: InstantView(2025-06-01T16:43:02.380255245+02:00), last_update: InstantView(2025-06-01T16:43:02.380255245+02:00)>
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - self.sceneScreensZopen = <SwitchItem name: Zone_Zuidscreens_Group_gray_Scene_preset_2_Scene, value: ON, last_change: InstantView(2025-06-01T16:43:02.378682646+02:00), last_update: InstantView(2025-06-01T16:43:02.378682646+02:00)>
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - ------------------------------------------------------------
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] -
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - --------------------------------------------------------------------------------
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - Traceback (most recent call last):
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "/opt/habapp/lib/python3.11/site-packages/HABApp/rule_manager/rule_file.py", line 79, in load
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - self.create_rules(created_rules)
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "/opt/habapp/lib/python3.11/site-packages/HABApp/rule_manager/rule_file.py", line 69, in create_rules
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - runpy.run_path(str(self.path), run_name=str(self.path), init_globals=rule_hook.in_dict())
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "<frozen runpy>", line 291, in run_path
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "<frozen runpy>", line 98, in _run_module_code
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "<frozen runpy>", line 88, in _run_code
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "/etc/openhab/habapp/rules/ScreenAutomation.py", line 106, in ScreenAutomation.py
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - ScreenAutomation()
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "/etc/openhab/habapp/rules/ScreenAutomation.py", line 23, in __init__
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - self.gem_bewolking=statistics.mean([self.bewolking0H, self.bewolking1H, self.bewolking2H, self.bewolking3H])
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "/usr/lib/python3.11/statistics.py", line 433, in mean
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - return _convert(total / n, T)
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - ^^^^^^^^^^^^^^^^^^^^^^
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - File "/usr/lib/python3.11/statistics.py", line 343, in _convert
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - return T(value)
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - ^^^^^^^^
2025-06-01 16:43:03.792 [ERROR] [HABApp.Rules ] - TypeError: QuantityInt.__new__() missing 1 required positional argument: 'unit'
2025-06-01 16:43:03.792 [WARN ] [HABApp.Rule ] - /opt/habapp/lib/python3.11/site-packages/HABApp/rule_manager/rule_file.py:86: RuntimeWarning:coroutine 'HABAppRuleContext.unload_rule' was never awaited
2025-06-01 16:43:03.792 [WARN ] [HABApp.Rules ] - Failed to load /etc/openhab/habapp/rules/ScreenAutomation.py!