#### # Rules to calculate outside light lux. # Rules are taken from Domoticz LUA script at https://www.domoticz.com/wiki/Real-time_solar_data_without_any_hardware_sensor_:_azimuth,_Altitude,_Lux_sensor... # Authors: S bastien Joly, Neutrino, Jmleglise # # Adapted to openHab rule by mherwege # Adapted further to work with astro and synop bindings by William # Adapted to jython by William # # For this script to work you need astro and synop. See the "Config section" #### from org.slf4j import LoggerFactory from core.triggers import when from core.rules import rule from datetime import date from datetime import datetime import math from decimal import Decimal ## Config section config_debugSolar=True config_useArbitraryTwilight=True config_SunElevation="LocalSun_Position_Elevation" config_SunTotalRadiation="LocalSun_Radiation_TotalRadiation" config_SynopOcta="SynopMessage_Octa" config_LuxItem="Lux" config_WeightedLuxItem="WeightedLux" ## @rule("CurrentVirtualLux", description="VirtualLux calculator", tags=["Example", "virtualLux"]) @when("Item "+config_SunElevation+" received update") @when("Item "+config_SunTotalRadiation+" received update") @when("Item "+config_SynopOcta+" received update") def CurrentVirtualLux(event): if config_debugSolar: CurrentVirtualLux.log.info("%s received update" % event.itemName) # Fetch data from configured OH items try: #Octa is sometimes not updated correctly, let's try to handle it and print a warning data_octa=unicode(ir.getItem(config_SynopOcta).getState()) except Exception as e: CurrentVirtualLux.log.warning("Error fetching Octa from OH, using 0 as Octa. error: %s" % e) data_octa=0 pass data_SunElev=unicode(ir.getItem(config_SunElevation).getState()) data_SunRadTotal=unicode(ir.getItem(config_SunTotalRadiation).getState()) if config_debugSolar: CurrentVirtualLux.log.info("synop cloudcoverage: %s SunElev: %s SunRadTotal: %s" % (data_octa, data_SunElev, data_SunRadTotal) ) # mangle data to help python make it Decimal() (split on space to remove the extra data from str eg. centigrade charecter and hPa) decimal_data_SunElev=Decimal(data_SunElev.split()[0]) decimal_data_SunRadTotal=Decimal(data_SunRadTotal.split()[0]) decimal_data_octa=Decimal(data_octa.split()[0]) if config_debugSolar: CurrentVirtualLux.log.info("synop cloudcoverage: %s SunElev: %s SunRadTotal: %s" % (decimal_data_octa, decimal_data_SunElev, decimal_data_SunRadTotal) ) # Calculate cloud coverage from octa float_cloudCoverage = float(1 - 0.75 * math.pow(float(decimal_data_octa)/8.0, 3.4)) if config_debugSolar: CurrentVirtualLux.log.info("cloudcoverage value: %s" % (float_cloudCoverage)) # Arbitrary twilight calculations (below 3 degrees calculations astro reports 0.0 for SunRadTotalArbitrary). # W/m^2 equal 800 Lux (the theoretical value is 4.74 but more accurate result with 6.32...) # In my situation I need the Lux to go all the way down to 0 (some automatic lights) arbitraryTwilightLux = 6.32 decimal_data_SunRadTotalArbitrary=Decimal(arbitraryTwilightLux - (1.0 - float(decimal_data_SunElev))/8.0 * arbitraryTwilightLux) if config_useArbitraryTwilight and decimal_data_SunRadTotal < 1.0: decimal_data_SunRadTotal=decimal_data_SunRadTotalArbitrary if config_debugSolar: CurrentVirtualLux.log.info("decimal_data_SunRadTotalArbitrary: %s" % (decimal_data_SunRadTotalArbitrary)) # Radiation in Lux. 1 Lux = 0.0079 W/m * decimal_vLux = float(decimal_data_SunRadTotal) / 0.0079 decimal_vLuxArbitrary=Decimal(decimal_data_SunRadTotalArbitrary / Decimal(0.0079)) # radiation of the Sun with the cloud layer decimal_vWeightedLux = float(decimal_vLux * float_cloudCoverage) decimal_vWeightedLuxArbitrary=Decimal(decimal_vLuxArbitrary * Decimal(float_cloudCoverage)) # If values are negative set them to 0 if decimal_vLux < 0.0: decimal_vLux=0 if decimal_vWeightedLux < 0.0: decimal_vWeightedLux=0 if decimal_vLuxArbitrary < 0.0: decimal_vLuxArbitrary=0 if decimal_vWeightedLuxArbitrary < 0.0: decimal_vWeightedLuxArbitrary=0 # print values to log, we did some stuff CurrentVirtualLux.log.info("Lux: %s WeightedLux: %s" % (decimal_vLux, decimal_vWeightedLux)) if config_debugSolar: CurrentVirtualLux.log.info("ArbitraryTwilight:%s Lux: %s WeightedLux: %s" % (config_useArbitraryTwilight, decimal_vLuxArbitrary, decimal_vWeightedLuxArbitrary)) # postUpdate OH items (use arbitrary twilight calculations if it is enabled) events.postUpdate(ir.getItem(config_LuxItem), float(decimal_vLux)) events.postUpdate(ir.getItem(config_WeightedLuxItem), float(decimal_vWeightedLux))