Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Visualisierung
  4. [Vorlage] MDCSS v2: ical Kalendar anzeigen

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.5k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.0k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    16
    1
    2.7k

[Vorlage] MDCSS v2: ical Kalendar anzeigen

Geplant Angeheftet Gesperrt Verschoben Visualisierung
vismaterial uimaterial css
56 Beiträge 15 Kommentatoren 8.3k Aufrufe 20 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • G G4l4h4d

    Ich habe das Script eingefügt und bekomme folgenden Fehler

    javascript.0	2020-05-09 22:09:19.604	error	(973) Function "setObject" is not allowed. Use adapter settings to allow it.
    javascript.0	2020-05-09 22:09:19.604	error	(973) Function "setObject" is not allowed. Use adapter settings to allow it.
    javascript.0	2020-05-09 22:09:19.603	error	(973) Function "setObject" is not allowed. Use adapter settings to allow it.
    javascript.0	2020-05-09 22:09:19.602	error	(973) Function "setObject" is not allowed. Use adapter settings to allow it.
    javascript.0	2020-05-09 22:09:19.601	error	(973) Function "setObject" is not allowed. Use adapter settings to allow it.
    

    Es wird in den Objekten auch kein Eintag in Userdata angelegt?

    UhulaU Offline
    UhulaU Offline
    Uhula
    schrieb am zuletzt editiert von
    #37

    @G4l4h4d sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

    Es wird in den Objekten auch kein Eintag in Userdata angelegt?

    Du musst im Admin in den Eigenschaften der Javascript-Instanz Erlaube das Kommando setObject einschalten.

    010b0b2b-b443-4b35-95b5-6739ce7359dd-image.png

    Uhula - Leise und Weise
    Ex: ioBroker on Gigabyte NUC Proxmox

    G 1 Antwort Letzte Antwort
    0
    • UhulaU Uhula

      @G4l4h4d sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

      Es wird in den Objekten auch kein Eintag in Userdata angelegt?

      Du musst im Admin in den Eigenschaften der Javascript-Instanz Erlaube das Kommando setObject einschalten.

      010b0b2b-b443-4b35-95b5-6739ce7359dd-image.png

      G Offline
      G Offline
      G4l4h4d
      schrieb am zuletzt editiert von
      #38

      @Uhula Vielen Dank, wusste gar nicht das es aus ist :-)

      1 Antwort Letzte Antwort
      0
      • ChaotC Offline
        ChaotC Offline
        Chaot
        schrieb am zuletzt editiert von Chaot
        #39

        @Uhula
        Ich bekomme beim zweiten Start die Fehlermeldung:

        javascript.0	2020-06-12 21:39:26.740	warn	(460) at script.js.Kalender.MDUI-Ical:724:18
        javascript.0	2020-06-12 21:39:26.740	warn	(460) at MduiShowIcal.start (script.js.Kalender.MDUI-Ical:112:26)
        javascript.0	2020-06-12 21:39:26.739	warn	(460) at MduiShowIcal.doStart (script.js.Kalender.MDUI-Ical:366:14)
        javascript.0	2020-06-12 21:39:26.739	warn	(460) at MduiShowIcal.onBuildHTML (script.js.Kalender.MDUI-Ical:608:73)
        javascript.0	2020-06-12 21:39:26.739	warn	(460) at MduiShowIcal.getState (script.js.Kalender.MDUI-Ical:187:16)
        javascript.0	2020-06-12 21:39:26.730	warn	(460) getState "0_userdata.0.mdui.showIcal.log0.filter" not found (3)
        

        Muss ich noch irgendwas einstellen das ich überlesen habe?

        Edit:
        Meldung ist jetzt plötzlich wieder weg.
        Egal.
        Danke für das Klasse Script!

        ioBroker auf NUC unter Proxmox; VIS: 12" Touchscreen und 17" Touch; Lichtsteuerung, Thermometer und Sensoren: Tasmota (39); Ambiente Beleuchtung: WLED (9); Heizung: DECT Thermostate (9) an Fritz 6690; EMS-ESP; 1 Echo V2; 3 Echo DOT; 1 Echo Connect; 2 Echo Show 5; Unifi Ap-Ac Lite.

        1 Antwort Letzte Antwort
        0
        • Lars WalpurgisL Offline
          Lars WalpurgisL Offline
          Lars Walpurgis
          schrieb am zuletzt editiert von Lars Walpurgis
          #40

          @Uhula Vielen Dank erstmal für das tolle Script es läuft wunderbar!
          Ich habe zwei kurze Fragen und zwar:

          1. Wie kann man anstatt des Datums vorn direkt anzeigen lassen, dass der Termin heute, in 1 Tage... ist? Der ical Adapter liefert das ja schon....!Datum.JPG

          2. Ich nutze noch die MDCSS V1.8 und vermute, dass deswegen das Kuchen icon (cake im oberen Bild) nicht angezeigt wird, liegt das daran? Kann ich das einfach nach implementieren, oder muss ich die MDCSS Verion hochrüsten? Und wenn ja, habe ich eine Kompatibilität?

          Danke für eure Antworten!

          1 Antwort Letzte Antwort
          0
          • Holger EtzelH Offline
            Holger EtzelH Offline
            Holger Etzel
            schrieb am zuletzt editiert von Holger Etzel
            #41

            Hallo,

            bekomme beim starten des Scripts folgende Meldung:

            14:54:45.933 warn javascript.0 (22584) at MduiShowIcal.getState (script.js.Allgemein.Kalenderansicht:187:16)
            14:54:45.934 warn javascript.0 (22584) at MduiShowIcal.onBuildHTML (script.js.Allgemein.Kalenderansicht:608:73)
            14:54:45.934 warn javascript.0 (22584) at MduiShowIcal.doStart (script.js.Allgemein.Kalenderansicht:366:14)
            14:54:45.935 warn javascript.0 (22584) at MduiShowIcal.start (script.js.Allgemein.Kalenderansicht:112:26)
            14:54:45.936 warn javascript.0 (22584) at script.js.Allgemein.Kalenderansicht:724:18
            14:54:46.027 info javascript.0 (22584) script.js.Allgemein.Kalenderansicht: [mduiShowIcal] script started
            14:54:46.027 info javascript.0 (22584) script.js.Allgemein.Kalenderansicht: registered 3 subscriptions and 0 schedules

            und im log:

            javascript.0 2020-07-19 15:00:08.698 warn (22584) at process.topLevelDomainCallback (domain.js:126:23)
            javascript.0 2020-07-19 15:00:08.697 warn (22584) at processImmediate (timers.js:658:5)
            javascript.0 2020-07-19 15:00:08.696 warn (22584) at tryOnImmediate (timers.js:676:5)
            javascript.0 2020-07-19 15:00:08.696 warn (22584) at runCallback (timers.js:705:18)
            javascript.0 2020-07-19 15:00:08.695 warn (22584) at Immediate.setImmediate (/opt/iobroker/node_modules/iobroker.js-controller/lib/adapter.js:5384:37)
            javascript.0 2020-07-19 15:00:08.695 warn (22584) at Object.stateChange (/opt/iobroker/node_modules/iobroker.javascript/main.js:451:25)
            javascript.0 2020-07-19 15:00:08.694 warn (22584) at Object.callback (/opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:1052:38)
            javascript.0 2020-07-19 15:00:08.694 warn (22584) at Object.subscribe.obj (script.js.Allgemein.Kalenderansicht:364:60)
            javascript.0 2020-07-19 15:00:08.694 warn (22584) at MduiShowIcal.onIcalTable (script.js.Allgemein.Kalenderansicht:391:12)
            javascript.0 2020-07-19 15:00:08.693 warn (22584) at MduiShowIcal.onBuildHTML (script.js.Allgemein.Kalenderansicht:608:73)
            javascript.0 2020-07-19 15:00:08.693 warn (22584) at MduiShowIcal.getState (script.js.Allgemein.Kalenderansicht:187:16)
            javascript.0 2020-07-19 15:00:08.690 warn (22584) getState "0_userdata.0.mdui.showIcal.log0.filter" not found (3)

            Habe ich noch was vergessen einzustellen?

            Nach stundenlanger Wartezeit geht es auf einmal.

            Gruß Holger

            E 1 Antwort Letzte Antwort
            0
            • Holger EtzelH Holger Etzel

              Hallo,

              bekomme beim starten des Scripts folgende Meldung:

              14:54:45.933 warn javascript.0 (22584) at MduiShowIcal.getState (script.js.Allgemein.Kalenderansicht:187:16)
              14:54:45.934 warn javascript.0 (22584) at MduiShowIcal.onBuildHTML (script.js.Allgemein.Kalenderansicht:608:73)
              14:54:45.934 warn javascript.0 (22584) at MduiShowIcal.doStart (script.js.Allgemein.Kalenderansicht:366:14)
              14:54:45.935 warn javascript.0 (22584) at MduiShowIcal.start (script.js.Allgemein.Kalenderansicht:112:26)
              14:54:45.936 warn javascript.0 (22584) at script.js.Allgemein.Kalenderansicht:724:18
              14:54:46.027 info javascript.0 (22584) script.js.Allgemein.Kalenderansicht: [mduiShowIcal] script started
              14:54:46.027 info javascript.0 (22584) script.js.Allgemein.Kalenderansicht: registered 3 subscriptions and 0 schedules

              und im log:

              javascript.0 2020-07-19 15:00:08.698 warn (22584) at process.topLevelDomainCallback (domain.js:126:23)
              javascript.0 2020-07-19 15:00:08.697 warn (22584) at processImmediate (timers.js:658:5)
              javascript.0 2020-07-19 15:00:08.696 warn (22584) at tryOnImmediate (timers.js:676:5)
              javascript.0 2020-07-19 15:00:08.696 warn (22584) at runCallback (timers.js:705:18)
              javascript.0 2020-07-19 15:00:08.695 warn (22584) at Immediate.setImmediate (/opt/iobroker/node_modules/iobroker.js-controller/lib/adapter.js:5384:37)
              javascript.0 2020-07-19 15:00:08.695 warn (22584) at Object.stateChange (/opt/iobroker/node_modules/iobroker.javascript/main.js:451:25)
              javascript.0 2020-07-19 15:00:08.694 warn (22584) at Object.callback (/opt/iobroker/node_modules/iobroker.javascript/lib/sandbox.js:1052:38)
              javascript.0 2020-07-19 15:00:08.694 warn (22584) at Object.subscribe.obj (script.js.Allgemein.Kalenderansicht:364:60)
              javascript.0 2020-07-19 15:00:08.694 warn (22584) at MduiShowIcal.onIcalTable (script.js.Allgemein.Kalenderansicht:391:12)
              javascript.0 2020-07-19 15:00:08.693 warn (22584) at MduiShowIcal.onBuildHTML (script.js.Allgemein.Kalenderansicht:608:73)
              javascript.0 2020-07-19 15:00:08.693 warn (22584) at MduiShowIcal.getState (script.js.Allgemein.Kalenderansicht:187:16)
              javascript.0 2020-07-19 15:00:08.690 warn (22584) getState "0_userdata.0.mdui.showIcal.log0.filter" not found (3)

              Habe ich noch was vergessen einzustellen?

              Nach stundenlanger Wartezeit geht es auf einmal.

              Gruß Holger

              E Offline
              E Offline
              Ente
              schrieb am zuletzt editiert von
              #42

              @sigi234

              Hallo siggi234,

              danke für den Install-Screenshot. ;-)

              sigi234S 1 Antwort Letzte Antwort
              0
              • E Ente

                @sigi234

                Hallo siggi234,

                danke für den Install-Screenshot. ;-)

                sigi234S Online
                sigi234S Online
                sigi234
                Forum Testing Most Active
                schrieb am zuletzt editiert von sigi234
                #43

                @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                @sigi234

                Hallo siggi234,

                danke für den Install-Screenshot. ;-)

                Screenshot (674)_LI.jpg

                /*
                *** MduiShowIcal
                Dieses Script überwacht den ical-Adapter und erzeugt bei Änderungen an dessen States HTML-List States für die Anzeige als 
                Kalender in Listform mit
                * Tagesauflösung von "von/bis"-Terminen, inkl. Berücksichtigung der Uhrzeiten
                * Tagesdatum, Kalendarfarben aus ical oder optional aus dem Script
                * Termintext und -ort
                * optionalem Icon je Kalendar
                * optionalem "ignore", wenn ein Kalendar unberücksichtigt bleiben soll
                
                Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner 
                befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget). 
                Über optionale Filter als string (Bsp:':Abfall:') oder als RegExp (Bsp:'/Feiertag|Geburtstag/') kann festgelegt werden, 
                welche Einträge beim Aufbau der list-HTML States berücksichtigt werden. 
                Bsp.: 
                log0 Filter: "abfall" oder ":Abfall:" (=Kalendarname) -> Zeigt nur Abfalltermine
                log0 Filter: "ferien" oder ":Ferien:" (=Kalendarname) -> Zeigt nur Ferientermine
                
                
                **** Installation
                Einfach als serverseitiges Script installieren und starten-5 Sek warten-stoppen-starten. Beim 1.Start werden 
                die notwendigen States unter STATE_PATH = '0_userdata.0.mdui.showIcal.' erzeugt. Erst beim 2.Start
                instanziiert das Script die Event-Handler und läuft dann.
                
                **** Konfiguration
                Eigentlich ist keine notwendig.
                Optional in der Funktion MduiShowIcal|doInit() eine Anpassung der KONFIGURATION vornehmen
                Optional Anpassung der tmpList.
                  
                **** Dokumentation
                https://github.com/Uhula/ioBroker-Material-Design-Style/wiki/3.5-MduiShowIcal
                
                ###### Um ein Feedback zu erhalten wäre es schön, wenn jeder, der diese Vorlagen nutzt, den  1.Beitrag des Themas positiv bewertet (Pfeil nach oben oder unten ;-) ). Ich kann dann auch abschätzen, ob sich die weitere Pflege lohnt. Thx!
                
                ***** States
                Unter dem STATE_PATH werden die folgenden States erzeugt:
                version : Script-Version, wird verwendet um Script-Updates zu erkennen
                updatePressed : auf true setzen, wenn ein table/list update außerhalb des Intervals erfolgen soll
                
                Weiterhin werden MAX_LOG_FOLDER Unterordner im STATE_PATH erzeugt (N=0-9):
                
                * LogN.table        : enthält die table-HTML für ein basic-string (unescaped) Widget
                * LogN.list         : enthält die list-HTML für ein basic-string (unescaped) Widget
                * LogN.count        : Anzahl der Log-Zeilen (wenn das Log mit '/:error:|:warn:/' gefiltert ist, dann ist es die Anzahl der Fehler/Warnungen)
                * LogN.filter       : Filter, der auch die logCache angewendet wurde im .table/.list zu erzeugen (siehe Filter)
                * LogN.lastUpdate   : Timestamp des letzten Updates
                
                
                ***** Filter
                In den filter-States können sowohl strings (Bsp:'error') als auch RegExp-Strings (Bsp:'/warn|error/') 
                hinterlegt werden. RegExp-Strings werden an den einschließenden  '/' erkannt. Über den ':' kann der Anfang
                eines Feldes mit in den Filter einbezogen werden. 
                Beispiele: 
                '/Feiertag|Geburtstag/' (RegExp) zeigt alle Zeilen an, in denen 'Feiertag' oder 'Geburtstag' in irgendeinem Feld vorkommen
                ':Abfall:' (string) zeigt alle Zeilen an, welche derKalendar 'Abfall' lautet
                'Arzt' (string) zeigt alle Zeilen an, in denen 'Arzt' in irgendeinem Feld vorkommt
                
                **** Lizenz
                (c) 2020 by UH, MIT License, no warranty, use on your own risc
                
                *** Changelog
                2020.05.01 UH 
                * Anpassung an neues MduiBase (intern)
                * Anpassung an MDCSS 2.5
                * Serientermine vor dem aktuellem Datum werden nicht mehr angezeigt
                
                */
                
                // ------------------------------------------------------------------------------------- 
                // MduiBase
                // ------------------------------------------------------------------------------------- 
                
                class MduiBase {
                
                    constructor() {
                      this.init();
                    }
                    
                    //
                    init() {
                        // const
                        this.DEBUG      = false;
                        this.VERSION    = '1.0/2020-01-01';
                        this.NAME       = 'mduiBase';
                        this.STATE_PATH = '0_userdata.0.mdui.base.';
                        this.STATE_UNKNOWN    =  0;
                        this.STATE_INSTALLING = 10;
                        this.STATE_INSTALLED  = 11;
                        this.STATE_STARTING   = 20;
                        this.STATE_STARTED    = 21;
                        this.STATE_STOPPING   = 30;
                        this.STATE_STOPPED    = 31;
                    
                        // var
                        this.state = this.STATE_UNKNOWN;
                        this.states = [];
                        this.subscribers = [];
                        this.schedulers = [];
                    
                        this.doInit();
                    
                        // init der states
                        this.states.push( { id:'version',     common:{name:'installed script-version', write:false, def:this.VERSION} } );
                    }
                    
                    //
                    // start the script/class
                    //
                    start() {
                        // beim 1.Start nur die States erzeugen
                        if ( !this.existState("version") || (this.getState('version').val!=this.VERSION) ) {
                            for (let s=0; s<this.states.length; s++) { this.createState( this.states[s].id ); }
                            this.logWarn('first script start, creating states for version '+this.VERSION+', automatic restarting script again in 10 sec ...');
                            setStateDelayed(this.STATE_PATH + 'version', this.VERSION, 3000);
                            setTimeout( this.start.bind(this), 10000 );
                            this.state = this.STATE_INSTALLED; 
                            return;
                        }
                        switch (this.state) {
                            case this.STATE_UNKNOWN : ;
                            case this.STATE_INSTALLING : ;
                            case this.STATE_INSTALLED : ;
                            case this.STATE_STOPPED : {
                                this.state = this.STATE_STARTING; 
                                if (this.doStart()) {
                                    this.log('script started');
                                    this.state = this.STATE_STARTED;
                                }
                                break;    
                            }
                            case this.STATE_STARTING : ;
                            case this.STATE_STARTED : {
                                this.logWarn('script already starting/started');
                                break;    
                            }
                            case this.STATE_STOPPING : {
                                this.logWarn('script is stopping, pls start later again');
                                break;    
                            }
                      
                        } 
                    }
                    
                    //
                    // stop the script/class
                    //
                    stop() {
                        switch (this.state) {
                            case this.STATE_STARTED : {
                                this.state = this.STATE_STOPPING; 
                                if (this.doStop()) {
                                    for (let i=0; i<this.subscribers.length; i++) if (this.subscribers[i] !== undefined) unsubscribe( this.subscribers[i] );
                                    this.subscribers = [];
                                    for (let i=0; i<this.schedulers.length; i++) if (this.schedulers[i] !== undefined) clearSchedule( this.schedulers[i] );
                                    this.schedulers = [];
                                    this.state = this.STATE_STOPPED; 
                                    this.log('script stopped');
                                }
                                break;    
                            }
                            default : {
                                this.log('cant stopp script, because not startet');
                            }
                        } 
                    }
                    
                    //
                    // virtual functions, overwrite it 
                    //
                    doInit() { return true; }
                    doStart() { return true; }
                    doStop() { return true; }
                    
                    // einen on-Handler registrieren
                    subscribe( handler ) {
                        this.subscribers.push( handler );
                    }
                    
                    // einen timer registrieren
                    schedule( handler ) {
                        this.schedulers.push( handler );
                    }
                    
                    //
                    // tool functions 
                    //
                    logDebug(msg) { if (this.DEBUG) console.log('['+this.NAME+'] '+msg); }
                    log(msg) { console.log('['+this.NAME+'] '+msg); }
                    logWarn(msg) { console.warn('['+this.NAME+'] '+msg); }
                    logError(msg) { console.error('['+this.NAME+'] '+msg); }
                    
                    // über den $-Operator nachsehen, ob der state bereits vorhanden ist
                    // getState().notExists geht auch, erzeugt aber Warnmeldungen!
                    existState(id) {
                        return ( $(this.STATE_PATH+id).length==0?false:true);
                    }
                    
                    // wrapper, adds statepath to state-ID
                    getState(id) {
                        return getState(this.STATE_PATH + id);
                    }
                    
                    // like setState(), but adds statepath to state_ID and checks if state exists, when not, creates it
                    setState(id,value) {
                        if ( !this.existState(id) ) this.createState(id,value,undefined);
                        else setState( this.STATE_PATH + id, value);
                    }
                    
                    // like cresteState(), but adds statepath to state_ID and checks if state exists, when not, creates it
                    createState(id,value,common) {
                        if ( !this.existState(id) ) {
                            if (common===undefined) {
                                // id im states-Array suchen
                                for (var i=0; i<this.states.length; i++) { 
                                    if (this.states[i].id==id) {
                                        if (this.states[i].hasOwnProperty('common'))
                                            common = this.states[i].common;
                                       break;
                                    }   
                                }
                            }
                            if ( (typeof value === 'undefined') && (common.hasOwnProperty('def'))) value = common.def;
                            // unter "0_userdata.0"
                            let obj = {};
                            obj.type = 'state';
                            obj.native = {};
                            obj.common = common;
                            setObject(this.STATE_PATH + id, obj, (err) => {
                                    if (err) {
                                        this.log('cant write object for state "' + this.STATE_PATH + id + '": ' + err);
                                    } else { 
                                        this.log('state "' + this.STATE_PATH + id + '" created');
                                    }
                            });
                    
                            setTimeout( setState, 3000, this.STATE_PATH + id, value );
                        }
                    }
                    
                    // true, if str contains filter string or regexp 
                    fitsFilter(str, filter) {
                        if ( (filter===undefined) || !filter || (filter=='') )
                            return true;
                        if ( filter instanceof RegExp )  {
                            if (str.match( filter ) != null) return true;
                        } else if (typeof filter == 'string') {
                            if(str.includes(filter)) return true;
                        }
                        return false;        
                    }
                    
                    //
                    escapeRegExp(str) {
                        return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 
                    }
                    
                    // wandelt eine Farbe im hex-Format (#000000) in ein RGB-Array[2] um
                    hexToRGB(hex) {
                        var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
                        return result 
                            ? [parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16)]
                            : [0,0,0];
                    };
                    
                    // Helligkeit berechnen
                    getLuminance(r, g, b) {
                        var a = [r, g, b].map(function (v) {
                            v /= 255;
                            return v <= 0.03928
                                ? v / 12.92
                                : Math.pow( (v + 0.055) / 1.055, 2.4 );
                        });
                        return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
                    }
                    
                    // Kontrats berechnen
                    getContrast(rgb1, rgb2) {
                        var l1 = this.getLuminance(rgb1[0], rgb1[1], rgb1[2]) + 0.05;
                        var l2 = this.getLuminance(rgb2[0], rgb2[1], rgb2[2]) + 0.05;
                        if ( l1 > l2 ) return l1 / l2 
                        else return l2 / l1;
                    }
                    
                    // liefert die fontColor auf Basis der backgroundColor durch Berechnung
                    // des Kontrasts
                    getFontColor(backgroundColor) {
                        if ( this.getContrast(this.hexToRGB(backgroundColor),this.hexToRGB("#000000")) < 6 ) 
                            return "#ffffff";
                        else
                            return "#000000";
                    }
                    
                    }
                    
                    // ------------------------------------------------------------------------------------- 
                    // MduiLogHMDevices
                    // ------------------------------------------------------------------------------------- 
                    
                    class MduiShowIcal extends MduiBase {
                    
                    constructor() {
                        super();
                    }
                    
                    doInit() {
                      super.doInit();
                    
                      // const
                      this.DEBUG = false;
                      this.VERSION = '1.0/2020-03-22';
                      this.NAME = 'mduiShowIcal';
                      this.DAY_MILLISECONDS = 60 * 60 * 24 * 1000;
                    
                      // -----------------------  
                      // optional: KONFIGURATION
                      // -----------------------  
                                           // state-Pfad unter dem die States angelegt werden  
                      this.STATE_PATH      = '0_userdata.0.mdui.showIcal.'; 
                                           // Anzahl der Table/List Ordner mit eigenem Filter/View
                      this.MAX_LOG_FOLDER  = 3;   
                                           // max.Anzahl der Zeilen für die Table/List Ausgabe
                      this.MAX_TABLE_ROWS  = 200; 
                                           // Objekt-Pfad zum ical.x.data.table
                      this.ICAL_TABLE      = 'ical.0.data.table';
                                           // siehe: https://github.com/ioBroker/ioBroker.javascript/blob/master/docs/en/javascript.md#formatdate
                      this.DATE_FORMAT     = 'W DD.MM.YYYY hh:mm';
                                           // optional können dem Kalendar noch Icons und abweichende
                                           // Farben angegeben werden (diese überschreiben jene aus iCal)
                                           // 'icon'     : 'Icon-Name' (MDCSS/Google WebFont)
                                           // 'calColor' : *#rrggbb' abweichende Kalendarfarbe 
                                           // 'ignore'   : true|false Kalendar komplett ignorieren
                      this.CALENDAR        = {'mdui-Abfall'      : {'icon':'delete_outline', 'calcolor':'orange' },
                                              'mdui-Geburtstage' : {'icon':'cake'},
                                              'Familie'          : {'ignore':true}
                                               
                                             };
                    
                      // -----------------------  
                      // ENDE KONFIGURATION
                      // -----------------------  
                    
                      // var
                      this.logs = [];
                      for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) 
                          this.logs.push({filter:'' });
                      
                    
                      // init der states
                      this.states.push( { id:'version',     common:{name:'installed script-version', write:false, def:this.VERSION} } );
                      this.states.push( { id:'updatePressed',common:{name:'update button pressed', write:true, type:'boolean', def:'false', role:'button' }} );
                      
                      let defFilter;
                      for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) {
                          switch (i) {
                              case 1 : defFilter = ':Abfall:'; break;   
                              case 2 : defFilter = 'Geburtstag'; break;   
                              case 3 : defFilter = ''; break;   
                              default: defFilter = undefined;
                          }
                          this.states.push( { id:'log'+i+'.table',      common:{name:'ioBroker-log as table', write:false, role:'html' }} );
                          this.states.push( { id:'log'+i+'.list',       common:{name:'ioBroker-log as list', write:false, role:'html' }} );
                          this.states.push( { id:'log'+i+'.count',      common:{name:'ioBroker-log count', write:false, type:'number', def:'0' }} );
                          this.states.push( { id:'log'+i+'.filter',     common:{name:'ioBroker-log filter', write:true, def:defFilter}} );
                          this.states.push( { id:'log'+i+'.lastUpdate', common:{name:'ioBroker-log last update', write:false, def:'0' }} );
                      }
                    
                      return true;  
                    }
                    
                    // start the script/class
                    doStart() {
                        super.doStart();
                        
                        // subscriber erzeugen
                        this.subscribe( on( this.STATE_PATH+'updatePressed', obj => { this.onUpdate(obj) } ));
                        this.subscribe( on( new RegExp( this.STATE_PATH+'*.filter' ), obj => { this.onFilter(obj) } ));
                        this.subscribe( on( this.ICAL_TABLE, obj => { this.onIcalTable(obj) } ));
                    
                        this.onBuildHTML();
                        return true;
                    }
                    
                    // stop the script/class
                    doStop() {
                        super.doStop();
                        return true;
                    }
                    
                    // 
                    onUpdate(obj) {
                        if (obj.state.val===true) {
                            this.onBuildHTML();
                        }
                        this.setState('updatePressed', false);
                    }
                    
                    // filter, sort events
                    onFilter(obj) {
                      this.onBuildHTML();
                    }
                    
                    // Ical table hat sich geändert
                    onIcalTable(obj) {
                      this.onBuildHTML();
                    }
                    
                    
                    
                    // creates the HTML states for every log
                    /*
                    'date' => "→ 16.10.2017" 
                    'event' => "9.30 - 16.30 Uhr Stopka " 
                    '_class' => "ical_Kerstin ical_today" 
                    '_date' => "2017-10-16T07:30:00.000Z" 
                    '_end' => "2017-10-16T14:30:00.000Z" 
                    '_section' => "" 
                    '_IDID' => "040000008200E00074C5B7101A82E008000000007645DC55A6DFC44FB2EC6FEA9EFEA33C100000007688316058136F42AD128D91103543C9" 
                    '_allDay' => "false" 
                    '_rule' => " " 
                    '_calName' => "Kerstin" 
                    
                    Optionen der ical-Instanz:
                        'daysPreview' => "7"
                        'colorize' => "false"
                        'defColor' => "white"
                        'fulltime' => " 00:00"
                        'dataPaddingWithZeros' => "true"
                        'replaceDates' => "false"
                        'language' => "de"
                        'everyCalOneColor' => "true"
                        'calendars' (array) 
                            '0' (array) 
                                'name' => "Abfall"
                                'url' => "https://calendar.google.com/calendar/ical/ruo0ddgalu03qq2ehpm8imqnk4%40group.calendar.google.com/private-a30aac0367f8b50cfd7373f6222d29b4/basic.ics"
                                'user' => ""
                                'pass' => ""
                                'sslignore' => ""
                                'color' => ""
                    */
                    
                    isSameDay(d1,d2) {
                        return (d1.getDate()==d2.getDate()) && (d1.getMonth()==d2.getMonth()) && (d1.getFullYear()==d2.getFullYear());
                    }
                    
                    getWeekNumber( date ) {
                        let d = new Date(date);
                        d.setHours(0,0,0);
                        d.setDate(d.getDate()+4-(d.getDay()||7));
                        return Math.ceil((((d-new Date(d.getFullYear(),0,1))/8.64e7)+1)/7);
                    };            
                    
                    //
                    buildEntry( entry ) {
                        const WEEKDAY_NAMES = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
                        const MONTH_NAMES = ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
                    
                        let beginDate = new Date( entry.beginDateISO );
                        entry.beginTime = beginDate.getTime();
                        entry.beginWeekDay = beginDate.getDay(); // 0=Sonntag 6=Samstag
                        entry.beginWeekDayName = WEEKDAY_NAMES[entry.beginWeekDay]; 
                        entry.beginDay = beginDate.getDate();
                        entry.beginMonth = beginDate.getMonth();
                        entry.beginMonthName = MONTH_NAMES[entry.beginMonth]; 
                        entry.beginYear = beginDate.getFullYear();
                        entry.beginHour = beginDate.getHours();
                        entry.beginMinute = beginDate.getMinutes();
                        entry.beginDate = formatDate(beginDate,  this.DATE_FORMAT);
                    
                        let currDate = new Date( entry.currDateISO );
                        entry.currTime = currDate.getTime();
                        entry.currWeekDay = currDate.getDay(); // 0=Sonntag 6=Samstag
                        entry.currWeekDayName = WEEKDAY_NAMES[entry.currWeekDay]; 
                        entry.currDay = currDate.getDate();
                        entry.currMonth = currDate.getMonth();
                        entry.currMonthName = MONTH_NAMES[entry.currMonth]; 
                        entry.currYear = currDate.getFullYear();
                        entry.currHour = currDate.getHours();
                        entry.currMinute = currDate.getMinutes();
                        entry.currDate = formatDate(currDate,  this.DATE_FORMAT);
                        entry.currDateOnly = entry.currYear*10000+entry.currMonth*100+entry.currDay;
                    
                    
                        let endDate = new Date( entry.endDateISO );
                        //allDay Korrektur: liefert immer einen Tag zu viel
                        if (entry.allDay && endDate.getHours()==0) endDate.setTime( endDate.getTime() - this.DAY_MILLISECONDS);
                        entry.endTime = endDate.getTime();
                        entry.endWeekDay = endDate.getDay(); // 0=Sonntag 6=Samstag
                        entry.endDay = endDate.getDate();
                        entry.endMonth = endDate.getMonth();
                        entry.endYear = endDate.getFullYear();
                        entry.endHour = endDate.getHours();
                        entry.endMinute = endDate.getMinutes();
                        entry.endDate = formatDate(endDate, this.DATE_FORMAT);
                    
                        // 
                        if (entry.currWeekDay==0 || entry.currWeekDay==6) entry.dayColor = '#f44336'
                        else entry.dayColor = 'inherited';
                    
                        // 
                        if (entry.currWeekDay==1) entry.week = this.getWeekNumber(currDate)+'.W';
                        else entry.week = '';
                    
                        // 
                        if (entry.currTime < Date.now() ) entry.opacity = '.66'
                        else entry.opacity = '1';
                    
                        // Zeitraumangabe berechnen
                        entry.hint = '';
                        if ( !this.isSameDay(beginDate, endDate) ) {
                                // mehrtägig
                                if (entry.allDay)
                                    entry.timeSpan = 'ganztägig ';
                                else if ( this.isSameDay(beginDate, currDate) ) 
                                        entry.timeSpan = 'ab ' + formatDate(beginDate,'hh:mm');
                                     else if ( this.isSameDay(endDate, currDate) ) 
                                              entry.timeSpan = 'bis ' + formatDate(endDate,'hh:mm');
                                          else 
                                               entry.timeSpan = 'ganztägig ';
                            } else {
                                // an einem Tag
                                if (entry.allDay)
                                    entry.timeSpan = 'ganztägig';
                                else if ( (entry.beginHour!=entry.endHour) || (entry.beginMinute!=entry.endMinute)  ) 
                                         entry.timeSpan = formatDate(beginDate,'hh:mm') + '-' + formatDate(endDate,'hh:mm');
                                     else   
                                         entry.timeSpan = formatDate(beginDate,'hh:mm');
                            }
                        return entry;        
                    };
                    
                    
                    onBuildHTML() { try {
                    
                        let json = [];  
                        let calTable = getState(this.ICAL_TABLE);
                        let inst     = getObject("system.adapter."+this.ICAL_TABLE.substr(0,6));
                        let instopt  = inst.native;
                        let calendar = {};
                        let cal      = {};
                        let calOptions = {};
                        let todayDate = new Date();
                        let today = todayDate.getFullYear()*10000+todayDate.getMonth()*100+todayDate.getDate();
                    
                    
                        for (var i = 0; i < calTable.val.length; i++) { 
                          cal = calTable.val[i];
                          let entry = {};
                          if ( cal._calName != calendar.name ) {
                                calendar = {};
                                // color suchen
                                for (let c = 0; c < instopt.calendars.length; c++ ) {
                                    if (cal._calName == instopt.calendars[c].name ) {
                                        calendar = instopt.calendars[c];
                                        break;
                                    }
                                }
                                // options suchen
                                if (this.CALENDAR.hasOwnProperty(cal._calName)) calOptions = this.CALENDAR[cal._calName];
                                else calOptions={};
                            }    
                            if (calOptions.hasOwnProperty('ignore') && calOptions.ignore ) continue;
                    
                            if (calOptions.hasOwnProperty('calcolor')) entry.calColor = calOptions.calcolor;
                            else if (calendar.color !== "") entry.calColor = calendar.color;
                                 else entry.calColor = '#000000';
                            entry.color = this.getFontColor( entry.calColor ); 
                            if (calOptions.hasOwnProperty('icon')) entry.icon = calOptions.icon;
                            else entry.icon='';
                    
                            entry.date = cal.date;
                            entry.event = cal.event;
                            entry.calName = cal._calName;
                            entry.beginDateISO = cal._date;
                            entry.currDateISO = cal._date;
                            entry.endDateISO  = cal._end;
                            entry.allDay  = cal._allDay; 
                            entry.location = cal.location;
                    
                            entry = this.buildEntry( entry);
                    
                            if (entry.currDateOnly >= today)
                                json.push( entry );
                    
                            // Listenansicht
                            // in calTable steht nur ein Eintrag für jeden Beginn, für die List-Darstellung
                            // sind diese auch je Tag notwendig - hier jetzt bilden 
                            if ( (entry.beginDay!=entry.endDay) || (entry.beginMonth!=entry.endMonth) || (entry.beginYear!=entry.endYear) ) {
                                let currTime = new Date(entry.beginDateISO).getTime() + this.DAY_MILLISECONDS;
                                let endTime = new Date(entry.endDateISO).getTime();
                                if (entry.allDay) endTime -= + this.DAY_MILLISECONDS;
                                let dayMax=Math.trunc( 2 + (endTime - currTime) /this. DAY_MILLISECONDS); 
                                entry.hint += ' (Tag 1/'+dayMax+')';
                                let dayCount=2; 
                                while (currTime <= endTime && dayCount<100) {
                                    let newEntry = {};
                                    Object.assign(newEntry, entry);
                                    newEntry.currDateISO = new Date(currTime).toISOString();
                                    newEntry = this.buildEntry( newEntry );
                                    newEntry.hint += ' (Tag '+dayCount+'/'+dayMax+')';
                                    if (newEntry.currDateOnly >= today)
                                        json.push( newEntry );
                                    currTime = currTime + this.DAY_MILLISECONDS;
                                    dayCount++;
                                }
                    
                            }
                        }
                    
                        // sortieren
                        json.sort( (l,r) => {
                                  let lv=l['currTime'],rv=r['currTime'];
                                  return ((lv < rv) ? -1 : (lv > rv) ? 1 : 0);
                              } );
                            
                      // build table/list HTML
                      for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) {
                          let log = this.logs[i];
                          log.filter = '';
                          log.ts = 0;
                          log.idState = 'log'+i;
                          if (this.existState(log.idState+'.filter')) log.filter = this.getState(log.idState+'.filter').val;
                          if (this.existState(log.idState+'.lastClear')) log.ts = this.getState(log.idState+'.lastClear').val;
                    
                          this.convertJSON2HTML(json, log);
                      }
                    } catch(err) { this.logError( 'onBuildHTML: '+err.message ); }  }
                    
                    
                    // color date event calName beginDate endDate allDay
                    convertJSON2HTML(json, log) {
                    const tmpTable = {
                    header : 
                    `<tr>
                    <th style="text-align:right;"></th>
                    <th style="text-align:left;"></th>
                    <th style="text-align:left;"></th>
                    <th style="text-align:left;"></th>
                    <th style="text-align:left;"></th>
                    <th style="text-align:left; min-width:12em;">Betreff</th>
                    <th style="text-align:left;">Zeit</th>
                    <th style="text-align:left;">Ort</th>
                    <th style="text-align:left;">Kalendar</th>
                    <th style="text-align:left;"></th>
                    </tr>`,
                    row : 
                    `<tr>
                    <td style="text-align:right;">
                       <span style="display:{showDay}; color:{dayColor}; font-size:1.5em; opacity:1; font-weight:bold;">{currDay}</span>
                    </td>
                    <td>
                       <span style="display:{showDay}; font-size:0.8em; margin-top:0.3em; margin-left:4px; opacity:.8;">{currMonthName}</span>
                    </td>
                    <td>
                       <span style="display:{showDay}; font-size:0.8em; margin-top:0.3em; opacity:.8;">{currWeekDayName}</span>
                    </td>
                    <td>
                      <span style="display:inline-block; width:.8em; height:.8em; margin-top:0.3em; background:{calColor}; border-radius:50%;">&nbsp;</span>
                    </td>
                    <td>
                      <i class='material-icons mdui-center {color}' style='font-size:1.2em;'>{icon}</i>
                    </td>
                    <td>{event}</td>
                    <td><span style="font-size:1.0em; opacity:.8;">{timeSpan} {hint}</span></td>
                    <td>{location}</td>
                    <td><span style="font-size:0.8em; opacity:.8;color:{calColor};">{calName}</span></td>
                    <td></td>
                    </tr>`
                    }
                    
                    const tmpList = {
                    row : 
                    `<div class="mdui-listitem" style="font-size:1em; width:100%; display:flex; opacity:{opacity};">
                      <div style="min-width:3.5em;">
                        <div style="display:{showDay}; color:{dayColor};">
                          <span style="font-size:1.5em; opacity:1; font-weight:bold;">{currDay}</span>
                          <span style="font-size:0.8em; margin:4px; opacity:.8;">{currMonthName}<br/>
                          {currWeekDayName}</span>
                        </div>
                        <div style="display:{showDay}; text-align:right; font-size:0.6em; opacity:.6;">{week}</div>
                      </div>
                      <div style="min-width:1.2em;">
                        <div style="width:.8em; height:.8em;  margin:.1em; text-align:center; background:{calColor}; border-radius:50%;">&nbsp;</div>
                        <div class="mdui-icon" style="font-size:1.1em; text-align:center; margin-top:0.33em;">{icon}</div>
                      </div>
                      <div style="width:100%; margin-left:.25em;">
                        <div style="">
                          <div style="font-size:1.1em;">{event}</div>
                        </div>
                        <div style="width:100%; display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between;">
                          <div style="font-size:1.0em; opacity:.8;">
                            {timeSpan}
                            <span style="font-size:0.8em;">{hint} {location}</span>
                          </div>
                          <div style="font-size:0.8em; opacity:.8;color:{calColor};">{calName}</div>
                        </div>
                      </div>
                    </div>`}
                        // build htmlTable and htmlList
                        let htmlTable  = "<table><thead>"+tmpTable.header+"</thead><tbody>";
                        for (let [key, value] of Object.entries(log)) htmlTable = htmlTable.replace(new RegExp('{'+key+'}','g'),value);
                       
                        let htmlList  = "";
                        let entry, tr;
                        let count = 0;
                        // filter as regex?
                        if ( log.filter!==undefined && typeof log.filter == 'string' && log.filter.startsWith('/') && log.filter.endsWith('/') && (log.filter.length>=2) )  {
                            log.filter = new RegExp(log.filter.substr(1,log.filter.length-2), 'i');
                        }
                    
                        let lastEntry = {};
                        for (var i = 0; i < json.length && count<this.MAX_TABLE_ROWS; i++) { 
                            entry = json[i];
                            if (this.fitsFilter(':' + entry.currDate + ':' + entry.event +':'+entry.calName + ':' + entry.location + ':',log.filter)) {
                                entry.showDay = (lastEntry=={}) || (entry.currDay!=lastEntry.currDay) || (entry.currMonth!=lastEntry.currMonth) || (entry.currYear!=lastEntry.currYear)?'flex':'none';
                                lastEntry = entry;
                                tr = tmpTable.row;    
                                for (let [key, value] of Object.entries(entry)) tr = tr.replace(new RegExp('{'+key+'}','g'),value);
                                htmlTable+=tr;
                                tr = tmpList.row;    
                                for (let [key, value] of Object.entries(entry)) tr = tr.replace(new RegExp('{'+key+'}','g'),value);
                                htmlList+=tr;
                                count++;
                            }
                        }
                        htmlTable+="</body></table>";    
                        this.setState(log.idState+'.table', htmlTable);  
                        this.setState(log.idState+'.list', htmlList);  
                        this.setState(log.idState+'.count', count);  
                        this.setState(log.idState+'.lastUpdate', +new Date());  
                    }
                    
                    }
                    
                    
                    // create instance and start
                    var mduiShowIcal = new MduiShowIcal( );
                    mduiShowIcal.start();
                    
                    // on script stop, stop instance too
                    onStop(function () { 
                        mduiShowIcal.stop(); 
                    }, 1000 );
                

                Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                Immer Daten sichern!

                E 1 Antwort Letzte Antwort
                0
                • sigi234S sigi234

                  @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                  @sigi234

                  Hallo siggi234,

                  danke für den Install-Screenshot. ;-)

                  Screenshot (674)_LI.jpg

                  /*
                  *** MduiShowIcal
                  Dieses Script überwacht den ical-Adapter und erzeugt bei Änderungen an dessen States HTML-List States für die Anzeige als 
                  Kalender in Listform mit
                  * Tagesauflösung von "von/bis"-Terminen, inkl. Berücksichtigung der Uhrzeiten
                  * Tagesdatum, Kalendarfarben aus ical oder optional aus dem Script
                  * Termintext und -ort
                  * optionalem Icon je Kalendar
                  * optionalem "ignore", wenn ein Kalendar unberücksichtigt bleiben soll
                  
                  Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner 
                  befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget). 
                  Über optionale Filter als string (Bsp:':Abfall:') oder als RegExp (Bsp:'/Feiertag|Geburtstag/') kann festgelegt werden, 
                  welche Einträge beim Aufbau der list-HTML States berücksichtigt werden. 
                  Bsp.: 
                  log0 Filter: "abfall" oder ":Abfall:" (=Kalendarname) -> Zeigt nur Abfalltermine
                  log0 Filter: "ferien" oder ":Ferien:" (=Kalendarname) -> Zeigt nur Ferientermine
                  
                  
                  **** Installation
                  Einfach als serverseitiges Script installieren und starten-5 Sek warten-stoppen-starten. Beim 1.Start werden 
                  die notwendigen States unter STATE_PATH = '0_userdata.0.mdui.showIcal.' erzeugt. Erst beim 2.Start
                  instanziiert das Script die Event-Handler und läuft dann.
                  
                  **** Konfiguration
                  Eigentlich ist keine notwendig.
                  Optional in der Funktion MduiShowIcal|doInit() eine Anpassung der KONFIGURATION vornehmen
                  Optional Anpassung der tmpList.
                    
                  **** Dokumentation
                  https://github.com/Uhula/ioBroker-Material-Design-Style/wiki/3.5-MduiShowIcal
                  
                  ###### Um ein Feedback zu erhalten wäre es schön, wenn jeder, der diese Vorlagen nutzt, den  1.Beitrag des Themas positiv bewertet (Pfeil nach oben oder unten ;-) ). Ich kann dann auch abschätzen, ob sich die weitere Pflege lohnt. Thx!
                  
                  ***** States
                  Unter dem STATE_PATH werden die folgenden States erzeugt:
                  version : Script-Version, wird verwendet um Script-Updates zu erkennen
                  updatePressed : auf true setzen, wenn ein table/list update außerhalb des Intervals erfolgen soll
                  
                  Weiterhin werden MAX_LOG_FOLDER Unterordner im STATE_PATH erzeugt (N=0-9):
                  
                  * LogN.table        : enthält die table-HTML für ein basic-string (unescaped) Widget
                  * LogN.list         : enthält die list-HTML für ein basic-string (unescaped) Widget
                  * LogN.count        : Anzahl der Log-Zeilen (wenn das Log mit '/:error:|:warn:/' gefiltert ist, dann ist es die Anzahl der Fehler/Warnungen)
                  * LogN.filter       : Filter, der auch die logCache angewendet wurde im .table/.list zu erzeugen (siehe Filter)
                  * LogN.lastUpdate   : Timestamp des letzten Updates
                  
                  
                  ***** Filter
                  In den filter-States können sowohl strings (Bsp:'error') als auch RegExp-Strings (Bsp:'/warn|error/') 
                  hinterlegt werden. RegExp-Strings werden an den einschließenden  '/' erkannt. Über den ':' kann der Anfang
                  eines Feldes mit in den Filter einbezogen werden. 
                  Beispiele: 
                  '/Feiertag|Geburtstag/' (RegExp) zeigt alle Zeilen an, in denen 'Feiertag' oder 'Geburtstag' in irgendeinem Feld vorkommen
                  ':Abfall:' (string) zeigt alle Zeilen an, welche derKalendar 'Abfall' lautet
                  'Arzt' (string) zeigt alle Zeilen an, in denen 'Arzt' in irgendeinem Feld vorkommt
                  
                  **** Lizenz
                  (c) 2020 by UH, MIT License, no warranty, use on your own risc
                  
                  *** Changelog
                  2020.05.01 UH 
                  * Anpassung an neues MduiBase (intern)
                  * Anpassung an MDCSS 2.5
                  * Serientermine vor dem aktuellem Datum werden nicht mehr angezeigt
                  
                  */
                  
                  // ------------------------------------------------------------------------------------- 
                  // MduiBase
                  // ------------------------------------------------------------------------------------- 
                  
                  class MduiBase {
                  
                      constructor() {
                        this.init();
                      }
                      
                      //
                      init() {
                          // const
                          this.DEBUG      = false;
                          this.VERSION    = '1.0/2020-01-01';
                          this.NAME       = 'mduiBase';
                          this.STATE_PATH = '0_userdata.0.mdui.base.';
                          this.STATE_UNKNOWN    =  0;
                          this.STATE_INSTALLING = 10;
                          this.STATE_INSTALLED  = 11;
                          this.STATE_STARTING   = 20;
                          this.STATE_STARTED    = 21;
                          this.STATE_STOPPING   = 30;
                          this.STATE_STOPPED    = 31;
                      
                          // var
                          this.state = this.STATE_UNKNOWN;
                          this.states = [];
                          this.subscribers = [];
                          this.schedulers = [];
                      
                          this.doInit();
                      
                          // init der states
                          this.states.push( { id:'version',     common:{name:'installed script-version', write:false, def:this.VERSION} } );
                      }
                      
                      //
                      // start the script/class
                      //
                      start() {
                          // beim 1.Start nur die States erzeugen
                          if ( !this.existState("version") || (this.getState('version').val!=this.VERSION) ) {
                              for (let s=0; s<this.states.length; s++) { this.createState( this.states[s].id ); }
                              this.logWarn('first script start, creating states for version '+this.VERSION+', automatic restarting script again in 10 sec ...');
                              setStateDelayed(this.STATE_PATH + 'version', this.VERSION, 3000);
                              setTimeout( this.start.bind(this), 10000 );
                              this.state = this.STATE_INSTALLED; 
                              return;
                          }
                          switch (this.state) {
                              case this.STATE_UNKNOWN : ;
                              case this.STATE_INSTALLING : ;
                              case this.STATE_INSTALLED : ;
                              case this.STATE_STOPPED : {
                                  this.state = this.STATE_STARTING; 
                                  if (this.doStart()) {
                                      this.log('script started');
                                      this.state = this.STATE_STARTED;
                                  }
                                  break;    
                              }
                              case this.STATE_STARTING : ;
                              case this.STATE_STARTED : {
                                  this.logWarn('script already starting/started');
                                  break;    
                              }
                              case this.STATE_STOPPING : {
                                  this.logWarn('script is stopping, pls start later again');
                                  break;    
                              }
                        
                          } 
                      }
                      
                      //
                      // stop the script/class
                      //
                      stop() {
                          switch (this.state) {
                              case this.STATE_STARTED : {
                                  this.state = this.STATE_STOPPING; 
                                  if (this.doStop()) {
                                      for (let i=0; i<this.subscribers.length; i++) if (this.subscribers[i] !== undefined) unsubscribe( this.subscribers[i] );
                                      this.subscribers = [];
                                      for (let i=0; i<this.schedulers.length; i++) if (this.schedulers[i] !== undefined) clearSchedule( this.schedulers[i] );
                                      this.schedulers = [];
                                      this.state = this.STATE_STOPPED; 
                                      this.log('script stopped');
                                  }
                                  break;    
                              }
                              default : {
                                  this.log('cant stopp script, because not startet');
                              }
                          } 
                      }
                      
                      //
                      // virtual functions, overwrite it 
                      //
                      doInit() { return true; }
                      doStart() { return true; }
                      doStop() { return true; }
                      
                      // einen on-Handler registrieren
                      subscribe( handler ) {
                          this.subscribers.push( handler );
                      }
                      
                      // einen timer registrieren
                      schedule( handler ) {
                          this.schedulers.push( handler );
                      }
                      
                      //
                      // tool functions 
                      //
                      logDebug(msg) { if (this.DEBUG) console.log('['+this.NAME+'] '+msg); }
                      log(msg) { console.log('['+this.NAME+'] '+msg); }
                      logWarn(msg) { console.warn('['+this.NAME+'] '+msg); }
                      logError(msg) { console.error('['+this.NAME+'] '+msg); }
                      
                      // über den $-Operator nachsehen, ob der state bereits vorhanden ist
                      // getState().notExists geht auch, erzeugt aber Warnmeldungen!
                      existState(id) {
                          return ( $(this.STATE_PATH+id).length==0?false:true);
                      }
                      
                      // wrapper, adds statepath to state-ID
                      getState(id) {
                          return getState(this.STATE_PATH + id);
                      }
                      
                      // like setState(), but adds statepath to state_ID and checks if state exists, when not, creates it
                      setState(id,value) {
                          if ( !this.existState(id) ) this.createState(id,value,undefined);
                          else setState( this.STATE_PATH + id, value);
                      }
                      
                      // like cresteState(), but adds statepath to state_ID and checks if state exists, when not, creates it
                      createState(id,value,common) {
                          if ( !this.existState(id) ) {
                              if (common===undefined) {
                                  // id im states-Array suchen
                                  for (var i=0; i<this.states.length; i++) { 
                                      if (this.states[i].id==id) {
                                          if (this.states[i].hasOwnProperty('common'))
                                              common = this.states[i].common;
                                         break;
                                      }   
                                  }
                              }
                              if ( (typeof value === 'undefined') && (common.hasOwnProperty('def'))) value = common.def;
                              // unter "0_userdata.0"
                              let obj = {};
                              obj.type = 'state';
                              obj.native = {};
                              obj.common = common;
                              setObject(this.STATE_PATH + id, obj, (err) => {
                                      if (err) {
                                          this.log('cant write object for state "' + this.STATE_PATH + id + '": ' + err);
                                      } else { 
                                          this.log('state "' + this.STATE_PATH + id + '" created');
                                      }
                              });
                      
                              setTimeout( setState, 3000, this.STATE_PATH + id, value );
                          }
                      }
                      
                      // true, if str contains filter string or regexp 
                      fitsFilter(str, filter) {
                          if ( (filter===undefined) || !filter || (filter=='') )
                              return true;
                          if ( filter instanceof RegExp )  {
                              if (str.match( filter ) != null) return true;
                          } else if (typeof filter == 'string') {
                              if(str.includes(filter)) return true;
                          }
                          return false;        
                      }
                      
                      //
                      escapeRegExp(str) {
                          return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 
                      }
                      
                      // wandelt eine Farbe im hex-Format (#000000) in ein RGB-Array[2] um
                      hexToRGB(hex) {
                          var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
                          return result 
                              ? [parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16)]
                              : [0,0,0];
                      };
                      
                      // Helligkeit berechnen
                      getLuminance(r, g, b) {
                          var a = [r, g, b].map(function (v) {
                              v /= 255;
                              return v <= 0.03928
                                  ? v / 12.92
                                  : Math.pow( (v + 0.055) / 1.055, 2.4 );
                          });
                          return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
                      }
                      
                      // Kontrats berechnen
                      getContrast(rgb1, rgb2) {
                          var l1 = this.getLuminance(rgb1[0], rgb1[1], rgb1[2]) + 0.05;
                          var l2 = this.getLuminance(rgb2[0], rgb2[1], rgb2[2]) + 0.05;
                          if ( l1 > l2 ) return l1 / l2 
                          else return l2 / l1;
                      }
                      
                      // liefert die fontColor auf Basis der backgroundColor durch Berechnung
                      // des Kontrasts
                      getFontColor(backgroundColor) {
                          if ( this.getContrast(this.hexToRGB(backgroundColor),this.hexToRGB("#000000")) < 6 ) 
                              return "#ffffff";
                          else
                              return "#000000";
                      }
                      
                      }
                      
                      // ------------------------------------------------------------------------------------- 
                      // MduiLogHMDevices
                      // ------------------------------------------------------------------------------------- 
                      
                      class MduiShowIcal extends MduiBase {
                      
                      constructor() {
                          super();
                      }
                      
                      doInit() {
                        super.doInit();
                      
                        // const
                        this.DEBUG = false;
                        this.VERSION = '1.0/2020-03-22';
                        this.NAME = 'mduiShowIcal';
                        this.DAY_MILLISECONDS = 60 * 60 * 24 * 1000;
                      
                        // -----------------------  
                        // optional: KONFIGURATION
                        // -----------------------  
                                             // state-Pfad unter dem die States angelegt werden  
                        this.STATE_PATH      = '0_userdata.0.mdui.showIcal.'; 
                                             // Anzahl der Table/List Ordner mit eigenem Filter/View
                        this.MAX_LOG_FOLDER  = 3;   
                                             // max.Anzahl der Zeilen für die Table/List Ausgabe
                        this.MAX_TABLE_ROWS  = 200; 
                                             // Objekt-Pfad zum ical.x.data.table
                        this.ICAL_TABLE      = 'ical.0.data.table';
                                             // siehe: https://github.com/ioBroker/ioBroker.javascript/blob/master/docs/en/javascript.md#formatdate
                        this.DATE_FORMAT     = 'W DD.MM.YYYY hh:mm';
                                             // optional können dem Kalendar noch Icons und abweichende
                                             // Farben angegeben werden (diese überschreiben jene aus iCal)
                                             // 'icon'     : 'Icon-Name' (MDCSS/Google WebFont)
                                             // 'calColor' : *#rrggbb' abweichende Kalendarfarbe 
                                             // 'ignore'   : true|false Kalendar komplett ignorieren
                        this.CALENDAR        = {'mdui-Abfall'      : {'icon':'delete_outline', 'calcolor':'orange' },
                                                'mdui-Geburtstage' : {'icon':'cake'},
                                                'Familie'          : {'ignore':true}
                                                 
                                               };
                      
                        // -----------------------  
                        // ENDE KONFIGURATION
                        // -----------------------  
                      
                        // var
                        this.logs = [];
                        for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) 
                            this.logs.push({filter:'' });
                        
                      
                        // init der states
                        this.states.push( { id:'version',     common:{name:'installed script-version', write:false, def:this.VERSION} } );
                        this.states.push( { id:'updatePressed',common:{name:'update button pressed', write:true, type:'boolean', def:'false', role:'button' }} );
                        
                        let defFilter;
                        for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) {
                            switch (i) {
                                case 1 : defFilter = ':Abfall:'; break;   
                                case 2 : defFilter = 'Geburtstag'; break;   
                                case 3 : defFilter = ''; break;   
                                default: defFilter = undefined;
                            }
                            this.states.push( { id:'log'+i+'.table',      common:{name:'ioBroker-log as table', write:false, role:'html' }} );
                            this.states.push( { id:'log'+i+'.list',       common:{name:'ioBroker-log as list', write:false, role:'html' }} );
                            this.states.push( { id:'log'+i+'.count',      common:{name:'ioBroker-log count', write:false, type:'number', def:'0' }} );
                            this.states.push( { id:'log'+i+'.filter',     common:{name:'ioBroker-log filter', write:true, def:defFilter}} );
                            this.states.push( { id:'log'+i+'.lastUpdate', common:{name:'ioBroker-log last update', write:false, def:'0' }} );
                        }
                      
                        return true;  
                      }
                      
                      // start the script/class
                      doStart() {
                          super.doStart();
                          
                          // subscriber erzeugen
                          this.subscribe( on( this.STATE_PATH+'updatePressed', obj => { this.onUpdate(obj) } ));
                          this.subscribe( on( new RegExp( this.STATE_PATH+'*.filter' ), obj => { this.onFilter(obj) } ));
                          this.subscribe( on( this.ICAL_TABLE, obj => { this.onIcalTable(obj) } ));
                      
                          this.onBuildHTML();
                          return true;
                      }
                      
                      // stop the script/class
                      doStop() {
                          super.doStop();
                          return true;
                      }
                      
                      // 
                      onUpdate(obj) {
                          if (obj.state.val===true) {
                              this.onBuildHTML();
                          }
                          this.setState('updatePressed', false);
                      }
                      
                      // filter, sort events
                      onFilter(obj) {
                        this.onBuildHTML();
                      }
                      
                      // Ical table hat sich geändert
                      onIcalTable(obj) {
                        this.onBuildHTML();
                      }
                      
                      
                      
                      // creates the HTML states for every log
                      /*
                      'date' => "→ 16.10.2017" 
                      'event' => "9.30 - 16.30 Uhr Stopka " 
                      '_class' => "ical_Kerstin ical_today" 
                      '_date' => "2017-10-16T07:30:00.000Z" 
                      '_end' => "2017-10-16T14:30:00.000Z" 
                      '_section' => "" 
                      '_IDID' => "040000008200E00074C5B7101A82E008000000007645DC55A6DFC44FB2EC6FEA9EFEA33C100000007688316058136F42AD128D91103543C9" 
                      '_allDay' => "false" 
                      '_rule' => " " 
                      '_calName' => "Kerstin" 
                      
                      Optionen der ical-Instanz:
                          'daysPreview' => "7"
                          'colorize' => "false"
                          'defColor' => "white"
                          'fulltime' => " 00:00"
                          'dataPaddingWithZeros' => "true"
                          'replaceDates' => "false"
                          'language' => "de"
                          'everyCalOneColor' => "true"
                          'calendars' (array) 
                              '0' (array) 
                                  'name' => "Abfall"
                                  'url' => "https://calendar.google.com/calendar/ical/ruo0ddgalu03qq2ehpm8imqnk4%40group.calendar.google.com/private-a30aac0367f8b50cfd7373f6222d29b4/basic.ics"
                                  'user' => ""
                                  'pass' => ""
                                  'sslignore' => ""
                                  'color' => ""
                      */
                      
                      isSameDay(d1,d2) {
                          return (d1.getDate()==d2.getDate()) && (d1.getMonth()==d2.getMonth()) && (d1.getFullYear()==d2.getFullYear());
                      }
                      
                      getWeekNumber( date ) {
                          let d = new Date(date);
                          d.setHours(0,0,0);
                          d.setDate(d.getDate()+4-(d.getDay()||7));
                          return Math.ceil((((d-new Date(d.getFullYear(),0,1))/8.64e7)+1)/7);
                      };            
                      
                      //
                      buildEntry( entry ) {
                          const WEEKDAY_NAMES = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
                          const MONTH_NAMES = ["Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
                      
                          let beginDate = new Date( entry.beginDateISO );
                          entry.beginTime = beginDate.getTime();
                          entry.beginWeekDay = beginDate.getDay(); // 0=Sonntag 6=Samstag
                          entry.beginWeekDayName = WEEKDAY_NAMES[entry.beginWeekDay]; 
                          entry.beginDay = beginDate.getDate();
                          entry.beginMonth = beginDate.getMonth();
                          entry.beginMonthName = MONTH_NAMES[entry.beginMonth]; 
                          entry.beginYear = beginDate.getFullYear();
                          entry.beginHour = beginDate.getHours();
                          entry.beginMinute = beginDate.getMinutes();
                          entry.beginDate = formatDate(beginDate,  this.DATE_FORMAT);
                      
                          let currDate = new Date( entry.currDateISO );
                          entry.currTime = currDate.getTime();
                          entry.currWeekDay = currDate.getDay(); // 0=Sonntag 6=Samstag
                          entry.currWeekDayName = WEEKDAY_NAMES[entry.currWeekDay]; 
                          entry.currDay = currDate.getDate();
                          entry.currMonth = currDate.getMonth();
                          entry.currMonthName = MONTH_NAMES[entry.currMonth]; 
                          entry.currYear = currDate.getFullYear();
                          entry.currHour = currDate.getHours();
                          entry.currMinute = currDate.getMinutes();
                          entry.currDate = formatDate(currDate,  this.DATE_FORMAT);
                          entry.currDateOnly = entry.currYear*10000+entry.currMonth*100+entry.currDay;
                      
                      
                          let endDate = new Date( entry.endDateISO );
                          //allDay Korrektur: liefert immer einen Tag zu viel
                          if (entry.allDay && endDate.getHours()==0) endDate.setTime( endDate.getTime() - this.DAY_MILLISECONDS);
                          entry.endTime = endDate.getTime();
                          entry.endWeekDay = endDate.getDay(); // 0=Sonntag 6=Samstag
                          entry.endDay = endDate.getDate();
                          entry.endMonth = endDate.getMonth();
                          entry.endYear = endDate.getFullYear();
                          entry.endHour = endDate.getHours();
                          entry.endMinute = endDate.getMinutes();
                          entry.endDate = formatDate(endDate, this.DATE_FORMAT);
                      
                          // 
                          if (entry.currWeekDay==0 || entry.currWeekDay==6) entry.dayColor = '#f44336'
                          else entry.dayColor = 'inherited';
                      
                          // 
                          if (entry.currWeekDay==1) entry.week = this.getWeekNumber(currDate)+'.W';
                          else entry.week = '';
                      
                          // 
                          if (entry.currTime < Date.now() ) entry.opacity = '.66'
                          else entry.opacity = '1';
                      
                          // Zeitraumangabe berechnen
                          entry.hint = '';
                          if ( !this.isSameDay(beginDate, endDate) ) {
                                  // mehrtägig
                                  if (entry.allDay)
                                      entry.timeSpan = 'ganztägig ';
                                  else if ( this.isSameDay(beginDate, currDate) ) 
                                          entry.timeSpan = 'ab ' + formatDate(beginDate,'hh:mm');
                                       else if ( this.isSameDay(endDate, currDate) ) 
                                                entry.timeSpan = 'bis ' + formatDate(endDate,'hh:mm');
                                            else 
                                                 entry.timeSpan = 'ganztägig ';
                              } else {
                                  // an einem Tag
                                  if (entry.allDay)
                                      entry.timeSpan = 'ganztägig';
                                  else if ( (entry.beginHour!=entry.endHour) || (entry.beginMinute!=entry.endMinute)  ) 
                                           entry.timeSpan = formatDate(beginDate,'hh:mm') + '-' + formatDate(endDate,'hh:mm');
                                       else   
                                           entry.timeSpan = formatDate(beginDate,'hh:mm');
                              }
                          return entry;        
                      };
                      
                      
                      onBuildHTML() { try {
                      
                          let json = [];  
                          let calTable = getState(this.ICAL_TABLE);
                          let inst     = getObject("system.adapter."+this.ICAL_TABLE.substr(0,6));
                          let instopt  = inst.native;
                          let calendar = {};
                          let cal      = {};
                          let calOptions = {};
                          let todayDate = new Date();
                          let today = todayDate.getFullYear()*10000+todayDate.getMonth()*100+todayDate.getDate();
                      
                      
                          for (var i = 0; i < calTable.val.length; i++) { 
                            cal = calTable.val[i];
                            let entry = {};
                            if ( cal._calName != calendar.name ) {
                                  calendar = {};
                                  // color suchen
                                  for (let c = 0; c < instopt.calendars.length; c++ ) {
                                      if (cal._calName == instopt.calendars[c].name ) {
                                          calendar = instopt.calendars[c];
                                          break;
                                      }
                                  }
                                  // options suchen
                                  if (this.CALENDAR.hasOwnProperty(cal._calName)) calOptions = this.CALENDAR[cal._calName];
                                  else calOptions={};
                              }    
                              if (calOptions.hasOwnProperty('ignore') && calOptions.ignore ) continue;
                      
                              if (calOptions.hasOwnProperty('calcolor')) entry.calColor = calOptions.calcolor;
                              else if (calendar.color !== "") entry.calColor = calendar.color;
                                   else entry.calColor = '#000000';
                              entry.color = this.getFontColor( entry.calColor ); 
                              if (calOptions.hasOwnProperty('icon')) entry.icon = calOptions.icon;
                              else entry.icon='';
                      
                              entry.date = cal.date;
                              entry.event = cal.event;
                              entry.calName = cal._calName;
                              entry.beginDateISO = cal._date;
                              entry.currDateISO = cal._date;
                              entry.endDateISO  = cal._end;
                              entry.allDay  = cal._allDay; 
                              entry.location = cal.location;
                      
                              entry = this.buildEntry( entry);
                      
                              if (entry.currDateOnly >= today)
                                  json.push( entry );
                      
                              // Listenansicht
                              // in calTable steht nur ein Eintrag für jeden Beginn, für die List-Darstellung
                              // sind diese auch je Tag notwendig - hier jetzt bilden 
                              if ( (entry.beginDay!=entry.endDay) || (entry.beginMonth!=entry.endMonth) || (entry.beginYear!=entry.endYear) ) {
                                  let currTime = new Date(entry.beginDateISO).getTime() + this.DAY_MILLISECONDS;
                                  let endTime = new Date(entry.endDateISO).getTime();
                                  if (entry.allDay) endTime -= + this.DAY_MILLISECONDS;
                                  let dayMax=Math.trunc( 2 + (endTime - currTime) /this. DAY_MILLISECONDS); 
                                  entry.hint += ' (Tag 1/'+dayMax+')';
                                  let dayCount=2; 
                                  while (currTime <= endTime && dayCount<100) {
                                      let newEntry = {};
                                      Object.assign(newEntry, entry);
                                      newEntry.currDateISO = new Date(currTime).toISOString();
                                      newEntry = this.buildEntry( newEntry );
                                      newEntry.hint += ' (Tag '+dayCount+'/'+dayMax+')';
                                      if (newEntry.currDateOnly >= today)
                                          json.push( newEntry );
                                      currTime = currTime + this.DAY_MILLISECONDS;
                                      dayCount++;
                                  }
                      
                              }
                          }
                      
                          // sortieren
                          json.sort( (l,r) => {
                                    let lv=l['currTime'],rv=r['currTime'];
                                    return ((lv < rv) ? -1 : (lv > rv) ? 1 : 0);
                                } );
                              
                        // build table/list HTML
                        for (let i=0; i<=this.MAX_LOG_FOLDER && i<10; i++) {
                            let log = this.logs[i];
                            log.filter = '';
                            log.ts = 0;
                            log.idState = 'log'+i;
                            if (this.existState(log.idState+'.filter')) log.filter = this.getState(log.idState+'.filter').val;
                            if (this.existState(log.idState+'.lastClear')) log.ts = this.getState(log.idState+'.lastClear').val;
                      
                            this.convertJSON2HTML(json, log);
                        }
                      } catch(err) { this.logError( 'onBuildHTML: '+err.message ); }  }
                      
                      
                      // color date event calName beginDate endDate allDay
                      convertJSON2HTML(json, log) {
                      const tmpTable = {
                      header : 
                      `<tr>
                      <th style="text-align:right;"></th>
                      <th style="text-align:left;"></th>
                      <th style="text-align:left;"></th>
                      <th style="text-align:left;"></th>
                      <th style="text-align:left;"></th>
                      <th style="text-align:left; min-width:12em;">Betreff</th>
                      <th style="text-align:left;">Zeit</th>
                      <th style="text-align:left;">Ort</th>
                      <th style="text-align:left;">Kalendar</th>
                      <th style="text-align:left;"></th>
                      </tr>`,
                      row : 
                      `<tr>
                      <td style="text-align:right;">
                         <span style="display:{showDay}; color:{dayColor}; font-size:1.5em; opacity:1; font-weight:bold;">{currDay}</span>
                      </td>
                      <td>
                         <span style="display:{showDay}; font-size:0.8em; margin-top:0.3em; margin-left:4px; opacity:.8;">{currMonthName}</span>
                      </td>
                      <td>
                         <span style="display:{showDay}; font-size:0.8em; margin-top:0.3em; opacity:.8;">{currWeekDayName}</span>
                      </td>
                      <td>
                        <span style="display:inline-block; width:.8em; height:.8em; margin-top:0.3em; background:{calColor}; border-radius:50%;">&nbsp;</span>
                      </td>
                      <td>
                        <i class='material-icons mdui-center {color}' style='font-size:1.2em;'>{icon}</i>
                      </td>
                      <td>{event}</td>
                      <td><span style="font-size:1.0em; opacity:.8;">{timeSpan} {hint}</span></td>
                      <td>{location}</td>
                      <td><span style="font-size:0.8em; opacity:.8;color:{calColor};">{calName}</span></td>
                      <td></td>
                      </tr>`
                      }
                      
                      const tmpList = {
                      row : 
                      `<div class="mdui-listitem" style="font-size:1em; width:100%; display:flex; opacity:{opacity};">
                        <div style="min-width:3.5em;">
                          <div style="display:{showDay}; color:{dayColor};">
                            <span style="font-size:1.5em; opacity:1; font-weight:bold;">{currDay}</span>
                            <span style="font-size:0.8em; margin:4px; opacity:.8;">{currMonthName}<br/>
                            {currWeekDayName}</span>
                          </div>
                          <div style="display:{showDay}; text-align:right; font-size:0.6em; opacity:.6;">{week}</div>
                        </div>
                        <div style="min-width:1.2em;">
                          <div style="width:.8em; height:.8em;  margin:.1em; text-align:center; background:{calColor}; border-radius:50%;">&nbsp;</div>
                          <div class="mdui-icon" style="font-size:1.1em; text-align:center; margin-top:0.33em;">{icon}</div>
                        </div>
                        <div style="width:100%; margin-left:.25em;">
                          <div style="">
                            <div style="font-size:1.1em;">{event}</div>
                          </div>
                          <div style="width:100%; display:flex; flex-wrap:wrap; align-items:baseline; justify-content:space-between;">
                            <div style="font-size:1.0em; opacity:.8;">
                              {timeSpan}
                              <span style="font-size:0.8em;">{hint} {location}</span>
                            </div>
                            <div style="font-size:0.8em; opacity:.8;color:{calColor};">{calName}</div>
                          </div>
                        </div>
                      </div>`}
                          // build htmlTable and htmlList
                          let htmlTable  = "<table><thead>"+tmpTable.header+"</thead><tbody>";
                          for (let [key, value] of Object.entries(log)) htmlTable = htmlTable.replace(new RegExp('{'+key+'}','g'),value);
                         
                          let htmlList  = "";
                          let entry, tr;
                          let count = 0;
                          // filter as regex?
                          if ( log.filter!==undefined && typeof log.filter == 'string' && log.filter.startsWith('/') && log.filter.endsWith('/') && (log.filter.length>=2) )  {
                              log.filter = new RegExp(log.filter.substr(1,log.filter.length-2), 'i');
                          }
                      
                          let lastEntry = {};
                          for (var i = 0; i < json.length && count<this.MAX_TABLE_ROWS; i++) { 
                              entry = json[i];
                              if (this.fitsFilter(':' + entry.currDate + ':' + entry.event +':'+entry.calName + ':' + entry.location + ':',log.filter)) {
                                  entry.showDay = (lastEntry=={}) || (entry.currDay!=lastEntry.currDay) || (entry.currMonth!=lastEntry.currMonth) || (entry.currYear!=lastEntry.currYear)?'flex':'none';
                                  lastEntry = entry;
                                  tr = tmpTable.row;    
                                  for (let [key, value] of Object.entries(entry)) tr = tr.replace(new RegExp('{'+key+'}','g'),value);
                                  htmlTable+=tr;
                                  tr = tmpList.row;    
                                  for (let [key, value] of Object.entries(entry)) tr = tr.replace(new RegExp('{'+key+'}','g'),value);
                                  htmlList+=tr;
                                  count++;
                              }
                          }
                          htmlTable+="</body></table>";    
                          this.setState(log.idState+'.table', htmlTable);  
                          this.setState(log.idState+'.list', htmlList);  
                          this.setState(log.idState+'.count', count);  
                          this.setState(log.idState+'.lastUpdate', +new Date());  
                      }
                      
                      }
                      
                      
                      // create instance and start
                      var mduiShowIcal = new MduiShowIcal( );
                      mduiShowIcal.start();
                      
                      // on script stop, stop instance too
                      onStop(function () { 
                          mduiShowIcal.stop(); 
                      }, 1000 );
                  
                  E Offline
                  E Offline
                  Ente
                  schrieb am zuletzt editiert von Ente
                  #44

                  @sigi234

                  Skript läuft. Vielen Dank.

                  Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

                  sigi234S 1 Antwort Letzte Antwort
                  0
                  • E Ente

                    @sigi234

                    Skript läuft. Vielen Dank.

                    Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

                    sigi234S Online
                    sigi234S Online
                    sigi234
                    Forum Testing Most Active
                    schrieb am zuletzt editiert von
                    #45

                    @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                    @sigi234

                    Skript läuft. Vielen Dank.

                    Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

                    Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner
                    befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget).

                    Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                    Immer Daten sichern!

                    E 1 Antwort Letzte Antwort
                    0
                    • sigi234S sigi234

                      @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                      @sigi234

                      Skript läuft. Vielen Dank.

                      Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

                      Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner
                      befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget).

                      E Offline
                      E Offline
                      Ente
                      schrieb am zuletzt editiert von Ente
                      #46

                      @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                      @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                      @sigi234

                      Skript läuft. Vielen Dank.

                      Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

                      Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner
                      befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget).

                      Genau das habe ich gerade gefunden. Es zeigt auch die Termine an,

                      feb6d00b-f448-415c-a618-733025c42ac5-image.png

                      leider nicht so wie in dem Bild im 1. Post. bzw. wie hier:

                      https://forum.iobroker.net/topic/31635/vorlage-mdcss-v2-ical-kalendar-anzeigen/15
                      1ad94760-95e1-46fb-ac36-f89d3a9b77ad-image.png

                      Ich vermute mal, dass ich das im Skript selbst ändern muss. Mal sehen.

                      Edit: Das Datum erscheint schon einmal. Jetzt will ich noch die Farben ändern. Den Filter habe ich auch nicht.

                      sigi234S 1 Antwort Letzte Antwort
                      0
                      • E Ente

                        @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                        @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                        @sigi234

                        Skript läuft. Vielen Dank.

                        Tut mir leid sigi. Wie bekomme ich das nun in meine vis integriert. Entschuldige bitte die Dummy-Frage.

                        Es werden States für n-Logs erzeugt, jedem, Log kann ein Standardfilter mitgegeben werden. In jedem Log-Ordner
                        befindet sich ein list-HTML State, welcher direkt in der vis angezeigt werden kann (jeweils im basic-string (unescaped) Widget).

                        Genau das habe ich gerade gefunden. Es zeigt auch die Termine an,

                        feb6d00b-f448-415c-a618-733025c42ac5-image.png

                        leider nicht so wie in dem Bild im 1. Post. bzw. wie hier:

                        https://forum.iobroker.net/topic/31635/vorlage-mdcss-v2-ical-kalendar-anzeigen/15
                        1ad94760-95e1-46fb-ac36-f89d3a9b77ad-image.png

                        Ich vermute mal, dass ich das im Skript selbst ändern muss. Mal sehen.

                        Edit: Das Datum erscheint schon einmal. Jetzt will ich noch die Farben ändern. Den Filter habe ich auch nicht.

                        sigi234S Online
                        sigi234S Online
                        sigi234
                        Forum Testing Most Active
                        schrieb am zuletzt editiert von sigi234
                        #47

                        @Ente

                        Hast du die Vorlage heruntergeladen und als View importiert?

                        https://github.com/Uhula/ioBroker-Material-Design-Style/tree/master/templates/MduiShowIcal

                        Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                        Immer Daten sichern!

                        E 1 Antwort Letzte Antwort
                        0
                        • sigi234S sigi234

                          @Ente

                          Hast du die Vorlage heruntergeladen und als View importiert?

                          https://github.com/Uhula/ioBroker-Material-Design-Style/tree/master/templates/MduiShowIcal

                          E Offline
                          E Offline
                          Ente
                          schrieb am zuletzt editiert von
                          #48

                          @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                          @Ente

                          Hast du die Vorlage heruntergeladen und als View importiert?

                          https://github.com/Uhula/ioBroker-Material-Design-Style/tree/master/templates/MduiShowIcal

                          Ja, den JS von MduiShowIcal_Tableview.json und als View importiert. Das Ergebnis, naja:

                          0ac27e47-3617-4816-886a-1fdd63e62982-image.png

                          Das ganze verstehe ich nicht. Das Anzeigen der Termine reicht.

                          sigi234S 1 Antwort Letzte Antwort
                          0
                          • E Ente

                            @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                            @Ente

                            Hast du die Vorlage heruntergeladen und als View importiert?

                            https://github.com/Uhula/ioBroker-Material-Design-Style/tree/master/templates/MduiShowIcal

                            Ja, den JS von MduiShowIcal_Tableview.json und als View importiert. Das Ergebnis, naja:

                            0ac27e47-3617-4816-886a-1fdd63e62982-image.png

                            Das ganze verstehe ich nicht. Das Anzeigen der Termine reicht.

                            sigi234S Online
                            sigi234S Online
                            sigi234
                            Forum Testing Most Active
                            schrieb am zuletzt editiert von
                            #49

                            @Ente

                            Welche Version hast du von MDCSS ?

                            Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                            Immer Daten sichern!

                            E 1 Antwort Letzte Antwort
                            0
                            • sigi234S sigi234

                              @Ente

                              Welche Version hast du von MDCSS ?

                              E Offline
                              E Offline
                              Ente
                              schrieb am zuletzt editiert von
                              #50

                              @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                              @Ente

                              Welche Version hast du von MDCSS ?

                              Äh?? Wo finde ich das?

                              sigi234S 1 Antwort Letzte Antwort
                              0
                              • E Ente

                                @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                @Ente

                                Welche Version hast du von MDCSS ?

                                Äh?? Wo finde ich das?

                                sigi234S Online
                                sigi234S Online
                                sigi234
                                Forum Testing Most Active
                                schrieb am zuletzt editiert von
                                #51

                                @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                @Ente

                                Welche Version hast du von MDCSS ?

                                Äh?? Wo finde ich das?

                                Screenshot (679)_LI.jpg

                                Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
                                Immer Daten sichern!

                                E 1 Antwort Letzte Antwort
                                0
                                • sigi234S sigi234

                                  @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                  @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                  @Ente

                                  Welche Version hast du von MDCSS ?

                                  Äh?? Wo finde ich das?

                                  Screenshot (679)_LI.jpg

                                  E Offline
                                  E Offline
                                  Ente
                                  schrieb am zuletzt editiert von Ente
                                  #52

                                  @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                  @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                  @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                  @Ente

                                  Welche Version hast du von MDCSS ?

                                  Äh?? Wo finde ich das?

                                  Screenshot (679)_LI.jpg

                                  Hab das Skript jetzt eingefügt. > 2.5

                                  Diese Objects habe allerdings ich nicht:

                                  a95da2c1-9777-4562-b34b-90108d967337-image.png

                                  Bei User.Datea habe ich nur das:

                                  82a25b33-1595-4d31-886d-c10049998f3e-image.png

                                  Irgendetwas habe ich grundsätzlich falsch gemacht.

                                  E 1 Antwort Letzte Antwort
                                  0
                                  • E Ente

                                    @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                    @Ente sagte in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                    @sigi234 said in [Vorlage] MDCSS v2: ical Kalendar anzeigen:

                                    @Ente

                                    Welche Version hast du von MDCSS ?

                                    Äh?? Wo finde ich das?

                                    Screenshot (679)_LI.jpg

                                    Hab das Skript jetzt eingefügt. > 2.5

                                    Diese Objects habe allerdings ich nicht:

                                    a95da2c1-9777-4562-b34b-90108d967337-image.png

                                    Bei User.Datea habe ich nur das:

                                    82a25b33-1595-4d31-886d-c10049998f3e-image.png

                                    Irgendetwas habe ich grundsätzlich falsch gemacht.

                                    E Offline
                                    E Offline
                                    Ente
                                    schrieb am zuletzt editiert von Ente
                                    #53

                                    Hallo,

                                    wie bekomme ich die Einträge in der view in weiß:

                                    3605cf02-589f-4329-93c0-daefbe795cf3-image.png

                                    Im Edit-Modus sind sie es.

                                    Edit: Gefunden:

                                    root.mdui-runtime {
                                    --content-background: #f8f8f8;
                                    --design-font-color: #000000;
                                    --frame-color:#cfcfcf;

                                    1 Antwort Letzte Antwort
                                    0
                                    • H Offline
                                      H Offline
                                      hendrik87
                                      schrieb am zuletzt editiert von
                                      #54

                                      Hallo

                                      Gibt es auch eine Möglichkeit sich die freien Tage anzeigen zu lassen?

                                      ChaotC 1 Antwort Letzte Antwort
                                      0
                                      • H hendrik87

                                        Hallo

                                        Gibt es auch eine Möglichkeit sich die freien Tage anzeigen zu lassen?

                                        ChaotC Offline
                                        ChaotC Offline
                                        Chaot
                                        schrieb am zuletzt editiert von
                                        #55

                                        @hendrik87 Was meinst du? Die Tage ohne Eintrag?
                                        Habe ich noch nicht probiert, aber versuche doch mal den Filter auf

                                        " "
                                        

                                        zu setzen und schau was passiert.

                                        ioBroker auf NUC unter Proxmox; VIS: 12" Touchscreen und 17" Touch; Lichtsteuerung, Thermometer und Sensoren: Tasmota (39); Ambiente Beleuchtung: WLED (9); Heizung: DECT Thermostate (9) an Fritz 6690; EMS-ESP; 1 Echo V2; 3 Echo DOT; 1 Echo Connect; 2 Echo Show 5; Unifi Ap-Ac Lite.

                                        H 1 Antwort Letzte Antwort
                                        0
                                        • ChaotC Chaot

                                          @hendrik87 Was meinst du? Die Tage ohne Eintrag?
                                          Habe ich noch nicht probiert, aber versuche doch mal den Filter auf

                                          " "
                                          

                                          zu setzen und schau was passiert.

                                          H Offline
                                          H Offline
                                          hendrik87
                                          schrieb am zuletzt editiert von
                                          #56

                                          @chaot

                                          Die Tage wo es keinen Termin zu gibt sollen auch angezeigt werden. Also in meinem Fall der 28, 30, 31, ....
                                          7997e083-d160-4a92-87e6-b6bf2b4b49b2-grafik.png

                                          Eigentlich bin ich auf der Suche nach einem monatsweisen Zeilenkalender.
                                          d82a5fed-789a-4e0b-a9d4-c0f19fb65e11-grafik.png

                                          Da habe ich mit dem MDCSS bislang die beste Lösung gefunden.

                                          1 Antwort Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          789

                                          Online

                                          32.4k

                                          Benutzer

                                          81.4k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe