mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[dwdunwetter] Rework channel creation (#9229)
Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
parent
8d389b7e2e
commit
af4371844d
@ -22,6 +22,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@NonNullByDefault
|
||||
public class DwdUnwetterConfiguration {
|
||||
public int refresh;
|
||||
public int warningCount;
|
||||
public int warningCount = 1;
|
||||
public String cellId = "";
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -30,9 +31,10 @@ import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.type.ChannelKind;
|
||||
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
||||
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.openhab.core.thing.util.ThingHandlerHelper;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
@ -54,7 +56,6 @@ public class DwdUnwetterHandler extends BaseThingHandler {
|
||||
private @Nullable DwdWarningsData data;
|
||||
|
||||
private boolean inRefresh;
|
||||
private boolean initializing;
|
||||
|
||||
public DwdUnwetterHandler(Thing thing) {
|
||||
super(thing);
|
||||
@ -79,14 +80,8 @@ public class DwdUnwetterHandler extends BaseThingHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if (initializing) {
|
||||
logger.trace("Still initializing. Ignoring refresh request.");
|
||||
return;
|
||||
}
|
||||
|
||||
ThingStatus status = getThing().getStatus();
|
||||
if (status != ThingStatus.ONLINE && status != ThingStatus.UNKNOWN) {
|
||||
logger.debug("Unable to refresh. Thing status is {}", status);
|
||||
if (!ThingHandlerHelper.isHandlerInitialized(getThing())) {
|
||||
logger.debug("Unable to refresh. Thing status is '{}'", getThing().getStatus());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -105,9 +100,7 @@ public class DwdUnwetterHandler extends BaseThingHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
if (status == ThingStatus.UNKNOWN) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
||||
updateState(getChannelUuid(CHANNEL_LAST_UPDATED), new DateTimeType());
|
||||
|
||||
@ -142,18 +135,36 @@ public class DwdUnwetterHandler extends BaseThingHandler {
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Start initializing!");
|
||||
initializing = true;
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
|
||||
DwdUnwetterConfiguration config = getConfigAs(DwdUnwetterConfiguration.class);
|
||||
warningCount = config.warningCount;
|
||||
int newWarningCount = config.warningCount;
|
||||
|
||||
if (warningCount != newWarningCount) {
|
||||
List<Channel> toBeAddedChannels = new ArrayList<>();
|
||||
List<Channel> toBeRemovedChannels = new ArrayList<>();
|
||||
if (warningCount > newWarningCount) {
|
||||
for (int i = newWarningCount + 1; i <= warningCount; ++i) {
|
||||
toBeRemovedChannels.addAll(removeChannels(i));
|
||||
}
|
||||
} else {
|
||||
for (int i = warningCount + 1; i <= newWarningCount; ++i) {
|
||||
toBeAddedChannels.addAll(createChannels(i));
|
||||
}
|
||||
}
|
||||
warningCount = newWarningCount;
|
||||
|
||||
ThingBuilder builder = editThing().withoutChannels(toBeRemovedChannels);
|
||||
for (Channel channel : toBeAddedChannels) {
|
||||
builder.withChannel(channel);
|
||||
}
|
||||
updateThing(builder.build());
|
||||
}
|
||||
|
||||
data = new DwdWarningsData(config.cellId);
|
||||
|
||||
updateThing(editThing().withChannels(createChannels()).build());
|
||||
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(this::refresh, 0, config.refresh, TimeUnit.MINUTES);
|
||||
initializing = false;
|
||||
|
||||
logger.debug("Finished initializing!");
|
||||
}
|
||||
|
||||
@ -165,70 +176,69 @@ public class DwdUnwetterHandler extends BaseThingHandler {
|
||||
return new ChannelUID(getThing().getUID(), typeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a trigger Channel.
|
||||
*/
|
||||
private Channel createTriggerChannel(String typeId, String label, int warningNumber) {
|
||||
ChannelUID channelUID = getChannelUuid(typeId, warningNumber);
|
||||
return ChannelBuilder.create(channelUID, "String") //
|
||||
.withType(new ChannelTypeUID(BINDING_ID, typeId)) //
|
||||
.withLabel(label + " (" + (warningNumber + 1) + ")")//
|
||||
.withKind(ChannelKind.TRIGGER) //
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a normal, state based, channel associated with a warning.
|
||||
*/
|
||||
private Channel createChannel(String typeId, String itemType, String label, int warningNumber) {
|
||||
private void createChannelIfNotExist(ThingHandlerCallback cb, List<Channel> channels, String typeId, String label,
|
||||
int warningNumber) {
|
||||
ChannelUID channelUID = getChannelUuid(typeId, warningNumber);
|
||||
return ChannelBuilder.create(channelUID, itemType) //
|
||||
.withType(new ChannelTypeUID(BINDING_ID, typeId)) //
|
||||
.withLabel(label + " (" + (warningNumber + 1) + ")")//
|
||||
.build();
|
||||
Channel existingChannel = getThing().getChannel(channelUID);
|
||||
if (existingChannel != null) {
|
||||
logger.trace("Thing '{}' already has an existing channel '{}'. Omit adding new channel '{}'.",
|
||||
getThing().getUID(), existingChannel.getUID(), channelUID);
|
||||
} else {
|
||||
channels.add(cb.createChannelBuilder(channelUID, new ChannelTypeUID(BINDING_ID, typeId))
|
||||
.withLabel(label + " " + getChannelLabelSuffix(warningNumber)).build());
|
||||
}
|
||||
}
|
||||
|
||||
private String getChannelLabelSuffix(int warningNumber) {
|
||||
return "(" + (warningNumber + 1) + ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a normal, state based, channel not associated with a warning.
|
||||
*/
|
||||
private Channel createChannel(String typeId, String itemType, String label) {
|
||||
ChannelUID channelUID = getChannelUuid(typeId);
|
||||
return ChannelBuilder.create(channelUID, itemType) //
|
||||
.withType(new ChannelTypeUID(BINDING_ID, typeId)) //
|
||||
.withLabel(label)//
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the ChannelsT for each warning.
|
||||
* Creates the Channels for each warning.
|
||||
*
|
||||
* @return The List of Channels
|
||||
* @return The List of Channels to be added
|
||||
*/
|
||||
private List<Channel> createChannels() {
|
||||
List<Channel> channels = new ArrayList<>(warningCount * 11 + 1);
|
||||
channels.add(createChannel(CHANNEL_LAST_UPDATED, "DateTime", "Last Updated"));
|
||||
for (int i = 0; i < warningCount; i++) {
|
||||
channels.add(createChannel(CHANNEL_WARNING, "Switch", "Warning", i));
|
||||
channels.add(createTriggerChannel(CHANNEL_UPDATED, "Updated", i));
|
||||
channels.add(createChannel(CHANNEL_SEVERITY, "String", "Severity", i));
|
||||
channels.add(createChannel(CHANNEL_DESCRIPTION, "String", "Description", i));
|
||||
channels.add(createChannel(CHANNEL_EFFECTIVE, "DateTime", "Issued", i));
|
||||
channels.add(createChannel(CHANNEL_ONSET, "DateTime", "Valid From", i));
|
||||
channels.add(createChannel(CHANNEL_EXPIRES, "DateTime", "Valid To", i));
|
||||
channels.add(createChannel(CHANNEL_EVENT, "String", "Type", i));
|
||||
channels.add(createChannel(CHANNEL_HEADLINE, "String", "Headline", i));
|
||||
channels.add(createChannel(CHANNEL_ALTITUDE, "Number:Length", "Height (from)", i));
|
||||
channels.add(createChannel(CHANNEL_CEILING, "Number:Length", "Height (to)", i));
|
||||
channels.add(createChannel(CHANNEL_INSTRUCTION, "String", "Instruction", i));
|
||||
channels.add(createChannel(CHANNEL_URGENCY, "String", "Urgency", i));
|
||||
private List<Channel> createChannels(int warningNumber) {
|
||||
logger.debug("Building channels for thing '{}'.", getThing().getUID());
|
||||
List<Channel> channels = new ArrayList<>();
|
||||
ThingHandlerCallback callback = getCallback();
|
||||
if (callback != null) {
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_UPDATED, "Updated", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_WARNING, "Warning", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_SEVERITY, "Severity", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_DESCRIPTION, "Description", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_EFFECTIVE, "Issued", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_ONSET, "Valid From", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_EXPIRES, "Valid To", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_EVENT, "Type", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_HEADLINE, "Headline", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_ALTITUDE, "Height (from)", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_CEILING, "Height (to)", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_INSTRUCTION, "Instruction", warningNumber);
|
||||
createChannelIfNotExist(callback, channels, CHANNEL_URGENCY, "Urgency", warningNumber);
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the Channels for each warning
|
||||
*
|
||||
* @return The List of Channels to be removed
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
private List<Channel> removeChannels(int warningNumber) {
|
||||
return getThing().getChannels().stream()
|
||||
.filter(channel -> channel.getLabel() != null
|
||||
&& channel.getLabel().endsWith(getChannelLabelSuffix(warningNumber)))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
final ScheduledFuture<?> job = refreshJob;
|
||||
|
||||
if (job != null) {
|
||||
job.cancel(true);
|
||||
}
|
||||
|
@ -7,6 +7,9 @@
|
||||
<thing-type id="dwdwarnings">
|
||||
<label>Weather Warnings</label>
|
||||
<description>Weather Warnings for an area</description>
|
||||
<channels>
|
||||
<channel typeId="lastUpdated" id="lastUpdated"></channel>
|
||||
</channels>
|
||||
<config-description>
|
||||
<parameter name="cellId" type="text" required="true">
|
||||
<label>Cell-ID</label>
|
||||
|
@ -10,11 +10,11 @@
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.dwdunwetter;
|
||||
package org.openhab.binding.dwdunwetter.internal.handler;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
@ -34,16 +34,17 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.openhab.binding.dwdunwetter.internal.DwdUnwetterBindingConstants;
|
||||
import org.openhab.binding.dwdunwetter.internal.handler.DwdUnwetterHandler;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.test.java.JavaTest;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerCallback;
|
||||
import org.openhab.core.thing.binding.builder.ChannelBuilder;
|
||||
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
@ -65,6 +66,10 @@ public class DwdUnwetterHandlerTest extends JavaTest {
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
when(callback.createChannelBuilder(any(ChannelUID.class), any(ChannelTypeUID.class)))
|
||||
.thenAnswer(invocation -> ChannelBuilder.create(invocation.getArgument(0, ChannelUID.class))
|
||||
.withType(invocation.getArgument(1, ChannelTypeUID.class)));
|
||||
|
||||
handler = new DwdUnwetterHandler(thing);
|
||||
handler.setCallback(callback);
|
||||
// mock getConfiguration to prevent NPEs
|
Loading…
Reference in New Issue
Block a user