[openwebnet] Improvements for ZigBee USB and Dimmers (#9662)

* [openwebnet] Log messages cleanup

Signed-off-by: Massimo Valla <mvcode00@gmail.com>

* [openwebnet] Fixed normalizeWhere
* added builder for Bus Where addresses
* added messages to OwnIdTest
* depend on own4j 0.3.3-SNAPSHOT

Signed-off-by: Massimo Valla <mvcode00@gmail.com>

* [openwebnet] Discovery & reconnect for ZigBee USB gateways
* added mgmt of disconnect/reconnect of ZigBee USB Gateway from serial (#9170)
* added ZigBee USB Gateway auto discovery (#9171)

Signed-off-by: Massimo Valla <mvcode00@gmail.com>

* [openwebnet] fixed up/down automation for old fw (#9651)
* now using openwebnet4j 0.3.3 (nrjavaserial 5.2.1)

Signed-off-by: Massimo Valla <mvcode00@gmail.com>

* [openwebnet] Fixes lowering dimmers from 20 to 10% does not change device level #9317
- bump openwebnet4j to 0.3.4

Signed-off-by: Massimo Valla <mvcode00@gmail.com>

* [openwebnet] changes after PR review

Signed-off-by: Massimo Valla <mvcode00@gmail.com>
This commit is contained in:
M Valla 2021-01-08 23:00:55 +01:00 committed by GitHub
parent d87c94d603
commit d7d4fda2b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 397 additions and 90 deletions

View File

@ -5,7 +5,7 @@ This binding integrates BTicino / Legrand MyHOME&reg; BUS and ZigBee wireless (M
The binding supports: The binding supports:
- both wired BUS/SCS (MyHOME) and wireless setups (MyHOME ZigBee). The two networks can be configured simultaneously - both wired BUS/SCS (MyHOME) and wireless setups (MyHOME ZigBee). The two networks can be configured simultaneously
- auto discovery of BUS/SCS IP gateways and devices and auto discovery of ZigBee USB devices - auto discovery of BUS/SCS IP and ZigBee USB gateways; auto discovery of devices
- commands from openHAB and feedback (events) from BUS/SCS and wireless network - commands from openHAB and feedback (events) from BUS/SCS and wireless network
![F454 Gateway](doc/F454_gateway.png) ![F454 Gateway](doc/F454_gateway.png)
@ -29,7 +29,7 @@ These gateways have been tested with the binding:
- **ZigBee USB Gateways**, such as [BTicino 3578](https://catalogo.bticino.it/BTI-3578-IT), also known as Legrand 088328 - **ZigBee USB Gateways**, such as [BTicino 3578](https://catalogo.bticino.it/BTI-3578-IT), also known as Legrand 088328
**NOTE** The new BTicino Living Now&reg; wireless system is not supported by this binding as it does not use the OpenWebNet protocol. **NOTE** The new BTicino Living Now&reg; and Livinglight Smart&reg; wireless systems are not supported by this binding as they do not use the OpenWebNet protocol.
The following Things and OpenWebNet `WHOs` are supported: The following Things and OpenWebNet `WHOs` are supported:
@ -58,19 +58,18 @@ Gateway and Things discovery is supported by this binding.
- BUS Gateway automatic discovery will work only for newer gateways supporting UPnP: F454, MyHOMEServer1, MH201, MH202, MH200N, MyHOME_Screen 10. - BUS Gateway automatic discovery will work only for newer gateways supporting UPnP: F454, MyHOMEServer1, MH201, MH202, MH200N, MyHOME_Screen 10.
For other gateways you can add them manually, see [Thing Configuration](#thing-configuration) below. For other gateways you can add them manually, see [Thing Configuration](#thing-configuration) below.
- After gateway is discovered and added a connection with default password (`12345`) is tested first: if it does not work the gateway will go offline and an error status will be set. A correct password must then be set in the gateway Thing configuration otherwise the gateway will not become online. - After gateway is discovered and added a connection with default password (`12345`) is tested first: if it does not work the gateway will go offline and an error status will be set. A correct password must then be set in the gateway Thing configuration otherwise the gateway will not become online.
- Once the gateway is online, a second Scan request from Inbox will discover BUS devices - Once the gateway is online, a second Inbox Scan will discover BUS devices
- BUS/SCS Dimmers must be ON and dimmed (30%-100%) during a Scan, otherwise they will be discovered as simple On/Off switches - BUS/SCS Dimmers must be ON and dimmed (30%-100%) during a Scan, otherwise they will be discovered as simple On/Off switches
- *KNOWN ISSUE*: In some cases dimmers connected to a F429 Dali-interface are not automatically discovered - *KNOWN ISSUE*: In some cases dimmers connected to a F429 Dali-interface are not automatically discovered
#### Discovery by Activation #### Discovery by Activation
BUS devices can also be discovered if activated while an Inbox Scan is active: start a new Scan, wait 15-20 seconds and then _while the Scan is still active_ (spinning arrow in Inbox), activate the physical device (for example dim the dimmer) to have it discovered by the binding. BUS devices can also be discovered if activated while an Inbox Scan is active: start a new Scan, wait 15-20 seconds and then _while the Scan is still active_, activate the physical device (for example dim the dimmer) to have it discovered by the binding.
If a device cannot be discovered automatically it's always possible to add it manually, see [Configuring Devices](#configuring-devices). If a device cannot be discovered automatically it's always possible to add it manually, see [Configuring Devices](#configuring-devices).
### ZigBee Discovery ### ZigBee Discovery
- ZigBee USB gateway discovery is *not supported* at the moment: the gateway thing must be added manually see [Thing Configuration](#thing-configuration) below
- The ZigBee USB Gateway must be inserted in one of the USB ports of the openHAB computer before a discovery is started - The ZigBee USB Gateway must be inserted in one of the USB ports of the openHAB computer before a discovery is started
- ***IMPORTANT NOTE:*** As for other openHAB bindings using the USB/serial ports, on Linux the `openhab` user must be member of the `dialout` group to be able to use USB/serial port; set the group with the following command: - ***IMPORTANT NOTE:*** As for other openHAB bindings using the USB/serial ports, on Linux the `openhab` user must be member of the `dialout` group to be able to use USB/serial port; set the group with the following command:
@ -79,7 +78,7 @@ If a device cannot be discovered automatically it's always possible to add it ma
``` ```
The user will need to logout and login to see the new group added. If you added your user to this group and still cannot get permission, reboot Linux to ensure the new group permission is attached to the `openhab` user. The user will need to logout and login to see the new group added. If you added your user to this group and still cannot get permission, reboot Linux to ensure the new group permission is attached to the `openhab` user.
- Once the USB gateway is configured/added, a discovery request from Inbox will discover devices connected to it. Because of the ZigBee radio network, discovery will take ~40-60 sec. Be patient! - Once the ZigBee USB Gateway is added and online, a second Inbox Scan will discover devices connected to it. Because of the ZigBee radio network, device discovery will take ~40-60 sec. Be patient!
- Wireless devices must be part of the same ZigBee network of the ZigBee USB Gateway to discover them. Please refer to [this video by BTicino](https://www.youtube.com/watch?v=CoIgg_Xqhbo) to setup a ZigBee wireless network which includes the ZigBee USB Gateway - Wireless devices must be part of the same ZigBee network of the ZigBee USB Gateway to discover them. Please refer to [this video by BTicino](https://www.youtube.com/watch?v=CoIgg_Xqhbo) to setup a ZigBee wireless network which includes the ZigBee USB Gateway
- Only powered wireless devices part of the same ZigBee network and within radio coverage of the ZigBee USB Gateway will be discovered. Unreachable or not powered devices will be discovered as *GENERIC* devices and cannot be controlled - Only powered wireless devices part of the same ZigBee network and within radio coverage of the ZigBee USB Gateway will be discovered. Unreachable or not powered devices will be discovered as *GENERIC* devices and cannot be controlled
- Wireless control units cannot be discovered by the ZigBee USB Gateway and therefore are not supported - Wireless control units cannot be discovered by the ZigBee USB Gateway and therefore are not supported
@ -108,12 +107,14 @@ Configuration parameters are:
- `serialPort` : the serial port where the ZigBee USB Gateway is connected (`String`, *mandatory*) - `serialPort` : the serial port where the ZigBee USB Gateway is connected (`String`, *mandatory*)
- Examples: `/dev/ttyUSB0` (Linux/RaPi), `COM3` (Windows) - Examples: `/dev/ttyUSB0` (Linux/RaPi), `COM3` (Windows)
Alternatively the ZigBee USB Gateway thing can be configured using the `.things` file, see `openwebnet.things` example [below](#full-example).
### Configuring Devices ### Configuring Devices
Devices can be discovered automatically after a gateway has been configured and connected. Devices can be discovered automatically using an Inbox Scan after a gateway has been configured and connected.
For any manually added devices, you must configure: For any manually added device, you must configure:
- the associated gateway (`Bridge Selection` menu) - the associated gateway (`Parent Bridge` menu)
- the `where` config parameter (`OpenWebNet Device Address`): - the `where` config parameter (`OpenWebNet Device Address`):
- example for BUS/SCS device with WHERE address Point to Point `A=2 PL=4` --> `where="24"` - example for BUS/SCS device with WHERE address Point to Point `A=2 PL=4` --> `where="24"`
- example for BUS/SCS device with WHERE address Point to Point `A=03 PL=11` on local bus --> `where="0311#4#01"` - example for BUS/SCS device with WHERE address Point to Point `A=03 PL=11` on local bus --> `where="0311#4#01"`
@ -160,7 +161,7 @@ Bridge openwebnet:bus_gateway:mybridge "MyHOMEServer1" [ host="192.168.1.35", pa
ZigBee USB Gateway and things configuration - for radio devices: ZigBee USB Gateway and things configuration - for radio devices:
```xtend ```xtend
Bridge openwebnet:zb_gateway:myZBgateway [serialPort="COM3"] { Bridge openwebnet:zb_gateway:myZBgateway [ serialPort="COM3" ] {
zb_dimmer myZB_dimmer [ where="765432101#9"] zb_dimmer myZB_dimmer [ where="765432101#9"]
zb_on_off_switch myZB_switch [ where="765432201#9"] zb_on_off_switch myZB_switch [ where="765432201#9"]
zb_on_off_switch2u myZB_2U_switch [ where="765432300#9"] zb_on_off_switch2u myZB_2U_switch [ where="765432300#9"]
@ -169,7 +170,7 @@ Bridge openwebnet:zb_gateway:myZBgateway [serialPort="COM3"] {
### openwebnet.items: ### openwebnet.items:
Items (Light, Dimmer, etc.) will be discovered by Google Assistant/Alexa/HomeKit if their tags are configured like in the example: Example items linked to BUS devices:
```xtend ```xtend
Switch iLR_switch "Light" <light> (gLivingRoom) [ "Lighting" ] { channel="openwebnet:bus_on_off_switch:mybridge:LR_switch:switch" } Switch iLR_switch "Light" <light> (gLivingRoom) [ "Lighting" ] { channel="openwebnet:bus_on_off_switch:mybridge:LR_switch:switch" }
@ -177,7 +178,7 @@ Dimmer iLR_dimmer "Dimmer [%.0f %%]" <Dimmabl
Rollershutter iLR_shutter "Shutter [%.0f %%]" <rollershutter> (gShutters, gLivingRoom) [ "Blinds" ] { channel="openwebnet:bus_automation:mybridge:LR_shutter:shutter" } Rollershutter iLR_shutter "Shutter [%.0f %%]" <rollershutter> (gShutters, gLivingRoom) [ "Blinds" ] { channel="openwebnet:bus_automation:mybridge:LR_shutter:shutter" }
``` ```
Example items linked to ZigBee devices: Example items linked to OpenWebNet ZigBee devices:
```xtend ```xtend
Dimmer iDimmer "Dimmer [%.0f %%]" <DimmableLight> (gKitchen) [ "Lighting" ] { channel="openwebnet:zb_dimmer:myZBgateway:myZB_dimmer:brightness" } Dimmer iDimmer "Dimmer [%.0f %%]" <DimmableLight> (gKitchen) [ "Lighting" ] { channel="openwebnet:zb_dimmer:myZBgateway:myZB_dimmer:brightness" }
@ -202,7 +203,7 @@ sitemap openwebnet label="OpenWebNet Binding Example Sitemap"
## Notes ## Notes
- The Open Web Net protocol is maintained and Copyright by BTicino/Legrand. The documentation of the protocol if freely accessible for developers on the [Legrand developer web site](https://developer.legrand.com/documentation/open-web-net-for-myhome/) - The OpenWebNet protocol is maintained and Copyright by BTicino/Legrand. The documentation of the protocol if freely accessible for developers on the [Legrand developer web site](https://developer.legrand.com/documentation/open-web-net-for-myhome/)
## Special thanks ## Special thanks

View File

@ -23,7 +23,7 @@
<dependency> <dependency>
<groupId>com.github.openwebnet4j</groupId> <groupId>com.github.openwebnet4j</groupId>
<artifactId>openwebnet4j</artifactId> <artifactId>openwebnet4j</artifactId>
<version>0.3.2-1</version> <version>0.3.4</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>

View File

@ -103,6 +103,8 @@ public class OpenWebNetBindingConstants {
// BUS gw config properties // BUS gw config properties
public static final String CONFIG_PROPERTY_HOST = "host"; public static final String CONFIG_PROPERTY_HOST = "host";
public static final String CONFIG_PROPERTY_SERIAL_PORT = "serialPort";
// properties // properties
public static final String PROPERTY_OWNID = "ownId"; public static final String PROPERTY_OWNID = "ownId";
public static final String PROPERTY_ZIGBEEID = "zigbeeid"; public static final String PROPERTY_ZIGBEEID = "zigbeeid";

View File

@ -41,6 +41,7 @@ import org.openwebnet4j.message.BaseOpenMessage;
import org.openwebnet4j.message.FrameException; import org.openwebnet4j.message.FrameException;
import org.openwebnet4j.message.GatewayMgmt; import org.openwebnet4j.message.GatewayMgmt;
import org.openwebnet4j.message.Where; import org.openwebnet4j.message.Where;
import org.openwebnet4j.message.WhereLightAutom;
import org.openwebnet4j.message.Who; import org.openwebnet4j.message.Who;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -129,6 +130,11 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
positionEstimation = POSITION_UNKNOWN; positionEstimation = POSITION_UNKNOWN;
} }
@Override
protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
return new WhereLightAutom(wStr);
}
@Override @Override
protected void requestChannelState(ChannelUID channel) { protected void requestChannelState(ChannelUID channel) {
logger.debug("requestChannelState() thingUID={} channel={}", thing.getUID(), channel.getId()); logger.debug("requestChannelState() thingUID={} channel={}", thing.getUID(), channel.getId());
@ -280,8 +286,9 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
@Override @Override
protected void handleMessage(BaseOpenMessage msg) { protected void handleMessage(BaseOpenMessage msg) {
logger.debug("handleMessage({}) for thing: {}", msg, thing.getUID());
updateAutomationState((Automation) msg); updateAutomationState((Automation) msg);
// REMINDER: update state, then update thing status in the super method, to avoid delays // REMINDER: update automation state, and only after update thing status using the super method, to avoid delays
super.handleMessage(msg); super.handleMessage(msg);
} }

View File

@ -111,7 +111,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
} else { } else {
updateStatus(ThingStatus.UNKNOWN); updateStatus(ThingStatus.UNKNOWN);
logger.debug("Trying to connect gateway..."); logger.debug("Trying to connect gateway {}... ", gw);
try { try {
gw.connect(); gw.connect();
scheduler.schedule(() -> { scheduler.schedule(() -> {
@ -233,22 +233,22 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
if (gw != null) { if (gw != null) {
if (!gw.isDiscovering()) { if (!gw.isDiscovering()) {
if (!gw.isConnected()) { if (!gw.isConnected()) {
logger.debug("------$$ Gateway is NOT connected, cannot search for devices"); logger.debug("------$$ Gateway '{}' is NOT connected, cannot search for devices", gw);
return; return;
} }
logger.info("------$$ STARTED active SEARCH for devices on gateway '{}'", this.getThing().getUID()); logger.info("------$$ STARTED active SEARCH for devices on bridge '{}'", thing.getUID());
try { try {
gw.discoverDevices(); gw.discoverDevices();
} catch (OWNException e) { } catch (OWNException e) {
logger.warn("------$$ OWNException while discovering devices on gateway {}: {}", logger.warn("------$$ OWNException while discovering devices on bridge '{}': {}", thing.getUID(),
this.getThing().getUID(), e.getMessage()); e.getMessage());
} }
} else { } else {
logger.debug("------$$ Searching devices on gateway {} already activated", this.getThing().getUID()); logger.debug("------$$ Searching devices on bridge '{}' already activated", thing.getUID());
return; return;
} }
} else { } else {
logger.debug("------$$ Cannot search devices: no gateway associated to this handler"); logger.warn("------$$ Cannot search devices: no gateway associated to this handler");
} }
} }
@ -268,7 +268,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
@Override @Override
public void onDiscoveryCompleted() { public void onDiscoveryCompleted() {
logger.info("------$$ FINISHED active SEARCH for devices on gateway '{}'", this.getThing().getUID()); logger.info("------$$ FINISHED active SEARCH for devices on bridge '{}'", thing.getUID());
} }
/** /**
@ -418,10 +418,10 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
return; return;
} }
if (gw instanceof USBGateway) { if (gw instanceof USBGateway) {
logger.info("------------------- CONNECTED to ZigBee USB gateway - USB port: {}", logger.info("---- CONNECTED to ZigBee USB gateway bridge '{}' (serialPort: {})", thing.getUID(),
((USBGateway) gw).getSerialPortName()); ((USBGateway) gw).getSerialPortName());
} else { } else {
logger.info("------------------- CONNECTED to BUS gateway '{}' ({}:{})", thing.getUID(), logger.info("---- CONNECTED to BUS gateway bridge '{}' ({}:{})", thing.getUID(),
((BUSGateway) gw).getHost(), ((BUSGateway) gw).getPort()); ((BUSGateway) gw).getHost(), ((BUSGateway) gw).getPort());
// update serial number property (with MAC address) // update serial number property (with MAC address)
if (properties.get(PROPERTY_SERIAL_NO) != gw.getMACAddr().toUpperCase()) { if (properties.get(PROPERTY_SERIAL_NO) != gw.getMACAddr().toUpperCase()) {
@ -437,7 +437,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
} }
if (propertiesChanged) { if (propertiesChanged) {
updateProperties(properties); updateProperties(properties);
logger.info("properties updated for '{}'", thing.getUID()); logger.info("properties updated for bridge '{}'", thing.getUID());
} }
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
} }
@ -450,7 +450,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
} else { } else {
errMsg = error.getMessage(); errMsg = error.getMessage();
} }
logger.info("------------------- ON CONNECTION ERROR: {}", errMsg); logger.info("---- ON CONNECTION ERROR for gateway {}: {}", gateway, errMsg);
isGatewayConnected = false; isGatewayConnected = false;
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errMsg); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errMsg);
tryReconnectGateway(); tryReconnectGateway();
@ -472,7 +472,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
} else { } else {
errMsg = e.getMessage(); errMsg = e.getMessage();
} }
logger.info("------------------- DISCONNECTED from gateway. OWNException={}", errMsg); logger.info("---- DISCONNECTED from gateway {}. OWNException: {}", gateway, errMsg);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR,
"Disconnected from gateway (onDisconnected - " + errMsg + ")"); "Disconnected from gateway (onDisconnected - " + errMsg + ")");
tryReconnectGateway(); tryReconnectGateway();
@ -483,29 +483,29 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
if (gw != null) { if (gw != null) {
if (!reconnecting) { if (!reconnecting) {
reconnecting = true; reconnecting = true;
logger.info("------------------- Starting RECONNECT cycle to gateway"); logger.info("---- Starting RECONNECT cycle to gateway {}", gw);
try { try {
gw.reconnect(); gw.reconnect();
} catch (OWNAuthException e) { } catch (OWNAuthException e) {
logger.info("------------------- AUTH error from gateway. Stopping reconnect"); logger.info("---- AUTH error from gateway. Stopping re-connect");
reconnecting = false; reconnecting = false;
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
"Authentication error. Check gateway password in Thing Configuration Parameters (" + e "Authentication error. Check gateway password in Thing Configuration Parameters (" + e
+ ")"); + ")");
} }
} else { } else {
logger.debug("------------------- reconnecting=true, do nothing"); logger.debug("---- reconnecting=true, do nothing");
} }
} else { } else {
logger.debug("------------------- cannot start RECONNECT, gateway is null"); logger.warn("---- cannot start RECONNECT, gateway is null");
} }
} }
@Override @Override
public void onReconnected() { public void onReconnected() {
reconnecting = false; reconnecting = false;
logger.info("------------------- RE-CONNECTED to gateway!");
OpenGateway gw = gateway; OpenGateway gw = gateway;
logger.info("---- RE-CONNECTED to bridge {}", thing.getUID());
if (gw != null) { if (gw != null) {
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
if (gw.getFirmwareVersion() != null) { if (gw.getFirmwareVersion() != null) {
@ -568,10 +568,10 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
if (where instanceof WhereZigBee) { if (where instanceof WhereZigBee) {
str = ((WhereZigBee) where).valueWithUnit(WhereZigBee.UNIT_ALL); // 76543210X#9 --> 765432100#9 str = ((WhereZigBee) where).valueWithUnit(WhereZigBee.UNIT_ALL); // 76543210X#9 --> 765432100#9
} else { } else {
if (str.indexOf("#4#") == 0) { // no changes needed for local bus: APL#4#bus if (str.indexOf("#4#") == -1) { // skip APL#4#bus case
if (str.indexOf('#') == 0) { // Thermo zone via central unit: #0 or #Z (Z=[1-99]) --> Z if (str.indexOf('#') == 0) { // Thermo central unit (#0) or zone via central unit (#Z, Z=[1-99]) --> Z
str = str.substring(1); str = str.substring(1);
} else if (str.indexOf('#') > 0) { // Thermo zone and actuator N: Z#N (Z=[1-99], N=[1-9]) --> Z } else if (str.indexOf('#') > 0) { // Thermo zone Z and actuator N (Z#N, Z=[1-99], N=[1-9]) --> Z
str = str.substring(0, str.indexOf('#')); str = str.substring(0, str.indexOf('#'));
} }
} }

View File

@ -21,6 +21,8 @@ import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.types.Command; import org.openhab.core.types.Command;
import org.openwebnet4j.message.BaseOpenMessage; import org.openwebnet4j.message.BaseOpenMessage;
import org.openwebnet4j.message.Where;
import org.openwebnet4j.message.WhereLightAutom;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -65,10 +67,15 @@ public class OpenWebNetGenericHandler extends OpenWebNetThingHandler {
return "G"; return "G";
} }
@Override
protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
return new WhereLightAutom(wStr);
}
@Override @Override
protected void handleMessage(BaseOpenMessage msg) { protected void handleMessage(BaseOpenMessage msg) {
super.handleMessage(msg); super.handleMessage(msg);
// do nothing // do nothing
logger.warn("handleMessage(): Nothing to do!"); logger.warn("handleMessage(): Nothing to do!");
} }
} // class }

View File

@ -35,6 +35,7 @@ import org.openwebnet4j.message.FrameException;
import org.openwebnet4j.message.Lighting; import org.openwebnet4j.message.Lighting;
import org.openwebnet4j.message.What; import org.openwebnet4j.message.What;
import org.openwebnet4j.message.Where; import org.openwebnet4j.message.Where;
import org.openwebnet4j.message.WhereLightAutom;
import org.openwebnet4j.message.WhereZigBee; import org.openwebnet4j.message.WhereZigBee;
import org.openwebnet4j.message.Who; import org.openwebnet4j.message.Who;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -53,15 +54,19 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler {
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.LIGHTING_SUPPORTED_THING_TYPES; public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.LIGHTING_SUPPORTED_THING_TYPES;
private static final int BRIGHTNESS_CHANGE_DELAY_MSEC = 1500; // delay before sending another brightness status // interval to interpret ON as response to requestStatus
// request private static final int BRIGHTNESS_STATUS_REQUEST_INTERVAL_MSEC = 250;
private static final int BRIGHTNESS_STATUS_REQUEST_DELAY_MSEC = 900; // we must wait some time to be sure dimmer has
// reached final level before requesting its // time to wait before sending a statusRequest, to avoid repeated requests and ensure dimmer has reached its final
// status // level
private static final int BRIGHTNESS_STATUS_REQUEST_DELAY_MSEC = 900;
private static final int UNKNOWN_STATE = 1000; private static final int UNKNOWN_STATE = 1000;
private long lastBrightnessChangeSentTS = 0; // timestamp when last brightness change was sent to the device private long lastBrightnessChangeSentTS = 0; // timestamp when last brightness change was sent to the device
private long lastStatusRequestSentTS = 0; // timestamp when last status request was sent to the device
private int brightness = UNKNOWN_STATE; // current brightness percent value for this device private int brightness = UNKNOWN_STATE; // current brightness percent value for this device
private int brightnessBeforeOff = UNKNOWN_STATE; // latest brightness before device was set to off private int brightnessBeforeOff = UNKNOWN_STATE; // latest brightness before device was set to off
@ -83,6 +88,7 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler {
Where w = deviceWhere; Where w = deviceWhere;
if (w != null) { if (w != null) {
try { try {
lastStatusRequestSentTS = System.currentTimeMillis();
Response res = send(Lighting.requestStatus(toWhere(channelId))); Response res = send(Lighting.requestStatus(toWhere(channelId)));
if (res != null && res.isSuccess()) { if (res != null && res.isSuccess()) {
// set thing online if not already // set thing online if not already
@ -214,8 +220,8 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler {
@Override @Override
protected void handleMessage(BaseOpenMessage msg) { protected void handleMessage(BaseOpenMessage msg) {
logger.debug("handleMessage({}) for thing: {}", msg, thing.getUID());
super.handleMessage(msg); super.handleMessage(msg);
logger.debug("handleMessage() for thing: {}", thing.getUID());
ThingTypeUID thingType = thing.getThingTypeUID(); ThingTypeUID thingType = thing.getThingTypeUID();
if (THING_TYPE_ZB_DIMMER.equals(thingType) || THING_TYPE_BUS_DIMMER.equals(thingType)) { if (THING_TYPE_ZB_DIMMER.equals(thingType) || THING_TYPE_BUS_DIMMER.equals(thingType)) {
updateBrightness((Lighting) msg); updateBrightness((Lighting) msg);
@ -230,47 +236,54 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler {
* @param msg the Lighting message received * @param msg the Lighting message received
*/ */
private synchronized void updateBrightness(Lighting msg) { private synchronized void updateBrightness(Lighting msg) {
long now = System.currentTimeMillis();
logger.debug(" $BRI updateBrightness({}) || bri={} briBeforeOff={}", msg, brightness, logger.debug(" $BRI updateBrightness({}) || bri={} briBeforeOff={}", msg, brightness,
brightnessBeforeOff); brightnessBeforeOff);
long now = System.currentTimeMillis();
long delta = now - lastBrightnessChangeSentTS; long delta = now - lastBrightnessChangeSentTS;
boolean belowThresh = delta < BRIGHTNESS_CHANGE_DELAY_MSEC; boolean belowThresh = delta < BRIGHTNESS_STATUS_REQUEST_DELAY_MSEC;
logger.debug(" $BRI delta={}ms {}", delta, (belowThresh ? "< DELAY" : "")); logger.debug(" $BRI delta={}ms {}", delta, (belowThresh ? "< DELAY" : ""));
if (belowThresh) { if (belowThresh) {
// we just sent a command from OH, so we can ignore this message from network // we just sent a command from OH, so we can ignore this message from network
logger.debug(" $BRI a request was sent {} < {} ms --> no action needed", delta, logger.debug(" $BRI a command was sent {} < {} ms --> no action needed", delta,
BRIGHTNESS_CHANGE_DELAY_MSEC); BRIGHTNESS_STATUS_REQUEST_DELAY_MSEC);
} else { } else {
if (msg.isOn()) { if (msg.isOn()) {
logger.debug(" $BRI \"ON\" notification from network, scheduling requestStatus..."); // if we have not just sent a requestStatus, on ON event we send requestStatus to know current level
// we must wait BRIGHTNESS_STATUS_REQUEST_DELAY_MSEC to be sure dimmer has reached final level long deltaStatusReq = now - lastStatusRequestSentTS;
scheduler.schedule(() -> { if (deltaStatusReq > BRIGHTNESS_STATUS_REQUEST_INTERVAL_MSEC) {
requestStatus(CHANNEL_BRIGHTNESS); logger.debug(" $BRI 'ON' is new notification from network, scheduling requestStatus...");
}, BRIGHTNESS_STATUS_REQUEST_DELAY_MSEC, TimeUnit.MILLISECONDS); // we must wait BRIGHTNESS_STATUS_REQUEST_DELAY_MSEC to be sure dimmer has reached its final level
} else { scheduler.schedule(() -> {
logger.debug(" $BRI update from network"); requestStatus(CHANNEL_BRIGHTNESS);
if (msg.getWhat() != null) { }, BRIGHTNESS_STATUS_REQUEST_DELAY_MSEC, TimeUnit.MILLISECONDS);
updateBrightnessState(msg); return;
} else { // dimension notification } else {
if (msg.getDim() == Lighting.DIM.DIMMER_LEVEL_100) { // otherwise we interpret this ON event as the requestStatus response event with level=1
int newBrightness; // so we proceed to call updateBrightnessState()
try { logger.debug(" $BRI 'ON' is the requestStatus response level");
newBrightness = msg.parseDimmerLevel100(); }
} catch (FrameException fe) { }
logger.warn("updateBrightness() Wrong value for dimmerLevel100 in message: {}", msg); logger.debug(" $BRI update from network");
return; if (msg.getWhat() != null) {
} updateBrightnessState(msg);
logger.debug(" $BRI DIMMER_LEVEL_100 newBrightness={}", newBrightness); } else { // dimension notification
updateState(CHANNEL_BRIGHTNESS, new PercentType(newBrightness)); if (msg.getDim() == Lighting.DIM.DIMMER_LEVEL_100) {
if (newBrightness == 0) { int newBrightness;
brightnessBeforeOff = brightness; try {
} newBrightness = msg.parseDimmerLevel100();
brightness = newBrightness; } catch (FrameException fe) {
} else { logger.warn("updateBrightness() Wrong value for dimmerLevel100 in message: {}", msg);
logger.warn("updateBrightness() Cannot handle message {} for thing {}", msg,
getThing().getUID());
return; return;
} }
logger.debug(" $BRI DIMMER_LEVEL_100 newBrightness={}", newBrightness);
updateState(CHANNEL_BRIGHTNESS, new PercentType(newBrightness));
if (newBrightness == 0) {
brightnessBeforeOff = brightness;
}
brightness = newBrightness;
} else {
logger.warn("updateBrightness() Cannot handle message {} for thing {}", msg, getThing().getUID());
return;
} }
} }
} }
@ -284,8 +297,12 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler {
* @param msg the Lighting message received * @param msg the Lighting message received
*/ */
private void updateBrightnessState(Lighting msg) { private void updateBrightnessState(Lighting msg) {
if (msg.getWhat() != null) { What w = msg.getWhat();
int newBrightnessWhat = msg.getWhat().value(); if (w != null) {
if (Lighting.WHAT.ON.equals(w)) {
w = Lighting.WHAT.DIMMER_LEVEL_2; // levels start at 2
}
int newBrightnessWhat = w.value();
int brightnessWhat = UNKNOWN_STATE; int brightnessWhat = UNKNOWN_STATE;
if (brightness != UNKNOWN_STATE) { if (brightness != UNKNOWN_STATE) {
brightnessWhat = Lighting.percentToWhat(brightness).value(); brightnessWhat = Lighting.percentToWhat(brightness).value();
@ -344,6 +361,11 @@ public class OpenWebNetLightingHandler extends OpenWebNetThingHandler {
} }
} }
@Override
protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
return new WhereLightAutom(wStr);
}
/** /**
* Returns a WHERE address string based on channelId string * Returns a WHERE address string based on channelId string
* *

View File

@ -34,7 +34,6 @@ import org.openwebnet4j.communication.Response;
import org.openwebnet4j.message.BaseOpenMessage; import org.openwebnet4j.message.BaseOpenMessage;
import org.openwebnet4j.message.OpenMessage; import org.openwebnet4j.message.OpenMessage;
import org.openwebnet4j.message.Where; import org.openwebnet4j.message.Where;
import org.openwebnet4j.message.WhereLightAutom;
import org.openwebnet4j.message.WhereZigBee; import org.openwebnet4j.message.WhereZigBee;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -77,7 +76,7 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
Where w; Where w;
try { try {
if (brH.isBusGateway()) { if (brH.isBusGateway()) {
w = new WhereLightAutom(deviceWhereStr); w = buildBusWhere(deviceWhereStr);
} else { } else {
w = new WhereZigBee(deviceWhereStr); w = new WhereZigBee(deviceWhereStr);
} }
@ -192,6 +191,14 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
*/ */
protected abstract void requestChannelState(ChannelUID channel); protected abstract void requestChannelState(ChannelUID channel);
/**
* Abstract builder for device Where address, to be implemented by each subclass to choose the right Where subclass
* (the method is used only if the Thing is associated to a BUS gateway).
*
* @param wStr the WHERE string
*/
protected abstract Where buildBusWhere(String wStr) throws IllegalArgumentException;
@Override @Override
public void dispose() { public void dispose() {
OpenWebNetBridgeHandler bh = bridgeHandler; OpenWebNetBridgeHandler bh = bridgeHandler;

View File

@ -60,7 +60,7 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractDiscoveryService
@Override @Override
public Set<ThingTypeUID> getSupportedThingTypes() { public Set<ThingTypeUID> getSupportedThingTypes() {
return OpenWebNetDeviceDiscoveryService.SUPPORTED_THING_TYPES; return SUPPORTED_THING_TYPES;
} }
@Override @Override

View File

@ -0,0 +1,237 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.openwebnet.internal.discovery;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.openwebnet.OpenWebNetBindingConstants;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.io.transport.serial.SerialPortIdentifier;
import org.openhab.core.io.transport.serial.SerialPortManager;
import org.openhab.core.thing.ThingUID;
import org.openwebnet4j.GatewayListener;
import org.openwebnet4j.OpenDeviceType;
import org.openwebnet4j.USBGateway;
import org.openwebnet4j.communication.OWNException;
import org.openwebnet4j.message.BaseOpenMessage;
import org.openwebnet4j.message.OpenMessage;
import org.openwebnet4j.message.Where;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link UsbGatewayDiscoveryService} extends {@link AbstractDiscoveryService} to detect ZigBee USB gateways
* connected via serial port. The service will iterate over the available serial ports and open each one to test if a
* OpenWebNet ZigBee USB gateway is connected. On successful connection, a new DiscoveryResult is created.
*
* @author Massimo Valla - Initial contribution
*/
@NonNullByDefault
@Component(service = DiscoveryService.class, configurationPid = "discovery.openwebnet")
public class UsbGatewayDiscoveryService extends AbstractDiscoveryService implements GatewayListener {
private final Logger logger = LoggerFactory.getLogger(UsbGatewayDiscoveryService.class);
private static final int DISCOVERY_TIMEOUT_SECONDS = 30;
private static final int PORT_CHECK_TIMEOUT_MSEC = 1500;
private CountDownLatch portCheckLatch = new CountDownLatch(1);
private @Nullable ScheduledFuture<?> connectTimeout;
private final SerialPortManager serialPortManager;
private @Nullable USBGateway zbGateway;
private String currentScannedPortName = "";
/**
* Keeps a boolean during time discovery process in progress.
*/
private boolean scanning;
/**
* Constructs a new UsbGatewayDiscoveryService with the specified ZigBee USB Bridge ThingTypeUID
*/
@Activate
public UsbGatewayDiscoveryService(final @Reference SerialPortManager spm) {
super(Collections.singleton(OpenWebNetBindingConstants.THING_TYPE_ZB_GATEWAY), DISCOVERY_TIMEOUT_SECONDS,
false);
// Obtain the serial port manager service using an OSGi reference
serialPortManager = spm;
}
/**
* Starts a new discovery scan. All available Serial Ports are scanned.
*/
@Override
protected void startScan() {
logger.debug("Started OpenWebNet ZigBee USB Gateway discovery scan");
removeOlderResults(getTimestampOfLastScan());
scanning = true;
Stream<SerialPortIdentifier> portEnum = serialPortManager.getIdentifiers();
// Check each available serial port
try {
for (SerialPortIdentifier portIdentifier : portEnum.toArray(SerialPortIdentifier[]::new)) {
if (scanning) {
currentScannedPortName = portIdentifier.getName();
logger.debug("[{}] == checking serial port", currentScannedPortName);
if (portIdentifier.isCurrentlyOwned()) {
logger.debug("[{}] serial port is owned by: {}", currentScannedPortName,
portIdentifier.getCurrentOwner());
} else {
logger.debug("[{}] trying to connect to a ZigBee USB Gateway...", currentScannedPortName);
USBGateway gw = new USBGateway(currentScannedPortName);
zbGateway = gw;
gw.subscribe(this);
portCheckLatch = new CountDownLatch(1);
connectTimeout = scheduler.schedule(() -> {
logger.debug("[{}] timeout expired", currentScannedPortName);
endGwConnection();
portCheckLatch.countDown();
}, PORT_CHECK_TIMEOUT_MSEC, TimeUnit.MILLISECONDS);
try {
gw.connect();
portCheckLatch.await();
} catch (OWNException e) {
logger.debug("[{}] OWNException while trying to connect to a ZigBee USB Gateway: {}",
currentScannedPortName, e.getMessage());
cancelConnectTimeout();
endGwConnection();
}
}
logger.debug("[{}] == finished checking port", currentScannedPortName);
}
}
logger.debug("Finished checking all serial ports");
} catch (InterruptedException ie) {
logger.warn("[{}] interrupted: {}", currentScannedPortName, ie.getMessage());
endGwConnection();
logger.debug("Interrupted while checking serial ports");
}
}
@Override
protected synchronized void stopScan() {
scanning = false;
cancelConnectTimeout();
endGwConnection();
portCheckLatch.countDown();
super.stopScan();
logger.debug("Stopped OpenWebNet ZigBee USB Gateway discovery scan");
}
/**
* Ends connection to the gateway
*/
private void endGwConnection() {
USBGateway gw = zbGateway;
if (gw != null) {
gw.closeConnection();
zbGateway = null;
logger.debug("[{}] connection to gateway closed", currentScannedPortName);
}
}
private void cancelConnectTimeout() {
ScheduledFuture<?> ct = connectTimeout;
if (ct != null && !ct.isDone()) {
ct.cancel(false);
ct = null;
logger.debug("[{}] timeout cancelled", currentScannedPortName);
}
}
/**
* Create and notify a new ZigBee USB Gateway thing has been discovered
*/
private void bridgeDiscovered() {
USBGateway gw = zbGateway;
if (gw != null) {
int gatewayZigBeeId = gw.getZigBeeIdAsDecimal();
ThingUID gatewayUID = new ThingUID(OpenWebNetBindingConstants.THING_TYPE_ZB_GATEWAY,
Integer.toString(gatewayZigBeeId));
Map<String, Object> gwProperties = new HashMap<>(3);
gwProperties.put(OpenWebNetBindingConstants.CONFIG_PROPERTY_SERIAL_PORT, gw.getSerialPortName());
gwProperties.put(OpenWebNetBindingConstants.PROPERTY_FIRMWARE_VERSION, gw.getFirmwareVersion());
gwProperties.put(OpenWebNetBindingConstants.PROPERTY_ZIGBEEID, String.valueOf(gatewayZigBeeId));
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(gatewayUID).withProperties(gwProperties)
.withLabel(OpenWebNetBindingConstants.THING_LABEL_ZB_GATEWAY + " (" + gw.getSerialPortName() + ")")
.withRepresentationProperty(OpenWebNetBindingConstants.PROPERTY_ZIGBEEID).build();
logger.debug("--- ZigBee USB Gateway thing discovered: {} fw: {}", discoveryResult.getLabel(),
gw.getFirmwareVersion());
thingDiscovered(discoveryResult);
}
}
@Override
public void onConnected() {
logger.debug("[{}] found ZigBee USB Gateway", currentScannedPortName);
cancelConnectTimeout();
bridgeDiscovered();
endGwConnection();
portCheckLatch.countDown();
}
@Override
public void onConnectionError(@Nullable OWNException error) {
OWNException e = error;
String msg = (e != null ? e.getMessage() : "");
logger.debug("[{}] onConnectionError(): {}", currentScannedPortName, msg);
}
@Override
public void onConnectionClosed() {
logger.debug("UsbGatewayDiscoveryService received onConnectionClosed()");
}
@Override
public void onDisconnected(@Nullable OWNException error) {
logger.debug("UsbGatewayDiscoveryService received onDisconnected()");
}
@Override
public void onReconnected() {
logger.debug("UsbGatewayDiscoveryService received onReconnected()");
}
@Override
public void onEventMessage(@Nullable OpenMessage msg) {
logger.debug("UsbGatewayDiscoveryService received onEventMessage(): {}", msg);
}
@Override
public void onNewDevice(@Nullable Where where, @Nullable OpenDeviceType deviceType,
@Nullable BaseOpenMessage message) {
logger.debug("UsbGatewayDiscoveryService received onNewDevice()");
}
@Override
public void onDiscoveryCompleted() {
logger.debug("UsbGatewayDiscoveryService received onDiscoveryCompleted()");
}
}

View File

@ -16,13 +16,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Bridge;
import org.openwebnet4j.message.Lighting; import org.openwebnet4j.message.BaseOpenMessage;
import org.openwebnet4j.message.FrameException;
import org.openwebnet4j.message.Where; import org.openwebnet4j.message.Where;
import org.openwebnet4j.message.WhereLightAutom; import org.openwebnet4j.message.WhereLightAutom;
import org.openwebnet4j.message.WhereZigBee; import org.openwebnet4j.message.WhereZigBee;
import org.openwebnet4j.message.Who; import org.openwebnet4j.message.Who;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Test class for {@link OpenWebNetBridgeHandler#ownID} and ThingID calculation using {@link OpenWebNetBridgeHandler} * Test class for {@link OpenWebNetBridgeHandler#ownID} and ThingID calculation using {@link OpenWebNetBridgeHandler}
@ -33,6 +37,8 @@ import org.openwebnet4j.message.Who;
@NonNullByDefault @NonNullByDefault
public class OwnIdTest { public class OwnIdTest {
private final Logger logger = LoggerFactory.getLogger(OwnIdTest.class);
// @formatter:off // @formatter:off
/** /**
* *
@ -57,22 +63,37 @@ public class OwnIdTest {
// @formatter:on // @formatter:on
public enum TEST { public enum TEST {
zb_switch(new WhereZigBee("789309801#9"), Who.fromValue(1), "789309800h9", "1.789309800h9", "789309800h9"), // @formatter:off
zb_switch_2u_1(new WhereZigBee("789301201#9"), Who.fromValue(1), "789301200h9", "1.789301200h9", "789301200h9"), zb_switch(new WhereZigBee("789309801#9"), Who.fromValue(1), "*1*1*789309801#9##", "789309800h9", "1.789309800h9", "789309800h9"),
zb_switch_2u_2(new WhereZigBee("789301202#9"), Who.fromValue(1), "789301200h9", "1.789301200h9", "789301200h9"), zb_switch_2u_1(new WhereZigBee("789301201#9"), Who.fromValue(1), "*1*1*789301201#9##", "789301200h9", "1.789301200h9", "789301200h9"),
bus_switch(new WhereLightAutom("51"), Who.fromValue(1), "51", "1.51", "51"), zb_switch_2u_2(new WhereZigBee("789301202#9"), Who.fromValue(1), "*1*1*789301202#9##", "789301200h9", "1.789301200h9", "789301200h9"),
bus_localbus(new WhereLightAutom("25#4#01"), Who.fromValue(1), "25h4h01", "1.25h4h01", "25h4h01"); bus_switch(new WhereLightAutom("51"), Who.fromValue(1), "*1*1*51##", "51", "1.51", "51"),
// bus_thermo("#1", "4", "1", "4.1", "1"), bus_localbus(new WhereLightAutom("25#4#01"), Who.fromValue(1), "*1*1*25#4#01##", "25h4h01", "1.25h4h01", "25h4h01");
//bus_thermo_zone(new WhereThermo("1"), Who.fromValue(4),"*#4*1*0*0020##" , "1", "4.1", "1"),
//bus_thermo_zone_act(new WhereThermo("2#1"), Who.fromValue(4),"*#4*2#1*20*0##" ,"2", "4.2", "2"),
//bus_thermo_via_cu(new WhereThermo("#1"), Who.fromValue(4),"*#4*#1*0*0020##" ,"1", "4.1", "1"),
// bus_tempSensor("500", "4", "500", "4.500", "500"), // bus_tempSensor("500", "4", "500", "4.500", "500"),
// bus_energy("51", "18", "51", "18.51", "51"); // bus_energy("51", "18", "51", "18.51", "51");
// @formatter:on
private final Logger logger = LoggerFactory.getLogger(TEST.class);
public final Where where; public final Where where;
public final Who who; public final Who who;
public final @Nullable BaseOpenMessage msg;
public final String norm, ownId, thingId; public final String norm, ownId, thingId;
private TEST(Where where, Who who, String norm, String ownId, String thingId) { private TEST(Where where, Who who, String msg, String norm, String ownId, String thingId) {
this.where = where; this.where = where;
this.who = who; this.who = who;
BaseOpenMessage bmsg = null;
try {
bmsg = (BaseOpenMessage) BaseOpenMessage.parse(msg);
} catch (FrameException e) {
logger.warn("something is wrong in the test table. ownIdFromMessage test will be skipped");
}
this.msg = bmsg;
this.norm = norm; this.norm = norm;
this.ownId = ownId; this.ownId = ownId;
this.thingId = thingId; this.thingId = thingId;
@ -83,13 +104,16 @@ public class OwnIdTest {
public void testOwnId() { public void testOwnId() {
Bridge mockBridge = mock(Bridge.class); Bridge mockBridge = mock(Bridge.class);
OpenWebNetBridgeHandler brH = new OpenWebNetBridgeHandler(mockBridge); OpenWebNetBridgeHandler brH = new OpenWebNetBridgeHandler(mockBridge);
BaseOpenMessage bmsg;
for (int i = 0; i < TEST.values().length; i++) { for (int i = 0; i < TEST.values().length; i++) {
TEST test = TEST.values()[i]; TEST test = TEST.values()[i];
// System.out.println("testing where=" + test.where); logger.info("testing where={}", test.where);
assertEquals(test.norm, brH.normalizeWhere(test.where)); assertEquals(test.norm, brH.normalizeWhere(test.where));
assertEquals(test.ownId, brH.ownIdFromWhoWhere(test.who, test.where)); assertEquals(test.ownId, brH.ownIdFromWhoWhere(test.who, test.where));
assertEquals(test.ownId, brH.ownIdFromMessage(Lighting.requestTurnOn(test.where.value()))); bmsg = test.msg;
if (bmsg != null) {
assertEquals(test.ownId, brH.ownIdFromMessage(bmsg));
}
assertEquals(test.thingId, brH.thingIdFromWhere(test.where)); assertEquals(test.thingId, brH.thingIdFromWhere(test.where));
} }
} }