Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
This commit is contained in:
committed by
GitHub
parent
d5f6bd326c
commit
64a713e74a
@@ -145,4 +145,7 @@ public class VeluxBindingConstants {
|
||||
|
||||
// Critical issues to be reported will use the following message
|
||||
public static final String LOGGING_CONTACT = "Please report to maintainer: ";
|
||||
|
||||
public static final String UNKNOWN_THING_TYPE_ID = "FAILED";
|
||||
public static final String UNKNOWN_IP_ADDRESS = "xxx.xxx.xxx.xxx";
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ class JClogin extends Login implements JsonBridgeCommunicationProtocol {
|
||||
private static final String URL = "/api/v1/auth";
|
||||
private static final String DESCRIPTION = "authenticate / login";
|
||||
|
||||
private static Request request = new Request();
|
||||
private static Response response = new Response();
|
||||
private Request request = new Request();
|
||||
private Response response = new Response();
|
||||
|
||||
/*
|
||||
* Message Objects
|
||||
|
||||
@@ -83,19 +83,19 @@ import org.slf4j.LoggerFactory;
|
||||
class JsonBridgeAPI implements BridgeAPI {
|
||||
private final Logger logger = LoggerFactory.getLogger(JsonBridgeAPI.class);
|
||||
|
||||
private static final GetDeviceStatus GETDEVICESTATUS = new JCgetDeviceStatus();
|
||||
private static final GetFirmware GETFIRMWARE = new JCgetFirmware();
|
||||
private static final GetLANConfig GETLANCONFIG = new JCgetLANConfig();
|
||||
private static final GetProducts GETPRODUCTS = new JCgetProducts();
|
||||
private static final GetScenes GETSCENES = new JCgetScenes();
|
||||
private static final GetWLANConfig GETWLANCONFIG = new JCgetWLANConfig();
|
||||
private static final Login LOGIN = new JClogin();
|
||||
private static final Logout LOGOUT = new JClogout();
|
||||
private static final RunProductDiscovery RUNPRODUCTDISCOVERY = new JCrunProductDiscovery();
|
||||
private static final RunProductIdentification RUNPRODUCTIDENTIFICATION = new JCrunProductIdentification();
|
||||
private static final RunProductSearch RUNPRODUCTSEARCH = new JCrunProductSearch();
|
||||
private static final RunScene RUNSCENE = new JCrunScene();
|
||||
private static final SetSceneVelocity SETSCENEVELOCITY = new JCsetSceneVelocity();
|
||||
private final GetDeviceStatus jsonGetDeviceStatus = new JCgetDeviceStatus();
|
||||
private final GetFirmware jsonGetFirmware = new JCgetFirmware();
|
||||
private final GetLANConfig jsonGetLanConfig = new JCgetLANConfig();
|
||||
private final GetProducts jsonGetProducts = new JCgetProducts();
|
||||
private final GetScenes jsonGetScenes = new JCgetScenes();
|
||||
private final GetWLANConfig jsonGetWLanConfig = new JCgetWLANConfig();
|
||||
private final Login jsonLogin = new JClogin();
|
||||
private final Logout jsonLogout = new JClogout();
|
||||
private final RunProductDiscovery jsonRunProductDiscovery = new JCrunProductDiscovery();
|
||||
private final RunProductIdentification jsonRunProductIdentification = new JCrunProductIdentification();
|
||||
private final RunProductSearch jsonRunProductSearch = new JCrunProductSearch();
|
||||
private final RunScene jsonRunScene = new JCrunScene();
|
||||
private final SetSceneVelocity jsonSetSceneVelocity = new JCsetSceneVelocity();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -113,12 +113,12 @@ class JsonBridgeAPI implements BridgeAPI {
|
||||
|
||||
@Override
|
||||
public GetDeviceStatus getDeviceStatus() {
|
||||
return GETDEVICESTATUS;
|
||||
return jsonGetDeviceStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetFirmware getFirmware() {
|
||||
return GETFIRMWARE;
|
||||
return jsonGetFirmware;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -128,7 +128,7 @@ class JsonBridgeAPI implements BridgeAPI {
|
||||
|
||||
@Override
|
||||
public GetLANConfig getLANConfig() {
|
||||
return GETLANCONFIG;
|
||||
return jsonGetLanConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,27 +148,27 @@ class JsonBridgeAPI implements BridgeAPI {
|
||||
|
||||
@Override
|
||||
public GetProducts getProducts() {
|
||||
return GETPRODUCTS;
|
||||
return jsonGetProducts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetScenes getScenes() {
|
||||
return GETSCENES;
|
||||
return jsonGetScenes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetWLANConfig getWLANConfig() {
|
||||
return GETWLANCONFIG;
|
||||
return jsonGetWLanConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Login login() {
|
||||
return LOGIN;
|
||||
return jsonLogin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logout logout() {
|
||||
return LOGOUT;
|
||||
return jsonLogout;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,22 +178,22 @@ class JsonBridgeAPI implements BridgeAPI {
|
||||
|
||||
@Override
|
||||
public RunProductDiscovery runProductDiscovery() {
|
||||
return RUNPRODUCTDISCOVERY;
|
||||
return jsonRunProductDiscovery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunProductIdentification runProductIdentification() {
|
||||
return RUNPRODUCTIDENTIFICATION;
|
||||
return jsonRunProductIdentification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunProductSearch runProductSearch() {
|
||||
return RUNPRODUCTSEARCH;
|
||||
return jsonRunProductSearch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunScene runScene() {
|
||||
return RUNSCENE;
|
||||
return jsonRunScene;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -203,6 +203,6 @@ class JsonBridgeAPI implements BridgeAPI {
|
||||
|
||||
@Override
|
||||
public SetSceneVelocity setSceneVelocity() {
|
||||
return SETSCENEVELOCITY;
|
||||
return jsonSetSceneVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,25 +83,25 @@ import org.slf4j.LoggerFactory;
|
||||
class SlipBridgeAPI implements BridgeAPI {
|
||||
private final Logger logger = LoggerFactory.getLogger(SlipBridgeAPI.class);
|
||||
|
||||
private static final GetDeviceStatus GETDEVICESTATUS = new SCgetDeviceStatus();
|
||||
private static final GetFirmware GETFIRMWARE = new SCgetFirmware();
|
||||
private static final GetHouseStatus GETHOUSESTATUS = new SCgetHouseStatus();
|
||||
private static final GetLANConfig GETLANCONFIG = new SCgetLANConfig();
|
||||
private static final GetProduct GETPRODUCT = new SCgetProduct();
|
||||
private static final GetProductLimitation GETPRODUCTLIMITATION = new SCgetLimitation();
|
||||
private static final GetProducts GETPRODUCTS = new SCgetProducts();
|
||||
private static final GetScenes GETSCENES = new SCgetScenes();
|
||||
private static final GetWLANConfig GETWLANCONFIG = new SCgetWLANConfig();
|
||||
private static final Login LOGIN = new SClogin();
|
||||
private static final Logout LOGOUT = new SClogout();
|
||||
private static final RunProductCommand RUNPRODUCTCOMMAND = new SCrunProductCommand();
|
||||
private static final RunProductDiscovery RUNPRODUCTDISCOVERY = new SCrunProductDiscovery();
|
||||
private static final RunProductIdentification RUNPRODUCTIDENTIFICATION = new SCrunProductIdentification();
|
||||
private static final RunProductSearch RUNPRODUCTSEARCH = new SCrunProductSearch();
|
||||
private static final RunScene RUNSCENE = new SCrunScene();
|
||||
private static final SetHouseStatusMonitor SETHOUSESTATUSMONITOR = new SCsetHouseStatusMonitor();
|
||||
private static final SetProductLimitation SETPRODUCTLIMITATION = new SCsetLimitation();
|
||||
private static final SetSceneVelocity SETSCENEVELOCITY = new SCsetSceneVelocity();
|
||||
private final GetDeviceStatus slipGetDeviceStatus = new SCgetDeviceStatus();
|
||||
private final GetFirmware slipGetFirmware = new SCgetFirmware();
|
||||
private final GetHouseStatus slipGetHouseStatus = new SCgetHouseStatus();
|
||||
private final GetLANConfig slipGetLanConfig = new SCgetLANConfig();
|
||||
private final GetProduct slipGetProduct = new SCgetProduct();
|
||||
private final GetProductLimitation slipGetProductLimitation = new SCgetLimitation();
|
||||
private final GetProducts slipGetProducts = new SCgetProducts();
|
||||
private final GetScenes slipGetScenes = new SCgetScenes();
|
||||
private final GetWLANConfig slipGetWLanConfig = new SCgetWLANConfig();
|
||||
private final Login slipLogin = new SClogin();
|
||||
private final Logout slipLogout = new SClogout();
|
||||
private final RunProductCommand slipRunProductCommand = new SCrunProductCommand();
|
||||
private final RunProductDiscovery slipRunProductDiscovery = new SCrunProductDiscovery();
|
||||
private final RunProductIdentification slipRunProductIdentification = new SCrunProductIdentification();
|
||||
private final RunProductSearch slipRunProductSearch = new SCrunProductSearch();
|
||||
private final RunScene slipRunScene = new SCrunScene();
|
||||
private final SetHouseStatusMonitor slipSetHouseMonitor = new SCsetHouseStatusMonitor();
|
||||
private final SetProductLimitation slipSetProductLimitation = new SCsetLimitation();
|
||||
private final SetSceneVelocity slipSetSceneVelocity = new SCsetSceneVelocity();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -118,96 +118,96 @@ class SlipBridgeAPI implements BridgeAPI {
|
||||
|
||||
@Override
|
||||
public GetDeviceStatus getDeviceStatus() {
|
||||
return GETDEVICESTATUS;
|
||||
return slipGetDeviceStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetFirmware getFirmware() {
|
||||
return GETFIRMWARE;
|
||||
return slipGetFirmware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable GetHouseStatus getHouseStatus() {
|
||||
return GETHOUSESTATUS;
|
||||
return slipGetHouseStatus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetLANConfig getLANConfig() {
|
||||
return GETLANCONFIG;
|
||||
return slipGetLanConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable GetProduct getProduct() {
|
||||
return GETPRODUCT;
|
||||
return slipGetProduct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable GetProductLimitation getProductLimitation() {
|
||||
return GETPRODUCTLIMITATION;
|
||||
return slipGetProductLimitation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SetProductLimitation setProductLimitation() {
|
||||
return SETPRODUCTLIMITATION;
|
||||
return slipSetProductLimitation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetProducts getProducts() {
|
||||
return GETPRODUCTS;
|
||||
return slipGetProducts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetScenes getScenes() {
|
||||
return GETSCENES;
|
||||
return slipGetScenes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetWLANConfig getWLANConfig() {
|
||||
return GETWLANCONFIG;
|
||||
return slipGetWLanConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Login login() {
|
||||
return LOGIN;
|
||||
return slipLogin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logout logout() {
|
||||
return LOGOUT;
|
||||
return slipLogout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable RunProductCommand runProductCommand() {
|
||||
return RUNPRODUCTCOMMAND;
|
||||
return slipRunProductCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunProductDiscovery runProductDiscovery() {
|
||||
return RUNPRODUCTDISCOVERY;
|
||||
return slipRunProductDiscovery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunProductIdentification runProductIdentification() {
|
||||
return RUNPRODUCTIDENTIFICATION;
|
||||
return slipRunProductIdentification;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunProductSearch runProductSearch() {
|
||||
return RUNPRODUCTSEARCH;
|
||||
return slipRunProductSearch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RunScene runScene() {
|
||||
return RUNSCENE;
|
||||
return slipRunScene;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SetHouseStatusMonitor setHouseStatusMonitor() {
|
||||
return SETHOUSESTATUSMONITOR;
|
||||
return slipSetHouseMonitor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SetSceneVelocity setSceneVelocity() {
|
||||
return SETSCENEVELOCITY;
|
||||
return slipSetSceneVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,8 @@ public class SlipVeluxBridge extends VeluxBridge {
|
||||
*/
|
||||
private synchronized boolean bridgeDirectCommunicate(SlipBridgeCommunicationProtocol communication,
|
||||
boolean useAuthentication) {
|
||||
logger.trace("bridgeDirectCommunicate({},{}authenticated) called.", communication.name(),
|
||||
String host = this.bridgeInstance.veluxBridgeConfiguration().ipAddress;
|
||||
logger.trace("bridgeDirectCommunicate({},{}authenticated) on {} called.", host, communication.name(),
|
||||
useAuthentication ? "" : "un");
|
||||
|
||||
assert this.bridgeInstance.veluxBridgeConfiguration().protocol.contentEquals("slip");
|
||||
@@ -213,15 +214,15 @@ public class SlipVeluxBridge extends VeluxBridge {
|
||||
Threads.findDeadlocked();
|
||||
}
|
||||
|
||||
logger.debug("bridgeDirectCommunicate({},{}authenticated) initiated by {}.", commandString,
|
||||
logger.debug("bridgeDirectCommunicate({},{}authenticated) on {} initiated by {}.", host, commandString,
|
||||
useAuthentication ? "" : "un", Thread.currentThread());
|
||||
boolean success = false;
|
||||
|
||||
communication: do {
|
||||
if (communicationStartInMSecs + COMMUNICATION_TIMEOUT_MSECS < System.currentTimeMillis()) {
|
||||
logger.warn(
|
||||
"{} bridgeDirectCommunicate({}): communication handshake failed (unexpected sequence of requests/responses).",
|
||||
VeluxBindingConstants.BINDING_VALUES_SEPARATOR, communication.name());
|
||||
"{} bridgeDirectCommunicate({}) on {}: communication handshake failed (unexpected sequence of requests/responses).",
|
||||
VeluxBindingConstants.BINDING_VALUES_SEPARATOR, communication.name(), host);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -234,67 +235,71 @@ public class SlipVeluxBridge extends VeluxBridge {
|
||||
}
|
||||
|
||||
// Normal processing
|
||||
logger.trace("bridgeDirectCommunicate(): working on request {} with {} bytes of data.", commandString,
|
||||
data.length);
|
||||
logger.trace("bridgeDirectCommunicate() on {}: working on request {} with {} bytes of data.", host,
|
||||
commandString, data.length);
|
||||
byte[] sendBytes = emptyPacket;
|
||||
if (Command.get(command) == Command.GW_OPENHAB_RECEIVEONLY) {
|
||||
logger.trace(
|
||||
"bridgeDirectCommunicate(): special command: determine whether there is any message waiting.");
|
||||
"bridgeDirectCommunicate() on {}: special command: determine whether there is any message waiting.",
|
||||
host);
|
||||
logger.trace("bridgeDirectCommunicate(): check for a waiting message.");
|
||||
if (!connection.isMessageAvailable()) {
|
||||
logger.trace("bridgeDirectCommunicate(): no message waiting, aborting.");
|
||||
logger.trace("bridgeDirectCommunicate() on {}: no message waiting, aborting.", host);
|
||||
break communication;
|
||||
}
|
||||
logger.trace("bridgeDirectCommunicate(): there is a message waiting.");
|
||||
logger.trace("bridgeDirectCommunicate() on {}: there is a message waiting.", host);
|
||||
} else {
|
||||
SlipEncoding t = new SlipEncoding(command, data);
|
||||
if (!t.isValid()) {
|
||||
logger.warn("bridgeDirectCommunicate(): SlipEncoding() failed, aborting.");
|
||||
logger.warn("bridgeDirectCommunicate() on {}: SlipEncoding() failed, aborting.", host);
|
||||
break;
|
||||
}
|
||||
logger.trace("bridgeDirectCommunicate(): transportEncoding={}.", t.toString());
|
||||
logger.trace("bridgeDirectCommunicate() on {}: transportEncoding={}.", host, t.toString());
|
||||
sendBytes = new SlipRFC1055().encode(t.toMessage());
|
||||
}
|
||||
do {
|
||||
if (communicationStartInMSecs + COMMUNICATION_TIMEOUT_MSECS < System.currentTimeMillis()) {
|
||||
logger.warn("bridgeDirectCommunicate(): receive takes too long. Please report to maintainer.");
|
||||
logger.warn("bridgeDirectCommunicate() on {}: receive takes too long. Please report to maintainer.",
|
||||
host);
|
||||
break communication;
|
||||
}
|
||||
byte[] receivedPacket;
|
||||
try {
|
||||
if (sendBytes.length > 0) {
|
||||
logger.trace("bridgeDirectCommunicate(): sending {} bytes.", sendBytes.length);
|
||||
logger.trace("bridgeDirectCommunicate() on {}: sending {} bytes.", host, sendBytes.length);
|
||||
if (isProtocolTraceEnabled) {
|
||||
logger.info("Sending command {}.", commandString);
|
||||
}
|
||||
} else {
|
||||
logger.trace("bridgeDirectCommunicate(): initiating receive-only.");
|
||||
logger.trace("bridgeDirectCommunicate() on {}: initiating receive-only.", host);
|
||||
}
|
||||
// (Optionally) Send and receive packet.
|
||||
receivedPacket = connection.io(this.bridgeInstance, sendBytes);
|
||||
// Once being sent, it should never be sent again
|
||||
sendBytes = emptyPacket;
|
||||
} catch (Exception e) {
|
||||
logger.warn("bridgeDirectCommunicate(): connection.io returns {}", e.getMessage());
|
||||
logger.warn("bridgeDirectCommunicate() on {}: connection.io returns {}", host, e.getMessage());
|
||||
break communication;
|
||||
}
|
||||
logger.trace("bridgeDirectCommunicate(): received packet {}.", new Packet(receivedPacket).toString());
|
||||
logger.trace("bridgeDirectCommunicate() on {}: received packet {}.", host,
|
||||
new Packet(receivedPacket).toString());
|
||||
byte[] response;
|
||||
try {
|
||||
response = new SlipRFC1055().decode(receivedPacket);
|
||||
} catch (ParseException e) {
|
||||
logger.warn("bridgeDirectCommunicate(): method SlipRFC1055() raised a decoding error: {}.",
|
||||
e.getMessage());
|
||||
logger.warn("bridgeDirectCommunicate() on {}: method SlipRFC1055() raised a decoding error: {}.",
|
||||
host, e.getMessage());
|
||||
break communication;
|
||||
}
|
||||
SlipEncoding tr = new SlipEncoding(response);
|
||||
if (!tr.isValid()) {
|
||||
logger.warn("bridgeDirectCommunicate(): method SlipEncoding() raised a decoding error.");
|
||||
logger.warn("bridgeDirectCommunicate() on {}: method SlipEncoding() raised a decoding error.",
|
||||
host);
|
||||
break communication;
|
||||
}
|
||||
short responseCommand = tr.getCommand();
|
||||
byte[] responseData = tr.getData();
|
||||
logger.debug("bridgeDirectCommunicate(): working on response {} with {} bytes of data.",
|
||||
logger.debug("bridgeDirectCommunicate() on {}: working on response {} with {} bytes of data.", host,
|
||||
Command.get(responseCommand).toString(), responseData.length);
|
||||
if (isProtocolTraceEnabled) {
|
||||
logger.info("Received answer {}.", Command.get(responseCommand).toString());
|
||||
@@ -302,63 +307,66 @@ public class SlipVeluxBridge extends VeluxBridge {
|
||||
// Handle some common (unexpected) answers
|
||||
switch (Command.get(responseCommand)) {
|
||||
case GW_NODE_INFORMATION_CHANGED_NTF:
|
||||
logger.trace("bridgeDirectCommunicate(): received GW_NODE_INFORMATION_CHANGED_NTF.");
|
||||
logger.trace("bridgeDirectCommunicate(): continue with receiving.");
|
||||
logger.trace("bridgeDirectCommunicate() on {}: received GW_NODE_INFORMATION_CHANGED_NTF.",
|
||||
host);
|
||||
logger.trace("bridgeDirectCommunicate() on {}: continue with receiving.", host);
|
||||
continue;
|
||||
case GW_NODE_STATE_POSITION_CHANGED_NTF:
|
||||
logger.trace(
|
||||
"bridgeDirectCommunicate(): received GW_NODE_STATE_POSITION_CHANGED_NTF, special processing of this packet.");
|
||||
"bridgeDirectCommunicate() on {}: received GW_NODE_STATE_POSITION_CHANGED_NTF, special processing of this packet.",
|
||||
host);
|
||||
SCgetHouseStatus receiver = new SCgetHouseStatus();
|
||||
receiver.setResponse(responseCommand, responseData, isSequentialEnforced);
|
||||
if (receiver.isCommunicationSuccessful()) {
|
||||
logger.trace("bridgeDirectCommunicate(): existingProducts().update() called.");
|
||||
logger.trace("bridgeDirectCommunicate() on {}: existingProducts().update() called.", host);
|
||||
bridgeInstance.existingProducts().update(new ProductBridgeIndex(receiver.getNtfNodeID()),
|
||||
receiver.getNtfState(), receiver.getNtfCurrentPosition(), receiver.getNtfTarget());
|
||||
}
|
||||
logger.trace("bridgeDirectCommunicate(): continue with receiving.");
|
||||
logger.trace("bridgeDirectCommunicate() on {}: continue with receiving.", host);
|
||||
continue;
|
||||
case GW_ERROR_NTF:
|
||||
switch (responseData[0]) {
|
||||
case 0:
|
||||
logger.warn(
|
||||
"bridgeDirectCommunicate(): received GW_ERROR_NTF on {} (Not further defined error), aborting.",
|
||||
commandString);
|
||||
"bridgeDirectCommunicate() on {}: received GW_ERROR_NTF on {} (Not further defined error), aborting.",
|
||||
host, commandString);
|
||||
break communication;
|
||||
case 1:
|
||||
logger.warn(
|
||||
"bridgeDirectCommunicate(): received GW_ERROR_NTF (Unknown Command or command is not accepted at this state) on {}, aborting.",
|
||||
commandString);
|
||||
"bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (Unknown Command or command is not accepted at this state) on {}, aborting.",
|
||||
host, commandString);
|
||||
break communication;
|
||||
case 2:
|
||||
logger.warn(
|
||||
"bridgeDirectCommunicate(): received GW_ERROR_NTF (ERROR on Frame Structure) on {}, aborting.",
|
||||
commandString);
|
||||
"bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (ERROR on Frame Structure) on {}, aborting.",
|
||||
host, commandString);
|
||||
break communication;
|
||||
case 7:
|
||||
logger.trace(
|
||||
"bridgeDirectCommunicate(): received GW_ERROR_NTF (Busy. Try again later) on {}, retrying.",
|
||||
commandString);
|
||||
"bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (Busy. Try again later) on {}, retrying.",
|
||||
host, commandString);
|
||||
sendBytes = emptyPacket;
|
||||
continue;
|
||||
case 8:
|
||||
logger.warn(
|
||||
"bridgeDirectCommunicate(): received GW_ERROR_NTF (Bad system table index) on {}, aborting.",
|
||||
commandString);
|
||||
"bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (Bad system table index) on {}, aborting.",
|
||||
host, commandString);
|
||||
break communication;
|
||||
case 12:
|
||||
logger.warn(
|
||||
"bridgeDirectCommunicate(): received GW_ERROR_NTF (Not authenticated) on {}, aborting.",
|
||||
commandString);
|
||||
"bridgeDirectCommunicate() on {}: received GW_ERROR_NTF (Not authenticated) on {}, aborting.",
|
||||
host, commandString);
|
||||
resetAuthentication();
|
||||
break communication;
|
||||
default:
|
||||
logger.warn("bridgeDirectCommunicate(): received GW_ERROR_NTF ({}) on {}, aborting.",
|
||||
responseData[0], commandString);
|
||||
logger.warn(
|
||||
"bridgeDirectCommunicate() on {}: received GW_ERROR_NTF ({}) on {}, aborting.",
|
||||
host, responseData[0], commandString);
|
||||
break communication;
|
||||
}
|
||||
case GW_ACTIVATION_LOG_UPDATED_NTF:
|
||||
logger.info("bridgeDirectCommunicate(): received GW_ACTIVATION_LOG_UPDATED_NTF.");
|
||||
logger.trace("bridgeDirectCommunicate(): continue with receiving.");
|
||||
logger.info("bridgeDirectCommunicate() on {}: received GW_ACTIVATION_LOG_UPDATED_NTF.", host);
|
||||
logger.trace("bridgeDirectCommunicate() on {}: continue with receiving.", host);
|
||||
continue;
|
||||
|
||||
case GW_COMMAND_RUN_STATUS_NTF:
|
||||
@@ -366,19 +374,21 @@ public class SlipVeluxBridge extends VeluxBridge {
|
||||
case GW_SESSION_FINISHED_NTF:
|
||||
if (!isSequentialEnforced) {
|
||||
logger.trace(
|
||||
"bridgeDirectCommunicate(): response ignored due to activated parallelism, continue with receiving.");
|
||||
"bridgeDirectCommunicate() on {}: response ignored due to activated parallelism, continue with receiving.",
|
||||
host);
|
||||
continue;
|
||||
}
|
||||
|
||||
default:
|
||||
}
|
||||
logger.trace("bridgeDirectCommunicate(): passes back command {} and data {}.",
|
||||
logger.trace("bridgeDirectCommunicate() on {}: passes back command {} and data {}.", host,
|
||||
new CommandNumber(responseCommand).toString(), new Packet(responseData).toString());
|
||||
communication.setResponse(responseCommand, responseData, isSequentialEnforced);
|
||||
} while (!communication.isCommunicationFinished());
|
||||
success = communication.isCommunicationSuccessful();
|
||||
} while (false); // communication
|
||||
logger.debug("bridgeDirectCommunicate({}) returns {}.", commandString, success ? "success" : "failure");
|
||||
logger.debug("bridgeDirectCommunicate({}) on {}: returns {}.", commandString, host,
|
||||
success ? "success" : "failure");
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.io.IOException;
|
||||
import java.net.ConnectException;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velux.internal.VeluxBindingConstants;
|
||||
import org.openhab.binding.velux.internal.bridge.VeluxBridgeInstance;
|
||||
import org.openhab.binding.velux.internal.bridge.slip.utils.Packet;
|
||||
import org.slf4j.Logger;
|
||||
@@ -59,6 +60,8 @@ public class Connection {
|
||||
*/
|
||||
private SSLconnection connectivity = SSLconnection.UNKNOWN;
|
||||
|
||||
private String host = VeluxBindingConstants.UNKNOWN_IP_ADDRESS;
|
||||
|
||||
/*
|
||||
* **************************
|
||||
* ***** Public Methods *****
|
||||
@@ -75,7 +78,7 @@ public class Connection {
|
||||
*/
|
||||
public synchronized byte[] io(VeluxBridgeInstance bridgeInstance, byte[] request)
|
||||
throws ConnectException, IOException {
|
||||
logger.trace("io() called.");
|
||||
logger.trace("io() on {}: called.", host);
|
||||
|
||||
lastCommunicationInMSecs = System.currentTimeMillis();
|
||||
|
||||
@@ -88,18 +91,18 @@ public class Connection {
|
||||
if (!connectivity.isReady()) {
|
||||
try {
|
||||
// From configuration
|
||||
String host = bridgeInstance.veluxBridgeConfiguration().ipAddress;
|
||||
host = bridgeInstance.veluxBridgeConfiguration().ipAddress;
|
||||
int port = bridgeInstance.veluxBridgeConfiguration().tcpPort;
|
||||
int timeoutMsecs = bridgeInstance.veluxBridgeConfiguration().timeoutMsecs;
|
||||
|
||||
logger.trace("io(): connecting to {}:{}.", host, port);
|
||||
logger.trace("io() on {}: connecting to port {}", host, port);
|
||||
connectivity = new SSLconnection(host, port);
|
||||
connectivity.setTimeout(timeoutMsecs);
|
||||
} catch (ConnectException ce) {
|
||||
throw new ConnectException(String
|
||||
.format("raised a non-recoverable error during connection setup: %s", ce.getMessage()));
|
||||
} catch (IOException e) {
|
||||
logger.warn("io(): raised an error during connection setup: {}.", e.getMessage());
|
||||
logger.warn("io() on {}: raised an error during connection setup: {}.", host, e.getMessage());
|
||||
lastIOE = new IOException(String.format("error during connection setup: %s.", e.getMessage()));
|
||||
continue;
|
||||
}
|
||||
@@ -107,65 +110,68 @@ public class Connection {
|
||||
if (request.length > 0) {
|
||||
try {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("io(): sending packet with {} bytes: {}", request.length, new Packet(request));
|
||||
logger.trace("io() on {}: sending packet with {} bytes: {}", host, request.length,
|
||||
new Packet(request));
|
||||
} else {
|
||||
logger.debug("io(): sending packet of size {}.", request.length);
|
||||
logger.debug("io() on {}: sending packet of size {}.", host, request.length);
|
||||
}
|
||||
if (connectivity.isReady()) {
|
||||
connectivity.send(request);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.info("io(): raised an error during sending: {}.", e.getMessage());
|
||||
logger.info("io() on {}: raised an error during sending: {}.", host, e.getMessage());
|
||||
break;
|
||||
}
|
||||
|
||||
// Give the bridge some time to breathe
|
||||
if (bridgeInstance.veluxBridgeConfiguration().timeoutMsecs > 0) {
|
||||
logger.trace("io(): wait time {} msecs.",
|
||||
logger.trace("io() on {}: wait time {} msecs.", host,
|
||||
bridgeInstance.veluxBridgeConfiguration().timeoutMsecs);
|
||||
try {
|
||||
Thread.sleep(bridgeInstance.veluxBridgeConfiguration().timeoutMsecs);
|
||||
} catch (InterruptedException ie) {
|
||||
logger.trace("io() wait interrupted.");
|
||||
logger.trace("io() on {}: wait interrupted.", host);
|
||||
}
|
||||
}
|
||||
}
|
||||
byte[] packet = new byte[0];
|
||||
logger.trace("io(): receiving bytes.");
|
||||
logger.trace("io() on {}: receiving bytes.", host);
|
||||
if (connectivity.isReady()) {
|
||||
packet = connectivity.receive();
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("io(): received packet with {} bytes: {}", packet.length, new Packet(packet));
|
||||
logger.trace("io() on {}: received packet with {} bytes: {}", host, packet.length,
|
||||
new Packet(packet));
|
||||
} else {
|
||||
logger.debug("io(): received packet with {} bytes.", packet.length);
|
||||
logger.debug("io() on {}: received packet with {} bytes.", host, packet.length);
|
||||
}
|
||||
lastSuccessfulCommunicationInMSecs = System.currentTimeMillis();
|
||||
lastCommunicationInMSecs = lastSuccessfulCommunicationInMSecs;
|
||||
logger.trace("io() finished.");
|
||||
logger.trace("io() on {}: finished.", host);
|
||||
return packet;
|
||||
} catch (IOException ioe) {
|
||||
logger.info("io(): Exception occurred during I/O: {}.", ioe.getMessage());
|
||||
logger.info("io() on {}: Exception occurred during I/O: {}.", host, ioe.getMessage());
|
||||
lastIOE = ioe;
|
||||
// Error Retries with Exponential Backoff
|
||||
long waitTime = ((long) Math.pow(2, retryCount)
|
||||
* bridgeInstance.veluxBridgeConfiguration().timeoutMsecs);
|
||||
logger.trace("io(): wait time {} msecs.", waitTime);
|
||||
logger.trace("io() on {}: wait time {} msecs.", host, waitTime);
|
||||
try {
|
||||
Thread.sleep(waitTime);
|
||||
} catch (InterruptedException ie) {
|
||||
logger.trace("io(): wait interrupted.");
|
||||
logger.trace("io() on {}: wait interrupted.", host);
|
||||
}
|
||||
}
|
||||
} while (retryCount++ < bridgeInstance.veluxBridgeConfiguration().retries);
|
||||
if (retryCount >= bridgeInstance.veluxBridgeConfiguration().retries) {
|
||||
logger.info("io(): socket I/O failed {} times.", bridgeInstance.veluxBridgeConfiguration().retries);
|
||||
logger.info("io() on {}: socket I/O failed {} times.", host,
|
||||
bridgeInstance.veluxBridgeConfiguration().retries);
|
||||
}
|
||||
logger.trace("io(): shutting down connection.");
|
||||
logger.trace("io() on {}: shutting down connection.", host);
|
||||
if (connectivity.isReady()) {
|
||||
connectivity.close();
|
||||
}
|
||||
logger.trace("io() finishes with failure by throwing exception.");
|
||||
logger.trace("io() on {}: finishes with failure by throwing exception.", host);
|
||||
throw lastIOE;
|
||||
}
|
||||
|
||||
@@ -175,7 +181,7 @@ public class Connection {
|
||||
* @return state as boolean.
|
||||
*/
|
||||
public boolean isAlive() {
|
||||
logger.trace("isAlive(): called.");
|
||||
logger.trace("isAlive() on {}: called.", host);
|
||||
return connectivity.isReady();
|
||||
}
|
||||
|
||||
@@ -185,17 +191,17 @@ public class Connection {
|
||||
* @return state as boolean.
|
||||
*/
|
||||
public synchronized boolean isMessageAvailable() {
|
||||
logger.trace("isMessageAvailable(): called.");
|
||||
logger.trace("isMessageAvailable() on {}: called.", host);
|
||||
try {
|
||||
if ((connectivity.isReady()) && (connectivity.available())) {
|
||||
logger.trace("isMessageAvailable(): there is a message waiting.");
|
||||
logger.trace("isMessageAvailable() on {}: there is a message waiting.", host);
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.trace("isMessageAvailable(): lost connection due to {}.", e.getMessage());
|
||||
logger.trace("isMessageAvailable() on {}: lost connection due to {}.", host, e.getMessage());
|
||||
resetConnection();
|
||||
}
|
||||
logger.trace("isMessageAvailable(): no message waiting.");
|
||||
logger.trace("isMessageAvailable() on {}: no message waiting.", host);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -223,18 +229,12 @@ public class Connection {
|
||||
* Resets an open connectivity by closing the socket and resetting the authentication information.
|
||||
*/
|
||||
public synchronized void resetConnection() {
|
||||
logger.trace("resetConnection() called.");
|
||||
if (connectivity.isReady()) {
|
||||
logger.trace("resetConnection(): shutting down connection.");
|
||||
try {
|
||||
if (connectivity.isReady()) {
|
||||
connectivity.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.info("resetConnection(): raised an error during connection close: {}.", e.getMessage());
|
||||
}
|
||||
logger.trace("resetConnection(): clearing authentication token.");
|
||||
logger.trace("resetConnection() on {}: called.", host);
|
||||
try {
|
||||
connectivity.close();
|
||||
} catch (IOException e) {
|
||||
logger.info("resetConnection() on {}: raised an error during connection close: {}.", host, e.getMessage());
|
||||
}
|
||||
logger.trace("resetConnection() done.");
|
||||
logger.trace("resetConnection() on {}: done.", host);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,23 +155,43 @@ class SSLconnection {
|
||||
|
||||
/**
|
||||
* Method to pass a message towards the bridge.
|
||||
* This method gets called when we are initiating a new SLIP transaction.
|
||||
* <p>
|
||||
* Note that DataOutputStream and DataInputStream are buffered I/O's. The SLIP protocol requires that prior requests
|
||||
* should have been fully sent over the socket, and their responses should have been fully read from the buffer
|
||||
* before the next request is initiated. i.e. Both read and write buffers should already be empty. Nevertheless,
|
||||
* just in case, we do the following..
|
||||
* <p>
|
||||
* 1) Flush from the read buffer any orphan response data that may have been left over from prior transactions, and
|
||||
* 2) Flush the write buffer directly to the socket to ensure that any exceptions are raised immediately, and the
|
||||
* KLF starts work immediately
|
||||
*
|
||||
* @param packet as Array of bytes to be transmitted towards the bridge via the established connection.
|
||||
* @throws java.io.IOException in case of a communication I/O failure.
|
||||
* @throws java.io.IOException in case of a communication I/O failure, and sets 'ready' = false
|
||||
*/
|
||||
@SuppressWarnings("null")
|
||||
synchronized void send(byte[] packet) throws IOException {
|
||||
logger.trace("send() called, writing {} bytes.", packet.length);
|
||||
if (!ready || (dOut == null)) {
|
||||
throw new IOException();
|
||||
}
|
||||
dOut.write(packet, 0, packet.length);
|
||||
if (logger.isTraceEnabled()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : packet) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
try {
|
||||
if (!ready || (dOut == null) || (dIn == null)) {
|
||||
throw new IOException();
|
||||
}
|
||||
logger.trace("send() finished after having send {} bytes: {}", packet.length, sb.toString());
|
||||
// flush the read buffer if (exceptionally) there is orphan response data in it
|
||||
flushReadBufffer();
|
||||
// copy packet data to the write buffer
|
||||
dOut.write(packet, 0, packet.length);
|
||||
// force the write buffer data to be written to the socket
|
||||
dOut.flush();
|
||||
if (logger.isTraceEnabled()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : packet) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
}
|
||||
logger.trace("send() finished after having send {} bytes: {}", packet.length, sb.toString());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
ready = false;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,26 +216,31 @@ class SSLconnection {
|
||||
* Method to get a message from the bridge.
|
||||
*
|
||||
* @return <b>packet</b> as Array of bytes as received from the bridge via the established connection.
|
||||
* @throws java.io.IOException in case of a communication I/O failure.
|
||||
* @throws java.io.IOException in case of a communication I/O failure, and sets 'ready' = false
|
||||
*/
|
||||
synchronized byte[] receive() throws IOException {
|
||||
logger.trace("receive() called.");
|
||||
if (!ready || (dIn == null)) {
|
||||
throw new IOException();
|
||||
}
|
||||
byte[] message = new byte[CONNECTION_BUFFER_SIZE];
|
||||
@SuppressWarnings("null")
|
||||
int messageLength = dIn.read(message, 0, message.length, ioTimeoutMSecs);
|
||||
byte[] packet = new byte[messageLength];
|
||||
System.arraycopy(message, 0, packet, 0, messageLength);
|
||||
if (logger.isTraceEnabled()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : packet) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
try {
|
||||
if (!ready || (dIn == null)) {
|
||||
throw new IOException();
|
||||
}
|
||||
logger.trace("receive() finished after having read {} bytes: {}", messageLength, sb.toString());
|
||||
byte[] message = new byte[CONNECTION_BUFFER_SIZE];
|
||||
@SuppressWarnings("null")
|
||||
int messageLength = dIn.read(message, 0, message.length, ioTimeoutMSecs);
|
||||
byte[] packet = new byte[messageLength];
|
||||
System.arraycopy(message, 0, packet, 0, messageLength);
|
||||
if (logger.isTraceEnabled()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : packet) {
|
||||
sb.append(String.format("%02X ", b));
|
||||
}
|
||||
logger.trace("receive() finished after having read {} bytes: {}", messageLength, sb.toString());
|
||||
}
|
||||
return packet;
|
||||
} catch (IOException e) {
|
||||
ready = false;
|
||||
throw e;
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,16 +256,19 @@ class SSLconnection {
|
||||
DataInputStreamWithTimeout dInX = dIn;
|
||||
if (dInX != null) {
|
||||
dInX.close();
|
||||
dIn = null;
|
||||
}
|
||||
// Just for avoidance of Potential null pointer access
|
||||
DataOutputStream dOutX = dOut;
|
||||
if (dOutX != null) {
|
||||
dOutX.close();
|
||||
dOut = null;
|
||||
}
|
||||
// Just for avoidance of Potential null pointer access
|
||||
SSLSocket socketX = socket;
|
||||
if (socketX != null) {
|
||||
socketX.close();
|
||||
socket = null;
|
||||
}
|
||||
logger.trace("close() finished.");
|
||||
}
|
||||
@@ -254,4 +282,32 @@ class SSLconnection {
|
||||
logger.debug("setTimeout() set timeout to {} milliseconds.", timeoutMSecs);
|
||||
ioTimeoutMSecs = timeoutMSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to flush the input buffer.
|
||||
*
|
||||
* @throws java.io.IOException in case of a communication I/O failure.
|
||||
*/
|
||||
private void flushReadBufffer() throws IOException {
|
||||
logger.trace("flushReadBuffer() called.");
|
||||
DataInputStreamWithTimeout dInX = dIn;
|
||||
if (!ready || (dInX == null)) {
|
||||
throw new IOException();
|
||||
}
|
||||
int byteCount = dInX.available();
|
||||
if (byteCount > 0) {
|
||||
byte[] byteArray = new byte[byteCount];
|
||||
dInX.readFully(byteArray);
|
||||
if (logger.isTraceEnabled()) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (byte currByte : byteArray) {
|
||||
stringBuilder.append(String.format("%02X ", currByte));
|
||||
}
|
||||
logger.trace("flushReadBuffer(): discarded {} unexpected bytes in the input buffer: {}", byteCount,
|
||||
stringBuilder.toString());
|
||||
} else {
|
||||
logger.warn("flushReadBuffer(): discarded {} unexpected bytes in the input buffer", byteCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,9 +64,9 @@ public class KLF200Response {
|
||||
*/
|
||||
public static void errorLogging(Logger logger, short responseCommand) {
|
||||
logger.trace("setResponse(): cannot handle response {} ({}).", Command.get(responseCommand).toString(),
|
||||
responseCommand);
|
||||
new CommandNumber(responseCommand).toString());
|
||||
logger.warn("Gateway response {} ({}) cannot be handled at this point of interaction.",
|
||||
Command.get(responseCommand).toString(), responseCommand);
|
||||
Command.get(responseCommand).toString(), new CommandNumber(responseCommand).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,10 +122,10 @@ public class KLF200Response {
|
||||
* @return <b>check4matchingAnyID</b> of type boolean which signals the equality.
|
||||
*/
|
||||
private static boolean check4matchingAnyID(Logger logger, String idName, int requestID, int responseID) {
|
||||
logger.trace("check4matchingAnyID() called for request{} {} and response{} {}.", idName, requestID, idName,
|
||||
logger.trace("check4matchingAnyID() called for request {} {} and response {} {}.", idName, requestID, idName,
|
||||
responseID);
|
||||
if (requestID != responseID) {
|
||||
logger.warn("Gateway response with {} {} unexpected as query asked for {} {}.", idName, requestID, idName,
|
||||
logger.warn("Gateway query for {} {} received unexpected response of {} {}.", idName, requestID, idName,
|
||||
responseID);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ public class SlipEncoding {
|
||||
private final Logger logger = LoggerFactory.getLogger(SlipEncoding.class);
|
||||
|
||||
private static final byte PROTOCOL_ID = 0;
|
||||
private static boolean encodingValid = false;
|
||||
private static byte[] message = new byte[0];
|
||||
private boolean encodingValid = false;
|
||||
private byte[] message = new byte[0];
|
||||
|
||||
/**
|
||||
* Builds a message based on command and parameters.
|
||||
|
||||
@@ -14,8 +14,10 @@ package org.openhab.binding.velux.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.velux.internal.VeluxBindingConstants.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.velux.internal.VeluxBindingConstants;
|
||||
import org.openhab.binding.velux.internal.VeluxBindingProperties;
|
||||
import org.openhab.binding.velux.internal.handler.VeluxBridgeHandler;
|
||||
@@ -60,7 +62,7 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
|
||||
private @NonNullByDefault({}) LocaleProvider localeProvider;
|
||||
private @NonNullByDefault({}) TranslationProvider i18nProvider;
|
||||
private Localization localization = Localization.UNKNOWN;
|
||||
private static @Nullable VeluxBridgeHandler bridgeHandler = null;
|
||||
private final Set<VeluxBridgeHandler> bridgeHandlers = new HashSet<>();
|
||||
|
||||
// Private
|
||||
|
||||
@@ -102,21 +104,11 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
|
||||
* Initializes the {@link VeluxDiscoveryService} with a reference to the well-prepared environment with a
|
||||
* {@link VeluxBridgeHandler}.
|
||||
*
|
||||
* @param bridge Initialized Velux bridge handler.
|
||||
* @param localizationHandler Initialized localization handler.
|
||||
*/
|
||||
public VeluxDiscoveryService(VeluxBridgeHandler bridge, Localization localizationHandler) {
|
||||
public VeluxDiscoveryService(Localization localizationHandler) {
|
||||
super(VeluxBindingConstants.SUPPORTED_THINGS_ITEMS, DISCOVER_TIMEOUT_SECONDS);
|
||||
logger.trace("VeluxDiscoveryService(bridge={},locale={},i18n={}) just initialized.", bridge, localeProvider,
|
||||
i18nProvider);
|
||||
|
||||
if (bridgeHandler == null) {
|
||||
logger.trace("VeluxDiscoveryService(): registering bridge {} for lateron use for Discovery.", bridge);
|
||||
} else if (!bridge.equals(bridgeHandler)) {
|
||||
logger.trace("VeluxDiscoveryService(): replacing already registered bridge {} by {}.", bridgeHandler,
|
||||
bridge);
|
||||
}
|
||||
bridgeHandler = bridge;
|
||||
logger.trace("VeluxDiscoveryService(locale={},i18n={}) just initialized.", localeProvider, i18nProvider);
|
||||
localization = localizationHandler;
|
||||
}
|
||||
|
||||
@@ -126,16 +118,14 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
|
||||
* Initializes the {@link VeluxDiscoveryService} with a reference to the well-prepared environment with a
|
||||
* {@link VeluxBridgeHandler}.
|
||||
*
|
||||
* @param bridge Initialized Velux bridge handler.
|
||||
* @param locationProvider Provider for a location.
|
||||
* @param localeProvider Provider for a locale.
|
||||
* @param i18nProvider Provider for the internationalization.
|
||||
*/
|
||||
public VeluxDiscoveryService(VeluxBridgeHandler bridge, LocationProvider locationProvider,
|
||||
LocaleProvider localeProvider, TranslationProvider i18nProvider) {
|
||||
this(bridge, new Localization(localeProvider, i18nProvider));
|
||||
logger.trace("VeluxDiscoveryService(bridge={},locale={},i18n={}) finished.", bridge, localeProvider,
|
||||
i18nProvider);
|
||||
public VeluxDiscoveryService(LocationProvider locationProvider, LocaleProvider localeProvider,
|
||||
TranslationProvider i18nProvider) {
|
||||
this(new Localization(localeProvider, i18nProvider));
|
||||
logger.trace("VeluxDiscoveryService(locale={},i18n={}) finished.", localeProvider, i18nProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,8 +147,8 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
|
||||
logger.debug("startScan(): registering new thing {}.", discoveryResult);
|
||||
thingDiscovered(discoveryResult);
|
||||
|
||||
if (bridgeHandler == null) {
|
||||
logger.debug("startScan(): VeluxDiscoveryService cannot proceed due to missing Velux bridge.");
|
||||
if (bridgeHandlers.isEmpty()) {
|
||||
logger.debug("startScan(): VeluxDiscoveryService cannot proceed due to missing Velux bridge(s).");
|
||||
} else {
|
||||
logger.debug("startScan(): Starting Velux discovery scan for scenes and actuators.");
|
||||
discoverScenes();
|
||||
@@ -185,29 +175,25 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
|
||||
*/
|
||||
private void discoverScenes() {
|
||||
logger.trace("discoverScenes() called.");
|
||||
// Just for avoidance of Potential null pointer access
|
||||
VeluxBridgeHandler bridgeHandlerX = bridgeHandler;
|
||||
if (bridgeHandlerX == null) {
|
||||
logger.debug("discoverScenes(): VeluxDiscoveryService.bridgeHandler not initialized, aborting discovery.");
|
||||
return;
|
||||
}
|
||||
ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
|
||||
logger.debug("discoverScenes(): discovering all scenes.");
|
||||
for (VeluxScene scene : bridgeHandlerX.existingScenes().values()) {
|
||||
String sceneName = scene.getName().toString();
|
||||
logger.trace("discoverScenes(): found scene {}.", sceneName);
|
||||
for (VeluxBridgeHandler bridgeHandlerX : bridgeHandlers) {
|
||||
ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
|
||||
logger.debug("discoverScenes(): discovering all scenes on bridge {}.", bridgeUID);
|
||||
for (VeluxScene scene : bridgeHandlerX.existingScenes().values()) {
|
||||
String sceneName = scene.getName().toString();
|
||||
logger.trace("discoverScenes(): found scene {}.", sceneName);
|
||||
|
||||
String label = sceneName.replaceAll("\\P{Alnum}", "_");
|
||||
logger.trace("discoverScenes(): using label {}.", label);
|
||||
String label = sceneName.replaceAll("\\P{Alnum}", "_");
|
||||
logger.trace("discoverScenes(): using label {}.", label);
|
||||
|
||||
ThingTypeUID thingTypeUID = THING_TYPE_VELUX_SCENE;
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
|
||||
.withProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME, sceneName)
|
||||
.withRepresentationProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME).withBridge(bridgeUID)
|
||||
.withLabel(label).build();
|
||||
logger.debug("discoverScenes(): registering new thing {}.", discoveryResult);
|
||||
thingDiscovered(discoveryResult);
|
||||
ThingTypeUID thingTypeUID = THING_TYPE_VELUX_SCENE;
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
|
||||
.withProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME, sceneName)
|
||||
.withRepresentationProperty(VeluxBindingProperties.PROPERTY_SCENE_NAME).withBridge(bridgeUID)
|
||||
.withLabel(label).build();
|
||||
logger.debug("discoverScenes(): registering new thing {}.", discoveryResult);
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
logger.trace("discoverScenes() finished.");
|
||||
}
|
||||
@@ -217,56 +203,87 @@ public class VeluxDiscoveryService extends AbstractDiscoveryService implements R
|
||||
*/
|
||||
private void discoverProducts() {
|
||||
logger.trace("discoverProducts() called.");
|
||||
// Just for avoidance of Potential null pointer access
|
||||
VeluxBridgeHandler bridgeHandlerX = bridgeHandler;
|
||||
if (bridgeHandlerX == null) {
|
||||
logger.debug("discoverScenes() VeluxDiscoveryService.bridgeHandlerR not initialized, aborting discovery.");
|
||||
return;
|
||||
}
|
||||
ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
|
||||
logger.debug("discoverProducts(): discovering all actuators.");
|
||||
for (VeluxProduct product : bridgeHandlerX.existingProducts().values()) {
|
||||
String serialNumber = product.getSerialNumber();
|
||||
String actuatorName = product.getProductName().toString();
|
||||
logger.trace("discoverProducts() found actuator {} (name {}).", serialNumber, actuatorName);
|
||||
String identifier;
|
||||
if (serialNumber.equals(VeluxProductSerialNo.UNKNOWN)) {
|
||||
identifier = actuatorName;
|
||||
} else {
|
||||
identifier = serialNumber;
|
||||
for (VeluxBridgeHandler bridgeHandlerX : bridgeHandlers) {
|
||||
ThingUID bridgeUID = bridgeHandlerX.getThing().getUID();
|
||||
logger.debug("discoverProducts(): discovering all actuators on bridge {}.", bridgeUID);
|
||||
for (VeluxProduct product : bridgeHandlerX.existingProducts().values()) {
|
||||
String serialNumber = product.getSerialNumber();
|
||||
String actuatorName = product.getProductName().toString();
|
||||
logger.trace("discoverProducts() found actuator {} (name {}).", serialNumber, actuatorName);
|
||||
String identifier;
|
||||
if (serialNumber.equals(VeluxProductSerialNo.UNKNOWN)) {
|
||||
identifier = actuatorName;
|
||||
} else {
|
||||
identifier = serialNumber;
|
||||
}
|
||||
String label = actuatorName.replaceAll("\\P{Alnum}", "_");
|
||||
logger.trace("discoverProducts(): using label {}.", label);
|
||||
ThingTypeUID thingTypeUID;
|
||||
boolean isInverted = false;
|
||||
logger.trace("discoverProducts() dealing with {} (type {}).", product, product.getProductType());
|
||||
switch (product.getProductType()) {
|
||||
case SLIDER_WINDOW:
|
||||
logger.trace("discoverProducts(): creating window.");
|
||||
thingTypeUID = THING_TYPE_VELUX_WINDOW;
|
||||
isInverted = true;
|
||||
break;
|
||||
|
||||
case SLIDER_SHUTTER:
|
||||
logger.trace("discoverProducts(): creating rollershutter.");
|
||||
thingTypeUID = THING_TYPE_VELUX_ROLLERSHUTTER;
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.trace("discoverProducts(): creating actuator.");
|
||||
thingTypeUID = THING_TYPE_VELUX_ACTUATOR;
|
||||
}
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
|
||||
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
|
||||
.withProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER, identifier)
|
||||
.withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_NAME, actuatorName)
|
||||
.withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_INVERTED, isInverted)
|
||||
.withRepresentationProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER)
|
||||
.withBridge(bridgeUID).withLabel(actuatorName).build();
|
||||
logger.debug("discoverProducts(): registering new thing {}.", discoveryResult);
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
String label = actuatorName.replaceAll("\\P{Alnum}", "_");
|
||||
logger.trace("discoverProducts(): using label {}.", label);
|
||||
ThingTypeUID thingTypeUID;
|
||||
boolean isInverted = false;
|
||||
logger.trace("discoverProducts() dealing with {} (type {}).", product, product.getProductType());
|
||||
switch (product.getProductType()) {
|
||||
case SLIDER_WINDOW:
|
||||
logger.trace("discoverProducts(): creating window.");
|
||||
thingTypeUID = THING_TYPE_VELUX_WINDOW;
|
||||
isInverted = true;
|
||||
break;
|
||||
|
||||
case SLIDER_SHUTTER:
|
||||
logger.trace("discoverProducts(): creating rollershutter.");
|
||||
thingTypeUID = THING_TYPE_VELUX_ROLLERSHUTTER;
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.trace("discoverProducts(): creating actuator.");
|
||||
thingTypeUID = THING_TYPE_VELUX_ACTUATOR;
|
||||
}
|
||||
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, label);
|
||||
|
||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID)
|
||||
.withProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER, identifier)
|
||||
.withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_NAME, actuatorName)
|
||||
.withProperty(VeluxBindingProperties.PROPERTY_ACTUATOR_INVERTED, isInverted)
|
||||
.withRepresentationProperty(VeluxBindingProperties.CONFIG_ACTUATOR_SERIALNUMBER)
|
||||
.withBridge(bridgeUID).withLabel(actuatorName).build();
|
||||
logger.debug("discoverProducts(): registering new thing {}.", discoveryResult);
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
logger.trace("discoverProducts() finished.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link VeluxBridgeHandler} to the {@link VeluxDiscoveryService}
|
||||
*
|
||||
* @param bridge Velux bridge handler.
|
||||
* @return true if the bridge was added, or false if it was already present
|
||||
*/
|
||||
public boolean addBridge(VeluxBridgeHandler bridge) {
|
||||
if (!bridgeHandlers.contains(bridge)) {
|
||||
logger.trace("VeluxDiscoveryService(): registering bridge {} for discovery.", bridge);
|
||||
bridgeHandlers.add(bridge);
|
||||
return true;
|
||||
}
|
||||
logger.trace("VeluxDiscoveryService(): bridge {} already registered for discovery.", bridge);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a {@link VeluxBridgeHandler} from the {@link VeluxDiscoveryService}
|
||||
*
|
||||
* @param bridge Velux bridge handler.
|
||||
* @return true if the bridge was removed, or false if it was not present
|
||||
*/
|
||||
public boolean removeBridge(VeluxBridgeHandler bridge) {
|
||||
return bridgeHandlers.remove(bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the {@link VeluxDiscoveryService} list of {@link VeluxBridgeHandler} is empty
|
||||
*
|
||||
* @return true if empty
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return bridgeHandlers.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,8 @@
|
||||
*/
|
||||
package org.openhab.binding.velux.internal.factory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@@ -32,7 +30,6 @@ import org.openhab.core.i18n.TranslationProvider;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
@@ -56,7 +53,8 @@ public class VeluxHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
// Class internal
|
||||
|
||||
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegistrations = new HashMap<>();
|
||||
private @Nullable ServiceRegistration<?> discoveryServiceRegistration = null;
|
||||
private @Nullable VeluxDiscoveryService discoveryService = null;
|
||||
|
||||
private Set<VeluxBindingHandler> veluxBindingHandlers = new HashSet<>();
|
||||
private Set<VeluxBridgeHandler> veluxBridgeHandlers = new HashSet<>();
|
||||
@@ -69,20 +67,25 @@ public class VeluxHandlerFactory extends BaseThingHandlerFactory {
|
||||
// Private
|
||||
|
||||
private void registerDeviceDiscoveryService(VeluxBridgeHandler bridgeHandler) {
|
||||
VeluxDiscoveryService discoveryService = new VeluxDiscoveryService(bridgeHandler, localization);
|
||||
ServiceRegistration<?> discoveryServiceReg = bundleContext.registerService(DiscoveryService.class.getName(),
|
||||
discoveryService, new Hashtable<>());
|
||||
discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), discoveryServiceReg);
|
||||
logger.trace("registerDeviceDiscoveryService({}) called.", bridgeHandler);
|
||||
boolean createNew = (discoveryService == null);
|
||||
if (createNew) {
|
||||
discoveryService = new VeluxDiscoveryService(localization);
|
||||
}
|
||||
discoveryService.addBridge(bridgeHandler);
|
||||
if (createNew) {
|
||||
discoveryServiceRegistration = bundleContext.registerService(DiscoveryService.class.getName(),
|
||||
discoveryService, new Hashtable<>());
|
||||
}
|
||||
}
|
||||
|
||||
// Even if the compiler tells, that the value of <remove> cannot be null, it is possible!
|
||||
// Therefore a @SuppressWarnings("null") is needed to suppress the warning
|
||||
@SuppressWarnings("null")
|
||||
private synchronized void unregisterDeviceDiscoveryService(ThingUID thingUID) {
|
||||
logger.trace("unregisterDeviceDiscoveryService({}) called.", thingUID);
|
||||
ServiceRegistration<?> remove = discoveryServiceRegistrations.remove(thingUID);
|
||||
if (remove != null) {
|
||||
remove.unregister();
|
||||
private synchronized void unregisterDeviceDiscoveryService(VeluxBridgeHandler bridgeHandler) {
|
||||
logger.trace("unregisterDeviceDiscoveryService({}) called.", bridgeHandler);
|
||||
if (discoveryService != null) {
|
||||
discoveryService.removeBridge(bridgeHandler);
|
||||
if (discoveryService.isEmpty()) {
|
||||
discoveryServiceRegistration.unregister();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +194,7 @@ public class VeluxHandlerFactory extends BaseThingHandlerFactory {
|
||||
if (thingHandler instanceof VeluxBridgeHandler) {
|
||||
logger.trace("removeHandler() removing bridge '{}'.", thingHandler.toString());
|
||||
veluxBridgeHandlers.remove(thingHandler);
|
||||
unregisterDeviceDiscoveryService(thingHandler.getThing().getUID());
|
||||
unregisterDeviceDiscoveryService((VeluxBridgeHandler) thingHandler);
|
||||
} else
|
||||
// Handle removal of Things behind the Bridge
|
||||
if (thingHandler instanceof VeluxHandler) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.openhab.binding.velux.internal.VeluxItemType;
|
||||
import org.openhab.binding.velux.internal.bridge.VeluxBridgeWLANConfig;
|
||||
import org.openhab.binding.velux.internal.handler.utils.StateUtils;
|
||||
import org.openhab.binding.velux.internal.handler.utils.ThingProperty;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.types.State;
|
||||
import org.slf4j.Logger;
|
||||
@@ -69,16 +70,15 @@ final class ChannelBridgeWLANconfig extends ChannelHandlerTemplate {
|
||||
if (thisBridgeHandler.bridgeParameters.wlanConfig.isRetrieved) {
|
||||
VeluxItemType itemType = VeluxItemType.getByThingAndChannel(thisBridgeHandler.thingTypeUIDOf(channelUID),
|
||||
channelUID.getId());
|
||||
String msg = thisBridgeHandler.localization.getText("config.velux.bridge.unAvailable");
|
||||
switch (itemType) {
|
||||
case BRIDGE_WLANSSID:
|
||||
newState = StateUtils.createState(thisBridgeHandler.bridgeParameters.lanConfig.openHABipAddress);
|
||||
ThingProperty.setValue(thisBridgeHandler, VeluxBindingConstants.PROPERTY_BRIDGE_WLANSSID,
|
||||
thisBridgeHandler.bridgeParameters.wlanConfig.openHABwlanSSID.toString());
|
||||
newState = StateUtils.createState(new StringType(msg));
|
||||
ThingProperty.setValue(thisBridgeHandler, VeluxBindingConstants.PROPERTY_BRIDGE_WLANSSID, msg);
|
||||
break;
|
||||
case BRIDGE_WLANPASSWORD:
|
||||
newState = StateUtils.createState(thisBridgeHandler.bridgeParameters.lanConfig.openHABsubnetMask);
|
||||
ThingProperty.setValue(thisBridgeHandler, VeluxBindingConstants.PROPERTY_BRIDGE_WLANPASSWORD,
|
||||
thisBridgeHandler.bridgeParameters.wlanConfig.openHABwlanPassword.toString());
|
||||
newState = StateUtils.createState(new StringType(msg));
|
||||
ThingProperty.setValue(thisBridgeHandler, VeluxBindingConstants.PROPERTY_BRIDGE_WLANPASSWORD, msg);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
package org.openhab.binding.velux.internal.handler;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.velux.internal.VeluxBindingConstants;
|
||||
import org.openhab.binding.velux.internal.VeluxBindingProperties;
|
||||
import org.openhab.binding.velux.internal.VeluxItemType;
|
||||
import org.openhab.binding.velux.internal.handler.utils.ExtendedBaseThingHandler;
|
||||
@@ -20,6 +21,7 @@ import org.openhab.binding.velux.internal.handler.utils.StateUtils;
|
||||
import org.openhab.binding.velux.internal.handler.utils.ThingProperty;
|
||||
import org.openhab.binding.velux.internal.utils.Localization;
|
||||
import org.openhab.binding.velux.internal.utils.ManifestInformation;
|
||||
import org.openhab.core.common.AbstractUID;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@@ -82,9 +84,13 @@ public class VeluxBindingHandler extends ExtendedBaseThingHandler {
|
||||
* @param channelUID for type {@link ChannelUID}.
|
||||
* @return thingTypeUID of type {@link ThingTypeUID}.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private ThingTypeUID thingTypeUIDOf(ChannelUID channelUID) {
|
||||
return channelUID.getThingUID().getThingTypeUID();
|
||||
String[] segments = channelUID.getAsString().split(AbstractUID.SEPARATOR);
|
||||
if (segments.length > 1) {
|
||||
return new ThingTypeUID(segments[0], segments[1]);
|
||||
}
|
||||
logger.warn("thingTypeUIDOf({}) failed.", channelUID);
|
||||
return new ThingTypeUID(VeluxBindingConstants.BINDING_ID, VeluxBindingConstants.UNKNOWN_THING_TYPE_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,6 +49,7 @@ import org.openhab.binding.velux.internal.things.VeluxProduct;
|
||||
import org.openhab.binding.velux.internal.things.VeluxProduct.ProductBridgeIndex;
|
||||
import org.openhab.binding.velux.internal.things.VeluxProductPosition;
|
||||
import org.openhab.binding.velux.internal.utils.Localization;
|
||||
import org.openhab.core.common.AbstractUID;
|
||||
import org.openhab.core.common.ThreadPoolManager;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
@@ -187,9 +188,13 @@ public class VeluxBridgeHandler extends ExtendedBaseBridgeHandler implements Vel
|
||||
* @param channelUID for type {@link ChannelUID}.
|
||||
* @return thingTypeUID of type {@link ThingTypeUID}.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
ThingTypeUID thingTypeUIDOf(ChannelUID channelUID) {
|
||||
return channelUID.getThingUID().getThingTypeUID();
|
||||
String[] segments = channelUID.getAsString().split(AbstractUID.SEPARATOR);
|
||||
if (segments.length > 1) {
|
||||
return new ThingTypeUID(segments[0], segments[1]);
|
||||
}
|
||||
logger.warn("thingTypeUIDOf({}) failed.", channelUID);
|
||||
return new ThingTypeUID(VeluxBindingConstants.BINDING_ID, VeluxBindingConstants.UNKNOWN_THING_TYPE_ID);
|
||||
}
|
||||
|
||||
// Objects and Methods for interface VeluxBridgeInstance
|
||||
|
||||
@@ -129,7 +129,7 @@ public class VeluxKLFAPI {
|
||||
UNDEFTYPE((short) -1, "Unknown command."),
|
||||
// Special item: Shutdown of the connection
|
||||
GW_OPENHAB_CLOSE((short) -2, "openHAB connection shutdown command."),
|
||||
// Special item: Shutdown of the connection
|
||||
// Special item: Empty Command (used to send nothing and process an incoming message only)
|
||||
GW_OPENHAB_RECEIVEONLY((short) -3, "openHAB receive command."),
|
||||
// Velux specific commands
|
||||
GW_ERROR_NTF((short) 0x0000, "Provides information on what triggered the error."),
|
||||
|
||||
@@ -68,6 +68,7 @@ config.velux.bridge.isSequentialEnforced.label = Enforce Sequential Mode
|
||||
config.velux.bridge.isSequentialEnforced.description = Enforce Sequential Actuator Control. Determine the mode of operation for long-time actions like running commands or activation of scenes. However the parallelism disables the in-depth protocol handshake processing which does not affect or limit any functionalities.
|
||||
config.velux.bridge.isProtocolTraceEnabled.label = Enable Protocol Trace
|
||||
config.velux.bridge.isProtocolTraceEnabled.description = Provide KLF200 protocol details.
|
||||
config.velux.bridge.unAvailable = Unavailable
|
||||
#
|
||||
config.velux.thing.scene.sceneName.label = Scene Name
|
||||
config.velux.thing.scene.sceneName.description = Name of the scene to be handled.
|
||||
|
||||
@@ -69,6 +69,7 @@ config.velux.bridge.isSequentialEnforced.label = Sequentielles Modus
|
||||
config.velux.bridge.isSequentialEnforced.description = Erzwingt den sequentiellen Modus von Operationen, insbesondere von länger andauernden Aktionen, wie der Aktivierung von Szenen.
|
||||
config.velux.bridge.isProtocolTraceEnabled.label = Protokolleinblick
|
||||
config.velux.bridge.isProtocolTraceEnabled.description = Aktiviert KLF200 Protokolldetails.
|
||||
config.velux.bridge.unAvailable = Nicht verfügbar
|
||||
#
|
||||
config.velux.thing.scene.sceneName.label = Scenenname
|
||||
config.velux.thing.scene.sceneName.description = Name der Szene, wie sie auf dem Kopplungselements definiert wurde.
|
||||
|
||||
@@ -65,6 +65,7 @@ config.velux.bridge.isSequentialEnforced.label = Håndhæv sekventiel tilstand
|
||||
config.velux.bridge.isSequentialEnforced.description = Håndhæv sekventiel aktuatorstyring. Bestem driftsmåden for handlinger i lang tid som at køre kommandoer eller aktivering af scener. Paralleliteten deaktiverer imidlertid den dybdegående protokolhåndtryksbehandling, som ikke påvirker eller begrænser nogen funktionaliteter.
|
||||
config.velux.bridge.isProtocolTraceEnabled.label = Protocol Insight
|
||||
config.velux.bridge.isProtocolTraceEnabled.description = Aktiverer KLF200-protokoldetaljer.
|
||||
config.velux.bridge.unAvailable = Utilgængelig
|
||||
#
|
||||
config.velux.thing.scene.sceneName.label = Scenavn
|
||||
config.velux.thing.scene.sceneName.description = Navn på den scene, der skal håndteres.
|
||||
|
||||
@@ -65,6 +65,7 @@ config.velux.bridge.isSequentialEnforced.label = Opeenvolgende modus afdwingen
|
||||
config.velux.bridge.isSequentialEnforced.description = Handhaving van sequentiële actuatorcontrole. Bepaal de werkingsmodus voor langdurige acties zoals het uitvoeren van opdrachten of het activeren van scènes. Het parallellisme schakelt echter de diepgaande protocolhandshake-verwerking uit die geen enkele functionaliteit beïnvloedt of beperkt.
|
||||
config.velux.bridge.isProtocolTraceEnabled.label = Protocol Insight
|
||||
config.velux.bridge.isProtocolTraceEnabled.description = Schakelt KLF200-protocoldetails in.
|
||||
config.velux.bridge.unAvailable = Niet beschikbaar
|
||||
#
|
||||
config.velux.thing.scene.sceneName.label = Scènenaam
|
||||
config.velux.thing.scene.sceneName.description = Naam van de te behandelen scène.
|
||||
|
||||
Reference in New Issue
Block a user