2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.samsungtv.internal.protocol;
15 import java.util.stream.Collectors;
17 import org.eclipse.jdt.annotation.NonNullByDefault;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.openhab.binding.samsungtv.internal.config.SamsungTvConfiguration;
20 import org.openhab.binding.samsungtv.internal.protocol.RemoteControllerWebSocket.App;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
24 import com.google.gson.JsonSyntaxException;
27 * Websocket class for remote control
29 * @author Arjan Mels - Initial contribution
32 class WebSocketRemote extends WebSocketBase {
33 private final Logger logger = LoggerFactory.getLogger(WebSocketRemote.class);
35 @SuppressWarnings("unused")
37 private static class JSONMessage {
74 * @param remoteControllerWebSocket
76 WebSocketRemote(RemoteControllerWebSocket remoteControllerWebSocket) {
77 super(remoteControllerWebSocket);
81 public void onWebSocketError(@Nullable Throwable error) {
82 super.onWebSocketError(error);
83 remoteControllerWebSocket.callback.connectionError(error);
87 public void onWebSocketText(@Nullable String msgarg) {
91 String msg = msgarg.replace('\n', ' ');
92 super.onWebSocketText(msg);
94 JSONMessage jsonMsg = remoteControllerWebSocket.gson.fromJson(msg, JSONMessage.class);
95 switch (jsonMsg.event) {
96 case "ms.channel.connect":
97 logger.debug("Remote channel connected. Token = {}", jsonMsg.data.token);
98 if (jsonMsg.data.token != null) {
99 this.remoteControllerWebSocket.callback.putConfig(SamsungTvConfiguration.WEBSOCKET_TOKEN,
101 // try opening additional websockets
103 this.remoteControllerWebSocket.openConnection();
104 } catch (RemoteControllerException e) {
105 logger.warn("{}: Error ({})", this.getClass().getSimpleName(), e.getMessage());
110 case "ms.channel.clientConnect":
111 logger.debug("Remote client connected");
113 case "ms.channel.clientDisconnect":
114 logger.debug("Remote client disconnected");
116 case "ed.edenTV.update":
117 logger.debug("edenTV update: {}", jsonMsg.data.update_type);
118 remoteControllerWebSocket.updateCurrentApp();
120 case "ed.apps.launch":
121 logger.debug("App launched: {}", jsonMsg.params.data.appId);
123 case "ed.installedApp.get":
124 handleInstalledApps(jsonMsg);
127 logger.debug("WebSocketRemote Unknown event: {}", msg);
130 } catch (JsonSyntaxException e) {
131 logger.warn("{}: Error ({}) in message: {}", this.getClass().getSimpleName(), e.getMessage(), msg, e);
135 private void handleInstalledApps(JSONMessage jsonMsg) {
136 remoteControllerWebSocket.apps.clear();
138 for (JSONMessage.App jsonApp : jsonMsg.data.data) {
139 App app = remoteControllerWebSocket.new App(jsonApp.appId, jsonApp.name, jsonApp.app_type);
140 remoteControllerWebSocket.apps.put(app.name, app);
142 if (logger.isDebugEnabled()) {
143 logger.debug("Installed Apps: {}", remoteControllerWebSocket.apps.entrySet().stream()
144 .map(entry -> entry.getValue().appId + " = " + entry.getKey()).collect(Collectors.joining(", ")));
147 remoteControllerWebSocket.updateCurrentApp();
150 @NonNullByDefault({})
151 static class JSONAppInfo {
152 @NonNullByDefault({})
153 static class Params {
154 String event = "ed.installedApp.get";
158 String method = "ms.channel.emit";
159 Params params = new Params();
163 sendCommand(remoteControllerWebSocket.gson.toJson(new JSONAppInfo()));
166 @NonNullByDefault({})
167 static class JSONSourceApp {
168 public JSONSourceApp(String appName, boolean deepLink) {
169 this(appName, deepLink, null);
172 public JSONSourceApp(String appName, boolean deepLink, String metaTag) {
173 params.data.appId = appName;
174 params.data.action_type = deepLink ? "DEEP_LINK" : "NATIVE_LAUNCH";
175 params.data.metaTag = metaTag;
178 @NonNullByDefault({})
179 static class Params {
180 @NonNullByDefault({})
187 String event = "ed.apps.launch";
189 Data data = new Data();
192 String method = "ms.channel.emit";
193 Params params = new Params();
196 public void sendSourceApp(String appName, boolean deepLink) {
197 sendCommand(remoteControllerWebSocket.gson.toJson(new JSONSourceApp(appName, deepLink)));
200 public void sendSourceApp(String appName, boolean deepLink, String metaTag) {
201 sendCommand(remoteControllerWebSocket.gson.toJson(new JSONSourceApp(appName, deepLink, metaTag)));
204 @NonNullByDefault({})
205 static class JSONRemoteControl {
206 public JSONRemoteControl(boolean press, String key) {
207 params.Cmd = press ? "Press" : "Click";
208 params.DataOfCmd = key;
211 @NonNullByDefault({})
212 static class Params {
215 String Option = "false";
216 String TypeOfRemote = "SendRemoteKey";
219 String method = "ms.remote.control";
220 Params params = new Params();
223 void sendKeyData(boolean press, String key) {
224 sendCommand(remoteControllerWebSocket.gson.toJson(new JSONRemoteControl(press, key)));