Hallo. Heute stelle ich euch einmal mein Skript "Luftdaten" vor. Dieses Skript liest Daten einer Websiteaus. Es ermittelt wie auch andere Skripts (z.B. Wetter, Biowetter, AlleStörungen, usw.) Daten und schreibt diese zur Weiterverarbeitung in einzelne Datenpunkte.
Ausgelesen werden Daten für Ozon, NO2, PM10 und PM25. Damit lassen sich einfache, individuelle Visualisierungen erstellen. Dies ist vielleicht ein weiteres Skript für Nutzer vom ioBroker.
VORARBEITEN für SKRIPT - Anleitung um meinen Ort und damit die URL zu finden
-
Adresse https://www.accuweather.com/ öffnen und im Suchfeld dein Ort eingeben und auswählen - Hinweis: Funktioniert mit Orten aus DE, AT, CH
-
Auf der neuen Seite, unterhalb des Suchfeldes auf den Link "LUFTQUALITÄT" klicken
-
In der ersten Karte (LUFTQUALITÄT HEUTE) unten rechts auf den Link "plume labs" klicken
-
Adresse im Browser kopieren und die Konstante sURL anpassen - sollte etwa so aussehen: https://air.plumelabs.com/air-quality-in-XXXXXX-aw-YYYYYYYY?utm_source=accuweather&utm_medium=current_aq_widget&utm_campaign=#ae16
VORARBEITEN für Visualisierung (VIS) - ICON
Nachfolgende Bilder müssen in den Ordner "luftdaten". Dieser ist ein Unterordner von "vis.0". Ergebnis: "/vis.0/luftdaten". Hinweis. Sollte eine andere Visualisierung genutzt werden, müssen ggfs. individuelle Anpassungen vorgenommen werden.
luftdaten-images.zip
//Version 1.0.0
//23.09.2024
//Ersteller Ro75.
//Voraussetzungen (Version 1.0.0 getestet mit)
//NodeJS: 20.x
//Javascript-Adapter: 8.7.6
//Admin-Adapter: 7.0.23
//JS-Controller: 6.0.11
//Vorarbeiten abarbeiten
const sMainPath = '0_userdata.0.Luftdaten.';
//URL zum Auslesen - bitte anpassen - Anleitung beachten!!
const sURL = 'https://air.plumelabs.com/air-quality-in-bautzen-aw-171290?utm_source=accuweather&utm_medium=current_aq_widget&utm_campaign=#ae16'; // Ermittlung Schritt 1 - 4
//nicht ändern!!!
const airBasis = 'O3,PM10,PM25,NO2';
const airDetails = 'hervorragend,angemessen,schlecht,ungesund,sehr ungesund,gefährlich';
function Initalisierung(){
let sAIR = airBasis.split(',');
for (let i = 0; i <= sAIR.length-1; i++) {
createState(sMainPath+sAIR[i]+'.value', 0, {name: 'Wert',type: 'number', read: true, write: true, unit: 'µg/m³'});
createState(sMainPath+sAIR[i]+'.index', 0, {name: 'Index',type: 'number', read: true, write: true});
createState(sMainPath+sAIR[i]+'.desc', '', {name: 'Beschreibung',type: 'string', read: true, write: true});
createState(sMainPath+sAIR[i]+'.image', '', {name: 'VIS',type: 'string', read: true, write: true});
}
createState(sMainPath+'data_json', '', {name: 'JSON',type: 'string', def: '[]', read: true, write: true, desc: 'JSON Widget'});
createState(sMainPath+'Gesamt.index', '', {name: 'Index',type: 'number', read: true, write: true});
createState(sMainPath+'Gesamt.value', '', {name: 'Wert',type: 'number', read: true, write: true});
createState(sMainPath+'Gesamt.desc', '', {name: 'Beschreibung',type: 'string', read: true, write: true});
createState(sMainPath+'Gesamt.image', '', {name: 'VIS',type: 'string', read: true, write: true});
//erster Datenabruf
LuftMessDaten();
}
//START
Initalisierung();
//automatischer Abruf aller 15 Minuten - weniger nicht empfohlen
schedule('*/15 * * * *', LuftMessDaten);
function NormZahl(wert) {
if(isNaN(wert)) {
wert = 0;
}
return wert;
}
function LuftMessDaten() {
httpGet(sURL, { timeout: 30000, "headers":{"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0"}}, (error, response) => {
if (!error && response.statusCode == 200) {
let info = response.data;
let sAIR = airBasis.split(',');
for (let i = 0; i <= sAIR.length-1; i++) {
AuswertungLuftMessDaten(info,sAIR[i]);
}
AuswertungLuftMessDatenEx();
CreateJSON();
info = '';
} else {
if (response.statusCode != 502) {
console.error('LuftMessDaten: ' + response.statusCode);
}
}
})
}
function CreateJSON() {
let JSON_List = [];
let sAIR = airBasis.split(',');
for (let i = 0; i <= sAIR.length-1; i++) {
JSON_List.push({"air": sAIR[i], "index": getState(sMainPath+sAIR[i]+'.index').val, "value": getState(sMainPath+sAIR[i]+'.value').val, "desc": getState(sMainPath+sAIR[i]+'.desc').val, "image": getState(sMainPath+sAIR[i]+'.image').val});
}
setState(sMainPath+'data_json', JSON.stringify(JSON_List), true);
JSON_List = [];
}
function AuswertungLuftMessDaten(sData='', sIndex=''){
var info = sData;
var Position = info.indexOf('window.current_data');
var dummy = info.substr(Position, 1000);
var Position = dummy.indexOf('"'+sIndex+'"');
var dummy = dummy.substr(Position, 100);
var Position = dummy.indexOf('"pi":');
var dummy = dummy.substr(Position+6, 7);
setState(sMainPath+sIndex+'.index', parseInt(dummy), true);
var lIndex = LuftIndex(parseInt(dummy));
setState(sMainPath+sIndex+'.desc', airDetails.split(',')[lIndex-1], true);
setState(sMainPath+sIndex+'.image', '/vis.0/luftdaten/aqip'+lIndex+'.png', true);
var Position = info.indexOf('window.current_data');
var dummy = info.substr(Position, 1000);
var Position = dummy.indexOf('"'+sIndex+'"');
var dummy = dummy.substr(Position, 100);
var Position = dummy.indexOf('"value_upm":');
var dummy = dummy.substr(Position+13, 7);
setState(sMainPath+sIndex+'.value', parseFloat(dummy), true);
}
function AuswertungLuftMessDatenEx(){
let sAIR = airBasis.split(',');
var aqi = Math.max(NormZahl(getState(sMainPath+sAIR[0]+'.index').val), NormZahl(getState(sMainPath+sAIR[1]+'.index').val), NormZahl(getState(sMainPath+sAIR[2]+'.index').val), NormZahl(getState(sMainPath+sAIR[3]+'.index').val));
var lIndex = LuftIndex(aqi);
setState(sMainPath+'Gesamt.value', aqi, true);
setState(sMainPath+'Gesamt.index', lIndex, true);
setState(sMainPath+'Gesamt.desc', airDetails.split(',')[lIndex-1], true);
setState(sMainPath+'Gesamt.image', '/vis.0/luftdaten/aqip'+lIndex+'.png', true);
}
function LuftIndex(aqi){
if (aqi <= 20) {
return 1;
} else if (aqi <= 50) {
return 2;
} else if (aqi <= 100) {
return 3;
} else if (aqi <= 150) {
return 4;
} else if (aqi <= 250) {
return 5;
} else {
return 6;
}
}
Im Grunde sollte alles selbsterklärend sein. Die hinzugefügten Kommentare geben Info und Einstellmöglichkeiten. Für Anregungen bin ich offen, auch wenn es ggfs. nicht gleich umgesetzt werden kann (die gute Zeit).
Ich wünsche euch viel Spaß.
Ro75.