Simple Python script that reads Google Calendar and updates OH items with event information

I’ll do that. Could take some time, but the weekend is free. :wink:

2 Likes

Here my rule for Trash Cans :slight_smile:

//GoogleCalender
String gCal_Abfall_Event1 (gCal_Abfall)
String gCal_Abfall_Event2 (gCal_Abfall)
String gCal_Abfall_Event3 (gCal_Abfall)

String gCal_Abfall_Event1_Summary "Mülltonne: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event1_Location "Event1 Loc.: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event1_Description "Event1 Desc. [%s]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event1_StartTime  "Abholung: [%1$td.%1$tm.%1$tY]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event1_EndTime "Event1 End [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <calendar> (gCal_Abfall_Event)
Switch gCal_Abfall_Event1_Approved "Mülltonne rausgestellt: [%s]" <calendar> (gCal_Abfall_Event)

String gCal_Abfall_Event2_Summary "Mülltonne: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event2_Location "Event1 Loc.: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event2_Description "Event1 Desc. [%s]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event2_StartTime  "Abholung: [%1$td.%1$tm.%1$tY]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event2_EndTime "Event1 End [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <calendar> (gCal_Abfall_Event)
Switch gCal_Abfall_Event2_Approved "Mülltonne rausgestellt: [%s]" <calendar> (gCal_Abfall_Event)

String gCal_Abfall_Event3_Summary "Mülltonne: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event3_Location "Event1 Loc.: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event3_Description "Event1 Desc. [%s]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event3_StartTime  "Abholung: [%1$td.%1$tm.%1$tY]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event3_EndTime "Event1 End [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <calendar> (gCal_Abfall_Event)
Switch gCal_Abfall_Event3_Approved "Mülltonne rausgestellt: [%s]" <calendar> (gCal_Abfall_Event)

Switch GelberSack "Gelber Sack" (gCal_Abfall_Item)
Switch Biotonne "Biotonne" (gCal_Abfall_Item)
Switch Restmuell "Restmüll" (gCal_Abfall_Item)
Switch Papiertonne "Papiertonne" (gCal_Abfall_Item)
//#############################//
//Check garbage calendar events//
//#############################//

rule "Check garbage calendar events"
when
	//Every 60 Minutes
	Time cron "0 0 * ? * * *"
then
	logInfo("Garbage calendar", "Execution started")
	gCal_Abfall.members.forEach[ gc |
		val eventStart = gCal_Abfall_Event.members.filter[ act | act.name == gc.name+"_StartTime"].head
		val eventDesc = gCal_Abfall_Event.members.filter[ act | act.name == gc.name+"_Description"].head
		val eventSum = gCal_Abfall_Event.members.filter[ act | act.name == gc.name+"_Summary"].head
    val eventApproved = gCal_Abfall_Event.members.filter[ act | act.name == gc.name+"_Approved"].head
	// Execution every (Time cron) (Max. 24 Hours before EventStartTime) until EventStartTime or Tasks is approved by Item
  if (eventApproved.state == OFF) {
    if (now.isAfter(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).minusDays(1)) &&
				now.isBefore(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli))) {
			val buffer = eventDesc.state.toString.split(";")
			val calItem = gCal_Abfall_Item.members.filter[ ci | ci.name == eventSum.state.toString].head
			if (calItem !== null) {
				logInfo("Garbage calendar", gc.name + " starting now with '" + calItem.name + "' -> " + buffer.get(0))
				sendCommand(calItem, buffer.get(0))
			}
			else {
				logInfo("Garbage calendar", "WARNING: cannot find item named '" + eventSum.state + "'")
			}
		 }
    }
		//Execution at EventStartTime if Task is not approved by Item
		if (now.isAfter(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)) &&
		//Change plusMinutes(60) to your Time Cron Interval
				now.isBefore(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).plusMinutes(60))) {
      //Reset eventApproved status!
      eventApproved.sendCommand(OFF)
      //Reset calItem!
			val buffer = eventDesc.state.toString.split(";")
      val calItem = gCal_Abfall_Item.members.filter[ ci | ci.name == eventSum.state.toString].head
			if (calItem !== OFF) {
				sendCommand(calItem, buffer.get(1))
				logInfo("Garbage calendar", gc.name + " ended now with'" + calItem.name + "' -> " + buffer.get(1))
			}
			else {
				logInfo("Garbage calendar", "WARNING: cannot find item named '" + eventSum.state + "'")
			}
		}
	]
	logInfo("Garbage calendar", "Execution finished")
end
1 Like

Hello Kevin,

I used your rules and settings to setup the trash calender as well, but I get some errors:

    2018-03-25 21:00:00.061 [INFO ] [rthome.model.script.Garbage calendar] - Execution started

    2018-03-25 21:00:00.084 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Check garbage calendar events': The name 'AbfallKalender' cannot be resolved to an item or type; line 11, column 2, length 14

    2018-03-25 21:00:01.190 [INFO ] [pse.smarthome.model.script.GoogleCal] - 

    Go to the following link in your browser:

        https://accounts.google.com/o/oauth2/auth?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar.readonly&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&response_type=code&client_id=1049162737451-un0ose13ps8hm5dpur1vk0es8bo4phtr.apps.googleusercontent.com&access_type=offline

    Enter verification code: Traceback (most recent call last):

      File "/etc/openhab2/scripts/CalSyncHAB/CalSyncHAB.py", line 127, in <module>

        Main()

      File "/etc/openhab2/scripts/CalSyncHAB/CalSyncHAB.py", line 30, in Main

        Credentials = GetCredentials()

      File "/etc/openhab2/scripts/CalSyncHAB/CalSyncHAB.py", line 25, in GetCredentials

        Credentials = tools.run_flow(AuthenticationFlow, CredentialStore, Flags)

      File "/usr/local/lib/python2.7/dist-packages/oauth2client/_helpers.py", line 133, in positional_wrapper

        return wrapped(*args, **kwargs)

      File "/usr/local/lib/python2.7/dist-packages/oauth2client/tools.py", line 240, in run_flow

        code = input('Enter verification code: ').strip()

    EOFError: EOF when reading a line

The first errors means that this item is not know, but I created a items as requested.
The secons error is the authentification of my calender. I did his before as mentioned in post one.

Any advices?

Thank you.
Jan

@jantum,
did you follow my instructions from last year?

EDIT
Got it working… needed to set the gCal_Abfall_items to OFF (they have been UNDEF

First of all… Awesome workaround in this whole topic here… Thanks guys :slight_smile: was trying to use caldav binding… but this seems to not run in OH2 so glad that i found this topic here…

i got almost everything running like I want to… jus have some small problems…

for the example of @ei_Gelb_Geek i needed to add

Group gCal_Abfall
Group gCal_Abfall_Event
Group gCal_Abfall_Item

for the VS Code errors to go away in the rules file… everything is working well… I get the Items from the python script… and also if i change the calendar entries… they were updated… great…

But I cant get the rule triggered with the “starting now with” loginfo…

	// Execution every (Time cron) (Max. 24 Hours before EventStartTime) until EventStartTime or Tasks is approved by Item
  if (eventApproved.state == OFF) {
    if (now.isAfter(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).minusDays(1)) &&
				now.isBefore(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli))) {
			val buffer = eventDesc.state.toString.split(";")
			val calItem = gCal_Abfall_Item.members.filter[ ci | ci.name == eventSum.state.toString].head
			if (calItem !== null) {
				logInfo("Garbage calendar", gc.name + " starting now with '" + calItem.name + "' -> " + buffer.get(0))
				sendCommand(calItem, buffer.get(0))
				sendTelegram( "bot1", "Muelltonne.")
			}
			else {
				logInfo("Garbage calendar", "WARNING: cannot find item named '" + eventSum.state + "'")
			}
		 }
    }

Anyone has a tip why this is not working?

Thanks

So since i was running into serval problems to get this working… and to help others to not get lost in this thread i will add all the steps needed here… most of them is copy&paste from this thread… Thanks to all who helped here :slight_smile: @davorf @FrankR @Mike_Bagdanoff @ei_Gelb_Geek @binderth

I also added some small adjustments and code lines for my Telegram Bot, which notifies our house group… so more than one human keep an eye on the trash cans :wink:

GCal_tut_3

  1. Make sure you have already python installed…

  2. Upgrade pip:

sudo easy_install --upgrade pip
  • after that is finished, run:
sudo python -m pip install --upgrade google-api-python-client
sudo python -m pip install configparser
sudo python -m pip install requests
  1. Create OAuth2 credentials
  • go to https://console.developers.google.com/ and create a project named “OpenHAB” and create a new OAuth Client ID, Type: “others”
  • download this OAuth 2.0-Client-ID as JSON (and save it for later)
  • activate the Google Calandar API
  1. create a folder “CalSyncHAB” within /etc/openhab2/scripts
  • create folder
sudo mkdir /etc/openhab2/scripts/CalSyncHAB
sudo git clone http://github.com/davorf/CalSyncHAB.git .
  • rename your OAuth 2.0-Client-ID to “CalSyncHABSecret.json” and put it in under /etc/openhab2/scripts/CalSyncHAB
sudo chown openhab:openhabian /etc/openhab2/scripts/CalSyncHAB
  • cd into CalSyncHAB folder and
sudo chown openhab:openhabian *
  • open .ini file and for setting “ClientSecretFile” enter the complete path, e.g.
ClientSecretFile: /etc/openhab2/scripts/CalSyncHAB/CalSyncHABSecret.json
  • create a script “/etc/openhab2/scripts/CalSyncHAB.sh” with: (in my case i need to remove the first line to get the .sh running)
#!/bin/sh
/usr/bin/python /etc/openhab2/scripts/CalSyncHAB/CalSyncHAB.py --noauth_local_webserver
sudo chown openhab:openhabian /etc/openhab2/scripts/CalSyncHAB.sh
  • after that run the .sh copy the url shown by the script into your browser, click “Allow” and paste the given code back into the script prompt.
sudo -u openhab /etc/openhab2/scripts/CalSyncHAB.sh
  • if this was successfull, we can delete that .sh file (we can use the .py file in our rules)

OpenHAB File Examples:

  • /etc/openhab2/scripts/CalSyncHAB/CalSyncHAB.ini
[General]
ApplicationName: OpenHAB

[Calendar]
Scope: https://www.googleapis.com/auth/calendar.readonly
CalendarId: <YOUR_CALENDAR_ID>@group.calendar.google.com
MaxEvents: 5
TimeZone: +02:00
ClientSecretFile: /etc/openhab2/scripts/CalSyncHAB/CalSyncHABSecret.json

[OpenHAB]
HostName: <IP_OF_YOUR_OH>
Port: 8080
ItemPrefix: gCal_Abfall_
  • GoogleCal.items
//GoogleCalender
Group gCal_Abfall
Group gCal_Abfall_Event
Group:Switch:OR(ON, OFF) gCal_Abfall_Item "Müll-Abfuhr Termine morgen [(%d)]" <softener>
Group:Switch:OR(ON, OFF) gCal_Geburtstag_Item "Geburtstage morgen [(%d)]" <smiley>
String gCal_Abfall_Event1 (gCal_Abfall)
String gCal_Abfall_Event2 (gCal_Abfall)
String gCal_Abfall_Event3 (gCal_Abfall)

// your Google Cal Items need to match the item names!  
Switch GelberSack "GelberSack" (gCal_Abfall_Item)
Switch Biotonne "Biotonne" (gCal_Abfall_Item)
Switch Restmuell "Restmuell" (gCal_Abfall_Item)
Switch Papiertonne "Papiertonne" (gCal_Abfall_Item)

String gCal_Abfall_Event1_Summary "Mülltonne: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event1_Location "Event1 Loc.: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event1_Description "Event1 Desc. [%s]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event1_StartTime  "Abholung: [%1$td.%1$tm.%1$tY]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event1_EndTime "Event1 End [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <calendar> (gCal_Abfall_Event)
Switch gCal_Abfall_Event1_Approved "Mülltonne rausgestellt: [%s]" <calendar> (gCal_Abfall_Event)

String gCal_Abfall_Event2_Summary "Mülltonne: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event2_Location "Event2 Loc.: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event2_Description "Event2 Desc. [%s]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event2_StartTime  "Abholung: [%1$td.%1$tm.%1$tY]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event2_EndTime "Event2 End [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <calendar> (gCal_Abfall_Event)
Switch gCal_Abfall_Event2_Approved "Mülltonne rausgestellt: [%s]" <calendar> (gCal_Abfall_Event)

String gCal_Abfall_Event3_Summary "Mülltonne: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event3_Location "Event3 Loc.: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event3_Description "Event3 Desc. [%s]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event3_StartTime  "Abholung: [%1$td.%1$tm.%1$tY]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event3_EndTime "Event3 End [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <calendar> (gCal_Abfall_Event)
Switch gCal_Abfall_Event3_Approved "Mülltonne rausgestellt: [%s]" <calendar> (gCal_Abfall_Event)

String gCal_Abfall_Event4_Summary "Mülltonne: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event4_Location "Event4 Loc.: [%s]" <calendar> (gCal_Abfall_Event)
String gCal_Abfall_Event4_Description "Event4 Desc. [%s]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event4_StartTime  "Abholung: [%1$td.%1$tm.%1$tY]" <calendar> (gCal_Abfall_Event)
DateTime gCal_Abfall_Event4_EndTime "Event4 End [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" <calendar> (gCal_Abfall_Event)
Switch gCal_Abfall_Event4_Approved "Mülltonne rausgestellt: [%s]" <calendar> (gCal_Abfall_Event)
  • GoogleCal.rules
// grab the calendar events from google via API
rule "GetCalEvents"
when
	//at second :00 Every 30 Minutes, everyday from 5PM to 9PM
	Time cron "0 0/30 17-21 ? * *"
then
	var String results = executeCommandLine("python /etc/openhab2/scripts/CalSyncHAB/CalSyncHAB.py", 120*1000)
	logInfo("GetCalEvents", results)
end

// Check garbage calendar events
rule "Check garbage calendar events"
when
	// 30 seconds delay to get "GetCalEvents" rule time to parse Google Cal API
	// at second :30 Every 30 Minutes, everyday from 5PM to 9PM
	Time cron "30 0/30 17-21 ? * *"
then
	logInfo("Garbage calendar", "Execution started")
	gCal_Abfall.members.forEach[ gc |
		val eventStart = gCal_Abfall_Event.members.filter[ act | act.name == gc.name+"_StartTime"].head
		val eventDesc = gCal_Abfall_Event.members.filter[ act | act.name == gc.name+"_Description"].head
		val eventSum = gCal_Abfall_Event.members.filter[ act | act.name == gc.name+"_Summary"].head
		val eventApproved = gCal_Abfall_Event.members.filter[ act | act.name == gc.name+"_Approved"].head
		// Execution every (Time cron) until EventStartTime or Tasks is approved by Item
		if (eventApproved.state == OFF) {
			// in this case i used 8 hours before EventStartTime (my events starting at 00:00, so I have enough time in the evening to get the trash cans out)
			if (now.isAfter(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).minusHours(8)) &&
				now.isBefore(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli))) {
				val buffer = eventDesc.state.toString.split(";")
				val calItem = gCal_Abfall_Item.members.filter[ ci | ci.name == eventSum.state.toString].head
				if (calItem !== null) {
					logInfo("Garbage calendar", gc.name + " starting now with '" + calItem.name + "' -> " + buffer.get(0))
					// you need to have images with the event names in your openhab "html" folder, otherwise comment the line out
					sendTelegramPhoto( "bot1", "http://openhabianpi:8080/static/" + calItem.name + ".png", "")
					sendTelegram( "bot1", "🗑" + gc.name + " ausgelöst...\n\n" + calItem.name + " wird morgen früh abgeholt...\n -> " + buffer.get(0) + "\n\n(Wiedervorlage dieser Nachricht jede Stunde bis der Schalter auf erledigt gesetzt wurde.. ;-) )")
					sendCommand(calItem, ON)
				}
				else {
					logInfo("Garbage calendar", "WARNING: cannot find item named '" + eventSum.state + "'")
				}
			}
		}
		//Execution at EventStartTime if Task is not approved by Item
		if (now.isAfter(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)) &&
		//Change plusMinutes(60) to your Time Cron Interval
		now.isBefore(new DateTime((eventStart.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli).plusMinutes(60))) {
			//Reset eventApproved status!
			eventApproved.sendCommand(OFF)
			//Reset calItem!
			val buffer = eventDesc.state.toString.split(";")
			val calItem = gCal_Abfall_Item.members.filter[ ci | ci.name == eventSum.state.toString].head
			if (calItem !== OFF) {
				sendCommand(calItem, OFF)
				logInfo("Garbage calendar", gc.name + " ended now with'" + calItem.name + "' -> " + buffer.get(1))
			}
			else {
				logInfo("Garbage calendar", "WARNING: cannot find item named '" + eventSum.state + "'")
			}
		}
	]
	logInfo("Garbage calendar", "Execution finished")
end
  • YOURSITEMAP.sitemap
	Frame label="Anstehende Termine für Morgen" {
		Text item=gCal_Abfall_Item {
			Frame label="Anstehende Müll-Abfuhr Termine" {
				//Group item=gCal_Abfall_Item label="Anstehende Müll-Abfuhr Termine"
				Text item=gCal_Abfall_Event1_Summary
				//Text item=gCal_Abfall_Event1_Location
				Text item=gCal_Abfall_Event1_Description
				Text item=gCal_Abfall_Event1_StartTime
				//Text item=gCal_Abfall_Event1_EndTime
				Switch item=gCal_Abfall_Event1_Approved
				Text item=gCal_Abfall_Event2_Summary
				//Text item=gCal_Abfall_Event2_Location
				Text item=gCal_Abfall_Event2_Description
				Text item=gCal_Abfall_Event2_StartTime
				//Text item=gCal_Abfall_Event2_EndTime
				Switch item=gCal_Abfall_Event2_Approved
				Text item=gCal_Abfall_Event3_Summary
				//Text item=gCal_Abfall_Event3_Location
				Text item=gCal_Abfall_Event3_Description
				Text item=gCal_Abfall_Event3_StartTime
				//Text item=gCal_Abfall_Event3_EndTime
				Switch item=gCal_Abfall_Event3_Approved
				Text item=gCal_Abfall_Event4_Summary
				//Text item=gCal_Abfall_Event4_Location
				Text item=gCal_Abfall_Event4_Description
				Text item=gCal_Abfall_Event4_StartTime
				//Text item=gCal_Abfall_Event4_EndTime
				Switch item=gCal_Abfall_Event4_Approved
			}
		}
		Text item=gCal_Geburtstag_Item
	}

Hope this helps some newbies… Thank you and have fun :slight_smile:

/Holger

.

8 Likes

Please add:
sudo python -m pip install --upgrade oauth2client

2 Likes

How do you guys use this with multiple accounts/calendarIDs? also “'1909-12-19T00:00:00.000+0100” often ended up in my items, so i edited the script a little bit, will share later.

Ok so I have done all except the last part because I keep getting errors trying to run the .sh on openhab

#!/bin/sh
/usr/bin/python C:/openhab/userdata/etc/scripts/scripts/CalSyncHAB/CalSyncHAB.py

but I only get errors

Launching the openHAB runtime...
Listening for transport dt_socket at address: 5005

                          __  _____    ____
  ____  ____  ___  ____  / / / /   |  / __ \
 / __ \/ __ \/ _ \/ __ \/ /_/ / /| | / __  /
/ /_/ / /_/ /  __/ / / / __  / ___ |/ /_/ /
\____/ .___/\___/_/ /_/_/ /_/_/  |_/_____/
    /_/                        2.3.0
                               Release Build

Hit '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.
Hit '<ctrl-d>' or type 'system:shutdown' or 'logout' to shutdown openHAB.

openhab> sudo -u openhab C:\\openhab\userdata\etc\scripts\CalSyncHAB.sh
20:39:50.202 [Karaf local console user openhab] ERROR org.apache.karaf.shell.support.ShellUtil - Exception caught while executing command
java.lang.NullPointerException: null
        at org.apache.karaf.shell.impl.console.ConsoleSessionImpl.run(ConsoleSessionImpl.java:348) [12:org.apache.karaf.shell.core:4.1.5]
        at java.lang.Thread.run(Thread.java:748) [?:?]
Error executing command: java.lang.NullPointerException

and then openhab crashes

You need to run this command outside the Karaf Console…

ok how do I do it outside the karaf console? cmd doesn’t recognise the command sudo?

Are you logged in as user openhabian?

I am hosting it on windows, I did say

how did you run the other sudo commands in my example then?

the python stuff I already did so I created a folder and downloaded the git hub (as a zip and extracted it in a folder “C:\openhab\uesrdata\etc\scripts\CalSyncHAB”) then I changed the secret file and created a script(both with notepad) then I tried running the sudo -u openhab but it didn’t work on karaf

Okay… so i dont know how to do this on windows… i’m running linux (openhabian)

Maybe a windows OH user can help here… or maybe google will help you…

I tried google, it didn’t work that’s why I thought I might get help on here

Thanks everybody. Especially to @davorf for the script and @kugelsicha (Holger) for the excellent tutorial! I need to test it this weekend, but so far the setup was quite easy and everything looked good.

Thanks Holger for your tutorial,it’s almost perfect and helped me a lot to follow installation steps in the right order :slight_smile:
Just one question for your sitenap file: you added the switch on/off for each event,but i din’t understand what they are used for…they win’t change automatically to off or to on…can you please explain to me?
Also another question,is it possible to add anither calendar to be shown?
For all the rest it’s perfect! Thanks to all who created this helpfull object :slight_smile:

1 Like

@rubenfuser: if you refer to the …Eventx_Approved items: Starting from 8 hours before event start time every 60 minutes he sends a telegram notification as a reminder. He stops sending the notifications when the event has been approved via the switch.

1 Like