diff --git a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/TibberBindingConstants.java b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/TibberBindingConstants.java index d0d479097f9..6bd373b0ff4 100644 --- a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/TibberBindingConstants.java +++ b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/TibberBindingConstants.java @@ -34,8 +34,8 @@ public class TibberBindingConstants { // Tibber base URL for queries and mutations public static final String BASE_URL = "https://api.tibber.com/v1-beta/gql"; - // Tibber websocket endpoint for live subscription - public static final String SUBSCRIPTION_URL = "wss://api.tibber.com/v1-beta/gql/subscriptions"; + // Tibber driver version + public static final String TIBBER_DRIVER = "com.tibber/1.8.3"; // List of all Thing Type UIDs public static final ThingTypeUID TIBBER_THING_TYPE = new ThingTypeUID(BINDING_ID, "tibberapi"); diff --git a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberHandler.java b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberHandler.java index fb2e64fc4ed..27ca48e64d6 100644 --- a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberHandler.java +++ b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberHandler.java @@ -26,6 +26,8 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; @@ -50,6 +52,7 @@ import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; +import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -76,6 +79,8 @@ public class TibberHandler extends BaseThingHandler { private @Nullable ScheduledFuture pollingJob; private @Nullable Future sessionFuture; private String rtEnabled = "false"; + private @Nullable String subscriptionURL; + private @Nullable String versionString; public TibberHandler(Thing thing) { super(thing); @@ -86,6 +91,9 @@ public class TibberHandler extends BaseThingHandler { updateStatus(ThingStatus.UNKNOWN); tibberConfig = getConfigAs(TibberConfiguration.class); + versionString = FrameworkUtil.getBundle(this.getClass()).getVersion().toString(); + logger.debug("Binding version: {}", versionString); + getTibberParameters(); startRefresh(tibberConfig.getRefresh()); } @@ -104,7 +112,9 @@ public class TibberHandler extends BaseThingHandler { try { httpHeader.put("cache-control", "no-cache"); httpHeader.put("content-type", JSON_CONTENT_TYPE); - httpHeader.put("Authorization", "Bearer " + tibberConfig.getToken()); + httpHeader.put(HttpHeader.USER_AGENT.asString(), + "openHAB/Tibber " + versionString + " Tibber driver " + TIBBER_DRIVER); + httpHeader.put(HttpHeader.AUTHORIZATION.asString(), "Bearer " + tibberConfig.getToken()); TibberPriceConsumptionHandler tibberQuery = new TibberPriceConsumptionHandler(); InputStream connectionStream = tibberQuery.connectionInputStream(tibberConfig.getHomeid()); @@ -124,6 +134,15 @@ public class TibberHandler extends BaseThingHandler { if ("true".equals(rtEnabled)) { logger.debug("Pulse associated with HomeId: Live stream will be started"); + + InputStream wsURL = tibberQuery.getWebsocketUrl(); + String wsResponse = HttpUtil.executeUrl("POST", BASE_URL, httpHeader, wsURL, null, REQUEST_TIMEOUT); + + JsonObject wsobject = (JsonObject) JsonParser.parseString(wsResponse); + subscriptionURL = wsobject.getAsJsonObject("data").getAsJsonObject("viewer") + .get("websocketSubscriptionUrl").toString().replaceAll("^\"|\"$", ""); + logger.debug("Subscribing to: {}", subscriptionURL); + open(); } else { logger.debug("No Pulse associated with HomeId: No live stream will be started"); @@ -318,7 +337,7 @@ public class TibberHandler extends BaseThingHandler { sslContextFactory.setTrustAll(true); sslContextFactory.setEndpointIdentificationAlgorithm(null); - client = new WebSocketClient(sslContextFactory); + client = new WebSocketClient(new HttpClient(sslContextFactory)); client.setMaxIdleTimeout(30 * 1000); this.client = client; @@ -330,8 +349,10 @@ public class TibberHandler extends BaseThingHandler { } ClientUpgradeRequest newRequest = new ClientUpgradeRequest(); - newRequest.setHeader("Authorization", "Bearer " + tibberConfig.getToken()); - newRequest.setSubProtocols("graphql-subscriptions"); + newRequest.setHeader(HttpHeader.USER_AGENT.asString(), + "openHAB/Tibber " + versionString + " Tibber driver " + TIBBER_DRIVER); + newRequest.setHeader(HttpHeader.AUTHORIZATION.asString(), "Bearer " + tibberConfig.getToken()); + newRequest.setSubProtocols("graphql-transport-ws"); try { logger.debug("Starting Websocket connection"); @@ -341,7 +362,7 @@ public class TibberHandler extends BaseThingHandler { } try { logger.debug("Connecting Websocket connection"); - sessionFuture = client.connect(socket, new URI(SUBSCRIPTION_URL), newRequest); + sessionFuture = client.connect(socket, new URI(subscriptionURL), newRequest); try { Thread.sleep(10 * 1000); } catch (InterruptedException e) { @@ -412,7 +433,8 @@ public class TibberHandler extends BaseThingHandler { public void onConnect(Session wssession) { TibberHandler.this.session = wssession; TibberWebSocketListener socket = TibberHandler.this.socket; - String connection = "{\"type\":\"connection_init\", \"payload\":\"token=" + tibberConfig.getToken() + "\"}"; + String connection = "{\"type\":\"connection_init\", \"payload\":{\"token\":\"" + tibberConfig.getToken() + + "\"}}"; try { if (socket != null) { logger.debug("Sending websocket connect message"); @@ -530,7 +552,7 @@ public class TibberHandler extends BaseThingHandler { } public void startSubscription() { - String query = "{\"id\":\"1\",\"type\":\"start\",\"payload\":{\"variables\":{},\"extensions\":{},\"operationName\":null,\"query\":\"subscription {\\n liveMeasurement(homeId:\\\"" + String query = "{\"id\":\"1\",\"type\":\"subscribe\",\"payload\":{\"variables\":{},\"extensions\":{},\"operationName\":null,\"query\":\"subscription {\\n liveMeasurement(homeId:\\\"" + tibberConfig.getHomeid() + "\\\") {\\n timestamp\\n power\\n lastMeterConsumption\\n accumulatedConsumption\\n accumulatedCost\\n currency\\n minPower\\n averagePower\\n maxPower\\n" + "voltagePhase1\\n voltagePhase2\\n voltagePhase3\\n currentL1\\n currentL2\\n currentL3\\n powerProduction\\n accumulatedProduction\\n minPowerProduction\\n maxPowerProduction\\n }\\n }\\n\"}}"; diff --git a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberPriceConsumptionHandler.java b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberPriceConsumptionHandler.java index a78f1c4e7ec..a32db9f5576 100644 --- a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberPriceConsumptionHandler.java +++ b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/handler/TibberPriceConsumptionHandler.java @@ -42,4 +42,9 @@ public class TibberPriceConsumptionHandler { + "\\\") {features {realTimeConsumptionEnabled }}}}\"}"; return new ByteArrayInputStream(realtimeenabledquery.getBytes(StandardCharsets.UTF_8)); } + + public InputStream getWebsocketUrl() { + String websocketquery = "{\"query\": \"{viewer {websocketSubscriptionUrl }}\"}"; + return new ByteArrayInputStream(websocketquery.getBytes(StandardCharsets.UTF_8)); + } }