dient zur anzeige der warnungen des fhem device Unwetterzentrale.
alle icons sind inline svg elemente, somit ist keine inet verbindung nötig um die component zu nutzen.
[update vom 28.08.23]
falls probleme mit dem weatherwarning auftreten ist es höchstwahrscheinlich ein swiper problem.
weshalb der swiper (https://forum.fhem.de/index.php?topic=134357.0) erst einmal auf einen aktuelleren stand gebracht werden muss.
weatherwarning.component.js
/*
* Weatherwarning component for FTUI version 3
* Frontend for Unwetterzentrale
*
* (c) 2023 by jones
*
* Under MIT License (http://www.opensource.org/licenses/mit-license.php)
*
* https://github.com/knowthelist/ftui
*/
/*
parameter (only device MUST be set, all others are optional)
-----------------------------------------------------------------------
device: the fhem UWZ device (on unknown device, a demo starts)
interval: the interval of the auto-swipe in seconds
0 for switch off autoswipe
txttype: short | long : UWZ texttype
auto: when "txtmaxlen" is reached switch to short txttype
txtmaxlen: (range: 100-650) clip text at this text-pos
size: (range: 0-4) ftui-label size for the warn-text
scrollbar: if set, the swiper shows scrollbars (NOT recommendet)
*/
import { FtuiElement } from '../element.component.js';
import { fhemService } from '../../modules/ftui/fhem.service.js';
import { dateFromString, dateFormat } from '../../modules/ftui/ftui.helper.js';
//////////////////////////////////////////////////////////////////////////////////////////////
// weatherwarning class: show weatherwarning
//////////////////////////////////////////////////////////////////////////////////////////////
export class FtuiWeatherwarning extends FtuiElement {
constructor(properties) {
super(Object.assign(FtuiWeatherwarning.properties, properties));
this.column = this.shadowRoot.getElementById('firstCol');
this.lastUpdate = 0;
this.showScroller = "";
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Reading of the fhem device has changed
//////////////////////////////////////////////////////////////////////////////////////////////
onChangeReading(read) {
if (!read) return;
let time = new Date().getTime();
if (time - this.lastUpdate > 4000) // MANY onChangeReading() events in first 4s after creating!?
{
//alert("onChangeReading()")
this.lastUpdate = time;
this.fetchData();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
// The html/css part of this component
//////////////////////////////////////////////////////////////////////////////////////////////
template() {
return `<ftui-column id="firstCol"></ftui-column>`
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Default properties (MUST be lowercase without whitespaces)
// Will be overwritten by parameter in <ftui-weaterwarning> html element
//////////////////////////////////////////////////////////////////////////////////////////////
static get properties() {
return {
device: 'Unwetterzentrale',
interval: '8',
txttype: 'long',
txtmaxlen: '650', // maximal length of the warning text
size: '1',
scrollbar: '',
};
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Convert properties to attributes
//////////////////////////////////////////////////////////////////////////////////////////////
static get observedAttributes() {
return [...this.convertToAttributes(FtuiWeatherwarning.properties), ...super.observedAttributes];
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Component has connected to fhem.
//////////////////////////////////////////////////////////////////////////////////////////////
onConnected() {
//alert("onConnected()")
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Triggers on every attribute defined in <ftui-weatherwarning> html element
//////////////////////////////////////////////////////////////////////////////////////////////
onAttributeChanged(name) {
switch (name) {
case 'device':
fhemService.getReadingEvents(this.device).subscribe(read => this.onChangeReading(read));
break;
case 'txttype':
if (this.txttype != "short" && this.txttype != "auto")
this.txttype = "long";
break;
case 'txtmaxlen':
if (this.txtmaxlen < 100 || this.txtmaxlen > 650)
this.txtmaxlen = 650;
break;
case 'scrollbar':
this.showScroller = "scrollbar";
break;
case 'size':
if (this.size < 0 || this.size > 4)
this.size = 1;
break;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
// Get the whole data for this device from fhem
//////////////////////////////////////////////////////////////////////////////////////////////
fetchData(){
fhemService.sendCommand('jsonlist2 ' + this.device)
.then(response => response.json())
.then((response) => {
////////////////////////////////////////////////////////////////////////////////////////
// response-Object: Name, PossibleSets, PossibleAttrs, Internals, Readings, Attributes
// Internals -> of the fhem device (DEF, FUUID, ...)
// Readings -> of the fhem Device (fc0_cloud00, ...)
// Attributes -> of the fhem Device (devStateIcon, ...)
////////////////////////////////////////////////////////////////////////////////////////
let readings;
if (response.Results[0]) {
readings = response.Results[0].Readings;
}
else { // Device unknown, start DEMO mode
const strDemo="<b>Fhem device <i><u>"+this.device+"</u></i> wurde nicht gefunden oder wird nicht unterstüzt.</b><br>Demo Modus ist jetzt aktiv.<br><br>Warnung ";
readings = {"WarnCount":{Value: 11},
"Warn_0_uwzLevel": {Value:1},"Warn_0_Start" :{Value:888},"Warn_0_End" :{Value:999},"Warn_0_LongText": {Value:strDemo+"1: unknown"}, "Warn_0_Type" :{Value: 1},
"Warn_1_uwzLevel": {Value:2},"Warn_1_Start" :{Value:888},"Warn_1_End" :{Value:999},"Warn_1_LongText": {Value:strDemo+"2: Sturm/Orkan"}, "Warn_1_Type" :{Value: 2},
"Warn_2_uwzLevel": {Value:3},"Warn_2_Start" :{Value:888},"Warn_2_End" :{Value:999},"Warn_2_LongText": {Value:strDemo+"3: Schneefall"}, "Warn_2_Type" :{Value: 3},
"Warn_3_uwzLevel": {Value:4},"Warn_3_Start" :{Value:888},"Warn_3_End" :{Value:999},"Warn_3_LongText": {Value:strDemo+"4: Regen"}, "Warn_3_Type" :{Value: 4},
"Warn_4_uwzLevel": {Value:5},"Warn_4_Start" :{Value:888},"Warn_4_End" :{Value:999},"Warn_4_LongText": {Value:strDemo+"5: Extremfrost"}, "Warn_4_Type" :{Value: 5},
"Warn_5_uwzLevel": {Value:1},"Warn_5_Start" :{Value:888},"Warn_5_End" :{Value:999},"Warn_5_LongText": {Value:strDemo+"6: Waldbrand"}, "Warn_5_Type" :{Value: 6},
"Warn_6_uwzLevel": {Value:2},"Warn_6_Start" :{Value:888},"Warn_6_End" :{Value:999},"Warn_6_LongText": {Value:strDemo+"7: Gewitter"}, "Warn_6_Type" :{Value: 7},
"Warn_7_uwzLevel": {Value:3},"Warn_7_Start" :{Value:888},"Warn_7_End" :{Value:999},"Warn_7_LongText": {Value:strDemo+"8: Glätte"}, "Warn_7_Type" :{Value: 8},
"Warn_8_uwzLevel": {Value:4},"Warn_8_Start" :{Value:888},"Warn_8_End" :{Value:999},"Warn_8_LongText": {Value:strDemo+"9: Hitze"}, "Warn_8_Type" :{Value: 9},
"Warn_9_uwzLevel": {Value:5},"Warn_9_Start" :{Value:888},"Warn_9_End" :{Value:999},"Warn_9_LongText": {Value:strDemo+"10: Glatteisregen"},"Warn_9_Type" :{Value:10},
"Warn_10_uwzLevel":{Value:1},"Warn_10_Start":{Value:888},"Warn_10_End":{Value:999},"Warn_10_LongText":{Value:strDemo+"11: Bodenfrost"}, "Warn_10_Type":{Value:11},
}
}
////////////////////////////////////////////////////////////////////////////////////////
// WarnTypes are listed here https://github.com/tobias-d-oe/fhem-uwz
// WarnTypes icons are made by jones and are under Creative Commons Zero-Lizenz (CC0)
// Inline svg instructions: de.wikipedia.org/wiki/Scalable_Vector_Graphics
// Inline svg Editor: https://yqnn.github.io/svg-path-editor/
////////////////////////////////////////////////////////////////////////////////////////
const warnType=[
// 0: Default [Ausrufezeichen]
'<path stroke="black" fill="black" d="M 51 104 A 6 6 0 1 0 51.10 104" /><path stroke="black" fill="black" stroke-width="10" stroke-linecap="round" d="M 51 96 v -27" />',
// 1: unknown [Ausrufezeichen]
'<path stroke="black" fill="black" d="M 51 104 A 6 6 0 1 0 51.10 104" /><path stroke="black" fill="black" stroke-width="10" stroke-linecap="round" d="M 51 96 v -27" />',
// 2: Sturm/Orkan [Windhose]
`<path stroke="black" fill="black" stroke-width="4" d="M 39 78 v 40 "/><path d="M 44 97.0 l 6 -1 v -16 l -6 -1"/>
<path d="M 52 95.6 l 6 -1 v -12.9 l -6 -1"/><path d="M 60 94.3 l 6 -1 v -10.3 l -6 -1"/>`,
// 3: Schneefall [Wolke mit Schneeflocken]
`<path stroke="black" stroke-width="2" fill="transparent" d="
m 45.5 96 a 7.2 7.2 90 1 1 -1.8 -19.8 q 0 -6.3 9 -5.4 q 7.2 0.9 7.2 9 a 7.2 7.2 90 1 1 0 16.2 z"/>
<path id ="flake" stroke="black" stroke-width="0.5" d="M 42 106 v -9 m -4.5 4.5 h 9 m -7.65 3.15 l 6.3 -6.3 m -6.3 0 l 6.3 6.3"/>
<use xlink:href="#flake" transform="translate(7, 3)"/><use xlink:href="#flake" transform="translate(15, -1)"/>
<use xlink:href="#flake" transform="translate(23, 2)"/>`,
// 4: Regen [Wolke mit Regentropfen]
`<path stroke="black" stroke-width="2" fill="transparent" d="
m 45.5 96 a 7.2 7.2 90 1 1 -1.8 -19.8 q 0 -6.3 9 -5.4 q 7.2 0.9 7.2 9 a 7.2 7.2 90 1 1 0 16.2 z"/>
<path id ="raindrop" stroke="black" stroke-width="2" fill="transparent" d="M 43 102 a 1 1 90 0 0 2 0 q 0 -1 -1 -2.5 q -1 1.5 -1 2.5"/>
<use xlink:href="#raindrop" transform="translate(5, 3)"/><use xlink:href="#raindrop" transform="translate(11, -1)"/>
<use xlink:href="#raindrop" transform="translate(17, 2)"/>`,
// 5: Extremfrost [Schneeflocke]
`<path stroke="black" stroke-width="4" stroke-linecap="round" d="M 49 80 l -3 -2 M 53 80 l 3 -2 M 51 76 v 32 M 60.4 84.3 l 0.2 -3.6
M 62.4 87.7 l 3.2 1.6 M 64.9 84 l -27.9 16 M 62.4 96.3 l 3.2 -1.6 M 60.4 99.7 l 0.2 3.6 M 64.9 100 l -27.9 -16 M 53 104 l 3 2
M 49 104 l -3 2 M 41.6 99.7 l -0.2 3.6 M 39.6 96.3 l -3.2 -1.6 M 39.6 87.7 l -3.2 1.6 M 41.6 84.3 l -0.2 -3.6"/>`,
// 6: Waldbrand [Tanne mit Feuer]
`<path stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="transparent" d="
M 64 108 l -8 -10 h 5 l -8 -10 h 5 l -8 -10 l -8 10 h 5 l -8 10 h 5 l -8 10 z m -10.5 0 v 5 h -7 v -5"/>
<path id ="fire" stroke="red" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="gold" d="
M 67 113 a 7 7 0 0 0 10 0 a 60 -16 0 0 0 -0.5 -8 a 7 7 0 0 0 -1.5 2 a 7 7 0 0 0 -5.5 -8 a 2 4 0 0 1 -2.5 8 a 9 7 0 0 0 0 6"/>
<use xlink:href="#fire" transform="translate(-26, 14) scale(0.8)"/><use xlink:href="#fire" transform="translate(-2, 47) scale(0.6)"/>`,
// 7: Gewitter [Blitz]
'<path d="M 47 70 l -10.6 27.7 l 13.2 -4 l -11.9 23.8 l 27.7 -34.3 l -15.8 4 l 9.2 -18.5 z" />',
// 8: Glätte [Rutschige Straße]
`<path id ="flake" stroke="black" stroke-width="0.5" stroke-linecap="round" fill="black" d="m 32.1 92.7 c 1.6 -7.7 1.4 -10 4.9 -9.9
l 2.6 -5.6 c 0.8 -2 2.1 -3.7 4.2 -3.5 l 15.7 1.5 c 2.1 0.2 3.2 2.1 3.5 4.3 l 0.8 5.7 c 2.8 1.6 2.6 1.9 1.8 11 l -3.7 -0.4 l -0.4 3.5
l -4.9 -0.5 l 0.4 -3.5 l -16.2 -1.7 l -0.5 3.4 l -4.9 -0.5 l 0.6 -3.5 z m 28.1 8.9 a 5.2 5.2 0 0 1 3 -0.5 a 3.2 3.2 0 0 0 -1.1 0.8
c -1.2 1.5 0.4 2.5 1.4 3.2 c 3.2 2.4 15.4 5.3 16.8 10.1 a 4.3 4.3 0 0 1 -0.8 2.9 h -8.7 a 3.4 3.4 0 0 0 1.4 -2.8
c -0.6 -2.6 -6.4 -4.5 -8.2 -5.6 a 16.1 16.1 0 0 1 -3.4 -2.6 c -1.5 -1.6 -2.8 -4.1 -0.4 -5.5 m -27.6 -2.2 a 5.1 5.1 0 0 1 3.5 -0.6
a 3.2 3.2 0 0 0 -1.6 1.4 c -0.7 1.6 1 2.7 2.1 3.4 c 3.8 2.6 15.8 5.7 17.3 10.9 a 4.9 4.9 0 0 1 -0.9 3.1 h -9 a 3.8 3.8 0 0 0 1.4 -3
c -0.3 -2.6 -6.6 -4.9 -8.5 -6.1 a 16.7 16.7 0 0 1 -3.5 -2.8 c -1.5 -1.7 -3.4 -4.6 -0.8 -6.3 m 6.9 -16.5 l 21.1 2
c 0 -6.5 -0.2 -7.8 -1.8 -7.9 l -14.1 -1.3 c -1.6 -0.2 -2.6 1.2 -3.2 2.7 l -2 4.5"/>`,
// 9: Hitze [Thermometer Hitze]
`<path stroke="black" stroke-width="2.2" fill="red" d="
M 54 91.4 h -6 m 6 -7.9 h -5.9 m 5.9 -7.5 h -6 m 6.1 -5 v 30.1 a 6 6 0 1 0 3.5 0 v -30.1"/>
<path stroke="black" stroke-width="2.2" fill="transparent" d="m 54.1 71 v -0.9 a 1 1 0 0 1 3.5 0 v 0.9
M 41 105 a 6 6 90 1 0 0 0.1 z m 1.952 0.042 l 5.08 0 m -21.114 -0.103 l -4.875 0 m 12.982 8.082 l 0 5.022 m 5.6319 -18.6999
l 3.5355 -3.5355 m -3.5355 14.8493 l 3.5355 3.5355 m -14.8493 -3.5355 l -3.5355 3.5355 m 3.5355 -14.8493 l -3.3311 -3.2961
m 8.988 0.953 v -5"/>`,
// 10: Glatteisregen [Wolke mit Schnee und Regen]
`<path stroke="black" stroke-width="2" fill="transparent" d="
m 45.5 96 a 7.2 7.2 90 1 1 -1.8 -19.8 q 0 -6.3 9 -5.4 q 7.2 0.9 7.2 9 a 7.2 7.2 90 1 1 0 16.2 z"/>
<path id ="flake" stroke="black" stroke-width="0.5" d="M 41 106 v -9 m -4.5 4.5 h 9 m -7.65 3.15 l 6.3 -6.3 m -6.3 0 l 6.3 6.3"/>
<path id ="raindrop" stroke="black" stroke-width="2" d="M 47 105 a 1 1 90 0 0 2 0 q 0 -1 -1 -2.5 q -1 1.5 -1 2.5"/>
<use xlink:href="#flake" transform="translate(15, 2)"/><use xlink:href="#raindrop" transform="translate(16, -2)"/>`,
// 11: Bodenfrost [Thermometer Kälte und Schneeflocke]
`<path stroke="black" stroke-width="2" stroke-linecap="round" d="M 33 98 l -2.1 -1.4 m 4.9 1.4 l 2.1 -1.4 m -3.5 -1.4 v 22.4 m 6.6 -16.6
l 0.1 -2.5 m 1.3 4.9 l 2.2 1.1 m -0.5 -3.7 l -19.5 11.2 m 17.8 -2.6 l 2.2 -1.1 m -3.6 3.5 l 0.1 2.5 m 3 -2.3 l -19.5 -11.2 m 11.2 14
l 2.1 1.4 m -4.9 -1.4 l -2.1 1.4 m -3.1 -4.4 l -0.1 2.5 m -1.3 -4.9 l -2.2 -1.1 m 2.2 -4.9 l -2.2 1.1 m 3.6 -3.5 l -0.1 -2.5"/>
<path stroke="blue" stroke-width="4" fill="blue" d="M 51.3 110.5 H 60.3 "/><path stroke="black" stroke-width="2.2" fill="transparent"
d="M 54 91.4 h -6 m 6 -7.9 h -5.9 m 5.9 -7.5 h -6 m 6.1 -5 v 30.1 a 6 6 0 1 0 3.5 0 v -30.1 M 54.1 71 v -0.9 a 1 1 0 0 1 3.5 0 v 0.9"/>`,
];
const warnLevel=[
"green", // 0: no warnings
"darkgreen", // 1: weather notice
"yellow", // 2: early warning
"orange", // 3: weather warning
"red", // 4: bad weather
"purple" // 5: extrem weather
];
this.column.textContent = ''; // delete all children
const sumWarnings = (readings["WarnCount"] === undefined)?-1:readings["WarnCount"].Value;
if (sumWarnings == -1)
return this.column.innerHTML = 'Kein reading "WarnCount" im fhem device '+this.device+' gefunden!';
if (sumWarnings == 0)
return this.column.innerHTML = 'Keine aktuellen Warnungen';
// remove @click as soon as swiper is working correctly!
//let content='<ftui-swiper ' + this.showScroller + ' style="width: 600px;color: black;border-radius: 15px;" @click="this.next(); this.checkInterval();" dots auto-play interval="'+this.interval+'">';
let content='<ftui-swiper ' + this.showScroller + ' style="width: 600px;color: black;border-radius: 15px;" dots auto-play interval="'+this.interval+'">';
for (let i = 0; i < sumWarnings; i++) {
const warnColor = warnLevel[readings["Warn_" + i + "_uwzLevel"].Value];
const warnStart = dateFormat(new Date(readings["Warn_" + i + "_Start"].Value * 1000), 'DD.MM.YYYY hh:mm');
const warnEnd = dateFormat(new Date(readings["Warn_" + i + "_End"].Value * 1000), 'DD.MM.YYYY hh:mm');
let text = readings["Warn_" + i + "_LongText"].Value; // default is LongText
if (this.txttype == "short" || (this.txttype == "auto" && text.length > this.txtmaxlen))
text = readings["Warn_" + i + "_ShortText"].Value;
text = (text.length < this.txtmaxlen)?text:text.substring(0, this.txtmaxlen)+"...";
////////////////////////////////////////////////////////////////////////////////////////
// build html
////////////////////////////////////////////////////////////////////////////////////////
content+=`<table id="Sw_` + i + `" style="background-color: ` + warnColor + `;"><tr><td style="width: 107px;">`;
// Empty warning sign
content+='<svg width="100" height="140">'
content+='<path stroke="white" stroke-width="10" stroke-linejoin="round" fill="white" d="M 51.1 43 l 45 80 h -90 z"/>';
content+='<path stroke="red" stroke-width="7" stroke-linejoin="round" fill="transparent" d="M 51.0 43 l 45 80 h -90 z"/>';
// warnType for the warning sign
let type = readings["Warn_" + i + "_Type"].Value;
content+= warnType[type>11?0:type] + '</svg>';
// warning period
content+='</td><td style="width:auto; text-align:left;"><ftui-label size="' +this.size + '" text="'+ text +'" scroll></ftui-label>';
content+='</td></tr><tr><td></td><td style="height:6px;"><i>Gültig vom: '+warnStart+' bis zum: '+warnEnd+'</i></td></tr>';
content+='</table>'
}
this.column.innerHTML = content + "</ftui-swiper>";
})
}
}
window.customElements.define('ftui-weatherwarning', FtuiWeatherwarning);
fragen an die profis:
1) manchmal wird der ftui-swiper nicht richtig geladen. dann sind sie warnungen nicht mehr hintereinander, sondern diese stehen alle untereinander.
weatherwarning.png
dies ist mir heute passiert, aber dann ging es plötzlich wieder.
ich kann das problem nicht zuverlässig auslösen, da es nur heute bei weatherwarning aufgetreten ist.
liegt dies an ftui3, am swiper, oder an meinem code?
was mir aufgefallen ist das, wenn das problem auftritt, die ladezeiten der icons/bilder auf der seite deutlich
länger zum laden brauchten.
habe dies auch schon bei den demos von ftui3 erlebt und habe zzt keine ahnung wo ich anfange soll zu suchen.
2) ich habe ein bischen mit css gespielt und gesehen das im swiper css der firefox spezifische code nicht vorhanden ist. habe einen vorschlag gemacht wie dies für firefox aussehen könnte.
ist dies etwas was in ftui3 aufgenommen werden könnte, oder warten wir noch auf eine gesamt lösung für den ftui-swiper welcher aller probleme löst?
Hi,
das ist ein FF/swiper Problem.
Die Startposition wird nicht immer korrekt gelesen und gesetzt.
Ist bei meinen Tests nur da aufgefallen.
Unter Chrome nicht.
LG
mist, ist irgendwie alles komplizierter als gedacht.
ich fürchte bis ich auf dem stand bin sowas zu lösen, gibts es schon ftui9 mit neuen problemne...
Hallo Jones,
kann man deine weatherwarning.component.js auch für das Modul DWD_OpenData erweitern?
Gruß Markus
Zitat von: meier81 am 03 September 2023, 21:56:41kann man deine weatherwarning.component.js auch für das Modul DWD_OpenData erweitern?
Davon abgesehen, dass diese component bestimmt erweitert werden kann, kann man jetzt schon DWD Warnungen aus dem DWD_OpenData Modul mit 95% der FTUI3-Bordmitteln anzeigen: [FTUI 3] DWD Warnungen des DWD-Opendata Moduls anzeigen (https://forum.fhem.de/index.php?topic=117858)
@meier81:
hätte kein problem damit es einzubauen wenn ich dwd gut finden würde.
das ist halt eine persönliche geschichte - habe es nach dem testen direkt wieder aus fhem gelöscht.
ich finde die kombination aus proplanta und unwetterzentrale deutlich besser/schöner/weiter.
wäre vielleicht auch über meinen schatten gesprungen wenn es nix anderes für dwd gegeben hätte,
aber wie yersinia schon sagte existiert da schon was.