From bba48dc24901b66a4118b9479d75bc8f4cf6b02b Mon Sep 17 00:00:00 2001 From: Pavion Date: Sat, 4 Dec 2021 12:07:56 +0100 Subject: [PATCH] Add current movie support --- README.md | 1 + .../internal/TwinklyTreeBindingConstants.java | 1 + .../internal/TwinklyTreeHandler.java | 95 ++++++++++++++----- .../resources/OH-INF/thing/thing-types.xml | 6 ++ 4 files changed, 77 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 8e96d7c..3e6d1e9 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ _You need to manually specify the IP address of the Twinkly controller_ | brightness | Dimmer | Adjust brightness | | mode | String | Set current mode | | currenteffect | Number | Set current effect for effect mode | +| currentmovie | Number | Set current movie for movie mode | ## Textual configuration example diff --git a/src/main/java/org/openhab/binding/twinklytree/internal/TwinklyTreeBindingConstants.java b/src/main/java/org/openhab/binding/twinklytree/internal/TwinklyTreeBindingConstants.java index da974b1..acd6b11 100644 --- a/src/main/java/org/openhab/binding/twinklytree/internal/TwinklyTreeBindingConstants.java +++ b/src/main/java/org/openhab/binding/twinklytree/internal/TwinklyTreeBindingConstants.java @@ -35,6 +35,7 @@ public class TwinklyTreeBindingConstants { public static final String CHANNEL_DIMMER = "dimmer"; public static final String CHANNEL_MODE = "mode"; public static final String CHANNEL_CURRENT_EFFECT = "currenteffect"; + public static final String CHANNEL_CURRENT_MOVIE = "currentmovie"; public static final String MODE_OFF = "off"; public static final String MODE_COLOR = "color"; diff --git a/src/main/java/org/openhab/binding/twinklytree/internal/TwinklyTreeHandler.java b/src/main/java/org/openhab/binding/twinklytree/internal/TwinklyTreeHandler.java index 1597ebd..2b997f2 100644 --- a/src/main/java/org/openhab/binding/twinklytree/internal/TwinklyTreeHandler.java +++ b/src/main/java/org/openhab/binding/twinklytree/internal/TwinklyTreeHandler.java @@ -36,6 +36,7 @@ import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.StringType; +import org.openhab.core.thing.Channel; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; @@ -100,7 +101,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { } break; case CHANNEL_MODE: - if (command instanceof RefreshType) { + if (command instanceof RefreshType || command.toFullString().toUpperCase().equals("REFRESH")) { updateState(channelUID, new StringType(getMode())); } else { setMode(command.toFullString()); @@ -114,12 +115,19 @@ public void handleCommand(ChannelUID channelUID, Command command) { setCurrentEffect(type.intValue()); } break; + case CHANNEL_CURRENT_MOVIE: + if (command instanceof RefreshType) { + updateState(channelUID, new DecimalType(getCurrentMovie())); + } else { + DecimalType type = (DecimalType) command; + setCurrentMovie(type.intValue()); + } + break; } - } catch (IOException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Could not control device at IP address " + config.host); - logger.error("Error communicating with Twinkly", e); + logger.error("Error communicating with Twinkly"/* , e */); config.token = null; } } @@ -152,20 +160,31 @@ private void setMode(String newMode) throws IOException, ProtocolException, Malf } private int getCurrentEffect() throws IOException, ProtocolException, MalformedURLException { - JSONObject getModeResponse = sendRequest(new URL(config.getBaseURL(), "/xled/v1/led/effects/current"), "GET", - null, config.token); - if (getModeResponse.has("preset_id")) { - return getModeResponse.getInt("preset_id"); + JSONObject response = sendRequest(new URL(config.getBaseURL(), "/xled/v1/led/effects/current"), "GET", null, + config.token); + if (response.has("preset_id")) { + return response.getInt("preset_id"); } else { - return getModeResponse.getInt("effect_id"); + return response.getInt("effect_id"); } } private void setCurrentEffect(int currentEffect) throws IOException, ProtocolException, MalformedURLException { - JSONObject setModeResponse = sendRequest(new URL(config.getBaseURL(), "/xled/v1/led/effects/current"), "POST", + JSONObject response = sendRequest(new URL(config.getBaseURL(), "/xled/v1/led/effects/current"), "POST", "{\"preset_id\":\"" + currentEffect + "\",\"effect_id\":\"" + currentEffect + "\"}", config.token); } + private int getCurrentMovie() throws IOException, ProtocolException, MalformedURLException { + JSONObject response = sendRequest(new URL(config.getBaseURL(), "/xled/v1/movies/current"), "GET", null, + config.token); + return response.getInt("id"); + } + + private void setCurrentMovie(int currentMovie) throws IOException, ProtocolException, MalformedURLException { + JSONObject response = sendRequest(new URL(config.getBaseURL(), "/xled/v1/movies/current"), "POST", + "{\"id\":" + currentMovie + "}", config.token); + } + private void logout() { updateStatus(ThingStatus.OFFLINE); try { @@ -205,7 +224,7 @@ public void initialize() { // Example for background initialization: // scheduler.execute(() -> { // login(); - pollingJob = scheduler.scheduleWithFixedDelay(this::refreshState, 100, 1, TimeUnit.MINUTES); + pollingJob = scheduler.scheduleWithFixedDelay(this::refreshState, 0, 1, TimeUnit.MINUTES); // if (token != null) { // updateStatus(ThingStatus.ONLINE); // } else { @@ -223,24 +242,30 @@ public void initialize() { } private void refreshState() { - try { - refreshIfNeeded(); - - boolean isOn = isOn(); - updateState(CHANNEL_SWITCH, isOn ? OnOffType.ON : OnOffType.OFF); - - int brightnessPct = 0; - if (isOn) { - brightnessPct = getBrightness(); - } - updateState(CHANNEL_DIMMER, new PercentType(brightnessPct)); - } catch (IOException e) { - config.token = null; - logger.error("Issue while polling for state ", e); + for (Channel channel : this.getThing().getChannels()) { + handleCommand(channel.getUID(), RefreshType.REFRESH); } + /* + * + * try { + * refreshIfNeeded(); + * + * boolean isOn = isOn(); + * updateState(CHANNEL_SWITCH, isOn ? OnOffType.ON : OnOffType.OFF); + * + * int brightnessPct = 0; + * if (isOn) { + * brightnessPct = getBrightness(); + * } + * updateState(CHANNEL_DIMMER, new PercentType(brightnessPct)); + * } catch (IOException e) { + * config.token = null; + * logger.error("Issue while polling for state ", e); + * } + */ } - private void login() { + private synchronized void login() { try { config.token = null; @@ -271,7 +296,25 @@ private boolean isTokenExpired() { return config.tokenExpiryDate.before(new Date()); } - private JSONObject sendRequest(URL loginURL, String httpMethod, @Nullable String requestString, + private synchronized JSONObject sendRequest(URL loginURL, String httpMethod, @Nullable String requestString, + @Nullable String token) throws ProtocolException { + JSONObject ret; + try { + ret = sendRequestWrapped(loginURL, httpMethod, requestString, token); + } catch (IOException ex) { + logger.debug("Invalid Token, attempting to reconnect"); + login(); + try { + ret = sendRequestWrapped(loginURL, httpMethod, requestString, config.token); + } catch (IOException ex2) { + logger.error("Attempt to reconnect failed with an exception: ", ex2); + ret = new JSONObject(); + } + } + return ret; + } + + private synchronized JSONObject sendRequestWrapped(URL loginURL, String httpMethod, @Nullable String requestString, @Nullable String token) throws IOException, ProtocolException { byte[] out = null; HttpURLConnection connection = (HttpURLConnection) loginURL.openConnection(); diff --git a/src/main/resources/OH-INF/thing/thing-types.xml b/src/main/resources/OH-INF/thing/thing-types.xml index cd8bef1..b3240e2 100644 --- a/src/main/resources/OH-INF/thing/thing-types.xml +++ b/src/main/resources/OH-INF/thing/thing-types.xml @@ -13,6 +13,7 @@ + @@ -55,4 +56,9 @@ Current effect in effect mode + + Number + + Current movie in movie mode +