Skip to content

cardlchart

tt-tom17 edited this page Jan 7, 2025 · 1 revision

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
  • onColor: Farbe des Graphen
let CardLChartExample: PageType =
{
    "type": "cardLChart",
    "heading": "Büro Temperatur",
    "useColor": true,
    'items': [{ 
                id: 'alias.0.Haus.Erdgeschoss.Buero.Charts.Temperatur',
                yAxis: 'Temperatur [°C]',
                onColor: Yellow
             }]
};

Erklärung zum nachfolgenden Beispiel-TS-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. TS-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.

TypeScript für Influx2

const Debug = false;

const NSPanel_Path = '0_userdata.0.NSPanel.1.';
const Path = NSPanel_Path + 'Influx2NSPanel.cardLChart.';
const InfluxInstance = 'influxdb.1';
const influxDbBucket = 'iobroker';
const numberOfHoursAgo = 24;
const xAxisTicksEveryM = 60;
const xAxisLabelEveryM = 240;

// this records holds all sensors and their corresponding states which act as the data source for the charts
// add all sensors which are to be displayed in this script, there is no need to use multiple scripts
const sensors : Record<string, string> = {};
/*         ↓ Id of the sensor                 ↓ Id of the data source for the charts */
sensors['deconz.0.Sensors.65.temperature'] = Path + 'buero_temperature';
sensors['deconz.0.Sensors.65.humidity'] = Path + 'buero_luftfeuchte';

// create data source for NsPanel on script startup
Object.keys(sensors).forEach(async x => {
    await generateDateAsync(x, sensors[x]);
});

// then listen to the sensors and update the data source states accordingly
on({ id: Object.keys(sensors), change: 'any' }, async function (obj) {
    if (!obj.id) {
        return;
    }

    await generateDateAsync(obj.id, sensors[obj.id]);
});

async function generateDateAsync(sensorId: string, dataPointId: string) {
    const query =[
        'from(bucket: "' + influxDbBucket + '")',
        '|> range(start: -' + numberOfHoursAgo + 'h)',
        '|> filter(fn: (r) => r["_measurement"] == "' + sensorId + '")',
        '|> 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);

    const result : any = await sendToAsync(InfluxInstance, 'query', query);
    if (result.error) {
        console.error(result.error);
        return;
    }
...

Link zum Script CardLChart_Influx2.js

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) {
 ...

Link zum Script CardLChart_History.js

Clone this wiki locally