Einlesen .ics-Kalenderdatei, auswerten, Alarmfunktion

Homematic-, TCL- und Shell-Script, Toolchain, C, etc.

Moderator: Co-Administratoren

Antworten
Freddy94
Beiträge: 5
Registriert: 11.04.2014, 21:32

Einlesen .ics-Kalenderdatei, auswerten, Alarmfunktion

Beitrag von Freddy94 » 19.12.2018, 15:22

Script-Spielerei zum Auslesen einer .ics-Kalenderdatei von unserem kommunalem Abfallentsorger und Benachrichtigung mit pushover

Ich wollte mich einfach mal ein wenig weiter in Programmierung von Scripten einarbeiten.
Da ist mir zufällig die Kalender-Datei von unserem Abfallentsorger "Zweckverband Abfallwirtschaft Donau-Wald" (Niederbayern) www.awg.de aufgefallen.
Beispieldatei als .ics kann ich leider nicht anhängen

Idee war, mich 1 Tag vorher an den Abholtermin von Restmülltonne, Biotonne oder Papiertonne zu erinnern.
Alarmierung bekomme ich über pushover.
Wenn die Datei den letzten Eintrag abgearbeitet hat, erinnert es daran die neue Datei einzuspielen.

Das Script ist mit Sicherheit "unter aller Kanone" programmiert, aber es funktioniert.
Das Einzige was ich noch nicht testen konnte, ist die Nachricht, wenn der letzte Eintrag der Datei abgearbeitet ist, um die Erinnerung zu erhalten, die neue Datei einzuspielen.

Es soll nur als Gedankenstütze für jene sein, die vielleicht auch mal irgendeine formatierte Textdatei über ein Script auswerten wollen.

Eine Unterstützung für etwaige Problemfälle kann ich leider nicht so bieten, da ich beruflich nur sporadisch immer wieder mal Zeit habe, mich mit dem Forum und den Scripten zu befassen.
Und auch bin ich nicht der "Programmierer-Typ", bei zählt dabei "try & error".

Die Erklärung, was wo eingetragen werden muß, steht im Script. CuxD und Pushover sind Vorraussetzung.

Viele Teile, Codeschnipsel habe ich mir aus anderen Scripten zusammengesucht, probiert und lauffähig angepasst.

Viel Spaß damit, vielleicht hilfts ja jemanden als Schnipsellieferant oder Anregung

Code: Alles auswählen

!Stand 15.11.2018 
! ----------------------------------------------------------
! Erklärung:
! Die Abfallentsorgung Außernzell www.awg.de bietet für jeden Abholstandort eine Kalenderdatei zum Download an
! Diese Datei abspeichern auf einem eigenen Server oder dgl., die mit http:// .. abrufbar ist
! Die Daten für Server und Dateiname im Script unter Eintrag 1 eintragen
! Daten für Token und User für pushover im Script 2mal eintragen
! Funktion:
! - Das Script liest die .ics Datei aus
! - holt sich das Systemdatum
! - Scriptausführung bei mir täglich um 8:45
! - Wenn am nächsten Tag ( 1 Tag Vorlauf, kann unter Eintrag 2 geändert werden) ein Abholtermin ansteht,
!   beachrichtigt mich pushover über den Standort und welche Tonne geleert wird
! - Sollte der letzte Eintag abgearbeitet sein, erinnert mich das Script, die neue .ics-Datei
!   neu auf den Server zu spielen ( Gültigkeit der Datei 1 Jahr )
!
! Vorraussetzung:
! pushover funktioniert
! CuxD-Gerät bei mir angelegt: CUX2801001 als Fernbedienung HM-RC-19 KEY
! evtl. CuxD-Gerätenummer anpassen


! -----------------------------------------------------------


! +++++ Definition Variablen +++++

string abfrage = "";

integer i ;
integer laenge ;

var t;
var uts;


! +++++ Aktuelle ics-Datei von AWG auf Server +++++

! Eintrag 1:

var url = "http://<Server>/<evtl.Ordner>/Leerungstermine123456.ics";

! +++++ Abfrage der Datei mit CUxD und Einlesen in Variable / Dateilänge in Variable +++++

dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget -q -O - '"#url#"'");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
string muell_txt = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
integer laenge = muell_txt.Length();



! +++++ Systemdatum einlesen, in UTS wandeln, Tage Vorlauf aufaddieren +++++

var uts = 1.0*(system.Date("%F").ToTime().ToInteger());

! Eintrag 2:
! +++++ Tage Vorlauf * Sekunden +++++++
uts = uts + ( 1* 86400);
var t = uts.ToTime();



!+++++ Abfrage der kompletten Variable nach Schlüsselwörter +++++

while (i < (laenge-12) ) 
      {	

! ----- Ort -------------------------------------------------------------
                string abfrage =muell_txt.Substr(i,21);

                if ( abfrage == "LOCATION;LANGUAGE=de:" )
                {
                  string ort =muell_txt.Substr((i+21),(35));
                };

! ----- Art -------------------------------------------------------------

              string abfrage =muell_txt.Substr(i,20);

                if ( abfrage == "SUMMARY;LANGUAGE=de:" )
                {
                 string art =muell_txt.Substr((i+20),(11));

                    if (art == "Restmuellto")
                    {art = "Restmülltonne";};

                    if (art == "Papiertonne")
                    {art = "Papiertonne";};

                    if (art == "Bioabfallbe")
                    {art = "Biotonne";};
                };

! ----- Datum mit Auswertung, ob Alarm erfolgt ---------------------------

                string abfrage =muell_txt.Substr(i,19);

                if ( abfrage == "DTSTART;VALUE=DATE:" )
                {
                 string datum =muell_txt.Substr((i+19),(8));
                  string YY = datum.Substr(0,4);
                  string MM = datum.Substr(4,2);
                  string DD = datum.Substr(6,2);
                  string sDate = YY#"-"#MM#"-"#DD#" 00:00:00";

                    if ( sDate == t)
                    {
                     ! +++++ Pushover, wenn Abholdatum und aktuelles Datum mit Vorlauftagen gleich ist ++++++
                     string nDate1 =sDate.Substr(0,4);
                     string nDate2=sDate.Substr(5,2);
                     string nDate3=sDate.Substr(8,2);
                     string nDate = nDate3#"."#nDate2#"."#nDate1;
                     string nachrichtstring =  art#": "#nDate#": "#ort;
                     string nachricht = nachrichtstring.UriEncode();

                     dom.GetObject("CUxD.CUX2801001:10.CMD_EXEC").State("LD_LIBRARY_PATH=/usr/local/addons/cuxd /usr/local/addons/cuxd/curl -s -d token=<token> -d user=<user> -d message="#nachricht#" -d sound=pushover -d priority=0 http://api.pushover.net/1/messages.json");
                    }

                };

! -----------------------------------------------------------------------

! +++++ Ende der while-Schleife +++++

       i=i+1;
      };

! ++++++++++++ Benachrichtigung letzter Eintrag der Datei +++++++++++++++

if ( sDate == t)
   {

    ! ++++++ Pushover ++++++++
    nachrichtenstring = "ACHTUNG: Letzter Eintrag der AWG-Datei - Neue Datei auf Server laden, sonst keine Alarmierung mehr möglich!";
    string nachricht = nachrichtstring.UriEncode();

    dom.GetObject("CUxD.CUX2801001:10.CMD_EXEC").State("LD_LIBRARY_PATH=/usr/local/addons/cuxd /usr/local/addons/cuxd/curl -s -d token=<token> -d user=<user> -d message="#nachricht#" -d sound=pushover -d priority=0 http://api.pushover.net/1/messages.json");

   };

! ===== Programmende =====

Raspberrymatic
1 x Schalt-Aktor HM-LC-Sw4-WM
1 x Schalt-Aktor HM-LC-SW4-PCB
6 x Rauchmelder HM-Sec-SD
3 x HM-RC-4-2
6 x Funk-Heizkörper-Thermostat HM-CC-RT-DN
1 x (Nachbauvariante) HM-WDS40-TH-I-BME280

michael9914
Beiträge: 117
Registriert: 05.12.2018, 08:21
Hat sich bedankt: 10 Mal

Re: Einlesen .ics-Kalenderdatei, auswerten, Alarmfunktion

Beitrag von michael9914 » 04.01.2019, 18:56

Ich habe das o.g. Script für meine Zwecke angepasst.
Die von mir gewünschte URL ist allerdings mit HTTPS, deshalb habe ich "--no-check-certificate" bei wget ergänzt.
(siehe: viewtopic.php?f=37&t=23424&start=10#p370288)

Dennoch führt der das Testen des Scripts zu keiner Ausgabe; allerdings auch nicht zu einem Fehler.
Woran kann das liegen?

Code: Alles auswählen

var url = "https://ics.teamup.com/feed/ks02aeb40195060298/9999999.ics";
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget --no-check-certificate -q -O - '"#url#"'");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
string kalender_txt = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
WriteLine(#kalender_txt);
Auch wenn ich die letzte Zeile wiefolgt austausche und das Script in ein Programm integriere, kommt kein Inhalt in der Systemvariablen an (leeres Feld, nicht "???"))

Code: Alles auswählen

dom.GetObject (ID_SYSTEM_VARIABLES).Get ("kalender_txt").State(kalender_txt);

alchy
Beiträge: 10752
Registriert: 24.02.2011, 01:34
System: CCU
Hat sich bedankt: 65 Mal
Danksagung erhalten: 672 Mal

Re: Einlesen .ics-Kalenderdatei, auswerten, Alarmfunktion

Beitrag von alchy » 06.01.2019, 23:11

Code: Alles auswählen

WriteLine(#kalender_txt);
ist auch falsch, das # ist an der Stelle zu viel.

Alchy

Blacklist................... almost full
Ignoranz ist die Summe aller Maßnahmen die man ergreift, um bestehende Tatsachen nicht sehen zu müssen.

© Sandra Pulsfort (*1974)

Lies bitte die Logik von WebUI Programmen und die Tipps und Tricks für Anfänger.

Wichtig auch CUxD ersetzt System.exec. Die HM Script Doku (Downloadart Skripte) hilft auch weiter.
Zum Testen von Scripten den >> HomeMatic Script Executor << von Anli benutzen.

michael9914
Beiträge: 117
Registriert: 05.12.2018, 08:21
Hat sich bedankt: 10 Mal

Re: Einlesen .ics-Kalenderdatei, auswerten, Alarmfunktion

Beitrag von michael9914 » 10.01.2019, 22:22

Klappt leider trotzdem nicht.

alchy
Beiträge: 10752
Registriert: 24.02.2011, 01:34
System: CCU
Hat sich bedankt: 65 Mal
Danksagung erhalten: 672 Mal

Re: Einlesen .ics-Kalenderdatei, auswerten, Alarmfunktion

Beitrag von alchy » 11.01.2019, 07:14

Mein Hinweis entfernt nur den SyntaxError und Scriptabbruch. Es klärt nicht die Voraussetzungen der allgemeinen Funktion dessen.
Soll heißen:

Selbst wenn du alle anderen Voraussetzungen korrekt erfüllen würdest, würde das Script ohne Ausgabe abbrechen wenn du das # da nicht entfernst.
Es würde einen Fehler im >> Fehlerprotokoll << erzeugen, was ja deiner Aussage nach nicht der Fall ist. :wink: Ich bin mir relativ sicher, das du da nicht nachgeschaut hast.

Und nun zu allen anderen Voraussetzungen
Wenn CUD.exec korrekt installiert ist und mit der Seriennummer funktioniert & wenn die url korrekt und ohne zusätzliche Authentifizierung funzt
( der Aufruf der url im Browser im Inkognito modus den Download der ics Datei bringt)

sollte das Script eine Rückgabe bringen nachdem du das # entfernt hast.

Alchy

Blacklist................... almost full
Ignoranz ist die Summe aller Maßnahmen die man ergreift, um bestehende Tatsachen nicht sehen zu müssen.

© Sandra Pulsfort (*1974)

Lies bitte die Logik von WebUI Programmen und die Tipps und Tricks für Anfänger.

Wichtig auch CUxD ersetzt System.exec. Die HM Script Doku (Downloadart Skripte) hilft auch weiter.
Zum Testen von Scripten den >> HomeMatic Script Executor << von Anli benutzen.

michael9914
Beiträge: 117
Registriert: 05.12.2018, 08:21
Hat sich bedankt: 10 Mal

Re: Einlesen .ics-Kalenderdatei, auswerten, Alarmfunktion

Beitrag von michael9914 » 12.01.2019, 17:56

Im Fehlerlog finde ich nichts. Aber im Log von CUxD:

Jan 11 18:45:28 homematic-ccu2 daemon.info cuxd[8905]: pclose(wget --no-check-certificate -q -O - 'https://ics.teamup.com/feed/ks02aeb4019 ... 999999.ics') exit(4) 0s

Dass dies ein Netzwerkfehler ist, habe ich recherchiert, aber wie zu lösen?

Gruß Michael

Boophus
Beiträge: 2
Registriert: 19.05.2023, 12:19
System: CCU

Re: Einlesen .ics-Kalenderdatei, auswerten, Alarmfunktion

Beitrag von Boophus » 19.05.2023, 12:36

Vielen Dank für das Script, @Freddy94, und auch deinen Tipp habe ich beherzigt @michael9914 :)
Es ist genau das, was ich gesucht habe und funktioniert nach Anpassungen auf die Eigenheiten der .ics-Datei unseres lokalen Anbieter super.

Da bei unserem Abfallkalender die Reihenfolge der Elemente anders ist, war die art immer um einen Tag verschoben :D

Aus diesem Grund habe ich die Ermittlung des Datums von der Auslösung des Alarms getrennt.
(--> "Datum mit Auswertung, ob Alarm erfolgt")

So dass der Alarm erst am Ende des Events ausgelöst, wenn alle Informationen ausgewertet worden sind.

Code: Alles auswählen

! ----- Datum des Events ---------------------------

            string abfrage = muell_txt.Substr(i,19);
            if ( abfrage == "DTSTART;VALUE=DATE:" )
            {
             string datum = muell_txt.Substr((i+19),(8));
             string YY = datum.Substr(0,4);
             string MM = datum.Substr(4,2);
             string DD = datum.Substr(6,2);
             string sDate = YY#"-"#MM#"-"#DD#" 00:00:00";
            };

! ----- Ende des VEVENT = Auslösen des Alarms ---------------------------
            
	    string abfrage = muell_txt.Substr(i,10);
            if ( abfrage == "END:VEVENT" )
            {
			if ( sDate == t)
                    {

                     ! +++++ Pushover, wenn Abholdatum und aktuelles Datum mit Vorlauftagen gleich ist ++++++
		     ! +++++ Vorbereitung +++++
                     string nDate1 =sDate.Substr(0,4);
                     string nDate2=sDate.Substr(5,2);
                     string nDate3=sDate.Substr(8,2);
                     string nDate = nDate3#"."#nDate2#"."#nDate1;
                     string nachrichtstring =  art#": "#nDate#": "#ort;
                     string nachricht = nachrichtstring.UriEncode();

                     ! +++++ Pushover: Action! +++++
		    dom.GetObject("CUxD.CUX2801001:10.CMD_EXEC").State("LD_LIBRARY_PATH=/usr/local/addons/cuxd /usr/local/addons/cuxd/curl -s -d token=<token> -d user=<user> -d message="#nachricht#" -d sound=pushover -d priority=0 http://api.pushover.net/1/messages.json");
                   		   					}		
		    WriteLine("Event: "#sDate #" - "#art)
		    };
		    

--------------------------------------------------------------
Background / Details: .ics

In der .ics ist jeder Termin ein Event.
Jedes Event beginnt mit BEGIN:VEVENT und endet mit END:VEVENT
Dazwischen werden die Details geklärt.
Die Reichenfolge der einzelnen Elemente kann variabel sein.

Beispiel:

Code: Alles auswählen

BEGIN:VEVENT
UID:6467299a6c6c2
DTSTART;VALUE=DATE:20231220
SEQUENCE:0
TRANSP:OPAQUE
DTEND;VALUE=DATE:20231221
SUMMARY:Verpackungstonne
CLASS:PUBLIC
X-MICROSOFT-CDO-ALLDAYEVENT:TRUE
DTSTAMP:20230519T074738Z
END:VEVENT

Antworten

Zurück zu „Softwareentwicklung für die HomeMatic CCU“