[yioremote] Fixed reconnection and thing creation issues (#8596)

Signed-off-by: Michael Loercher <MichaelLoercher@web.de>
This commit is contained in:
miloit 2020-09-29 19:48:11 +02:00 committed by GitHub
parent 4e72980c6c
commit 4b91bfcfa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 128 additions and 32 deletions

View File

@ -8,7 +8,7 @@ Since this binding allows actual you to trigger IR send/receive actions on YIO D
## Supported Things
* Thing Type ID: `yioremotedock`
* Thing Type ID: `yioRemoteDock`
The following are the configurations available to each of the bridges/things:
@ -41,7 +41,7 @@ rule "yioremote Action Example"
when
...
then
val actions = getActions("yioremote", "yioremote:yioremotedock:livingroom")
val actions = getActions("yioremote", "yioremote:yioRemoteDock:livingroom")
if (actions === null)
{
......
@ -58,22 +58,20 @@ end
.things
```
yioremote:yioremotedock:livingroom [ host="192.168.178.21", accesstoken="0" ]
yioremote:yioRemoteDock:livingroom [ host="xxx.xxx.xxx.xxx", accesstoken="0" ]
```
.items
```
String sendircode "IR CODE [%s]" {channel="yioremote:yioremotedock:livingroom:input# sendircode"}
Switch receiverswitch "IR recieving switch" {channel="yioremote:yioremotedock:livingroom:input# receiverswitch"}
String status "YIO Dock status[%s]" {channel="yioremote:yioremotedock:livingroom:output# status"}
Switch receiverswitch "IR recieving switch" {channel="yioremote:yioRemoteDock:livingroom:input# receiverswitch"}
String status "YIO Dock status[%s]" {channel="yioremote:yioRemoteDock:livingroom:output# status"}
```
.sitemap
```
sitemap Basic label="YIO Dock" {
Text item= sendircode
Switch item= receiverswitch
Text item= status
}

View File

@ -33,7 +33,9 @@ public class YIOremoteBindingConstants {
AUTHENTICATION_FAILED,
AUTHENTICATION_COMPLETE,
CONNECTION_FAILED,
CONNECTION_ESTABLISHED;
CONNECTION_ESTABLISHED,
COMMUNICATION_ERROR,
RECONNECTION_PROCESS;
}
public static enum YioRemoteMessages {
@ -45,7 +47,7 @@ public class YIOremoteBindingConstants {
}
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_YIOREMOTEDOCK = new ThingTypeUID(BINDING_ID, "yioremotedock");
public static final ThingTypeUID THING_TYPE_YIOREMOTEDOCK = new ThingTypeUID(BINDING_ID, "yioRemoteDock");
// List of all Channel Groups Group Channel ids
public static final String GROUP_INPUT = "input";

View File

@ -69,6 +69,7 @@ public class YIOremoteDockHandler extends BaseThingHandler {
private @Nullable URI websocketAddress;
private YioRemoteDockHandleStatus yioRemoteDockActualStatus = YioRemoteDockHandleStatus.UNINITIALIZED_STATE;
private @Nullable Future<?> webSocketPollingJob;
private @Nullable Future<?> webSocketReconnectionPollingJob;
public String receivedMessage = "";
private JsonObject recievedJson = new JsonObject();
private boolean heartBeat = false;
@ -119,7 +120,10 @@ public class YIOremoteDockHandler extends BaseThingHandler {
switch (yioRemoteDockActualStatus) {
case CONNECTION_ESTABLISHED:
case AUTHENTICATION_PROCESS:
authenticate();
authenticateWebsocket();
break;
case COMMUNICATION_ERROR:
reconnectWebsocket();
break;
default:
break;
@ -132,13 +136,15 @@ public class YIOremoteDockHandler extends BaseThingHandler {
}
@Override
public void onError() {
if (webSocketPollingJob != null) {
webSocketPollingJob.cancel(true);
}
public void onClose() {
reconnectWebsocket();
}
@Override
public void onError(Throwable cause) {
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.COMMUNICATION_ERROR;
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Connection lost no ping from YIO DOCK");
updateState(GROUP_OUTPUT, STATUS_STRING_CHANNEL, UnDefType.UNDEF);
"Communication lost no ping from YIO DOCK");
}
});
@ -174,8 +180,9 @@ public class YIOremoteDockHandler extends BaseThingHandler {
heartBeat = true;
success = true;
} else {
if (irCodeSendHandler.getCode().equalsIgnoreCase("\"0;0x0;0;0\"")) {
if (irCodeSendHandler.getCode().equalsIgnoreCase("0;0x0;0;0")) {
logger.debug("Send heartBeat Code success");
receivedStatus = "Send heartBeat Code success";
} else {
receivedStatus = "Send IR Code failure";
}
@ -242,8 +249,12 @@ public class YIOremoteDockHandler extends BaseThingHandler {
@Override
public void dispose() {
if (webSocketPollingJob != null) {
webSocketPollingJob.cancel(true);
disposeWebsocketPollingJob();
if (webSocketReconnectionPollingJob != null) {
if (!webSocketReconnectionPollingJob.isCancelled() && webSocketReconnectionPollingJob != null) {
webSocketReconnectionPollingJob.cancel(true);
}
webSocketReconnectionPollingJob = null;
}
}
@ -287,7 +298,7 @@ public class YIOremoteDockHandler extends BaseThingHandler {
updateState(id, new StringType(value));
}
private void authenticate() {
private void authenticateWebsocket() {
switch (yioRemoteDockActualStatus) {
case CONNECTION_ESTABLISHED:
authenticationMessageHandler.setToken(localConfig.accessToken);
@ -298,13 +309,15 @@ public class YIOremoteDockHandler extends BaseThingHandler {
if (authenticationOk) {
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.AUTHENTICATION_COMPLETE;
updateStatus(ThingStatus.ONLINE);
webSocketPollingJob = scheduler.scheduleWithFixedDelay(this::pollingWebsocket, 0, 30,
webSocketPollingJob = scheduler.scheduleWithFixedDelay(this::pollingWebsocketJob, 0, 150,
TimeUnit.SECONDS);
} else {
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.AUTHENTICATION_FAILED;
}
break;
default:
disposeWebsocketPollingJob();
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.COMMUNICATION_ERROR;
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Connection lost no ping from YIO DOCK");
updateState(GROUP_OUTPUT, STATUS_STRING_CHANNEL, UnDefType.UNDEF);
@ -312,7 +325,16 @@ public class YIOremoteDockHandler extends BaseThingHandler {
}
}
private void pollingWebsocket() {
private void disposeWebsocketPollingJob() {
if (webSocketPollingJob != null) {
if (!webSocketPollingJob.isCancelled() && webSocketPollingJob != null) {
webSocketPollingJob.cancel(true);
}
webSocketPollingJob = null;
}
}
private void pollingWebsocketJob() {
switch (yioRemoteDockActualStatus) {
case AUTHENTICATION_COMPLETE:
if (getAndResetHeartbeat()) {
@ -321,19 +343,16 @@ public class YIOremoteDockHandler extends BaseThingHandler {
logger.debug("heartBeat ok");
sendMessage(YioRemoteMessages.HEARTBEAT_MESSAGE, "");
} else {
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.CONNECTION_FAILED;
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.COMMUNICATION_ERROR;
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Connection lost no ping from YIO DOCK");
updateState(GROUP_OUTPUT, STATUS_STRING_CHANNEL, UnDefType.UNDEF);
if (webSocketPollingJob != null) {
webSocketPollingJob.cancel(true);
}
disposeWebsocketPollingJob();
reconnectWebsocket();
}
break;
default:
if (webSocketPollingJob != null) {
webSocketPollingJob.cancel(true);
}
disposeWebsocketPollingJob();
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.COMMUNICATION_ERROR;
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Connection lost no ping from YIO DOCK");
updateState(GROUP_OUTPUT, STATUS_STRING_CHANNEL, UnDefType.UNDEF);
@ -347,6 +366,55 @@ public class YIOremoteDockHandler extends BaseThingHandler {
return result;
}
public void reconnectWebsocket() {
if (webSocketReconnectionPollingJob == null) {
webSocketReconnectionPollingJob = scheduler.scheduleWithFixedDelay(this::reconnectWebsocketJob, 0, 30,
TimeUnit.SECONDS);
}
}
public void reconnectWebsocketJob() {
switch (yioRemoteDockActualStatus) {
case COMMUNICATION_ERROR:
logger.debug("Reconnecting YIORemoteHandler");
try {
disposeWebsocketPollingJob();
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Connection lost no ping from YIO DOCK");
yioremoteDockwebSocketClient.closeWebsocketSession();
webSocketClient.stop();
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.RECONNECTION_PROCESS;
} catch (Exception e) {
logger.debug("Connection error {}", e.getMessage());
}
try {
websocketAddress = new URI("ws://" + localConfig.host + ":946");
yioRemoteDockActualStatus = YioRemoteDockHandleStatus.AUTHENTICATION_PROCESS;
} catch (URISyntaxException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
"Initialize web socket failed: " + e.getMessage());
}
try {
webSocketClient.start();
webSocketClient.connect(yioremoteDockwebSocketClient, websocketAddress,
yioremoteDockwebSocketClientrequest);
} catch (Exception e) {
logger.debug("Connection error {}", e.getMessage());
}
break;
case AUTHENTICATION_COMPLETE:
if (webSocketReconnectionPollingJob != null) {
if (!webSocketReconnectionPollingJob.isCancelled() && webSocketReconnectionPollingJob != null) {
webSocketReconnectionPollingJob.cancel(true);
}
webSocketReconnectionPollingJob = null;
}
break;
default:
break;
}
}
public void sendMessage(YioRemoteMessages messageType, String messagePayload) {
switch (messageType) {
case AUTHENTICATE_MESSAGE:

View File

@ -17,6 +17,8 @@ import java.io.IOException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
@ -61,7 +63,25 @@ public class Websocket {
public void onError(Throwable cause) {
logger.warn("WebSocketError {}", cause.getMessage());
if (websocketHandler != null) {
websocketHandler.onError();
websocketHandler.onError(cause);
}
}
@OnWebSocketClose
public void onClose(int statusCode, String reason) {
if (statusCode != StatusCode.NORMAL) {
logger.debug("WebSocket Connection closed: {} - {}", statusCode, reason);
}
if (session != null) {
if (!session.isOpen()) {
if (session != null) {
session.close();
}
}
session = null;
}
if (websocketHandler != null) {
websocketHandler.onClose();
}
}
@ -74,4 +94,10 @@ public class Websocket {
}
}
}
public void closeWebsocketSession() {
if (session != null) {
session.close();
}
}
}

View File

@ -24,7 +24,9 @@ public interface WebsocketInterface {
public void onConnect(boolean connected);
public void onClose();
public void onMessage(String decodedmessage);
public void onError();
public void onError(Throwable cause);
}