Skip to content

ioBroker Card Definitionen (Seiten)

Thomas edited this page Apr 24, 2023 · 141 revisions

cardEntities

image

4 vertikal angeordnete Steuerelemente (Erstellung der "PageItem" siehe ioBroker ALIAS Definition)

var Sprechender_eindeutiger_Seitenname = <PageEntities>
{
    "type": "cardEntities",
    "heading": "Deine Überschrift",
    "useColor": true,
    "subPage": false,
    "parent": undefined,
    "items": [
        <PageItem>{ id: "Dein_Erstellter_Alias_1", Weitere Parameter siehe Alias Definition },
        <PageItem>{ id: "Dein_Erstellter_Alias_2", Weitere Parameter siehe Alias Definition },
        <PageItem>{ id: "Dein_Erstellter_Alias_3", Weitere Parameter siehe Alias Definition },
        <PageItem>{ id: "Dein_Erstellter_Alias_4", Weitere Parameter siehe Alias Definition }
    ]
};

cardGrid

image

image

6 horizontal angeordnete Steuerelemente (in 2 Reihen je 3 Steuerelemente) (Erstellung der "PageItem" siehe ioBroker ALIAS Definition)

var Sprechender_eindeutiger_Seitenname = <PageGrid>
{
    "type": "cardGrid",
    "heading": "Deine Überschrift",
    "useColor": true,
    "subPage": false,
    "parent": undefined,
    "items": [
        <PageItem>{ id: "Dein_Erstellter_Alias_1", Weitere Parameter siehe Alias Definition },
        <PageItem>{ id: "Dein_Erstellter_Alias_2", Weitere Parameter siehe Alias Definition },
        <PageItem>{ id: "Dein_Erstellter_Alias_3", Weitere Parameter siehe Alias Definition },
        <PageItem>{ id: "Dein_Erstellter_Alias_4", Weitere Parameter siehe Alias Definition },
        <PageItem>{ id: "Dein_Erstellter_Alias_5", Weitere Parameter siehe Alias Definition },
        <PageItem>{ id: "Dein_Erstellter_Alias_6", Weitere Parameter siehe Alias Definition }
    ]
};

cardUnlock (ab v4.0.0)

Die cardUnlock dient der Absicherung spezieller Seiten, die vor unbefugtem Zugriff (ggfs. Service Pages) geschützt werden sollen:
image

Bei Benutzung der cardUnlock wird die Zielseite aus dem Page-Array herausgenommen. Die Target-Page sollte nicht als Top-Level-Page, sondern als Subpage definiert sein.

im Datenpunkt 0_userdata.0.NSPanel.X.Unlock.UnlockPin kann eine PIN vergeben werden. Default wird diese PIN als 0000 definiert.

Erstellung des Alias:
Es wird muss ein Alias vom Gerätetyp "Feueralarm" wie folgt erstellt werden:
image

Beispiel der Seitenerstellung:

let Unlock_Service = <PageUnlock>
{
    'type': 'cardUnlock',
    'heading': 'Service Pages',
    'useColor': true,
    'items': [<PageItem>{ id: 'alias.0.Unlock', targetPage: 'NSPanel_Service' }]
};

cardAlarm

image

(Erstellung des alias.0.Alarm siehe ioBroker ALIAS Definition)

let Sprechender_eindeutiger_Seitenname = <PageAlarm>
{
    "type": "cardAlarm",
    "heading": "Deine Überschrift",
    "useColor": true,
    "subPage": false,
    "parent": undefined,
    "items": [
        <PageItem>{ id: alias.0.Alarm}
    ]
};

cardMedia v2.0 (ab Release v3.9.0)

image

Neue Elemente

  • Shuffle (nach verfügbarkeit des Adapters)
    image

  • Neue Auswahl für Speakerauswahl/-wechsel
    image

  • Playlist
    image

  • Tracklist (Bei Playlist und falls verfügbar)
    image

  • Equalizer-Profile
    image
    Link: Blockly für Klangsteuerung in der cardMedia

  • Repeat (nach Verfügbarkeit des Adapters)
    image

(Erstellung des "PageItem" siehe ioBroker ALIAS Definition)

Definition ab TS-Version 3.9.0 (Breaking Changes)

alexa2-Adapter

let Alexa = <PageMedia> 
{
    'type': 'cardMedia',
    'heading': 'Alexa',
    'useColor': true,
    'subPage': false,
    'parent': undefined,
    'items': [<PageItem>{   
                id: AliasPath + 'Media.PlayerAlexa', 
                adapterPlayerInstance: 'alexa2.0.',
                mediaDevice: 'G0XXXXXXXXXXXXXX', // Eigene Seriennummer des primären Device einstellen
                speakerList: ['Überall','Gartenhaus','Esszimmer','Heimkino','Echo Dot Küche','Echo Spot Buero'],
                //analog alexa2 Music-Provider
                //Mögliche Playlists:
                playList: ['Spotify-Playlist.Party Playlist',
                           'Amazon-Music-Playlist.Mein Discovery Mix',
                           'My-Library-Playlist.2020',
                           'My-Library-Playlist.2021',
                           'TuneIn.Radio Bob Rock',
                           'TuneIn.NDR2',
                           'Spotify-Playlist.Sabaton Radio',
                           'Spotify-Playlist.Rock Party',
                           'Spotify-Playlist.This Is Nightwish',
                           'Spotify-Playlist.Metal Christmas'],
                equalizerList: ['Bassboost','Klassik','Dance', 'Deep', 'Electronic', 'Flat', 'Hip-Hop', 'Rock', 
                                'Metal', 'Jazz', 'Latin', 'Tonstärke', 'Lounge', 'Piano'],
                colorMediaIcon: colorAlexa,
                colorMediaArtist: Yellow,
                colorMediaTitle: Yellow,
                autoCreateALias : true
             }]
};

spotify-premium Adapter

let SpotifyPremium = <PageMedia> 
{
    "type": "cardMedia",
    "heading": "Spotify-Premium",
    "useColor": true,
    "subPage": false,
    "parent": undefined,
    "items": [<PageItem>{ 
                id: AliasPath + 'Media.PlayerSpotifyPremium', 
                adapterPlayerInstance: "spotify-premium.0.",
                speakerList: ['LENOVO-W11-01','Terrasse','Überall','Gartenhaus','Esszimmer','Heimkino','Echo Dot Küche',
                              'Echo Spot Buero'],
                //Favoriten Playlists aus Spotify in Liste eintragen 
                playList: ['Party Playlist','Sabaton Radio','Rock Party','This Is Nightwish','Metal Christmas'],
                repeatList: ['off','context','track'],
                equalizerList: ['Bassboost','Klassik','Dance', 'Deep', 'Electronic', 'Flat', 'Hip-Hop', 'Rock', 
                                'Metal', 'Jazz', 'Latin', 'Tonstärke', 'Lounge', 'Piano'],
                colorMediaIcon: colorSpotify,
                colorMediaArtist: Yellow,
                colorMediaTitle: Yellow,
                autoCreateALias : true
             }]
};

Volumio-Player

let VolumioBoss = <PageMedia> 
{
    'type': 'cardMedia',
    'heading': 'Volumio-Büro',
    'useColor': true,
    'subPage': false,
    'parent': undefined,
    'items': [<PageItem>{   
                id: 'alias.0.NSPanel.Volumio-Boss', 
                adapterPlayerInstance: 'volumio.0.',
                speakerList: [], /* this must, no function */
                playList: [],    /* empty for dynamic reading */
                colorMediaIcon: colorSpotify,
                colorMediaTitle: colorSpotify,
                colorMediaArtist: Yellow,
                autoCreateALias : true
             }]
};

Parameter

adapterPlayerInstance: "alexa.0." oder "spotify-premium.0." oder "sonos.0." oder "chromecast.0." oder "squeezeboxrpc.0.Players.DeinPlayer.

mediaDevice:

  • für "alexa.0.": Seriennummer oder Gruppennummer des primären Alexa-Device
  • für "sonos.0.": IP-Adresse des Sonsos primären Sonos-Device (getrennt mit "_") --> Beispiel: 192_168_1_250
  • für "spotify-premium.0.": Zeile kann gelöscht werden, da Spotify immer nur einen Speaker oder Gruppe steuern kann (automatische Ermittlung)
  • für "chromecast.0.": Zeile kann gelöscht werden, da GoogleHome keine Funktionalitäten zum Wechseln von Lautsprechern zur Verfügung stellt
  • für "squeezeboxrpc.0.": Zeile kann gelöscht werden, da squeezeboxrpc keine Funktionalitäten zum Wechseln von Lautsprechern zur Verfügung stellt

speakerList: (Namen und Reihenfolge der Speaker selbst bestimmen)

  • für "alexa.0.": Device-Namen aus alexa2 möglich. Wenn leer [] , dann alle Devices des alexa2-Adapter
  • für "sonos.0.": Zeile kann gelöscht werden, da Funktionalität zum schieben auf andere Devices im Sonos-Adapter nicht möglich
  • für "spotify-premium.0.": Alle SmartDevice-Namen aus Spotify möglich (Im Gegensatz zu Alexa auch Smartphones und Rechner)
  • für "chromecast.0.": Zeile kann gelöscht werden, da GoogleHome keine Funktionalitäten zum Wechseln von Lautsprechern zur Verfügung stellt
  • für "squeezeboxrpc.0.": "Bekannte Player unter Players (aktuell keine Funktion)

cardQR

image

Beispiel: Erstellung des "PageItem" und Alias vom Typ "Info" siehe (https://github.com/joBr99/nspanel-lovelace-ui/wiki/ioBroker---FAQ-&-Anleitungen#5-qr-code-page) by Kuckuckmann

var Sprechender_eindeutiger_Seitenname = <PageQR> 
{
    "type": "cardQR",
    "heading": "Deine Überschrift",
    "useColor": true,
    "subPage": false,
    "parent": undefined,
    "items": [<PageItem>{ id: "alias.0.NSPanel_1.Guest_Wifi" }] // Beispiel
};

Parameter:

hidePassword: true/false

cardThermo

(Erstellung der "PageItem" siehe ioBroker ALIAS Definition)

Für Thermostat und Klimaanlage (Unterschied im zu erstellenden Alias)

image

image

image

image

var Sprechender_eindeutiger_Seitenname = <PageThermo> 
{
    "type": "cardThermo",
    "heading": "Test Klimaanlage",
    "useColor": true,
    "subPage": false,
    "parent": undefined,
    "items": [<PageItem>{   
                id: "alias.0.NSPanel_1.TestKlimaanlage", 
                minValue: 50, 
                maxValue: 250,
                stepValue: 5,
                popupThermoMode1: ['Auto','0','1','2','3'],
                popupThermoMode2: ['Auto','0','1','2','3','4','5'],
                popupThermoMode3: ['Auto','Manual','Boost',],
                popUpThermoName: ["Schwenk-Modus", 'Speed', 'Temperatur'],
                icon: 'fan',
                setThermoAlias: ['MODE1','MODE2','MODE3'],
                setThermoDestTemp2: 'ACTUAL2'
             }]
};

Parameter:
minValue: Minimale einzustellende Temperatur (Beispiel: 17°C entspricht 170)
maxValue: Maximale einzustellende Temperatur (Beispiel: 30,5°C entspricht 305) stepValue: Schrittgröße der Temperaturänderungen (Beispiel: 0,5°C Schritte entspricht 5)

cardPower (ab TS-Script v.3.4.1)

Nextion_Editor_9AYbpowjZS

Beispiel: Erstellung des "PageItem" und Alias vom Typ "Info"

var CardPowerExample = <PagePower>
{
    "type": "cardPower",
    "heading": "cardPower Emulator",
    "useColor": true,
    "subPage": false,
    "parent": undefined,
    "items": [
//        <PageItem>{  }, //Demomode
        <PageItem>{ id: "alias.0.NSPanel_1.Power.PowerCard" },
    ]
};

Parameter:
Es gibt nur einen einzigen externen Datenpunkt (anzulegen in 0_userdata.0.), auf den ein Alias vom Typ "Info" zugreift. Dieser muss mit einem JSON-Objekt in nachfolgender Struktur befüllt werden. Der Alias-Datenpunkt "ACTUAL" sollte hierbei auf diesen neuen Datenpunkt in "0_userdata.0.) gebunden sein.

[
  {
    "id": 0,
    "value": 13,
    "unit": "kW",
    "icon": "emoticon-happy-outline",
    "iconColor": 0
  },
  {
    "id": 1,
    "value": 3,
    "unit": "kW",
    "icon": "battery-charging-60",
    "iconColor": 10,
    "speed": 30
  },
  {
    "id": 2,
    "value": 4.7,
    "unit": "kW",
    "icon": "solar-power-variant",
    "iconColor": 3,
    "speed": -20
  },
  {
    "id": 3,
    "value": 4.3,
    "unit": "kW",
    "icon": "wind-turbine",
    "iconColor": 1,
    "speed": -30
  },
  {
    "id": 4,
    "value": 3.4,
    "unit": "kW",
    "icon": "shape",
    "iconColor": 10,
    "speed": 30
  },
  {
    "id": 5,
    "value": 0.1,
    "unit": "kW",
    "icon": "transmission-tower",
    "iconColor": 0,
    "speed": 20
  },
  {
    "id": 6,
    "value": 2.5,
    "unit": "kW",
    "icon": "car",
    "iconColor": 5,
    "speed": 20
  }
]

iconColor kann einen Wert von 0-10 annehmen und entspricht der ColorScale Grün -> Gelb -> Rot
speed kann positive und negative Werte annehmen, wobei positive Werte den Punkt vom Haus weggehen lassen und negative Werte zum Haus
cardPower Emulator (Blockly)

Zum Blockly

Kurze Anleitung:
Der Code dient nur der Orientierung und stellt keine Lösung für die eigene Visualisierung dar. Somit soll z.B. der Aufbau des JSON-Objektes verdeutlicht werden.

Für dieses Beispiel sind in 0_userdata für die 6 Werte in der cardPower entsprechende Datenpunkte (number) manuell angelegt worden:
image

Im oberen Teil des Blocklys wird lediglich eine Emulation auf 4 von 6 Datenpunkten je Minute erzeugt. Bei Produktivnutzung sollte dieses Codeobjekt gelöscht (deaktiviert) werden.

image

Produktivnutzung:

Die Datenpunkte zu den entsprechenden Piktogrammen (id's) sollten mit den jeweiligen eigenen Adapter-Datenpunkten ersetzt werden. Im Beispiel werden folgende Datenpunkte zugewiesen:

1 - Batteriespeicher (Einspeisung/Bezug)
2 - Photovoltaik Ertrag
3 - Windenergieanlage Ertrag
4 - Sämtliche aktiven Verbraucher des Hauses
5 - Energielieferant (Netz-Einspeisung/Netz-Bezug)
6 - Ladestation Verbrauch (E-Car)

Für eine abweichende Darstellung ist das JSON entsprechend zu befüllen. Wenn eine Entität nicht visualisiert werden soll, so sollte in allen Werten zur id ein leerer String "" übergeben werden. Beispiel:

  {
    "id": 3,
    "value": "",
    "unit": "",
    "icon": "",
    "iconColor": "",
    "speed": ""
  },

Das Skript stellt nur eine exemplarische Möglichkeit der Befüllung dar. Es kann frei definiert und auf eigene Bedürfnisse angepasst werden, soll aber keine finale Lösung für jede Smart Home Situation abbilden! Ebenso kann die Erstellung des JSON natürlich auch über JavaScript oder TypeScript erfolgen.

Ein kleines einfaches Javascript von @l4rs, für die erzeugung des JSON-String.

/**
* generate an JSON for display Power-Card on NSPanel
* Source: https://github.com/joBr99/nspanel-lovelace-ui/wiki/ioBroker-Card-Definitionen-(Seiten)#cardpower-ab-ts-script-v341
* Version: 0.1 - L4rs
*/
schedule("* * * * *", function () {
 
    // Definition der Datenpunkte für das JSON der POWER-Card und der anzuzeigenden Leistungswerte
    var powerCardJson = "0_userdata.0.NSPanel.Energie.PowerCard",
      pwr1 = "", // Batterie
      pwr2 = Math.round(getState("mqtt.0.SmartHome.Energie.PV.openDTU.114180710360.0.power").val),    // Solar
      pwr3 = "",    // Wind
      pwr4 = "",   // Verbraucher
      pwr5 = Math.round(getState("hm-rpc.0.MEQ0706303.1.POWER").val),    // Stromnetz
      pwr6 = 0, // Auto
      pwrHome = Math.round(pwr5 - pwr2);    // Berechnung des Energiefluss anstelle eines Datenpunktes
    
    // Definition der Keys im JSON
    var keys = ["id", "value", "unit", "icon", "iconColor", "speed"];
    
    // Definition der "Kacheln", inkl. StandardIcon. Es können alle Icon aus dem Iconmapping genutzt werden.
    // Kacheln die nicht genutzt werden sollen, müssen wie z.b. item1 formatiert sein
    var home = [0, pwrHome, "W", "home-lightning-bolt-outline", 0]; // Icon home
    var item1 = [1, pwr1, "", "", 0, ""];   // Icon battery-charging-60
    var item2 = [2, pwr2, "W", "solar-power-variant-outline", 3, pwr2 > 0 ? -2 : 0]; // Icon solar-power-variant
    var item3 = [3, pwr3, "", "", 0, ""];   // Icon wind-turbine
    var item4 = [4, pwr4, "", "", 0, ""];   // Icon shape
    var item5 = [5, pwr5, "W", "transmission-tower", 10, 10];   // Icon transmission-tower
    var item6 = [6, pwr6, "kW", "car-electric-outline", 5, 0];  // Icon car
    
    /**
     * JSON generieren und in den Datenpunkt schreiben,
     *
     *  --- ab hier keine Änderungen mehr ---
     */
    function func(tags, values) {
      return Object.assign(
        ...tags.map((element, index) => ({ [element]: values[index] }))
      );
    }
    
    setState(
      powerCardJson,
      JSON.stringify([
        func(keys, home),
        func(keys, item1),
        func(keys, item2),
        func(keys, item3),
        func(keys, item4),
        func(keys, item5),
        func(keys, item6),
      ])
    );
   });

Hinweis: Aktuell erfolgt die Animation gleicher Speed Werte bei der US-P Firmware durch die geänderte Orientierung in umgekehrter Reihenfolge.

cardChart (ab TS-Script v.3.7.0)

ab Release v3.7.0

image

Für das unten abgebildete Blockly-Script wurden die Werte eines Datenpunktes "sonoff.0.DZG_DWSB20_2H.DZG_Leistung_Aktuell" in einer Influx 2.0 Datenbank gespeichert.

Es wird für das Skript ein Datenpunkt (hier im Beispiel "0_userdata.0.Test.cardChart.txt") benötigt, um das Chart für die cardChart aufzubereiten.

Alias-Erstellung:
Es wird lediglich ein Alias vom Gerätetyp "Info" benötigt: image

PageItem Beispiel:

let CardChartExample = <PageChart>
{
    "type": "cardChart",
    "heading": "Stromzähler L1+L2+L3",
    "useColor": true,
    "subPage": false,
    "parent": undefined,
    "items": [<PageItem>{ 
                id: 'alias.0.NSPanel_1.cardChart', 
                yAxis: 'Leistung [kW]', 
                yAxisTicks: [2,4,6,8,10,2,4,6,8,20,2], 
                onColor: Yellow
             }]
};

image

Blockly für Influx 2.0

image

Zum Blockly

Javascript für History Adapter

var sourceDP = 'alias.0.Wohnzimmer.Heizung.ACTUAL';
var targetDP = '0_userdata.0.Test.chartTest';
var rangeHours = 24;
var maxXAchsisTicks = 6;
var historyInstance = 'history.0';

on({id: sourceDP, change: "any"}, async function (obj) {
    sendTo(historyInstance, 'getHistory', {
        id: sourceDP,
        options: {
            start:     Date.now() - (60 * 60 * 1000 * rangeHours),
            end:       Date.now(),
            count:     rangeHours,
            limit:     rangeHours,
            aggregate: 'average'
        }
    }, function (result) {
        var cardChartString = "";
        var stepXAchsis = rangeHours / maxXAchsisTicks;

        for (var i = 0; i < rangeHours; i++){
            var deltaHour = rangeHours - i;
            var targetDate = new Date(Date.now() - (deltaHour * 60 * 60 * 1000));

            //Check history items for requested hours
            for (var j = 0, targetValue = 0; j < result.result.length; j++) {
                var valueDate = new Date(result.result[j].ts);
                var value = (Math.round(result.result[j].val * 10) / 10);

                if (valueDate > targetDate){                        
                    if ((targetDate.getHours() % stepXAchsis) == 0){
                        cardChartString += targetValue + '^' + targetDate.getHours() + ':00' + '~';
                    } else {
                        cardChartString += targetValue + '~';
                    }
                    break;
                } else {
                    targetValue = value;
                }
            }
        }
        
        cardChartString = cardChartString.substring(0,cardChartString.length-1);
        if (existsState(targetDP) == false ) { 
            createState(targetDP, cardChartString, true, { type: 'string' });
        } else {
            setState(targetDP, cardChartString, true);
        }
    });    
});

cardLChart (Line Charts ab TS-Script v.3.9.0)

ab TS-Script Release v3.9.0

image

Seitendefinition

Der Alias unter der PageItem.id ist ein Alias vom Gerätetyp: Info

  • type: Für Liniendiagramme muss der Seiten-Typ "cardLChart" sein.
  • id: Es wird ein Alias vom Gerätetyp "Info" erstellt, der auf den erzeugenden Datenpunkt des unten aufgeführten Beispiel-Scriptes zeigt.
  • yAxis: Bezeichner der Y-Achse
  • yAxisTicks: Skala des Wertebereiches der Y-Achse als Array oder ObjektId zu einem Datenpunkt welcher die Skala enthält
  • onColor: Farbe des Graphen
let CardLChartExample = <PageChart>
{
    "type": "cardLChart",
    "heading": "Büro Temperatur",
    "useColor": true,
    'items': [<PageItem>{ 
                id: 'alias.0.Haus.Erdgeschoss.Buero.Charts.Temperatur',
                yAxis: 'Temperatur [°C]',
                yAxisTicks: [160,170,180,190,200,210,220,230],
                onColor: Yellow
             }]
};

Erklärung zum nachfolgenden Beispiel-JS-Script:

Wichtiger Hinweis und Voraussetzungen:
Für das Beispiel muss der InfluxDB Adapter installiert sein. Ebenfalls sollte über einen Zeitraum X bereits Sensordaten an eine Infux 2.X DB übertragen worden sein, welche jetzt zum Abruf bereit stehen!

Zu definieren ist der Pfad für den Datenpunkt (im Beispiel 0.userdata.0.NSPanel.Influx2NSPanel.buero_temperature) in den das u.a. JS-Script die aufbereiteten Daten für das NSPanel schreiben kann. Für das Beispiel wurde ein Datenpunkt (deconz.0.Sensors.65.temperature) aus dem DeConz-Adapter mit einem Zigbee-Temperatursensor gewählt.

Bei Bedarf kann das Query angepasst werden:
Es ist darauf zu achten, die Anzahl an Werten aus der Datenbank möglichst gering zu halten. Im nachfolgenden Beispiel wurden diese nochmals aggregiert. Die Summe an Zeichen für das Payload an die HMI des NSPanels ist begrenzt. Falls zu viele Werte verarbeitet werden, wird der Payload von der HMI gekürzt und die folge wäre eine schwarze Seite resultierend aus einem Fehlerzustand.

Javascript für Influx2

const Debug = true;

const NSPanel_Path = '0_userdata.0.NSPanel.';
const Path = NSPanel_Path + 'Influx2NSPanel.cardLChart.';
const PathSensor = Path + 'buero_temperature';

const Sensor = 'deconz.0.Sensors.65.temperature';

const numberOfHoursAgo = 24;
const xAxisTicksEveryM = 60;
const xAxisLabelEveryM = 240;

const InfluxInstance = 'influxdb.0';

let coordinates = ''; 

createState(PathSensor, 0, {
        name: 'SensorGrid',
        desc: 'Sensor Values [~<time>:<value>]*',
        type: 'string',
        role: 'value',
    });

on({ id: Sensor, change: 'any' }, async function (obj) {

    let query =[
        'from(bucket: "iobroker")',
        '|> range(start: -' + numberOfHoursAgo + 'h)',
        '|> filter(fn: (r) => r["_measurement"] == "' + Sensor+ '")',
        '|> filter(fn: (r) => r["_field"] == "value")',
        '|> drop(columns: ["from", "ack", "q"])',
        '|> aggregateWindow(every: 1h, fn: last, createEmpty: false)',
        '|> map(fn: (r) => ({ r with _rtime: int(v: r._time) - int(v: r._start)}))',
        '|> yield(name: "_result")'].join('');

    if (Debug) console.log('Query: ' + query);

    sendTo(InfluxInstance, 'query', query, function (result) {
        if (result.error) {
            console.error(result.error);
        } else {
            // show result
            if (Debug) console.log(result);
            let numResults = result.result.length;
            for (let r = 0; r < numResults; r++) 
            {
                let list = []
                let numValues = result.result[r].length;

                for (let i = 0; i < numValues; i++) 
                {
                    let time = Math.round(result.result[r][i]._rtime/1000/1000/1000/60);
                    let value = Math.round(result.result[r][i]._value * 10);
                    list.push(time + ":" + value);
                }

                coordinates = list.join("~");

                if (Debug) console.log(coordinates);
            }
        }
    });

    let timeOut = setTimeout (
        function () {
            let ticksAndLabelsList = []
            let date = new Date();
            date.setMinutes(0, 0, 0);
            let ts = Math.round(date.getTime() / 1000);
            let tsYesterday = ts - (numberOfHoursAgo * 3600);
            if (Debug) console.log('Iterate from ' + tsYesterday + ' to ' + ts + ' stepsize=' + (xAxisTicksEveryM * 60));
            for (let x = tsYesterday, i = 0; x < ts; x += (xAxisTicksEveryM * 60), i += xAxisTicksEveryM)
            {
                if ((i % xAxisLabelEveryM))
                    ticksAndLabelsList.push(i);
                else
                {
                    let currentDate = new Date(x * 1000);
                    // Hours part from the timestamp
                    let hours = "0" + String(currentDate.getHours());
                    // Minutes part from the timestamp
                    let minutes = "0" + String(currentDate.getMinutes());
                    let formattedTime = hours.slice(-2) + ':' + minutes.slice(-2);

                    ticksAndLabelsList.push(String(i) + "^" + formattedTime);
                }
            }
            if (Debug) console.log('Ticks & Label: ' + ticksAndLabelsList);
            if (Debug) console.log('Coordinates: ' + coordinates);
            setState(PathSensor, ticksAndLabelsList.join("+") + '~' + coordinates, true);
        }, 
    1500
    ) ;
});

Javascript für History adapter

const sourceDP = 'alias.0.Wohnzimmer.Heizung.ACTUAL';
const targetDP = '0_userdata.0.Test.chartTest';
const numberOfHoursAgo = 24;   // Period of time in hours which shall be visualized
const xAxisTicksEveryM = 60;   // Time after x axis gets a tick  in minutes
const xAxisLabelEveryM = 240;  // Time after x axis is labeled  in minutes
const historyInstance = 'history.0';

const Debug = false;
const maxX = 1420;
const limitMeasurements = 35;

createState(targetDP, "", {
        name: 'SensorGrid',
        desc: 'Sensor Values [~<time>:<value>]*',
        type: 'string',
        role: 'value',
});

on({id: sourceDP, change: "any"}, async function (obj) {
    sendTo(historyInstance, 'getHistory', {
        id: sourceDP,
        options: {
            start:     Date.now() - (numberOfHoursAgo * 60 * 60 * 1000 ), //Time in ms: hours * 60m * 60s * 1000ms
            end:       Date.now(),
            count:     limitMeasurements,
            limit:     limitMeasurements,
            aggregate: 'average'
        }
    }, function (result) {
        var ticksAndLabels = ""
        var coordinates = "";
        var cardLChartString = "";

        let ticksAndLabelsList = []
        var date = new Date();
        date.setMinutes(0, 0, 0);
        var ts = Math.round(date.getTime() / 1000);
        var tsYesterday = ts - (numberOfHoursAgo * 3600);
        
        for (var x = tsYesterday, i = 0; x < ts; x += (xAxisTicksEveryM * 60), i += xAxisTicksEveryM)
        {
            if (i % xAxisLabelEveryM) 
            {
                ticksAndLabelsList.push(i);
            } else 
            {
                var currentDate = new Date(x * 1000);
                // Hours part from the timestamp
                var hours = "0" + currentDate.getHours();
                // Minutes part from the timestamp
                var minutes = "0" + currentDate.getMinutes();
                // Seconds part from the timestamp
                var seconds = "0" + currentDate.getSeconds();
                var formattedTime = hours.slice(-2) + ':' + minutes.slice(-2);
                ticksAndLabelsList.push(String(i) + "^" + formattedTime);
            }
        }
        ticksAndLabels = ticksAndLabelsList.join("+");        

        let list = [];
        let offSetTime = Math.round(result.result[0].ts / 1000);
        let counter = Math.round((result.result[result.result.length -1 ].ts / 1000 - offSetTime) / maxX);        
        for (var i = 0; i <  result.result.length; i++) 
        {           
            var time = Math.round(((result.result[i].ts / 1000) - offSetTime) / counter);
            var value = Math.round(result.result[i].val * 10);
            if ((value != null) && (value != 0)){
                list.push(time + ":" + value)
            }
        }

        coordinates = list.join("~");
        cardLChartString = ticksAndLabels + '~' + coordinates
        setState(targetDP, cardLChartString, true);
        
        if (Debug) console.log(cardLChartString);
    });    
});

popUpNotify

Status: in Erstellung:

Das ganze LUI Thema ist am Wachsen. Nun gibt es von der popUpNotify Page schon zwei verschiedene Varianten. Diese wollen wir hier beschreiben:

popUpNotify - alte Variante

Beschreibung:
Die alte Variante kennt man am ehesten von Info-Popus zur Tasmota oder TFT Version.

image

Datenpunkte:

  • popupNotifyHeading
  • popupNotifyText
  • popupNotifyInternalName
  • popupNotifyButton1Text
  • popupNotifyButton2Text
  • popupNotifySleepTimeout
  • popupNotifyAction

Zuordnung Datenpunkte:

popupnotify_v1

Nutzung:
Vor der Version v3.5.0 per Default nutzbar. Ab der Version v3.5.0 bleibt die alte Version erstmal per Default nutzbar. Stellt man den Datenpunkt popupNotifyLayout auf 2 erhält man das neue popUpNotify, zur Nutzung des alten muss man dann den Wert 1 hinterlegen.

Beispiel:

Bei der Anleitung der AlarmCard gibt es zwei verschiedene Beispiele für die Nutzung der popUpNotify Page.

popUpNotify - Layout 2

Beschreibung:
Ab Version v3.5.0 verfügbar.
Layout 2 bringt neue Funktionen mit sich wie Schriftgröße, Schriftfarbe, ein Icon mit definierbarer Farbe, etc.

image

Neue Datenpunkte:
Die neuen Datenpunkte werden automatisch beim Starten des Skriptes angelegt. Zur Übersicht hier die neuen Datenpunkte aufgelistet:

  • popupNotifyHeadingColor
  • popupNotifyTextColor
  • popupNotifyButton1TextColor
  • popupNotifyButton2TextColor
  • popupNotifyLayout
  • popupNotifyFontIdText (Schriftgröße)
  • popupNotifyIcon
  • popupNotifyIconColor

Zuordnung Datenpunkte:

popupnotify_v2

Nutzung:
Ab der Version v3.5.0 bleibt die alte Version erstmal per Default nutzbar. Stellt man den Datenpunkt popupNotifyLayout auf 2 erhält man das neue popUpNotify, zur Nutzung des alten muss man dann den Wert 1 hinterlegen.

Emulator (Layout 2):
Zum Blockly

Clone this wiki locally