Skip to content
Merged
1 change: 1 addition & 0 deletions bundles/org.openhab.binding.http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ The `image` channel-type supports `stateExtension` only.
| `stateTransformation` | yes | - | One or more transformation applied to received values before updating channel. |
| `commandTransformation` | yes | - | One or more transformation applied to channel value before sending to a remote. |
| `stateContent` | yes | - | Content for state requests (if method is `PUT` or `POST`) |
| `refreshAfterCommand` | yes | `FALSE` | Refresh channel state after command execution |
| `mode` | no | `READWRITE` | Mode this channel is allowed to operate. `READONLY` means receive state, `WRITEONLY` means send commands. |

Some channels have additional parameters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,20 +114,19 @@ public void handleCommand(ChannelUID channelUID, Command command) {
return;
}

String key = channelUrls.get(channelUID);
RefreshingUrlCache refreshingUrlCache = (key != null) ? urlHandlers.get(key) : null;

if (command instanceof RefreshType) {
String key = channelUrls.get(channelUID);
if (key != null) {
RefreshingUrlCache refreshingUrlCache = urlHandlers.get(key);
if (refreshingUrlCache != null) {
try {
refreshingUrlCache.get().ifPresentOrElse(itemValueConverter::process, () -> {
if (config.strictErrorHandling) {
itemValueConverter.process(null);
}
});
} catch (IllegalArgumentException | IllegalStateException e) {
logger.warn("Failed processing REFRESH command for channel {}: {}", channelUID, e.getMessage());
}
if (refreshingUrlCache != null) {
try {
refreshingUrlCache.getCached().ifPresentOrElse(itemValueConverter::process, () -> {
if (config.strictErrorHandling) {
itemValueConverter.process(null);
}
});
} catch (IllegalArgumentException | IllegalStateException e) {
logger.warn("Failed processing REFRESH command for channel {}: {}", channelUID, e.getMessage());
}
}
} else {
Expand All @@ -138,6 +137,10 @@ public void handleCommand(ChannelUID channelUID, Command command) {
} catch (IllegalStateException e) {
logger.debug("Writing to read-only channel {} not permitted", channelUID);
}

if (refreshingUrlCache != null) {
refreshingUrlCache.refreshAfterCommand(scheduler);
}
}
}

Expand Down Expand Up @@ -332,10 +335,9 @@ private void createChannel(Channel channel) {
// we need a key consisting of stateContent and URL, only if both are equal, we can use the same cache
String key = channelConfig.stateContent + "$" + stateUrl;
channelUrls.put(channelUID, key);
Objects.requireNonNull(
urlHandlers.computeIfAbsent(key,
k -> new RefreshingUrlCache(rateLimitedHttpClient, stateUrl, config,
channelConfig.stateContent, config.contentType, this)))
Objects.requireNonNull(urlHandlers.computeIfAbsent(key,
k -> new RefreshingUrlCache(rateLimitedHttpClient, stateUrl, config, channelConfig.stateContent,
config.contentType, this, channelConfig.refreshAfterCommand)))
.addConsumer(itemValueConverter::process);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ public class HttpChannelConfig extends ChannelValueConverterConfig {
public @Nullable List<String> stateTransformation;
public @Nullable List<String> commandTransformation;
public String stateContent = "";
public Boolean refreshAfterCommand = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,19 @@ public class RefreshingUrlCache {
private final String httpContent;
private final @Nullable String httpContentType;
private final HttpStatusListener httpStatusListener;
private final boolean refreshAfterCommand;

private @Nullable ScheduledFuture<?> future;
private @Nullable ChannelHandlerContent lastContent;

public RefreshingUrlCache(RateLimitedHttpClient httpClient, String url, HttpThingConfig thingConfig,
String httpContent, @Nullable String httpContentType, HttpStatusListener httpStatusListener) {
this(httpClient, url, thingConfig, httpContent, httpContentType, httpStatusListener, false);
}

public RefreshingUrlCache(RateLimitedHttpClient httpClient, String url, HttpThingConfig thingConfig,
String httpContent, @Nullable String httpContentType, HttpStatusListener httpStatusListener,
boolean refreshAfterCommand) {
this.httpClient = httpClient;
this.url = url;
this.strictErrorHandling = thingConfig.strictErrorHandling;
Expand All @@ -74,6 +81,7 @@ public RefreshingUrlCache(RateLimitedHttpClient httpClient, String url, HttpThin
this.httpContent = httpContent;
this.httpContentType = httpContentType;
this.httpStatusListener = httpStatusListener;
this.refreshAfterCommand = refreshAfterCommand;
fallbackEncoding = thingConfig.encoding;
}

Expand All @@ -100,6 +108,13 @@ private void refresh() {
refresh(false);
}

public void refreshAfterCommand(ScheduledExecutorService executor) {
if (refreshAfterCommand) {
executor.schedule(() -> this.refresh(), 1, TimeUnit.SECONDS);
logger.trace("Started refresh task for URL '{}'", url);
}
}

private void refresh(boolean isRetry) {
if (consumers.isEmpty()) {
// do not refresh if we don't have listeners
Expand Down Expand Up @@ -151,7 +166,7 @@ public void addConsumer(Consumer<@Nullable ChannelHandlerContent> consumer) {
consumers.add(consumer);
}

public Optional<ChannelHandlerContent> get() {
public Optional<ChannelHandlerContent> getCached() {
return Optional.ofNullable(lastContent);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
<description>Content for state request (only used if method is POST/PUT)</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
<parameter name="mode" type="text">
<label>Read/Write Mode</label>
<options>
Expand Down Expand Up @@ -69,6 +74,11 @@
<description>Content for state request (only used if method is POST/PUT)</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
<parameter name="onValue" type="text">
<label>On Value</label>
<description>The value that represents ON</description>
Expand Down Expand Up @@ -140,6 +150,11 @@
<description>Content for state request (only used if method is POST/PUT)</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
<parameter name="openValue" type="text" required="true">
<label>Open Value</label>
<description>The value that represents OPEN</description>
Expand Down Expand Up @@ -177,6 +192,11 @@
<description>This value is added to the base URL configured in the thing for retrieving values.</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
<parameter name="commandExtension" type="text">
<label>Command URL Extension</label>
<description>This value is added to the base URL configured in the thing for sending values.</description>
Expand Down Expand Up @@ -233,6 +253,11 @@
<description>Content for state request (only used if method is POST/PUT)</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
</config-description>

<config-description uri="channel-type:http:channel-config-number">
Expand All @@ -251,6 +276,11 @@
<description>This value is added to the base URL configured in the thing for retrieving values.</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
<parameter name="commandExtension" type="text">
<label>Command URL Extension</label>
<description>This value is added to the base URL configured in the thing for sending values.</description>
Expand Down Expand Up @@ -295,6 +325,11 @@
<description>This value is added to the base URL configured in the thing for retrieving values.</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
<parameter name="commandExtension" type="text">
<label>Command URL Extension</label>
<description>This value is added to the base URL configured in the thing for sending values.</description>
Expand Down Expand Up @@ -358,6 +393,11 @@
<description>This value is added to the base URL configured in the thing for retrieving values.</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
<parameter name="commandExtension" type="text">
<label>Command URL Extension</label>
<description>This value is added to the base URL configured in the thing for sending values.</description>
Expand Down Expand Up @@ -423,6 +463,11 @@
<description>Content for state request (only used if method is POST/PUT)</description>
<advanced>true</advanced>
</parameter>
<parameter name="refreshAfterCommand" type="boolean">
<label>Refresh After Command</label>
<description>Refresh channel state after command execution</description>
<advanced>true</advanced>
</parameter>
<parameter name="onValue" type="text" required="true">
<label>On Value</label>
<description>The value that represents ON</description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ channel-type.config.http.channel-config-color.onValue.label = On Value
channel-type.config.http.channel-config-color.onValue.description = The value that represents ON
channel-type.config.http.channel-config-color.stateContent.label = State Content
channel-type.config.http.channel-config-color.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config-color.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config-color.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config-color.stateExtension.label = State URL Extension
channel-type.config.http.channel-config-color.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config-color.stateTransformation.label = State Transformation
Expand All @@ -117,6 +119,8 @@ channel-type.config.http.channel-config-contact.openValue.label = Open Value
channel-type.config.http.channel-config-contact.openValue.description = The value that represents OPEN
channel-type.config.http.channel-config-contact.stateContent.label = State Content
channel-type.config.http.channel-config-contact.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config-contact.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config-contact.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config-contact.stateExtension.label = State URL Extension
channel-type.config.http.channel-config-contact.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config-contact.stateTransformation.label = State Transformation
Expand All @@ -139,6 +143,8 @@ channel-type.config.http.channel-config-dimmer.onValue.label = On Value
channel-type.config.http.channel-config-dimmer.onValue.description = The value that represents ON
channel-type.config.http.channel-config-dimmer.stateContent.label = State Content
channel-type.config.http.channel-config-dimmer.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config-dimmer.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config-dimmer.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config-dimmer.stateExtension.label = State URL Extension
channel-type.config.http.channel-config-dimmer.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config-dimmer.stateTransformation.label = State Transformation
Expand All @@ -147,6 +153,8 @@ channel-type.config.http.channel-config-dimmer.step.label = Increase/Decrease St
channel-type.config.http.channel-config-dimmer.step.description = The value by which the current brightness is increased/decreased if the corresponding command is received
channel-type.config.http.channel-config-image.stateContent.label = State Content
channel-type.config.http.channel-config-image.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config-image.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config-image.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config-image.stateExtension.label = State URL Extension
channel-type.config.http.channel-config-image.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config-number.commandExtension.label = Command URL Extension
Expand All @@ -159,6 +167,8 @@ channel-type.config.http.channel-config-number.mode.option.READONLY = Read Only
channel-type.config.http.channel-config-number.mode.option.WRITEONLY = Write Only
channel-type.config.http.channel-config-number.stateContent.label = State Content
channel-type.config.http.channel-config-number.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config-number.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config-number.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config-number.stateExtension.label = State URL Extension
channel-type.config.http.channel-config-number.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config-number.stateTransformation.label = State Transformation
Expand Down Expand Up @@ -187,6 +197,8 @@ channel-type.config.http.channel-config-player.rewindValue.label = Rewind Value
channel-type.config.http.channel-config-player.rewindValue.description = The value that represents REWIND
channel-type.config.http.channel-config-player.stateContent.label = State Content
channel-type.config.http.channel-config-player.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config-player.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config-player.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config-player.stateExtension.label = State URL Extension
channel-type.config.http.channel-config-player.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config-player.stateTransformation.label = State Transformation
Expand All @@ -205,6 +217,8 @@ channel-type.config.http.channel-config-rollershutter.moveValue.label = Move Val
channel-type.config.http.channel-config-rollershutter.moveValue.description = The value that represents MOVE
channel-type.config.http.channel-config-rollershutter.stateContent.label = State Content
channel-type.config.http.channel-config-rollershutter.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config-rollershutter.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config-rollershutter.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config-rollershutter.stateExtension.label = State URL Extension
channel-type.config.http.channel-config-rollershutter.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config-rollershutter.stateTransformation.label = State Transformation
Expand All @@ -227,6 +241,8 @@ channel-type.config.http.channel-config-switch.onValue.label = On Value
channel-type.config.http.channel-config-switch.onValue.description = The value that represents ON
channel-type.config.http.channel-config-switch.stateContent.label = State Content
channel-type.config.http.channel-config-switch.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config-switch.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config-switch.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config-switch.stateExtension.label = State URL Extension
channel-type.config.http.channel-config-switch.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config-switch.stateTransformation.label = State Transformation
Expand All @@ -241,6 +257,8 @@ channel-type.config.http.channel-config.mode.option.READONLY = Read Only
channel-type.config.http.channel-config.mode.option.WRITEONLY = Write Only
channel-type.config.http.channel-config.stateContent.label = State Content
channel-type.config.http.channel-config.stateContent.description = Content for state request (only used if method is POST/PUT)
channel-type.config.http.channel-config.refreshAfterCommand.label = Refresh after Command
channel-type.config.http.channel-config.refreshAfterCommand.description = Refresh channel state after command execution
channel-type.config.http.channel-config.stateExtension.label = State URL Extension
channel-type.config.http.channel-config.stateExtension.description = This value is added to the base URL configured in the thing for retrieving values.
channel-type.config.http.channel-config.stateTransformation.label = State Transformation
Expand Down