Set channel states to UNDEF instead of NULL; Fixed SAT warnings (#10421)

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2021-03-31 21:42:33 +02:00 committed by GitHub
parent aa97da083c
commit 12b0908806
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 70 additions and 63 deletions

View File

@ -132,7 +132,9 @@ then
end
```
dwdunwetter_de.map
```
ON=aktiv
OFF=inaktiv
@ -151,8 +153,6 @@ NULL=undefiniert
UNDEF=undefiniert
```
dwdunwetter_urgency_de.map
```

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import java.time.Instant;
import java.time.temporal.ChronoUnit;

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import java.math.BigDecimal;
import java.time.Instant;

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import java.io.IOException;
import java.net.URLEncoder;

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import java.io.StringReader;
import java.math.BigDecimal;
@ -218,18 +218,18 @@ public class DwdWarningsData {
public State getSeverity(int number) {
DwdWarningData data = getGemeindeData(number);
return data == null ? UnDefType.NULL : StringType.valueOf(data.getSeverity().getText());
return data == null ? UnDefType.UNDEF : StringType.valueOf(data.getSeverity().getText());
}
public State getDescription(int number) {
DwdWarningData data = getGemeindeData(number);
return data == null ? UnDefType.NULL : StringType.valueOf(data.getDescription());
return data == null ? UnDefType.UNDEF : StringType.valueOf(data.getDescription());
}
public State getEffective(int number) {
DwdWarningData data = getGemeindeData(number);
if (data == null) {
return UnDefType.NULL;
return UnDefType.UNDEF;
}
ZonedDateTime zoned = ZonedDateTime.ofInstant(data.getEffective(), ZoneId.systemDefault());
return new DateTimeType(zoned);
@ -238,7 +238,7 @@ public class DwdWarningsData {
public State getExpires(int number) {
DwdWarningData data = getGemeindeData(number);
if (data == null) {
return UnDefType.NULL;
return UnDefType.UNDEF;
}
ZonedDateTime zoned = ZonedDateTime.ofInstant(data.getExpires(), ZoneId.systemDefault());
return new DateTimeType(zoned);
@ -247,7 +247,7 @@ public class DwdWarningsData {
public State getOnset(int number) {
DwdWarningData data = getGemeindeData(number);
if (data == null) {
return UnDefType.NULL;
return UnDefType.UNDEF;
}
ZonedDateTime zoned = ZonedDateTime.ofInstant(data.getOnset(), ZoneId.systemDefault());
return new DateTimeType(zoned);
@ -255,18 +255,18 @@ public class DwdWarningsData {
public State getEvent(int number) {
DwdWarningData data = getGemeindeData(number);
return data == null ? UnDefType.NULL : StringType.valueOf(data.getEvent());
return data == null ? UnDefType.UNDEF : StringType.valueOf(data.getEvent());
}
public State getHeadline(int number) {
DwdWarningData data = getGemeindeData(number);
return data == null ? UnDefType.NULL : StringType.valueOf(data.getHeadline());
return data == null ? UnDefType.UNDEF : StringType.valueOf(data.getHeadline());
}
public State getAltitude(int number) {
DwdWarningData data = getGemeindeData(number);
if (data == null) {
return UnDefType.NULL;
return UnDefType.UNDEF;
}
return new QuantityType<>(data.getAltitude(), ImperialUnits.FOOT);
}
@ -274,19 +274,19 @@ public class DwdWarningsData {
public State getCeiling(int number) {
DwdWarningData data = getGemeindeData(number);
if (data == null) {
return UnDefType.NULL;
return UnDefType.UNDEF;
}
return new QuantityType<>(data.getCeiling(), ImperialUnits.FOOT);
}
public State getInstruction(int number) {
DwdWarningData data = getGemeindeData(number);
return data == null ? UnDefType.NULL : StringType.valueOf(data.getInstruction());
return data == null ? UnDefType.UNDEF : StringType.valueOf(data.getInstruction());
}
public State getUrgency(int number) {
DwdWarningData data = getGemeindeData(number);
return data == null ? UnDefType.NULL : StringType.valueOf(data.getUrgency().getText());
return data == null ? UnDefType.UNDEF : StringType.valueOf(data.getUrgency().getText());
}
public boolean isNew(int number) {

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import java.util.Arrays;

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import java.util.Arrays;

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import java.util.Comparator;

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import java.util.Arrays;

View File

@ -23,7 +23,7 @@ import java.util.stream.Collectors;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.dwdunwetter.internal.config.DwdUnwetterConfiguration;
import org.openhab.binding.dwdunwetter.internal.data.DwdWarningsData;
import org.openhab.binding.dwdunwetter.internal.dto.DwdWarningsData;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.thing.Channel;

View File

@ -1,10 +1,10 @@
# binding
binding.dwdunwetter.name = DWD Unwetter Binding
binding.dwdunwetter.description = Das DWD Unwetter Binding ermöglicht es über die API des DWD aktuelle Unwetterwarnungen abzurufen
binding.dwdunwetter.description = Das DWD Unwetter Binding ermöglicht es über die API des DWD aktuelle Unwetterwarnungen abzurufen.
# thing types
thing-type.dwdunwetter.dwdwarnings.label = DWD Unwetter Warnungen
thing-type.dwdunwetter.dwdwarnings.description = DWD Unwetterwarnungen für ein Gebiet
thing-type.dwdunwetter.dwdwarnings.description = DWD Unwetterwarnungen für ein Gebiet.
thing-type.config.dwdunwetter.dwdwarnings.cellId.label=Cell-ID
thing-type.config.dwdunwetter.dwdwarnings.cellId.description=ID der abzufragenden Zelle.\
@ -20,29 +20,29 @@ Die Warnungen werden dabei nach Severity und dann nach Beginn sortiert. Die erst
channel-type.dwdunwetter.warning.label = Warnung
channel-type.dwdunwetter.warning.description = Steht auf ON, wenn eine Warning vorliegt, OFF wenn keine vorliegt.\
Es ist garantiert, dass wenn der Channel von OFF auf ON umspringt, die anderen Channels bereits gefüllt sind, mit Ausnahme des Trigger Channels.\
Es ist garantiert, dass wenn der Channel von ON auf OFF umspringt, die anderen Channels erst danach auf NULL gesetzt werden.
Es ist garantiert, dass wenn der Channel von ON auf OFF umspringt, die anderen Channels erst danach auf UNDEF gesetzt werden.
channel-type.dwdunwetter.updated.label = Aktualisiert
channel-type.dwdunwetter.updated.description = Triggered, wenn eine Warnung das erste mal gesendet wird.\
Dies passiert als letztes, nachdem alle anderen Channels bereits gesetzt sind.
channel-type.dwdunwetter.severity.label = Schwere-Grad
channel-type.dwdunwetter.severity.description = Schwere-Grad der Warnung. Mögliche Werte sind Minor, Moderate, Severe und Extreme.
channel-type.dwdunwetter.description.label = Beschreibung
channel-type.dwdunwetter.description.description = Klartext Beschreibung der Warnung
channel-type.dwdunwetter.description.description = Klartext Beschreibung der Warnung.
channel-type.dwdunwetter.effective.label = Ausgegeben
channel-type.dwdunwetter.effective.description = Datum und Uhrzeit, wann die Warnung ausgegeben wurde
channel-type.dwdunwetter.effective.description = Datum und Uhrzeit, wann die Warnung ausgegeben wurde.
channel-type.dwdunwetter.onset.label = Gültig ab
channel-type.dwdunwetter.onset.description = Datum und Uhrzeit, ab dem die Warnung gültig ist
channel-type.dwdunwetter.onset.description = Datum und Uhrzeit, ab dem die Warnung gültig ist.
channel-type.dwdunwetter.expires.label = Gültig bis
channel-type.dwdunwetter.expires.description = Datum und Uhrzeit, bis zu dem die Warnung gültig ist
channel-type.dwdunwetter.expires.description = Datum und Uhrzeit, bis zu dem die Warnung gültig ist.
channel-type.dwdunwetter.headline.label = Titel
channel-type.dwdunwetter.headline.description = Titel der Warnung z.B. "Amtliche Warnung vor FROST"
channel-type.dwdunwetter.headline.description = Titel der Warnung z.B. "Amtliche Warnung vor FROST".
channel-type.dwdunwetter.event.label = Art
channel-type.dwdunwetter.event.description = Art der Warnung, z.B. FROST
channel-type.dwdunwetter.event.description = Art der Warnung, z.B. FROST.
channel-type.dwdunwetter.altitude.label = Höhe von
channel-type.dwdunwetter.altitude.description = Höhe über dem Meeresspiegel, ab dem die Warnung gilt
channel-type.dwdunwetter.altitude.description = Höhe über dem Meeresspiegel, ab dem die Warnung gilt.
channel-type.dwdunwetter.ceiling.label = Höhe bis
channel-type.dwdunwetter.ceiling.description = Höhe über dem Meeresspiegel, bis zu dem die Warnung gilt
channel-type.dwdunwetter.ceiling.description = Höhe über dem Meeresspiegel, bis zu dem die Warnung gilt.
channel-type.dwdunwetter.urgency.label=Zeitrahmen
channel-type.dwdunwetter.urgency.description=Zeitrahmen der Meldung - Vorabinformation oder Warnung
channel-type.dwdunwetter.urgency.description=Zeitrahmen der Meldung - Vorabinformation oder Warnung.
channel-type.dwdunwetter.instruction.label=Zusatztext
channel-type.dwdunwetter.instruction.description=Zusatztext zur Warnung (Instruktionen und Sicherheitshinweise)
channel-type.dwdunwetter.instruction.description=Zusatztext zur Warnung (Instruktionen und Sicherheitshinweise).

View File

@ -6,9 +6,9 @@
<thing-type id="dwdwarnings">
<label>Weather Warnings</label>
<description>Weather Warnings for an area</description>
<description>Weather Warnings for an area.</description>
<channels>
<channel typeId="lastUpdated" id="lastUpdated"></channel>
<channel typeId="lastUpdated" id="lastUpdated"/>
</channels>
<config-description>
<parameter name="cellId" type="text" required="true">
@ -35,7 +35,8 @@ The warnings are sorted by severity first and begin second so the first warning
<channel-type id="lastUpdated">
<item-type>DateTime</item-type>
<label>Last Updated</label>
<description>Timestamp of the last update from the endpoint</description>
<description>Timestamp of the last update from the endpoint.</description>
<category>Time</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="warning">
@ -43,14 +44,14 @@ The warnings are sorted by severity first and begin second so the first warning
<label>Warning</label>
<description><![CDATA[ON if a warning is present, OFF else.
While be switched to ON only after all other channels - except the trigger channel - are updated.
Will be switched to OFF before all other channels are updated to NULL]]></description>
Will be switched to OFF before all other channels are updated to UNDEF.]]></description>
<state readOnly="true"/>
</channel-type>
<channel-type id="updated">
<kind>trigger</kind>
<label>Updated</label>
<description><![CDATA[Triggers NEW if a warning is send the first time.
This happens after all other channels are populated]]></description>
This happens after all other channels are populated.]]></description>
<event>
<options>
<option value="NEW">New</option>
@ -79,49 +80,52 @@ This happens after all other channels are populated]]></description>
<channel-type id="effective">
<item-type>DateTime</item-type>
<label>Issued</label>
<description>Issued Date and Time</description>
<description>Issued Date and Time.</description>
<category>Time</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="onset">
<item-type>DateTime</item-type>
<label>Valid From</label>
<description>Start Date and Time for which the warning is valid</description>
<description>Start Date and Time for which the warning is valid.</description>
<category>Time</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="expires">
<item-type>DateTime</item-type>
<label>Valid To</label>
<description>End Date and Time for which the warning is valid</description>
<description>End Date and Time for which the warning is valid.</description>
<category>Time</category>
<state readOnly="true"/>
</channel-type>
<channel-type id="headline">
<item-type>String</item-type>
<label>Headline</label>
<description>Headline of the warning like "Amtliche Warnung vor FROST"</description>
<description>Headline of the warning like "Amtliche Warnung vor FROST".</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="event">
<item-type>String</item-type>
<label>Type</label>
<description>Type of the warning, e.g. FROST</description>
<description>Type of the warning, e.g. FROST.</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="altitude">
<item-type>Number:Length</item-type>
<label>Height (from)</label>
<description>Lower Height above sea level for which the warning is valid</description>
<description>Lower Height above sea level for which the warning is valid.</description>
<state readOnly="true" pattern="%d m"/>
</channel-type>
<channel-type id="ceiling">
<item-type>Number:Length</item-type>
<label>Height (to)</label>
<description>Upper Height above sea level for which the warning is valid</description>
<description>Upper Height above sea level for which the warning is valid.</description>
<state readOnly="true" pattern="%d m"/>
</channel-type>
<channel-type id="instruction">
<item-type>String</item-type>
<label>Instruction</label>
<description>Instructions and safety information</description>
<description>Instructions and safety information.</description>
<state readOnly="true"/>
</channel-type>
<channel-type id="urgency">

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@ -21,7 +21,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* Tests for {@link DwdWarningCache}
* Tests for {@link org.openhab.binding.dwdunwetter.internal.dto.DwdWarningCache}
*
* @author Martin Koehler - Initial contribution
*/

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.dwdunwetter.internal.data;
package org.openhab.binding.dwdunwetter.internal.dto;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
@ -30,14 +30,17 @@ import org.openhab.core.library.types.OnOffType;
import org.openhab.core.types.UnDefType;
/**
* Tests for {@link DwdWarningsData}
* Tests for {@link org.openhab.binding.dwdunwetter.internal.dto.DwdWarningsData}
*
* <p>
* Uses the warnings.xml from the resources directory instead of accessing the api endpoint.
*
* <p>
* The XML has 2 Entries:
*
* <ol>
* <li>Amtliche WARNUNG vor WINDBÖEN, MINOR</li>
* <li>Amtliche WARNUNG vor STURMBÖEN, MODERATE</li>
* <li>Amtliche WARNUNG vor WINDBÖEN, MINOR
* <li>Amtliche WARNUNG vor STURMBÖEN, MODERATE
* </ol>
*
* @author Martin Koehler - Initial contribution
@ -60,21 +63,21 @@ public class DwdWarningsDataTest {
public void testGetHeadline() {
assertThat(warningsData.getHeadline(0), is("Amtliche WARNUNG vor STURMBÖEN"));
assertThat(warningsData.getHeadline(1), is("Amtliche WARNUNG vor WINDBÖEN"));
assertThat(warningsData.getHeadline(2), is(UnDefType.NULL));
assertThat(warningsData.getHeadline(2), is(UnDefType.UNDEF));
}
@Test
public void testGetSeverity() {
assertThat(warningsData.getSeverity(0), is("Moderate"));
assertThat(warningsData.getSeverity(1), is("Minor"));
assertThat(warningsData.getSeverity(2), is(UnDefType.NULL));
assertThat(warningsData.getSeverity(2), is(UnDefType.UNDEF));
}
@Test
public void testGetEvent() {
assertThat(warningsData.getEvent(0), is("STURMBÖEN"));
assertThat(warningsData.getEvent(1), is("WINDBÖEN"));
assertThat(warningsData.getEvent(2), is(UnDefType.NULL));
assertThat(warningsData.getEvent(2), is(UnDefType.UNDEF));
}
@Test
@ -83,21 +86,21 @@ public class DwdWarningsDataTest {
"Es treten Sturmböen mit Geschwindigkeiten zwischen 60 km/h (17m/s, 33kn, Bft 7) und 80 km/h (22m/s, 44kn, Bft 9) anfangs aus südwestlicher, später aus westlicher Richtung auf. In Schauernähe sowie in exponierten Lagen muss mit schweren Sturmböen um 90 km/h (25m/s, 48kn, Bft 10) gerechnet werden."));
assertThat(warningsData.getDescription(1), is(
"Es treten Windböen mit Geschwindigkeiten bis 60 km/h (17m/s, 33kn, Bft 7) aus westlicher Richtung auf. In Schauernähe sowie in exponierten Lagen muss mit Sturmböen bis 80 km/h (22m/s, 44kn, Bft 9) gerechnet werden."));
assertThat(warningsData.getDescription(2), is(UnDefType.NULL));
assertThat(warningsData.getDescription(2), is(UnDefType.UNDEF));
}
@Test
public void testGetAltitude() {
assertThat(warningsData.getAltitude(0).format("%.0f ft"), is("0 ft"));
assertThat(warningsData.getAltitude(1).format("%.0f ft"), is("0 ft"));
assertThat(warningsData.getAltitude(2), is(UnDefType.NULL));
assertThat(warningsData.getAltitude(2), is(UnDefType.UNDEF));
}
@Test
public void testGetCeiling() {
assertThat(warningsData.getCeiling(0).format("%.0f ft"), is("9843 ft"));
assertThat(warningsData.getCeiling(1).format("%.0f ft"), is("9843 ft"));
assertThat(warningsData.getCeiling(2), is(UnDefType.NULL));
assertThat(warningsData.getCeiling(2), is(UnDefType.UNDEF));
}
@Test
@ -107,7 +110,7 @@ public class DwdWarningsDataTest {
.toString(), is("2018-12-22T18:00Z[UTC]"));
assertThat(((DateTimeType) warningsData.getExpires(1)).getZonedDateTime().withZoneSameInstant(ZoneId.of("UTC"))
.toString(), is("2018-12-23T01:00Z[UTC]"));
assertThat(warningsData.getExpires(2), is(UnDefType.NULL));
assertThat(warningsData.getExpires(2), is(UnDefType.UNDEF));
}
@Test
@ -117,7 +120,7 @@ public class DwdWarningsDataTest {
.toString(), is("2018-12-21T10:00Z[UTC]"));
assertThat(((DateTimeType) warningsData.getOnset(1)).getZonedDateTime().withZoneSameInstant(ZoneId.of("UTC"))
.toString(), is("2018-12-22T18:00Z[UTC]"));
assertThat(warningsData.getOnset(2), is(UnDefType.NULL));
assertThat(warningsData.getOnset(2), is(UnDefType.UNDEF));
}
@Test
@ -127,7 +130,7 @@ public class DwdWarningsDataTest {
.withZoneSameInstant(ZoneId.of("UTC")).toString(), is("2018-12-22T03:02Z[UTC]"));
assertThat(((DateTimeType) warningsData.getEffective(1)).getZonedDateTime()
.withZoneSameInstant(ZoneId.of("UTC")).toString(), is("2018-12-22T10:15Z[UTC]"));
assertThat(warningsData.getEffective(2), is(UnDefType.NULL));
assertThat(warningsData.getEffective(2), is(UnDefType.UNDEF));
}
@Test