Ephemeris Time of Day - troubleshooting

@rlkoshak

This is moving from the github comments https://github.com/openhab-scripters/openhab-helper-libraries/pull/282

Here are my items

Group Ephem_TimeOfDay_StartTimes
Group Ephem_Default (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="default"] }
String vTimeOfDay "Current Time of Day [MAP(weather.map):%s]" <tod>
DateTime vDaylightStart_Time "Daylight Start [%1$tH:%1$tM]" <sun> (Ephem_Default){ channel="astro:sun:local:daylight#start", ToD="init"[tod_state="DAY"]}
DateTime vNightStart_Time "Night Start [%1$tH:%1$tM]" <sunset> (Ephem_Default){ channel="astro:sun:local:daylight#end", ToD="init"[tod_state="NIGHT"] }
DateTime vBed_Time "Bed [%1$tH:%1$tM]" <bedroom_blue> (Ephem_Default) { ToD="init"[start_time="00:01",tod_state="BED"]}

As for my ephemeris config i think i did this in paperUI under settings do you just want a screenshot of that?

ephem_tod.py

"""
Author: Rich Koshak
Implements the Time of Day Design Pattern using Ephemeris to determine the day
type so one can have a different set of times of day for different day types.
Requirements:
    - openHAB 2.5 M4 or later
    - Ephemeris configured
Limitations:
    - If using the Astro binding, the Rule that creates the Timers may be
      triggered more than once 30 seconds after midnight as Astro updates the
      Items. In testing this doesn't appear to cause any problems.
    - This script needs to be reloaded if Items are added or removed from
      tod_group_ephem or metadata changed on any of the Items this script
      needs to be reloaded.
License
=======
Copyright (c) contributors to the openHAB Scripters project
"""

from core.rules import rule
from core.triggers import when
from core.actions import Ephemeris, ScriptExecution
from core.metadata import get_key_value
from core.utils import send_command_if_different, post_update_if_different
from configuration import tod_group_ephem, tod_item_ephem
import threading
from org.joda.time import DateTime
from time import sleep

# Semiphore for keeping the Rule from triggering while the Items are being
# updated by the tod_update_items function.
updating = threading.BoundedSemaphore(1)

def tod_update_items(log):
    """
    Updates all descendents of tod_item_ephem if they posesses a ToD start_time
    metadata value and that start time string for today is different from the
    current state of the Item. This will thus update the Item's date to today if
    we have passed midnight.
    Arguments:
        - log: Logger passed in from the Rule that calls this function
    """
    # acquire a semiphore to keep these updates from executing the tod Rule
    if not updating.acquire(False):
        log.error("Failed to acquire the semiphore to initialize ToD Items!")
        return

    # loop through all the decendents of the group, for those with metadata
    # refresh the Item with the value in the metadata
    log.debug("Updating ToD Items from metadata")

    now = DateTime.now()
    items_initialized = False
    for start_time in ir.getItem(tod_group_ephem).allMembers:

        # Get the time string from the Item metadata
        time_str = get_key_value(start_time.name, "ToD", "start_time")

        # If there is a value, parse it and set the Item to that time for today
        if time_str != {}:
            log.debug("Handling {}".format(start_time))
            time_parts = time_str.split(':')
            num_parts = len(time_parts)
            if num_parts < 2:
                log.error("{} is malformed metadata to initialize"
                          " {}".format(t, start_time.name))
            else:
                tod_t = now.withTime(int(time_parts[0]),
                                     int(time_parts[1]),
                                     int(time_parts[2]) if num_parts > 2 else 0,
                                     int(time_parts[3]) if num_parts > 3 else 0)
                if str(start_time.state) != str(tod_t):
                    if post_update_if_different(start_time, str(tod_t)):
                        log.debug("Updated {} to {}".format(start_time.name,
                                                            tod_t))
                        items_initialized = True

    # Sleep for a little bit if one or more Items were updated
    try:
        if items_initialized:
            sleep(0.3) # Give Items a chance to update
    except:
        log.warn("Interrupted while sleeping waiting for Items to finsih "
                 "updating! Hoping for the best.")

    finally:
        # release the semiphore
        updating.release()
        log.debug("Done updating ToD Items")

def get_start_times(log):
    def get_group(type, check, curr, is_day):
        """
        Checks to see if there is a Group defined for type and whether today is
        in that that type.
        Arguments:
            - type: the day type.
            - check: check to perform to see if a Group defines the start times
                     for the given type
            - curr: the currently selected Group of start times.
            - is_day: True if today is of type
        Returns:
            - The first found Group that has metadata that matches type if
              is_day is True.
            - curr if is_day is False or there is no Group found for type.
        """

        # skip if it's not this day type
        if not is_day:
            return curr

        # get the group of start times if one exists
        log.debug("Checking for {}:".format(type))
        grps = [grp for grp in tod_grps if check(grp, type)]
        rval = curr
        if len(grps) > 0:
            rval = grps[0]
        if len(grps) > 1:
            log.warn("There is more than one {} Group! Only using the"
                               " first one {}".format(type, rval.name))
        return rval

    def get_groups(type, check, curr, key, day_check):
        """
        Determines if today is defined in any of the custom daysets or custom
        holiday files.
        Arguments:
            - type: the day type
            - check: the test to find the Groups that represent the day type
                     from the list of members of tod_grps_ephem
            - curr: the current Group of start times selected
            - key: name of the key containing additional relevant information
                ("set" for custom daysets or "file" for custom bank holidays)
            - day_check: function to call to determine if today is in the dayset
                         or custom bank holidays file.
        Returns:
            - One of the Groups if today is in the defined dayset or holiday
            file. If there is more than one, it is not fixed which Group is
            returned.
            - curr if today is not a defined in the dayset or custom bank
              holiday file.
        """
        log.debug("Checking for {}:".format(type))
        rval = curr
        for grp in [grp for grp in tod_grps if check(grp, type)]:
            value = get_key_value(grp.name, "ToD", key)
            if value == {}:
                log.error("Group {} doesn't have a key {}!"
                                    .format(grp.name, key))
            elif day_check(value):
                rval = curr
                log.debug("Today is in {}, it's a special day!".format(value))
        return rval

    tod_grps = ir.getItem(tod_group_ephem).members
    check = lambda grp, type: get_key_value(grp.name, "ToD", "type") == type
    start_times = None

    start_times = get_group("default",
                            lambda grp, type: check(grp, type) or get_key_value(grp.name, "ToD", "type") == {},
                            start_times,
                            True)

    start_times = get_group("weekday", check, start_times,
                            not Ephemeris.isWeekend())

    start_times = get_group("weekend", check, start_times, Ephemeris.isWeekend())

    start_times = get_groups("dayset", check, start_times, "set",
                             lambda ds: Ephemeris.isInDayset(ds))

    holiday = Ephemeris.getBankHolidayName()
    start_times = get_group("holiday", check, start_times, holiday is not None)
    if holiday is not None:
        ephem_tod.log.debug("It's {}, time to celebrate!".format(holiday))

    start_times = get_groups("custom", check, start_times, "file",
                 lambda file: Ephemeris.isBankHoliday(0, file))

    ephem_tod.log.debug("Creating Time of Day timers using {}".format(start_times.name))
    return start_times

# Time of Day timers to that drive the time of day events.
tod_timers = {}

def clear_timers():
    """ Cancel all the existing time of day timers. """
    for name, timer in tod_timers.items():
        if timer is not None and not timer.hasTerminated():
            timer.cancel()
        del tod_timers[name]

def create_tod_timers(log, start_times):
    """
    Using the passed in Group, create Timers for each start time to command the
    tod_item_ephem to the new time of day state.
    Arguments:
        - log: logger from the Rule
        - start_times: Group with DateTime Items as it's members that indicate
          the start time of a time of day (state) and the name of the state
          defined in metadata.
    """

    now = DateTime.now()
    clear_timers()

    # Create timers for all the members of tod_group.
    most_recent_time = now.minusDays(1)
    most_recent_state = str(items[tod_item_ephem])
    for start_time in start_times.members:

        item_time = DateTime(str(start_time.state))
        trigger_time = now.withTime(item_time.getHourOfDay(),
                                    item_time.getMinuteOfHour(),
                                    item_time.getSecondOfMinute(),
                                    item_time.getMillisOfSecond())

        # Update the Item if it still has yesterday's date.
        if item_time.isBefore(trigger_time):
            events.postUpdate(start_time, str(trigger_time))

        state = get_key_value(start_time.name, "ToD", "tod_state")
        # If there is no state we can't use this Item.
        if state == {}:
            log.error("{} does not have tod_state metadata!"
                      .format(start_time.name))

        # If we have already passed this time, keep track of the most recent
        # time and state.
        elif (trigger_time.isBefore(now)
                and trigger_time.isAfter(most_recent_time)):
            most_recent_time = trigger_time
            most_recent_state = state
            log.debug("The most recent state is now {}".format(state))

        # Create future timers
        elif trigger_time.isAfter(now):

            def tod_transition(state, log):
                """
                Called at a time of day transition, commands to the new time of
                day state.
                """
                log.info("Transitioning time of day from {} to {}."
                         .format(items[tod_item_ephem],state))
                events.sendCommand(tod_item_ephem, state)

            log.debug("Setting timer for Item {}, Time {}, and State {}"
                              ".".format(start_time.name, trigger_time, state))
            tod_timers[start_time.name] = ScriptExecution.createTimer(
                                            trigger_time,
                                            lambda s=state: tod_transition(s,
                                                                           log))

        else:
            log.debug("{} is in the past but there is a more recent "
                      "state".format(state))

    # Command the time of day to the current state
    log.info("Ephemeris time of day is now {}".format(most_recent_state))
    send_command_if_different(tod_item_ephem, most_recent_state)

@rule("Time of Day with Ephemeris",
      description=("Reusable Time of Day using Ephemeris to define different "
                   "times of day based on day type."),
      tags=["designpattern"])
@when("System started")
@when("Time cron 0 1 0 * * ? *")
@when("Descendent of {} changed".format(tod_group_ephem))
def ephem_tod(event):
    """
    Time of Day: A time based state machine which commands a state Item
    (tod_item_ephem in configuration.py) with the current time of day as a
    String.
    This Rule uses Ephemeris to determine the type of day (e.g. weekday) and
    selects the Group of start times for each time of day state based on the
    day type. See the Ephemeris documentation for details.
    To create the state machine, first create a Group and populate
    tod_group_ephem with that Group's name in configuration.py. Then create a
    Group for each type of day you have a different set of times of day. Add
    metadata to these Groups to identify what type of day those start times
    define.
    Supported types of days include:
        - default: this Group will be selected if no other type of day is
                   detected. Defined with the following metadata:
                       - Empty (i.e. no metadata)
                       - ToD="day"[type="default"]
        - weekday: this Group will be selected when Ephemeris.isWeekend()
                   returns False. Which days are defined as weekdays can be
                   configred in PaperUI. Defined with the following metadata:
                       - ToD="day"[type="weekday"]
        - weekend: this Group will be selected when Ephemeris.isWeekend()
                   returns True. Which days are defined as weekends can be
                   configured in PaperUI. Defined with the following metadata:
                       - ToD="day"[type="weekend"]
        - dayset: Ephemeris allows you to define custom daysets in
                  $OH_CONF/services/ephemeris.cfg. For example, if you have work
                  days that differ from your weekend/weekday schedule, you can
                  define a "workday" dayset. Defined with the following
                  metadata:
                      - ToD="day"[type="dayset", set="school"]
                  Use the name of the set as it is defined in ephemeris.cfg.
        - holiday: When Ephemeris is configured with country and region (and
                   city if used) in PaperUI, Ephemeris will automatically be
                   populated with the list of bank holidays (see the JollyDay
                   package on github). Defined with the following metadata:
                       - ToD="day"[type="holiday"]
        - custom: The Ephemeris capability allows one to define their own sets
                  of special days (e.g. birthdays and anniversaries) in a
                  specially formatted XML file. This allows you to define
                  additional bank holidays, an alternitive set of bank holidays
                  if the JollyDay list doesn't correspond with your actual
                  special days, or just define special days you want to treat
                  differently. Defined with the following metadata:
                      - ToD="day"[type="custom", file="/openhab/conf/services/custom1.xml"]
    For example, to define times of day that covers the weekend, weekdays, and
    a custom set of bank holidays you might have the following Groups.
        Group Ephem_TimeOfDay_StartTimes
        Group Ephem_Weekday (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="weekday"] }
        Group Ephem_Weekend (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="weekend"] }
        Group Ephem_Custom1 (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="custom", file="/openhab/conf/services/custom1.xml"] }
    You must be sure to define a Group for every type of day about. It can be
    handy to define the default Group to ensure that happens. The day types are
    checked in the order listed above. So, for example, if you have all of the
    above types defined, on a day that is a work day (custom dataset) that is a
    custom holiday, the custom holiday Group will be chosen.
    You can define multiple Groups for dayset and custom. If you define more
    than one Group for any of the rest, only the first one found will be used.
    Now that you have the days defined, you must define a set of DateTime Items
    which hold the start times for each time of day state used on that day and
    add those Item to the given day's Group. For example, the start times for
    the weekend would be added to the Ephem_Weekend Group above.
    The values stored in the Items can come from anywhere but the two most
    common will be from Astro or statically defined. For Astro, just link the
    Item to the appropriate Astro Channel. For statically defined the time is
    defined and the Item initialized through metadata.
    The expected metadata is : Tod="init"[start_time="HH:MM:SS:MS", tod_state="EXAMPLE"]
    where
        - HH is hours
        - MM is minutes
        - SS is seconds and optional
        - MS is milliseconds and optional
        - EXAMPLE is the State String
    All members of tod_group are required to have a tod_state metadata entry.
    Only static Items require the start_time metadata entry.
    This Rule triggeres at system started, one minute after midnight, and if any
    member of tod_group_ephem changes. When the Rule triggers, it creates timers
    to go off at the indicated times.
    For example, they full set of Groups and Items for a weekend, weekday and
    standard bank holiday system might be something like the following:
        Group Ephem_TimeOfDay_StartTimes
        Group Ephem_Weekday (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="weekday"] }
        Group Ephem_Weekend (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="weekend"] }
        Group Ephem_Holiday (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="holiday] }
        DateTime vMorning_Time "Morning [%1$tH:%1$tM]"
            <sunrise> (Ephem_Weekday)
            { ToD="init"[start_time="06:00",tod_state="MORNING"] }
        DateTime vDay_Time "Day1 [%1$tH:%1$tM]"
            <sun> (Ephem_Weekend, Ephem_Holiday)
            { channel="astro:sun:local:rise#start",
              ToD="init"[tod_state="DAY"] }
        DateTime vAfternoon_Time "Afternoon [ %1$tH:%1$tM]"
            <sunset> (Ephem_Weekday, Ephem_Weekend, Ephem_Holiday)
            { channel="astro:sun:set120:set#start",
              ToD="init"[tod_state="AFTERNOON"] }
        DateTime vEvening_Time "Evening [%1$tH:%1$tM]"
            <sunset> (Ephem_Weekday, Ephem_Weekend, Ephem_Holiday)
            { channel="astro:sun:local:set#start",
              ToD="init"[tod_state="EVENING"] }
        DateTime vNight_Time "Night [%1$tH:%1$tM]"
            <moon> (Ephem_Weekday)
            { ToD="init"[start_time="23:00", tod_state="NIGHT"] }
        DateTime vBed_Time "Bed [%1$tH:%1$tM]"
            <bedroom_blue> (Ephem_Weekend, Ephem_Holiday)
            { ToD="init"[start_time="00:02",tod_state="BED"] }
        DateTime vBed_Time_Weekend "Holiday Bed [%1$tH:%1$tM]"
            <bedroom_blue> (Ephem_Weekend, Ephem_Holiday)
    Take notice that one DateTime Item can be a member of more than one Group.
    Also take notice that each day has a different set of times of day defined.
    Finally notice that some of the times are static and others driven by Astro.
"""

    # Initialize ToD Items from their metadata. First check to see if this Rule
    # triggered because the Items are being updated by trying to actuire the
    # updating semiphore. If we succeed in grabbing the semiphore, make sure to
    # release it before calling the function to initiate the update.
    if not updating.acquire(False):
        ephem_tod.log.debug("Items are updating, ignoring rule trigger")
        return
    updating.release()
    tod_update_items(ephem_tod.log)

    # Determine the type of day and select the right Group of Items
    start_times = get_start_times(ephem_tod.log)
    if start_times is None:
        ephem_tod.log.error("No start times were found for today, please check "
                            "your Time of Day Items and Groups configurations.")
        return

    # Create the Timers
    create_tod_timers(ephem_tod.log, start_times)

def scriptUnloaded():
    """ Clears out all existing timers on script unload."""
    clear_timers()

configuration.py

# -*- coding: utf-8 -*-
LOG_PREFIX = "jsr223.jython"

admin_email = "volfan6415@gmail.com"

openhabHost = "localhost"
openhabPort = "8080"# "8443"


# Create a tod_group_ephem variable with the name of the Group of Groups of
# DateTime Items that drive the time of day.
#
# Create a tod_item_ephem variable with the name of the Time of Day Item that
# will receive the time of day state String.
#
# Create a Group for each type of day for which you have a different set of
# times of day states. Add metadata to these Groups to identify what type of
# day those start times define.
#
# Supported types of days include:
#     - default: this Group will be selected if no other type of day is
#                detected. Defined with the following metadata:
#                    - Empty (i.e. no metadata)
#                    - ToD="day"[type="default"]
#     - weekday: this Group will be selected when Ephemeris.isWeekend()
#                returns False. Defined with the following metadata:
#                    - ToD="day"[type="weekday"]
#     - weekend: this Group will be selected when Ephemeris.isWeekend()
#                returns True. Defined with the following metadata:
#                    - ToD="day"[type="weekend"]
#     - dayset: Ephemeris allows you to define custom daysets in
#               $OH_CONF/services/ephemeris.cfg. Defined with the following
#               metadata:
#                   - ToD="day"[type="dayset", set="school"]
#               Use the name of the set as it is defined in ephemeris.cfg.
#     - holiday: Defined with the following metadata:
#                    - ToD="day"[type="holiday"]
#     - custom: The Ephemeris capability allows one to define their own sets
#               of special days (e.g. birthdays and anniversaries) in a
#               specially formatted XML file. Defined with the following metadata:
#                   - ToD="day"[type="custom", file="/openhab/conf/services/custom1.xml"]
#
# For example, to define times of day that covers the weekend, weekdays, and
# a custom set of bank holidays you might have the following Groups.
#
#     Group Ephem_TimeOfDay_StartTimes
#     Group Ephem_Weekday (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="weekday"] }
#     Group Ephem_Weekend (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="weekend"] }
#     Group Ephem_Custom1 (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="custom", file="/openhab/conf/services/custom1.xml"] }
#
# You must be sure to define a Group for every type of day about. It can be
# handy to define the default Group to ensure that happens. The day types are
# checked in the order listed above and the bottom day type wins (e.g. if it's
# a weekday and a custom day the custom day will be selected).
#
# You can define multiple Groups for dayset and custom. If you define more
# than one Group for any of the rest, only the first one found will be used.
#
# Now that you have the days defined, you must define a set of DateTime Items
# which hold the start times for each time of day state used on that day and
# add those Items to the given day's Group. For example, the start times for
# the weekend would be added to the Ephem_Weekend Group above.
#
# The expected metadata is : Tod="init"[start_time="HH:MM:SS:MS", tod_state="EXAMPLE"]
# where
#     - HH is hours
#     - MM is minutes
#     - SS is seconds and optional
#     - MS is milliseconds and optional
#     - EXAMPLE is the State String
#
# All members of tod_group are required to have a tod_state metadata entry.
# Only static Items (Items whose time is not populated by something else like
# the Astro binding) require the start_time metadata entry.
#
# For example, the full set of Groups and Items for a weekend, weekday and
# standard bank holiday system might be something like the following:
#
#     Group Ephem_TimeOfDay_StartTimes
#     Group Ephem_Weekday (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="weekday"] }
#     Group Ephem_Weekend (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="weekend"] }
#     Group Ephem_Holiday (Ephem_TimeOfDay_StartTimes) { ToD="day"[type="holiday] }
#
#     DateTime vMorning_Time "Morning [%1$tH:%1$tM]"
#         <sunrise> (Ephem_Weekday)
#         { ToD="init"[start_time="06:00",tod_state="MORNING"] }
#
#     DateTime vDay_Time "Day1 [%1$tH:%1$tM]"
#         <sun> (Ephem_Weekend, Ephem_Holiday)
#         { channel="astro:sun:local:rise#start",
#           ToD="init"[tod_state="DAY"] }
#
#     DateTime vAfternoon_Time "Afternoon [ %1$tH:%1$tM]"
#         <sunset> (Ephem_Weekday, Ephem_Weekend, Ephem_Holiday)
#         { channel="astro:sun:set120:set#start",
#           ToD="init"[tod_state="AFTERNOON"] }
#
#     DateTime vEvening_Time "Evening [%1$tH:%1$tM]"
#         <sunset> (Ephem_Weekday, Ephem_Weekend, Ephem_Holiday)
#         { channel="astro:sun:local:set#start",
#           ToD="init"[tod_state="EVENING"] }
#
#     DateTime vNight_Time "Night [%1$tH:%1$tM]"
#         <moon> (Ephem_Weekday)
#         { ToD="init"[start_time="23:00", tod_state="NIGHT"] }
#
#     DateTime vBed_Time "Bed [%1$tH:%1$tM]"
#         <bedroom_blue> (Ephem_Weekend, Ephem_Holiday)
#         { ToD="init"[start_time="00:02",tod_state="BED"] }
#
#     DateTime vBed_Time_Weekend "Holiday Bed [%1$tH:%1$tM]"
#         <bedroom_blue> (Ephem_Weekend, Ephem_Holiday)
#
# Take notice that one DateTime Item can be a member of more than one Group.
# Also take notice that each day has a different set of times of day defined.
# Finally notice that some of the times are static and others driven by Astro.

tod_group_ephem = "Ephem_TimeOfDay_StartTimes"
tod_item_ephem = "vTimeOfDay"

And for clarity here are the current errors i am getting (copied from the github comment)

`2020-02-04 22:36:48.523 [INFO ] [me.core.service.AbstractWatchService] - Loading script 'python/community/ephem_tod.py'
2020-02-04 22:36:53.149 [INFO ] [ort.shared.ScriptedAutomationManager] - removeAll added handlers
2020-02-04 22:36:53.160 [INFO ] [me.core.service.AbstractWatchService] - Loading script 'python/community/ephem_tod.py'
2020-02-04 22:36:53.184 [WARN ] [23.jython.Time of Day with Ephemeris] - Interrupted while sleeping waiting for Items to finsih updating! Hoping for the best.
2020-02-04 22:36:53.267 [ERROR] [23.jython.Time of Day with Ephemeris] - Traceback (most recent call last):
File "/etc/openhab2/automation/lib/python/core/log.py", line 51, in wrapper
return fn(*args, **kwargs)
File "<script>", line 394, in ephem_tod
File "<script>", line 172, in get_start_times
IllegalStateException: java.lang.IllegalStateException: Cannot instantiate configuration from URL 'null'.

2020-02-04 22:36:53.270 [ERROR] [e.automation.internal.RuleEngineImpl] - Failed to execute rule '68fed1d5-4dab-43ba-a84d-84710bd4a4fa': Fail to execute action: 1
2020-02-04 22:36:54.276 [ERROR] [23.jython.Time of Day with Ephemeris] - Traceback (most recent call last):
File "/etc/openhab2/automation/lib/python/core/log.py", line 51, in wrapper
return fn(*args, **kwargs)
File "<script>", line 394, in ephem_tod
File "<script>", line 172, in get_start_times
IllegalStateException: java.lang.IllegalStateException: Cannot instantiate configuration from URL 'null'.

2020-02-04 22:36:54.277 [ERROR] [e.automation.internal.RuleEngineImpl] - Failed to execute rule '7a1f281a-70b9-4d35-9c02-0da4aa2f5f89': Fail to execute action: 1`

Let me know what else you need or what i should try. For the most part i think i have copied everything verbatium from the github pull request.

I am using the latest openhab (on testing releases)

OK, I’m assuming you just set the Weekend then. Did you see any errors in the logs when you did that? I know some people have had some problems with Ephemeris when updating from 2.4 to 2.5. You must have the weekend defined or else the call to Ephemeris.isWeekend() will fail with an error I think. That could explain the error.

Try creating just a super simple Rule with a call to Ephemeris.isWeekend(). Something like

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

@rule("test rule")
@when("System started")
def test(event):
    if Ephemeris.isWeekend():
        test.log.info("It's the weekend")
    else:
        test.log.info("It's a workday.")

Let’s see if my suspicion is true and it’s Ephemeris that is messed up.

Your Items look OK. As does your configuration.py (though you may want to remove your email address.

EDIT: It looks like the line it is failing on is

holiday = Ephemeris.getBankHolidayName()

So add a test to the simple rule above to call that function as well.

Did you set your country and region?

1 Like

So interesting. When i went to confirm that Ephemeris was correct and take a screenshot. I noticed that the Region was blank so i selected that region.

And then had it reload the script file:

and now it seems like it is working! So think you were right Ephemeris was messed up somehow.

2020-02-05 13:40:17.701 [INFO ] [me.core.service.AbstractWatchService] - Loading script 'python/community/ephem_tod.py'
2020-02-05 13:40:18.957 [DEBUG] [model.script.actions.ScriptExecution] - Scheduled code for execution at 2020-02-05T17:39:00.000-06:00
2020-02-05 13:40:18.959 [INFO ] [23.jython.Time of Day with Ephemeris] - Ephemeris time of day is now DAY

But then when i reboot openhab i noticed the errors come back and when navigating to my Ephemeris config screen i get this

The location has changed from Louisiana (with a drop down menu) to “la” ?? City has quotes and the country is gone?

So you are correct something is going on with my Ephemeris config

2020-02-05 13:47:25.482 [ERROR] [23.jython.Time of Day with Ephemeris] - Traceback (most recent call last):
  File "/etc/openhab2/automation/lib/python/core/log.py", line 51, in wrapper
    return fn(*args, **kwargs)
  File "<script>", line 394, in ephem_tod
  File "<script>", line 172, in get_start_times
IllegalStateException: java.lang.IllegalStateException: Cannot instantiate configuration from URL 'null'.

2020-02-05 13:47:25.485 [ERROR] [e.automation.internal.RuleEngineImpl] - Failed to execute rule '1271f0ea-a6f5-4c76-9a3e-12d9b371e148': Fail to execute action: 1
2020-02-05 13:47:25.528 [ERROR] [23.jython.Time of Day with Ephemeris] - Traceback (most recent call last):
  File "/etc/openhab2/automation/lib/python/core/log.py", line 51, in wrapper
    return fn(*args, **kwargs)
  File "<script>", line 394, in ephem_tod
  File "<script>", line 172, in get_start_times
IllegalStateException: java.lang.IllegalStateException: Cannot instantiate configuration from URL 'null'.

Hmmm, so I think I can test for this in a future version of the code but it’s not something I can really just fix.

Was New Orleans in a drop down list or did you type it in. Looking at the original Jollyday XML, in the US I don’t see any cities with their own holidays listed. I do think that might mess things up. The “la” isn’t unexpected, it wants the two letter abbreviation for the state anyway. The fact that US disappeared from the Country is odd though too.

Try this:

  • Delete the city and region
  • Reselect the weekend days
  • Reselct the country
  • Reselct the region
  • Do not enter anything for the city

Watch the logs for errors each step of the way.

If this fails, we’ll move to text based configs.

To see what’s defined, the XML file that lists all the US holidays is at https://github.com/svendiedrichsen/jollyday/blob/master/src/main/resources/holidays/Holidays_us.xml. The country wide holidays are at the top, Lousiana starts at about line 180 and you will notice there are not cities defined.

Did these and country keeps disappearing on restart…

Still have the same errors in my log.

I should also add i didn’t not see any log entries for ephemeris or with ephemeris in the text other than the errors above with the rule failing to execute

Don’t know if i need to change the logging level for org.openhab.ephemeris?

Also what is wierd is that if i give PaperUI some time and check back eventually the region (which on reboot starts as “la”) becomes blank as well with a drop down. Then i am free to select Louisiana from the list… at which point if i force a reload of the script it starts working again as noted above.

OK, we can keep debugging PaperUI or punt and do the config in ephermeris.cfg. I recommend the latter.

Create $OH_CONF/services/ephemeris.cfg and populate it with:

country="us"
region="la"
dayset-weekend=[SATURDAY,SUNDAY]

This will override anything that PaperUI is trying to do.

Done i vastly prefer text configuration files over graphical anyways.

Performed a reboot and all seems well now. Thanks as always for your help.

This was the last step in migrating all of my rules DSL rules (roughly 6000 lines of code) over to jsr223 rules. The rest have been done in javascript but didn’t want to reinvent the wheel on this one since you had already done the work on it.

One note for anyone else that finds this the file should have a .cfg extension.

@rlkoshak you reference that in the first part but then in the file creation line you use .config. So just want to make sure that’s clear.

Yep, that was a mistake. The cfg eventually becomes a config file in /var/lib/openhab2/config/org/openhab/. I’ll fix the original.

Long story short here is my configuration file that finally had things consistently working on startup

country=us
region=la
dayset-weekend=[SATURDAY,SUNDAY]
dayset-school=[MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY]

Note that there are no quotes around us or la

What i noticed is that for the time immeadietly at bootup when i had the quotes around them the config file would have the region and country with quotes around them in the actual .config file. I.e. it would look like this region="“la”" Then at some point that was corrected but it took time at bootup.

Just thinking that this may be why the reload configuration is needed in your config or why you don’t notice this issue?

I don’t use the config file so I couldn’t guess why it worked for me and not you.

Hello, just updated my openhab to 2.5, and there 2 files named ephemeris.config and ephermeris.config im my folder. Updating the weekend values via paperui is not working.

Maybe a typo somewhere

[14:20:59] openhabian@openHABianPi:/var/lib/openhab2/config/org/openhab$ cat ephemeris.config
:org.apache.felix.configadmin.revision:=L"6"
dayset-weekend=( \
  "SATURDAY,SUNDAY", \
)
service.pid="org.openhab.ephemeris"
[14:22:52] openhabian@openHABianPi:/var/lib/openhab2/config/org/openhab$ cat ephermeris.config
:org.apache.felix.configadmin.revision:=L"1"
dayset-school="Monday,Tuesday,Wednesday,Thursday,Friday"
dayset-weekend="Saturday,Sunday"
service.pid="org.openhab.ephermeris"

Did you create a typo in your /etc/openhab2/services/ephemeris.cfg file? There is no such thing as ephermeris and the only way I can think of that file being created is if you created /etc/openhab2/services/ephermeris.cfg which is incorrect and would not be used by anything in OH because of the error in the file name.

Hello Rich, the files are created by the system, not by me. (ephermeris at openhab start if deleted)

I commented an issue here

Aymeric

If this is caused by a bug, it is not related to the Issue you commented on. Also, if it were a bug in the feature, there would be all sorts of complaints on the forum.

As I asked, do you have the file /etc/openhab2/services/ephermeris.cfg? That is almost certainly where the ephermeris.config is being generated from.

You’re absolutely right !
I deleted all eph*.config from both folder and restarted and reselected my settings via paperui system configuration.
Everything is fine and no error in the log now.
Thank you.