OH2 Astro binding - Question or feature request: calculate next day's sunrise time

Hi Justus,

that would be it, just a very crude piece of python. Run on a Linux terminal with e.g.
$ nohup local.py > log.txt &

and it should stay running until the machine is shut down. All you need then is a mqtt broker. I added the “tomorrow” computation without running it, so please make sure I did not make a typo or so. As I said before the difference between today and tomorrow is typically only a few minutes away from 24hrs.

The script local.py:

#!/usr/bin/python3
import ephem
import datetime, time
import paho.mqtt.client as mqtt

mqtt_broker="127.0.0.1" 
mqttc = mqtt.Client()
mqttc.connect(mqtt_broker, 1883, 60)

# define location Local and start of today
local = ephem.Observer()
local.lat = '<lat>' 
local.lon = '<lon>' 
local.elevation = 500
tomorrow = local

sun = ephem.Sun()

old = 0
sun_alt_old = 0
sun_az_old = 0
moon_alt_old = 0
moon_az_old = 0
moon_fli_old = 0

mqttc.loop_start()

while True:
    now = ephem.Date(datetime.datetime.utcnow())
    # Make sure we have today's date and times:
    if (now - old) > 1.0:
        # IMPORTANT: This is in UTC. If you live significantly away from lon=0, adjust for your timezone by subtracting TZ-offset
        # This is to make sure the computation is done after dusk and before dawn. Otherwise no effect, so needs not be precise.
        # E.g. subtracting "lon/360" will do just fine, unless you live in arctic regions.
        local.date = ephem.Date(datetime.datetime.utcnow().date()) 
        old =  local.date
        # Compute the relevant time points:
        sunrise = local.next_rising(sun)
        sunset = local.next_setting(sun)
        transit = local.next_transit(sun)
        # Modify "horizon" altitude for dusk and dawn. Common values are 6,12,18 (civil, nautical, astro)
        local.horizon = '-12'
        dawn = local.next_rising(sun)
        dusk = local.next_setting(sun)
        local.horizon = '0'
        #
        mqttc.publish('local/sun/dawn', payload=int(dawn.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        mqttc.publish('local/sun/rise', payload=int(sunrise.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        mqttc.publish('local/sun/transit', payload=int(transit.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        mqttc.publish('local/sun/set', payload=int(sunset.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        mqttc.publish('local/sun/dusk', payload=int(dusk.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        tomorrow.date = local.date + 1
       # Compute the relevant time points tomorrow:
        sunrise_t = tomorrow.next_rising(sun)
        sunset_t = tomorrow.next_setting(sun)
        transit_t = tomorrow.next_transit(sun)
        # Modify "horizon" altitude for dusk and dawn. 
        tomorrow.horizon = '-12'
        dawn_t = tomorrow.next_rising(sun)
        dusk_t = tomorrow.next_setting(sun)
        tomorrow.horizon = '0'
        mqttc.publish('tomorrow/sun/dawn', payload=int(dawn_t.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        mqttc.publish('tomorrow/sun/rise', payload=int(sunrise_t.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        mqttc.publish('tomorrow/sun/transit', payload=int(transit_t.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        mqttc.publish('tomorrow/sun/set', payload=int(sunset_t.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)
        mqttc.publish('tomorrow/sun/dusk', payload=int(dusk_t.datetime().replace(tzinfo=datetime.timezone.utc).timestamp()), qos=0, retain=True)



    # Compute Sun and Moon for now and publish if changed
    local.date = now
    sol = ephem.Sun(local)
    luna = ephem.Moon(local)
    sun_alt = int(sol.alt*180/ephem.pi)
    if sun_alt != sun_alt_old:
        mqttc.publish('local/sun/alt', payload=sun_alt, qos=0, retain=True)
        sun_alt_old = sun_alt
    sun_az = int(sol.az*180/ephem.pi)
    if sun_az != sun_az_old:
        mqttc.publish('local/sun/az', payload=sun_az, qos=0, retain=True)
        sun_az_old = sun_az
    moon_alt = int(luna.alt*180/ephem.pi)
    if moon_alt != moon_alt_old:
        mqttc.publish('local/moon/alt', payload=moon_alt, qos=0, retain=True)
        moon_alt_old = moon_alt
    moon_az = int(luna.az*180/ephem.pi)
    if moon_az != moon_az_old:
        mqttc.publish('local/moon/az', payload=moon_az, qos=0, retain=True)
        moon_az_old = moon_az
    moon_fli = int(luna.phase)
    if moon_fli != moon_fli_old:
        mqttc.publish('local/moon/fli', payload=moon_fli, qos=0, retain=True)
        moon_fli_old = moon_fli

    time.sleep(10)

In openhab then have the items from mqtt defined like this (vers 2.3 or lower, I’ve heard 2.4 may look different, but I don’t run it):

//
// Solar and lunar data f. Local
DateTime  Local_Dawn    {mqtt="<[raspi-serverMQTT:local/sun/dawn:state:JS(timestamp.js)]"}
DateTime  Local_Rise    {mqtt="<[raspi-serverMQTT:local/sun/rise:state:JS(timestamp.js)]"}
DateTime  Local_Transit {mqtt="<[raspi-serverMQTT:local/sun/transit:state:JS(timestamp.js)]"}
DateTime  Local_Set     {mqtt="<[raspi-serverMQTT:local/sun/set:state:JS(timestamp.js)]"}
DateTime  Local_Dusk    {mqtt="<[raspi-serverMQTT:local/sun/dusk:state:JS(timestamp.js)]"}

DateTime  Tomorrow_Dawn    {mqtt="<[raspi-serverMQTT:tomorrow/sun/dawn:state:JS(timestamp.js)]"}
DateTime  Tomorrow_Rise    {mqtt="<[raspi-serverMQTT:tomorrow/sun/rise:state:JS(timestamp.js)]"}
DateTime  Tomorrow_Transit {mqtt="<[raspi-serverMQTT:tomorrow/sun/transit:state:JS(timestamp.js)]"}
DateTime  Tomorrow_Set     {mqtt="<[raspi-serverMQTT:tomorrow/sun/set:state:JS(timestamp.js)]"}
DateTime  Tomorrow_Dusk    {mqtt="<[raspi-serverMQTT:tomorrow/sun/dusk:state:JS(timestamp.js)]"}

Number  Local_SunAlt     {mqtt="<[raspi-serverMQTT:local/sun/alt:state:default]"}
Number  Local_SunAz      {mqtt="<[raspi-serverMQTT:local/sun/az:state:default]"}
Number  Local_MoonAlt    {mqtt="<[raspi-serverMQTT:local/moon/alt:state:default]"}
Number  Local_MoonAz     {mqtt="<[raspi-serverMQTT:local/moon/az:state:default]"}
Number  Local_MoonFLI    {mqtt="<[raspi-serverMQTT:local/moon/fli:state:default]"}

and the timestamp.js transformation is just:

(function(i) {
    var date = new Date(i * 1000.);
    return date.toISOString();
})(input)