Vorraussetzungen damit das Script läuft: nix
Dieses Script blockiert keine Rega Aufrufe und ist von der Konfiguration her möglichst simpel aufgebaut.
Systemvariablen werden z.B. automatisch angelegt.
Als Zeitraum zum Aufrufen verwende ich 20 Minuten.
Die Daten von OpenWeather werden aufbereitet, so das die Windgeschwindigkeiten in km/h erfolgen und eine Durchschnittsberechnung/Min/Max der nächsten 24 und 48 Stunden erfolgt. Diese Werte brauche ich für die Heizungssteuerung.
Nachdem der API-Key (Link: https://openweathermap.org/price - FREE "Get API Key") eingetragen ist, sollte es mit den mMn interessanten Tageswerten auch schon laufen.
Code: Alles auswählen
! HM_OpenWeather - Wetterdaten
! Copyleft Michael Henke
! Version: 0.8
!
! https://openweathermap.org/price - FREE
string appid = "Hier den API Key eintragen!";
! Werte eintragen, falls nicht vorhanden
var lat = system.Latitude();
var lon = system.Longitude();
! DP anpassen,
string para = '{
"DP": [
// [ Datenpunkt, Einheit, Name der Systemvariable/topic, Typ/Beschreibung ]
// Um Datenpunkte zu aktivieren die // entfernen
// Erweiterte Datenpunkte
["current.description", "", "Kurztext", "Info"],
// ["Temp24h.schnitt", "°C", "Next24h.Schnitt", "Info"],
// ["Temp24h.max", "°C", "Next24h.Max", "Info"],
// ["Temp24h.min", "°C", "Next24h.Min", "Info"],
// ["Temp48h.schnitt", "°C", "Next48h.Schnitt", "Info"],
// ["Temp48h.max", "°C", "Next48h.Max", "Info"],
// ["Temp48h.min", "°C", "Next48h.Min", "Info"],
["current.ACTUAL_TEMPERATURE", "°C", "ACTUAL_TEMPERATURE", "DP"],
["current.HUMIDITY", "%", "HUMIDITY", "DP"],
["current.wind_cardinal", "", "Windrichtung", "Info"],
// DP siehe https://openweathermap.org/api/one-call-3
// Beispiel Zugriff auf tägliche Werte
// ["daily.0.moon_phase", "", "MondPhase", "Info"],
["current.wind_speed", "km/h", "wind_speed", "DP"],
["current.wind_gust", "km/h", "wind_gust", "DP"],
["current.wind_deg", "°", "wind_deg", "DP"],
["current.pressure", "hPa", "pressure", "DP"],
["current.rain", "mm", "rain", "DP"],
// ["current.feels_like", "°C", "feels_like", "Info"],
// ["current.dew_point", "°C", "Taupunkt", "Info"],
// ["current.uvi", "", "UV_index_öäü", "Info"],
// ["current.clouds", "%", "Wolken", "Info"],
// ["current.visibility", "m", "Sicht", "Info"],
// NICHT ändern, muss als letzter bleiben
["","","",""]
],
"CCU": { "hostname": "localhost", "auth": "" },
"SysVar": { "Out": true, "Name": "OpenWeather" },
"pt": {
"hour12": false
},
// Werte für den Api Aufruf
"api": {
"lat": "${lat}",
"lon": "${lon}",
"appid": "${appid}",
"units": "metric",
"lang": "de",
"exclude": "minutely"
}
}';
! Ab hier, Finger weg :-)
para = para.Replace( "${lat}", lat).Replace( "${lon}", lon).Replace( "${appid}", appid);
!WriteLine ( para );
string js = '
const ScriptName = "HM_OpenWeather";
// HM_OpenWeather - Wetterdaten
// Copyleft Michael Henke
// Version: 0.8
var para = {};
try {
if (node) { }
if (msg.payload)
para = msg.payload;
}
catch (e) {
var node = null;
var msg = {};
ErrOut("script");
}
if (!node) {
if (process.argv[2]) {
let zeilen = process.argv[2].split ("\\n");
let jp = "";
zeilen.forEach(function (element) {
let z = element.trim();
if ( z.substring ( 0, 2 ) != "//" )
jp += z;
});
para = JSON.parse(jp);
console.log(para);
}
}
let url = "https://api.openweathermap.org/data/2.5/onecall";
{
let addUrl = "";
for (const key of Object.keys(para.api)) {
if (addUrl)
addUrl += "&";
addUrl += key + "=" + para.api[key];
}
if (addUrl)
url += "?" + addUrl;
}
httpGet(url, "OW")
.then((res) => {
let json = JSON.parse(res.data);
{
let akt = json.current;
if (typeof akt.temp != "number")
return;
if (akt.wind_deg == 360)
akt.wind_deg = 0;
{
let rain = 0;
if (akt.rain && akt.rain["1h"])
rain = akt.rain["1h"];
akt.rain = rain;
}
if (!akt.wind_gust) {
akt.wind_gust = 0; // msg.payload.hourly[0].wind_gust;
}
else {
// node.warn("Böen: " + pay.wind_gust);
}
function schnitt(hourly, anz) {
if (anz < hourly.lenght)
return;
let sch = {
max: Number.NEGATIVE_INFINITY,
min: Number.POSITIVE_INFINITY
};
// node.send({ payload: [] });
let sum = 0;
for (let index = 0; index < anz; index++) {
const ele = hourly[index];
if (ele.temp < sch.min)
sch.min = ele.temp;
if (ele.temp > sch.max)
sch.max = ele.temp;
sum += ele.temp;
}
sch.schnitt = Math.round(sum / anz * 10) / 10;
return sch;
}
json["Temp24h"] = schnitt(json.hourly, 24);
json["Temp48h"] = schnitt(json.hourly, 48);
akt.description = akt.weather[0].description;
akt.ACTUAL_TEMPERATURE = Math.round(akt.temp * 10) / 10;
akt.HUMIDITY = Math.round(akt.humidity * 100) / 100;
akt.wind_speed_mph = akt.wind_speed;
akt.wind_speed = Math.round(akt.wind_speed * 3.6 * 100) / 100;
akt.wind_gust_mph = akt.wind_gust;
akt.wind_gust = Math.round(akt.wind_gust * 3.6 * 100) / 100;
akt.wind_cardinal = degreesToCardinal(json.current.wind_deg);
para.DP.forEach(function (element) {
if ( !element[0] )
return;
let subAr = element[0].split(".");
let pos = json;
subAr.forEach(function (ss) {
pos = pos[ss];
});
sendDp(element, pos);
});
}
if (node)
{
dashboard(json);
node.status({ fill: "green", shape: "dot", text: new Date().toLocaleString("de") });
}
})
.catch((error) => {
ErrOut(error);
});
/**
* @param {any[]} ele
* @param {any} pay
*/
function sendDp(ele, pay) {
if (node)
node.send([null, null, { ts: new Date().getTime(), datapoint: ele[2], payload: pay, unit: ele[1], para: ele[3] }]);
// else
{
setSysvar(para.SysVar.Name + "." + ele[2], pay, ele[1], ele[3]);
// console.log("datapoint: " + ele[2] + "Wert: " + pay + " " + ele[1] + " - " + ele[3]);
}
}
/**
* @param {number} deg
*/
function degreesToCardinal(deg) {
if (deg > 11.25 && deg <= 33.75) { return "NNE"; }
else if (deg > 33.75 && deg < 56.25) { return "NE"; }
else if (deg > 56.25 && deg < 78.75) { return "ENE"; }
else if (deg > 78.75 && deg < 101.25) { return "E"; }
else if (deg > 101.25 && deg < 123.75) { return "ESE"; }
else if (deg > 123.75 && deg < 146.25) { return "SE"; }
else if (deg > 146.25 && deg < 168.75) { return "SSE"; }
else if (deg > 168.75 && deg < 191.25) { return "S"; }
else if (deg > 191.25 && deg < 213.75) { return "SSW"; }
else if (deg > 213.75 && deg < 236.25) { return "SW"; }
else if (deg > 236.25 && deg < 258.75) { return "WSW"; }
else if (deg > 258.75 && deg < 281.25) { return "W"; }
else if (deg > 281.25 && deg < 303.75) { return "WNW"; }
else if (deg > 303.75 && deg < 326.25) { return "NW"; }
else if (deg > 326.25 && deg < 348.75) { return "NNW"; }
else { return "N"; }
}
function dashboard(json) {
let mg = msg;
mg.payload = json;
let pt_hour12 = para.pt.hour12;
let units = para.api.units;
if (units === undefined) { units = "imperial"; }
let pt_lang = para.api.lang;
function timeConvert(UNIX_timestamp) {
let dateObject = new Date(UNIX_timestamp * 1000);
if (pt_hour12) { // 12 hour time format
return dateObject.toLocaleString("en", { timeZone: json.timezone, hour12: true, hour: "numeric", minute: "2-digit" }).toLowerCase();
} else { // 24 hour time format
return dateObject.toLocaleString("en", { timeZone: json.timezone, hour12: false, hour: "numeric", minute: "2-digit" });
}
}
if (units == "imperial") {
mg.payload.temp = json.current.temp.toFixed() + " °F";
mg.payload.wind_speed_Txt = json.current.wind_speed_mph.toFixed() + " mph";
}
else // metric units
{
mg.payload.temp = json.current.temp.toFixed(1) + " °C";
mg.payload.wind_speed_Txt = (json.current.wind_speed_mph * 3.6).toFixed();
if (json.current.wind_gust)
mg.payload.wind_speed_Txt += "/" + (json.current.wind_gust_mph * 3.6).toFixed();
mg.payload.wind_speed_Txt += " km/h";
}
mg.payload.wind_speed_Txt += " " + json.current.wind_cardinal;
mg.payload.sunrise = timeConvert(json.current.sunrise);
mg.payload.sunset = timeConvert(json.current.sunset);
function formatTemp(high, low) {
let temp = "";
if (units == "imperial") {
if (low) {
temp = parseFloat(high).toFixed() + "/" + parseFloat(low).toFixed()
}
else {
temp = parseFloat(high).toFixed() + "°F"
}
}
else { // metric
if (low) {
temp = parseFloat(high).toFixed() + "/" + parseFloat(low).toFixed()
}
else {
temp = parseFloat(high).toFixed() + "°C"
}
}
return temp;
}
function dayName(unixTime) {
let dateObject = new Date(unixTime * 1000);
return dateObject.toLocaleString(pt_lang, { timeZone: json.timezone, weekday: "short" });
}
function timeConvertIcons(UNIX_timestamp) {
let dateObject = new Date(UNIX_timestamp * 1000);
if (pt_hour12) { // 12 hour time format
return dateObject.toLocaleString("en", { timeZone: json.timezone, hour12: true, hour: "numeric" }).toLowerCase();
} else { // 24 hour time format
return dateObject.toLocaleString("en", { timeZone: json.timezone, hour12: false, hour: "numeric" }) /*+ ":00"*/;
}
}
// prepare forecast data for CSS based ui widget
mg.hourly = { rowtext: { data01: {}, data02: {} }, rowicons: { data01: {} }, rowInfoIcon: { data01: {} } };
let count = 1;
json.hourly.forEach(function (element) {
mg.hourly.rowicons.data01["cell" + count] = element.weather[0].icon;
mg.hourly.rowtext.data01["cell" + count] = timeConvertIcons(element.dt);
mg.hourly.rowtext.data02["cell" + count] = formatTemp(element.temp);
mg.hourly.rowInfoIcon.data01["cell" + count] = info2(element);
if (count > 10)
return;
count++;
});
mg.daily = { rowtext: { data01: {}, data02: {} }, rowicons: { data01: {} }, rowInfoIcon: { data01: {} } };
count = 1;
json.daily.forEach(function (element) {
mg.daily.rowicons.data01["cell" + count] = element.weather[0].icon;
mg.daily.rowtext.data01["cell" + count] = dayName(element.dt);
mg.daily.rowtext.data02["cell" + count] = formatTemp(element.temp.max, element.temp.min);
mg.daily.rowInfoIcon.data01["cell" + count] = info2(element);
count++;
});
let iconString = "wi-owm-" + json.current.weather[0].icon + " wi-4x";
let icon = {
ui_control: {
icon: iconString
}
};
if (node)
node.send([mg, icon]);
function info2(element) {
let rain = 0;
if (element.rain) {
if (element.rain["1h"])
rain = element.rain["1h"];
else
rain = element.rain;
}
let txt = "";
let icon = "";
if (rain >= 1) {
txt = Math.round(rain);
icon = "fa fa-tint";
}
if (element.wind_gust && (element.wind_gust >= 60 / 3.6)) {
txt = Math.round(element.wind_gust * 3.6);
icon = "wi wi-darksky-wind";
}
return [icon, txt];
}
}
function ErrOut(txt = "") {
if (node) {
node.error(txt);
node.status({ fill: "red", shape: "dot", text: "Fehler: " + txt });
}
else {
console.error(txt);
}
}
function httpGet(url, typ = "") {
if (!url)
return null;
return new Promise((resolve, reject) => {
const httpUse = (url.indexOf("https://") === 0) ? require("https") : require("http");
// debugger;
httpUse.get(url, (res) => {
// console.log("statusCode:", res.statusCode);
if (res.statusCode != 200) {
reject("statusCode: " + res.statusCode);
return;
}
// console.log("headers:", res.headers);
let data = "";
res.on("data", (chunk) => {
// console.log(chunk);
data += chunk;
});
res.on("end", () => {
// console.log(data);
resolve({ typ: typ, data: data });
});
}).on("error", (e) => {
reject(e);
});
});
}
// Systemvariable CCU anlegen und Wert schreiben
function setSysvar(name, wert, unit = "", beschreibung = "") {
// beschreibung += "öäs";
if (!para.SysVar.Out)
return;
// debugger;
let type;
let addMinMax = false;
switch (typeof wert) {
case "number":
type = { t: "ivtFloat", s: "istGeneric" };
addMinMax = true;
break;
case "string":
default:
type = { t: "ivtString", s: "istChar8859" };
// wert += "äää";
break;
}
let script = `
var ww = "${wert}";
if ( ${type.t} == ivtFloat ) { ww = ww.ToFloat(); }
string sName = "${name}";
object svObj = dom.GetObject (ID_SYSTEM_VARIABLES).Get (sName);
if (!svObj) {
svObj = dom.CreateObject(OT_VARDP,sName);
svObj.DPInfo("${beschreibung}");
svObj.ValueUnit("${unit}");
dom.GetObject (ID_SYSTEM_VARIABLES).Add(svObj);
svObj.ValueType(${type.t});
svObj.ValueSubType(${type.s});
if ( ${addMinMax} )
{
svObj.ValueMin(0);
svObj.ValueMax(0);
}
svObj.State (ww);
dom.RTUpdate(0);
}
else
{ svObj.State(ww);}
`;
runScript(script);
}
function runScript(script, callback = null) {
const http = require("http");
let postData = Buffer.from(script, "latin1");
const options = {
hostname: para.CCU.hostname,
port: 8181,
path: "/rega.exe",
method: "POST",
encoding: "iso-8859-1",
// encoding: "utf-8",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": postData.length,
},
};
if (para.CCU.auth)
options.auth = para.CCU.auth;
const req = http.request(options, (res) => {
// console.log(`STATUS: ${res.statusCode}`);
// console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
// res.setEncoding("utf-8");
res.setEncoding("binary");
let data = "";
res.on("data", (chunk) => {
// debugger;
// console.log(chunk);
data += chunk;
});
res.on("end", () => {
if (callback)
callback(data);
});
});
req.on("error", (e) => {
ErrOut("CCU problem with request: " + e);
});
// Write data to request body
req.write(postData);
req.end();
}
';
string stdout; string stderr;
system.Exec( "node -e '" # js # "' ' ' '" # para.ToUTF8() # "' &",&stdout,&stderr);
js = "";
para = "";
if (stderr) { Write(stderr); quit; }
WriteLine( stdout);