Ephemeris binding?

Tags: #<Tag:0x00007fc20e03cc30>

I am interest, any updates on this?

Yes, it in progress, not merged but I expect it could be done quite soon

Yes, we made progress on it some days ago

Envoyé de mon iPhone

And, sorry to pry, but what does it do?
What does it look like?

It gives rules DSL (for now, NRE later) to access isWeekend, check current holidays, school holidays…

So basically like Astro only for calendar events instead of astronomical events? Very cool! I hope it gets merged quickly.

Why is NGRE only supported in the future? If the binding is using Things and Items NGRE should work just fine. Is there something I’m missing?

NGRE in the future because I did not had time to implement it right now, and this will be a core service, exposing functions to scripting, not items nor channels.

Ah, so it’s an Action add-on, not a binding. Even so, it should be supported in NGRE. We can use Actions there as well right now. There may not be anything you need to do for NGRE support.

I noticed an Ephemeris entry pop up in the PaperUI settings but I can’t find anything in the docs about how to use it. Obviously, setting the weekend days is intuitive enough, but how would I access the from Rules?

AFAIK @glhopital is working on a piece of documentation :wink:. You can get an idea of how it is working in here:

rule "Ephemeris started rule"
when System started
then
   if (!isWeekend()) {
	logInfo(filename,"Journée de semaine")
   }
   if (isWeekend(1)) {
	logInfo(filename,"Demain c'est le weekend")
   }
   if (isInDayset("school")) {
	logInfo(filename,"Y'a de l'école aujourd'hui")
   }
   if (!isInDayset("school",1)) {
	logInfo(filename,"Mais demain les filles se reposent")
   }
   logInfo(filename, getBankHolidayName(10))
   logInfo(filename,"Poubelles : ", getBankHolidayName(0,"/etc/openhab2/ephemeris/poubelles.xml"))
   logInfo(filename,"Saint du jour : ", getBankHolidayName(0,"/etc/openhab2/ephemeris/ephemeris_sotd.xml"))
end

Note: The used XML-files are linked here.

I am working in an integration for NGRE (Ephemeris conditions / no actions) too.

Some more information about the configuration - WIP status - can be found here. Textual configuration can be placed in a ephemeris.cfg file in:

dayset-school=Monday,Tuesday,Wednesday,Thursday,Friday
dayset-weekend=Saturday,Sunday
country=de
region=nw

Hope it helps for the moment.

2 Likes

It does indeed. I eagerly await the NGRE integration. This helps solve a problem I’m currently working on. I’ve converted the Time of Day design pattern into something that can be distributed as a library and I’m now working to expand it to support different sets of times based on the type of day. Ephemeris will make that easy.

1 Like

Ephemeris is already available for JSR223 here’s some exemples :

from core.actions import Ephemeris

@rule("Cron : Publish Tomorrow Trash Status")
@when("Time cron 0 0 18 ? * * *")
def cron_trash_status(event):
	poubelle_demain = Ephemeris.getBankHolidayName(1,"/etc/openhab2/db/poubelles.xml")
	if poubelle_demain is not None:
		notification(u"Demain c'est les {}".format(poubelle_demain), 1)

@rule("Cron : Petit resume du jour")
@when("Time cron 0 10 7 ? * * *") 
def cron_resume_du_jour(event):
	cron_resume_du_jour.log.debug(u"Lance le résumé du jour")
	ferie = Ephemeris.getBankHolidayName(0)
	if ferie is not None:
		notification(u"Aujourd'hui c'est férié, c'est {}".format(ferie))
	else:
		ferie = Ephemeris.getBankHolidayName(1)
		if ferie is not None:
			notification(u"Demain, c'est férié, c'est {}".format(ferie))
			
	evenement = Ephemeris.getBankHolidayName(0,"/etc/openhab2/db/events.xml")
	if evenement is not None:
		notification(u"Aujourd'hui c'est {}".format(evenement))
	else:
		evenement = Ephemeris.getBankHolidayName(1,"/etc/openhab2/db/events.xml")
		if evenement is not None:
			notification(u"Demain, c'est {}".format(evenement))
	
	anniversaire = Ephemeris.getBankHolidayName(0,"/etc/openhab2/db/birthdays.xml")
	if anniversaire is not None:
		notification(u"Aujourd'hui c'est l'anniversaire de {}".format(anniversaire))
	else:
		anniversaire = Ephemeris.getBankHolidayName(1,"/etc/openhab2/db/birthdays.xml")
		if anniversaire is not None:
			notification(u"Demain, c'est l'anniversaire de {}".format(anniversaire))
		
	saint_du_jour = Ephemeris.getBankHolidayName(1,"/etc/openhab2/db/sotd.xml");
	notification(u"Demain, c'est la saint {}".format(saint_du_jour))

	poubelle = Ephemeris.getBankHolidayName(1,"/etc/openhab2/db/poubelles.xml")
	if poubelle is not None:
		notification(u"Penser aux poubelles : {} ".format(poubelle),2)

@rule("Cron : Routine des filles")
@when("Time cron 0 10 8 ? * MON,TUE,THU,FRI *") 
def routine_filles(event):
	ferie = Ephemeris.getBankHolidayName(0)
	if ferie is None:
		school = Ephemeris.isInDayset("school")
		if school:
			if isinstance(items["currentVacances"], UnDefType):
				notification(u"Victoria, Eléonore, il est l'heure de se préparer à partir à l'école. Nono, mets tes chaussures",1,True,False,True)
				school_demain = Ephemeris.isInDayset("school",1)
				Timer(10*60, lambda : notification("Eléonore, Victoria, maintenant il faut partir à l'école. Tu es prête Victoria ?",1,True,False,True))
				if not school_demain:
					notification(u"Demain vous pourrez vous reposer les filles",0,True,False,True)
			else:
				notification(u"Il devrait y avoir de l'école aujourd'hui mais c'est les vacances")
		else:
			notification(u"Aujourd'hui il n'y a pas d'école")

2 Likes

I’m starting to look into implementing this as part of the Time of Day Design pattern and I’ve a few questions/comments:

  • Are docs being written? I couldn’t find any but I didn’t look at the open PRs so may have missed them. I might be able to help with that as I learn how it works.
  • In PaperUI I can choose country and state but it’s not clear that it does anything. I tried to use the offset to get to the next holiday but it returned None. If this is supposed to work, where does it get the list of holidays from? Does it download one of those xml files and if so where does it put it?
  • Is the recommended place to put the xml files as you have it in your example, $OH_CONF/db? Are users expected to write these (as hinted at by the anniversary file in your example)? Is there a way to define specific days like holidays in the cfg file or is that done limited to days of the week? Is there a UI planned to define holidays? Is it planned for PaperUI it only for it’s replacement?
  • can I mix Fixed and FixedWeekday the same xml file?
  • does this only support querying from Rules or does it now or is planned to in there future generate events that can trigger Rules?

I think I have a party forward with Time of Day but I want to understand more before I proceed.

It looks really good. Thanks for all the great work on this.

Hello Rich, thanks for your questions :

Are docs being written?

No, I completely dropped this point as I had troubles with getting a functional IDE (seems solved now). And now, I’m a bit lazy to come back on this. So I think our exchanges will be a good base to start this long awaited documentation. And you’re more than welcome to help :wink:

In PaperUI I can choose country and state but it’s not clear that it does anything

The country select the default official holiday list used by Ephemeris. In some countries there exists local state/region related holidays. Germany comes to my mind, maybe US also ?

I tried to use the offset to get to the next holiday but it returned None.

The offset meand today + or - offset days. So if you use +1 and tomorrow is not an holiday, you’ll get None. But it could be an added feature to get ‘NextHoliday’ what/when.

where does it get the list of holidays from?

Ephemeris is built on Jollyday package, list of holidays are contained in this library for many countries over the world.

Is the recommended place to put the xml files as you have it in your example, $OH_CONF/db? Are users expected to write these (as hinted at by the anniversary file in your example)?

From scratch, Ephemeris does not need any added XML file. I decided to use a $OH_CONF/db to centralize some of my personnal data used by OH2 (XMLTV, Ephemeris…) but user defined Holiday files can be placed anywhere.

Is there a way to define specific days like holidays in the cfg file or is that done limited to days of the week?

Depends.
In the cfg, minimum definition based on days of the week is weekend. This is handled by PaperUI configuration. You can define personal sets at any time like this :

dayset-trash=Monday,Friday

and query it this way (JSR223 exemple) :

trashTomorrow = Ephemeris.isInDayset("trash",1)

If one need more complex than day of the week definitions, you’ll have to go to an XML file using Jolliday XML syntax as presented here.

One important thing while defining XML files : they are cached in memory at first load, avoiding cost of loading, parsing the file. Counterpart is that changes in XML need a start/stop of the module (or OH itself) to become effective.

Is there a UI planned to define holidays? Is it planned for PaperUI it only for it’s replacement?

I have no UI planned on my side as I can cope with XML. I do not know what’s planned for PaperUI replacement. There exists an XSD definition of the XML syntax, so I suppose an UI could (should for sake of end users) be defined but this is not my specialty.

can I mix Fixed and FixedWeekday the same xml file?

From what I see in the XML description linked above, yes.

does this only support querying from Rules or does it now or is planned to in there future generate events that can trigger Rules?

Good point. Currently only queries from Rules, we could imagine having this triggering events but it was out of the scope of my PR.
Currently, I’m using it to populate an array of elements, initialized in the morning this way :

@rule("Cron : Petit resume du jour")
@when("Time cron 0 10 7 ? * * *") 
def cron_resume_du_jour(event):
	cron_resume_du_jour.log.debug(u"Lance le résumé du jour")

	for key in dayEvents:
		dayEvents[key] = None

	for i in [0,1]:
		ferie = Ephemeris.getBankHolidayName(i)
		dayEvents[(dayEventKind.ferie,i)] = None if ferie is None else u"C'est férié : {}".format(ferie)

		school = Ephemeris.isInDayset("school",i)
		dayEvents[(dayEventKind.school,i)] = "Repos" if not school else "Ecole !!!"
		
		event = Ephemeris.getBankHolidayName(0,"/etc/openhab2/db/events.xml")
		dayEvents[(dayEventKind.event,i)] = None if event is None else u"C'est {}".format(event)
		
		birthday = Ephemeris.getBankHolidayName(i,"/etc/openhab2/db/birthdays.xml")
		dayEvents[(dayEventKind.birthday,i)] = None if birthday is None else u"C'est l'anniversaire de {}".format(birthday)

		sotd = Ephemeris.getBankHolidayName(i,"/etc/openhab2/db/sotd.xml")
		dayEvents[(dayEventKind.sotd,i)] = None if sotd is None else u"C'est la saint {}".format(sotd)

		dayEvents[(dayEventKind.trash,i)] = Ephemeris.getBankHolidayName(i,"/etc/openhab2/db/poubelles.xml")
	
	currentVacances = items["currentVacances"]
	if not isinstance(currentVacances,UnDefType):
		dayEvents[(dayEventKind.school,0)] = currentVacances.toString()
					
	cron_resume_du_jour.log.debug(repr(dayEvents).decode("unicode-escape"))

with this placed in configuration.py :

from enum import Enum
class dayEventKind(Enum):
	trash = 1
	school = 2
	worked = 4
	ferie = 5
	holiday = 6
	event = 7
	birthday = 8
	sotd = 9

dayEvents = {
	(dayEventKind.trash,0) : None,
	(dayEventKind.trash,1) : None,
	(dayEventKind.school,0) : None,
	(dayEventKind.school,1) : None,
	(dayEventKind.worked,0) : None,
	(dayEventKind.worked,1) : None,
	(dayEventKind.ferie,0) : None,
	(dayEventKind.ferie,1) : None,
	(dayEventKind.event,0) : None,
	(dayEventKind.event,1) : None,
	(dayEventKind.birthday,0) : None,
	(dayEventKind.birthday,1) : None,
	(dayEventKind.sotd,0) : None,
	(dayEventKind.sotd,1) : None,
	(dayEventKind.holiday,0) : None,
	(dayEventKind.holiday,1) : None
}

This is a work in progress, maybe it can give you ideas for your DP.

Usually there are not state holidays that are the equivalent of bank holidays. And whether or not a person actually gets those days off differs from one company to the next so I suspect that most US users will be needing to manually create the list of holidays. For example, Columbus Day/Indigenous People’s Day and President’s Day are often listed as official holidays but very few people actually get those days off.

I did get that and I tried to use an offset to next Christmas and got None back. Though I’ve tried it again and I see that it works so I must have done the math wrong. I should have asked Google instead of trying to hand count the days. :wink:

But it still would be useful to see the list of holidays that it actually does pull down so I can compare the list with which days I actually have off work. How different they are could determine whether I add some if statements to a Rule or need to write my own events.xml file.

I can see that being pretty handy. I can see someone wanting to put a countdown to Christmas on their HABPanel or the like. Maybe not just a NextHoliday but also a “WhenIs(“Christmas”)” method too?

OK, we should definitely link to that in the docs.

Now that I see the XML I can see what’s going on. Does Jollyday do the translation from the XML to the nicer way it’s presented in the library? For example, Jollyday lists

<tns:FixedWeekday which="FOURTH" weekday="THURSDAY" month="NOVEMBER" validFrom="1863" descriptionPropertiesKey="THANKSGIVING"/>

And Ephemeris.getBankHolidayName() returns “Thanksgiving Day”.

But

<tns:Fixed month="DECEMBER" day="25" descriptionPropertiesKey="CHRISTMAS"/>

returns just “Christmas”. So my question is what is changing it from all caps and in the Thanksgiving case adding the “Day”? It would be best if the users didn’t have to figure out the names of the holidays through trial and error so they can write their Rules with confidence they will not fail because they forgot to add “Day” to their if statement. The fact that it added the “Day” to Thanksgiving but not “Christmas” means that the translation is not consistent and therefore not predictable.

They do not need to, but are they expected to in normal usage? Based on what I’ve seen so far, I expect that I may need to as the list of holidays I get off do not overlap very well with the list from Jollyday and since I’m trying to build generic code it will be easier to write by creating my own file than trying to encode exceptions in a configuration.

I understand why this is the case. I just don’t like that there are two configuration files that use two vastly different syntax. Perhaps someday we can have a tool in the new UI to help create these configs.

We need to make sure this is documented.

Thanks! And I’m actually pushing for a reusable library instead of a DP for this. Ultimately I want to have a Rule Template that users can just import from where ever Rule Templates get published, configure it through a UI, and use it. I know we are a ways away from that but getting it in the Helper Libraries is a start.

This is a really valid point. Ephemeris uses Jollyday ability to translate an “holiday code” (THANKSGIVING) to a nice user friendly “holiday name” more descriptive and localized.
You can see the mappings here
But rules and triggers do not need so much attention, so I think we should have an alternative way to get both of these informations made available.

So I think I’ll plan three evolutions for Ephemeris :

  • Ability to get both code and localized name
  • Ability to query toward a given holiday code
  • Ability to get next coming holiday
2 Likes

PR pushed here

Excellent! I look forward to testing it (probably can’t even try this week so I can wait for the merge).

One thing I noticed which might be a bug but I’ve not gone back to test to make sure as it might have been related to https://github.com/openhab/openhab-core/issues/903, but I think I get a bunch of exceptions in the log file if I try to fill in the City in PaperUI when there are no entries for city in JollyDay’s XML. When I get a chance I’ll do some more deliberate tests and file an issue but thought I’d mention it here in the mean time.

I’ve made a first cut at documentation at [WIP] Ephemeris Documentation. It’s a wiki so if I got anything wrong or you have suggestions or changes please edit the original.

My Time of Day implementation that uses Ephemeris is posted to [Scripted Automation] Multi-day Time of Day Library. It’s currently to be considered beta level.

Thanks!

1 Like

@rlkoshak : evolutions of the Ephemeris merged. Should be available in snapshots soon.