[SOLVED] JSON Path weather warnings DWD (Deutscher Wetterdienst)

Hello Martin,
great binding. Works perfectly.
Unfortunately, I get the date and time displayed in the Habpanel in a long string.
Can I change that without using a big rule?
greeting
Oliver

Can you try the newest version from https://github.com/limdul79/openhab2-addons/tree/dwd and re-create the item? The item should be of the Type DateTime. With that, you should be able to format the Item in HABPanel with Format Strings.

@LimDul copied yesterday a new .jar file on his google drive. Thank you!

So far no error in the logs.

When i read the table in the documentation (thank you!) here: https://github.com/limdul79/openhab2-addons/tree/dwd/addons/binding/org.openhab.binding.dwdunwetter there is no “last update” item?

In the lack of “Unwetter” i can’t test the function … :slight_smile:

For testing, I look for regions with active warnings and change my thing :slight_smile:

Yes, there is no lastUpdate Item - SImple Reason I haven’t thought about ist. But I might add one (only one per thing, regardless of the number of warnings provided)

The lastUpdate Item is, in my opinion, only useful to check if the DWD Server is online and if the OpenHAB Binding ist working. (I wasn’t aware that my existing installation was not working … so missed a lot of warnings :slight_smile: )

it workes :slight_smile:

The switch is off … normal?

Should not be off. I have updated the binding and uploaded new Jars, including a last updated Channel :slight_smile:

I fixed the problem that at the first startup there were empty items and only after waiting the refresh Time it got populated.

1 Like

Now we need a “Unwetter” to test :slight_smile:
Or should it also output “Amtliche WARNUNG vor GLATTEIS” ?
And if yes, when the “Warnung” is updated or is ok if the warning exists, before activating the binding?

Thing

dwdunwetter:dwdwarnings:home    "Wetterwarnungen Ludwigshafen"  [ cellId="107314000", refresh=15, warningCount=3 ]

Items

DateTime    dwdUnwetter_Home_LastUpdate                     "Letzte Aktualisierung [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]" <time>    { channel="dwdunwetter:dwdwarnings:home:lastUpdated" }
    Switch      dwdUnwetter_Home_Event1_isWarning               "Wetterwarnung"                                                    { channel="dwdunwetter:dwdwarnings:home:warning1" }
    String      dwdUnwetter_Home_Event1_Type                    "Typ [%s]"                                                         { channel="dwdunwetter:dwdwarnings:home:event1" }
    String      dwdUnwetter_Home_Event1_Severity                "Stufe [%s]"                                                       { channel="dwdunwetter:dwdwarnings:home:severity1" }
    String      dwdUnwetter_Home_Event1_Title                   "Titel [%s]"                                                       { channel="dwdunwetter:dwdwarnings:home:headline1" }
    String      dwdUnwetter_Home_Event1_Description             "Beschreibung [%s]"                                                { channel="dwdunwetter:dwdwarnings:home:description1" }
    String      dwdUnwetter_Home_Event1_Altitude                "Höhe ab [%d m]"                                                   { channel="dwdunwetter:dwdwarnings:home:altitude1" }
    String      dwdUnwetter_Home_Event1_Ceiling                 "Höhe bis [%d m]"                                                  { channel="dwdunwetter:dwdwarnings:home:ceiling1" }
    String      dwdUnwetter_Home_Event1_DatePublished           "Herausgegeben [%s]"                                               { channel="dwdunwetter:dwdwarnings:home:effective1" }
    String      dwdUnwetter_Home_Event1_ValidFrom               "Gültig ab [%s]"                                                   { channel="dwdunwetter:dwdwarnings:home:onset1" }
    String      dwdUnwetter_Home_Event1_ValidTo                 "Gültig bis [%s]"                                                  { channel="dwdunwetter:dwdwarnings:home:expires1" }
    DateTime    dwdUnwetter_Home_Event1_Updated                 "Aktualisiert am [%1$td.%1$tm.%1$tY, %1$tH:%1$tM]" <time>          { channel="dwdunwetter:dwdwarnings:home:updated1" }


Does anyone have an idea, why no Warning is triggered or if ice-warnings and so on should be visible in OpenHAB?

I only receive dwdunwetter:dwdwarnings:home:updated1 .

Update: Now it works. Magic! :slight_smile: @AzraelMasters You are using the id of the city. Have you tried the identifier of the community?

807314000 Stadt Ludwigshafen am Rhein or
907338999 Rhein-Pfalz-Kreis und Stadt Ludwigshafen

Haven’t tried so far. I only did some Tests with other Cities.
I will give 807314000 a try. But currently no Warning for Germany, so I have to wait :slight_smile:

Thanks for your help and the idea :wink:

I created a new thread for the binding. So we can finally leave this one here in peace. :slight_smile:

Hi all,
DWD weather raises an error and doesn’t work at the moment.

newString:

May 25 07:21:00 raspberrypi karaf[3705]: newString warnWetter.loadWarnings({"time":1558761150000,"warnings":{},"vorabInformation":{},"copyright":"Copyright Deutscher Wetterdienst"});

openhab.log:

2019-05-25 07:20:00.336 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'DWD Warnungen': For input string: "warnWetter.loadWarnings({"time":1558761150000,"warnings":{},"vorabInformation":{},"copyright":"Copyright Deutscher Wetterdienst"});"

Do you have the same issue?

Thanks

Hello,

I found it quite annoying that the telegram message is sent every 30 minutes even without changes in the event. I added a md5 sum calculation to the warning and the message is now being sent only one the content changes. Maybe someone is interested.

calculate_md5.js in transform folder:

/*

function md5cycle(x, k) {
var a = x[0], b = x[1], c = x[2], d = x[3];

a = ff(a, b, c, d, k[0], 7, -680876936);
d = ff(d, a, b, c, k[1], 12, -389564586);
c = ff(c, d, a, b, k[2], 17,  606105819);
b = ff(b, c, d, a, k[3], 22, -1044525330);
a = ff(a, b, c, d, k[4], 7, -176418897);
d = ff(d, a, b, c, k[5], 12,  1200080426);
c = ff(c, d, a, b, k[6], 17, -1473231341);
b = ff(b, c, d, a, k[7], 22, -45705983);
a = ff(a, b, c, d, k[8], 7,  1770035416);
d = ff(d, a, b, c, k[9], 12, -1958414417);
c = ff(c, d, a, b, k[10], 17, -42063);
b = ff(b, c, d, a, k[11], 22, -1990404162);
a = ff(a, b, c, d, k[12], 7,  1804603682);
d = ff(d, a, b, c, k[13], 12, -40341101);
c = ff(c, d, a, b, k[14], 17, -1502002290);
b = ff(b, c, d, a, k[15], 22,  1236535329);

a = gg(a, b, c, d, k[1], 5, -165796510);
d = gg(d, a, b, c, k[6], 9, -1069501632);
c = gg(c, d, a, b, k[11], 14,  643717713);
b = gg(b, c, d, a, k[0], 20, -373897302);
a = gg(a, b, c, d, k[5], 5, -701558691);
d = gg(d, a, b, c, k[10], 9,  38016083);
c = gg(c, d, a, b, k[15], 14, -660478335);
b = gg(b, c, d, a, k[4], 20, -405537848);
a = gg(a, b, c, d, k[9], 5,  568446438);
d = gg(d, a, b, c, k[14], 9, -1019803690);
c = gg(c, d, a, b, k[3], 14, -187363961);
b = gg(b, c, d, a, k[8], 20,  1163531501);
a = gg(a, b, c, d, k[13], 5, -1444681467);
d = gg(d, a, b, c, k[2], 9, -51403784);
c = gg(c, d, a, b, k[7], 14,  1735328473);
b = gg(b, c, d, a, k[12], 20, -1926607734);

a = hh(a, b, c, d, k[5], 4, -378558);
d = hh(d, a, b, c, k[8], 11, -2022574463);
c = hh(c, d, a, b, k[11], 16,  1839030562);
b = hh(b, c, d, a, k[14], 23, -35309556);
a = hh(a, b, c, d, k[1], 4, -1530992060);
d = hh(d, a, b, c, k[4], 11,  1272893353);
c = hh(c, d, a, b, k[7], 16, -155497632);
b = hh(b, c, d, a, k[10], 23, -1094730640);
a = hh(a, b, c, d, k[13], 4,  681279174);
d = hh(d, a, b, c, k[0], 11, -358537222);
c = hh(c, d, a, b, k[3], 16, -722521979);
b = hh(b, c, d, a, k[6], 23,  76029189);
a = hh(a, b, c, d, k[9], 4, -640364487);
d = hh(d, a, b, c, k[12], 11, -421815835);
c = hh(c, d, a, b, k[15], 16,  530742520);
b = hh(b, c, d, a, k[2], 23, -995338651);

a = ii(a, b, c, d, k[0], 6, -198630844);
d = ii(d, a, b, c, k[7], 10,  1126891415);
c = ii(c, d, a, b, k[14], 15, -1416354905);
b = ii(b, c, d, a, k[5], 21, -57434055);
a = ii(a, b, c, d, k[12], 6,  1700485571);
d = ii(d, a, b, c, k[3], 10, -1894986606);
c = ii(c, d, a, b, k[10], 15, -1051523);
b = ii(b, c, d, a, k[1], 21, -2054922799);
a = ii(a, b, c, d, k[8], 6,  1873313359);
d = ii(d, a, b, c, k[15], 10, -30611744);
c = ii(c, d, a, b, k[6], 15, -1560198380);
b = ii(b, c, d, a, k[13], 21,  1309151649);
a = ii(a, b, c, d, k[4], 6, -145523070);
d = ii(d, a, b, c, k[11], 10, -1120210379);
c = ii(c, d, a, b, k[2], 15,  718787259);
b = ii(b, c, d, a, k[9], 21, -343485551);

x[0] = add32(a, x[0]);
x[1] = add32(b, x[1]);
x[2] = add32(c, x[2]);
x[3] = add32(d, x[3]);

}

function cmn(q, a, b, x, s, t) {
a = add32(add32(a, q), add32(x, t));
return add32((a << s) | (a >>> (32 - s)), b);
}

function ff(a, b, c, d, x, s, t) {
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}

function gg(a, b, c, d, x, s, t) {
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}

function hh(a, b, c, d, x, s, t) {
return cmn(b ^ c ^ d, a, b, x, s, t);
}

function ii(a, b, c, d, x, s, t) {
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}

function md51(s) {
txt = '';
var n = s.length,
state = [1732584193, -271733879, -1732584194, 271733878], i;
for (i=64; i<=s.length; i+=64) {
md5cycle(state, md5blk(s.substring(i-64, i)));
}
s = s.substring(i-64);
var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
for (i=0; i<s.length; i++)
tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3);
tail[i>>2] |= 0x80 << ((i%4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i=0; i<16; i++) tail[i] = 0;
}
tail[14] = n*8;
md5cycle(state, tail);
return state;
}

/* there needs to be support for Unicode here,
 * unless we pretend that we can redefine the MD-5
 * algorithm for multi-byte characters (perhaps
 * by adding every four 16-bit characters and
 * shortening the sum to 32 bits). Otherwise
 * I suggest performing MD-5 as if every character
 * was two bytes--e.g., 0040 0025 = @%--but then
 * how will an ordinary MD-5 sum be matched?
 * There is no way to standardize text to something
 * like UTF-8 before transformation; speed cost is
 * utterly prohibitive. The JavaScript standard
 * itself needs to look at this: it should start
 * providing access to strings as preformed UTF-8
 * 8-bit unsigned value arrays.
 */
function md5blk(s) { /* I figured global was faster.   */
var md5blks = [], i; /* Andy King said do it this way. */
for (i=0; i<64; i+=4) {
md5blks[i>>2] = s.charCodeAt(i)
+ (s.charCodeAt(i+1) << 8)
+ (s.charCodeAt(i+2) << 16)
+ (s.charCodeAt(i+3) << 24);
}
return md5blks;
}

var hex_chr = '0123456789abcdef'.split('');

function rhex(n)
{
var s='', j=0;
for(; j<4; j++)
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F]
+ hex_chr[(n >> (j * 8)) & 0x0F];
return s;
}

function hex(x) {
for (var i=0; i<x.length; i++)
x[i] = rhex(x[i]);
return x.join('');
}

function md5(s) {
return hex(md51(s));
}

/* this function is much faster,
so if possible we use it. Some IEs
are the only ones I know of that
need the idiotic second function,
generated by an if clause.  */

function add32(a, b) {
return (a + b) & 0xFFFFFFFF;
}

if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {
function add32(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF),
msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
}

(function(i) {
    return md5(i);
})(input)

Wetter_DWD.items:

DateTime        DWD_Warnung_start                   "von: [%1$td.%1$tm.%1$tY %1$tH:%1$tM Uhr]"        <time>                        
DateTime        DWD_Warnung_end                     "bis: [%1$td.%1$tm.%1$tY %1$tH:%1$tM Uhr]"        <time>
Number          DWD_Warnung_level                   "Warnstufe: [MAP(Wetter_DWD.map):%s]"             <dwdwarnung>
String          DWD_Warnung_description             "Beschreibung: [%s]"                              <warnung>
String          DWD_Warnung_headline                "Betreff: [%s]"                                   <warnung>
String          DWD_Warnung_instruction             "Hinweis: [%s]"                                   <warnung>
String          DWD_Warnung_event                   "Event: [%s]"                                     <warnung>
String          DWD_Warnung_md5                     "MD5: [%s]"                                       <warnung>

String          DWDSelectedSite

Wetter_DWD.rules:

rule "DWD Warnungen"
when
Time cron "0 */30 * ? * *"  //every 30 Minutes
//Time cron "0 * * ? * *"    //every 1 Minute

then
var String jsonString = sendHttpGetRequest("https://www.dwd.de/DWD/warnungen/warnapp/json/warnings.json")
var String newString = transform("JS", "Wetter_DWD_getWarningsJSON.js", jsonString)
if (newString !="NULL") {
var String newStart = transform("JSONPATH", "$.start", newString)
var DateTime timestart = new DateTime(Long::parseLong(newStart))
DWD_Warnung_start.postUpdate(new DateTimeType(timestart.toString))
var String newEnd = transform("JSONPATH", "$.end", newString)
if (newEnd !==null) {
var DateTime timeend = new DateTime(Long::parseLong(newEnd))
DWD_Warnung_end.postUpdate(new DateTimeType(timeend.toString))
}

DWD_Warnung_level.postUpdate(transform("JSONPATH","$.level",newString))
DWD_Warnung_description.postUpdate(transform("JSONPATH","$.description",newString))
DWD_Warnung_headline.postUpdate(transform("JSONPATH","$.headline",newString))
DWD_Warnung_instruction.postUpdate(transform("JSONPATH","$.instruction",newString))
DWD_Warnung_event.postUpdate(transform("JSONPATH","$.event",newString))

    
// Create MD5 of the event data
jsonString = DWD_Warnung_level.toString + DWD_Warnung_description.toString + DWD_Warnung_headline.toString + DWD_Warnung_instruction.toString + DWD_Warnung_event.toString
var String md5ofdata = transform("JS", "calculate_md5.js", jsonString)

//First or changed event? Send message
if(DWD_Warnung_md5.state.toString == "-" || DWD_Warnung_md5.state.toString != md5ofdata) {
    
    DWD_Warnung_md5.postUpdate(md5ofdata)

    // Benachrichtigung per Telegram an Bot senden
    sendTelegram("botolf1", "Wetterwarnung in Teltow" + "\n" +
                                    "\nWarnstufe: " + DWD_Warnung_level.state.toString +
                                    "\nBeschreibung: " + DWD_Warnung_description.state.toString +
                                    "\nBetreff: " + DWD_Warnung_headline.state.toString +
                                    "\nHinweis: " + DWD_Warnung_instruction.state.toString +
                                    "\nEvent: " + DWD_Warnung_event.state.toString + 
                                    "\nMD5: " + DWD_Warnung_md5.state.toString)
} 


}

if (newString =="NULL") {
DWD_Warnung_start.postUpdate("NULL")
DWD_Warnung_end.postUpdate("NULL")
DWD_Warnung_level.postUpdate(0)
DWD_Warnung_description.postUpdate("-")
DWD_Warnung_headline.postUpdate("derzeit keine Warnungen")
DWD_Warnung_instruction.postUpdate("-")
DWD_Warnung_event.postUpdate("-")    
DWD_Warnung_md5.postUpdate("-")     
}
end

Hey Stefan,
thanks for the great tutorial.

At my sitemap it looks like:

Why did I have empty white fields? Und why did you have a guiedline?

Greeting, Ansgr

In my Sitemap it is the same.
The reason is the visibility !="-"

Thanks.

Did you try to get info for 2 or more citys?

No sorry