* [openwebnet] Fixed config, handling and discovery of ZigBee devices (fixes #8915 and fixes #8917). Added test for ownID. Now uses openwebnet4j v0.3.2
* [openwebnet] ZigBee: improved handling of wrong 'where' parameter. Updated README. Improved logging.
* [openwebnet] Improved discoveryByActivation to distinguish dimmers from lights. Now using openwebnet4j 0.3.2-1
Signed-off-by: Massimo Valla <mvcode00@gmail.com>
- commands from openHAB and feedback (events) from BUS/SCS and wireless network

-
+
## Supported Things
### For BUS/SCS
-| Category | WHO | Thing Type IDs | Description | Status |
-| -------------------- | :----------: | :---------------------------------: | ----------------------------------------------------------- | ---------------- |
-| Gateway Management | `13` | `bus_gateway` | Any IP gateway supporting OpenWebNet protocol should work (e.g. F454 / MyHOMEServer1 / MH202 / F455 / MH200N, ...) | Successfully tested: F454, MyHOMEServer1, MyHOME_Screen10, F455, F452, F453AV, MH201, MH202, MH200N. Some connection stability issues/gateway resets reported with MH202 |
-| Lighting | `1` | `bus_on_off_switch`, `bus_dimmer` | BUS switches and dimmers. | Successfully tested: F411/2, F411/4, F411U2, F422, F429. Some discovery issues reported with F429 (DALI Dimmers) |
-| Automation | `2` | `bus_automation` | BUS roller shutters, with position feedback and auto-calibration | Successfully tested: LN4672M2 |
+| Category | WHO | Thing Type IDs | Description | Status |
+| -------------------- | :----------: | :------------------------------------------: | -------------------------------------------------------------- | ---------------- |
+| Gateway Management | `13` | `bus_gateway` | Any IP gateway supporting OpenWebNet protocol should work (e.g. F454 / MyHOMEServer1 / MH202 / F455 / MH200N, ...) | Successfully tested: F454, MyHOMEServer1, MyHOME_Screen10, F455, F452, F453AV, MH201, MH202, MH200N. Some connection stability issues/gateway resets reported with MH202 |
+| Lighting | `1` | `bus_on_off_switch`, `bus_dimmer` | BUS switches and dimmers | Successfully tested: F411/2, F411/4, F411U2, F422, F429. Some discovery issues reported with F429 (DALI Dimmers) |
+| Automation | `2` | `bus_automation` | BUS roller shutters, with position feedback and auto-calibration | Successfully tested: LN4672M2 |
### For ZigBee (Radio)
-| Category | WHO | Thing Type IDs | Description | Status |
-| ---------- | :---: | :-------------------------------: | :-------------------------------------------------------------------: | ------------------------------------ |
-| Gateway | `13` | `zb_gateway` | Wireless ZigBee USB Gateway (models: BTI-3578 / LG 088328) | Tested: BTI-3578 and LG 088328 |
-| Lighting | `1` | `zb_dimmer`, `zb_on_off_switch`, `zb_on_off_switch2u` | ZigBee dimmers, switches and 2-unit switches | Tested: BTI-4591, BTI-3584, BTI-4585 |
-| Automation | `2` | `zb_automation` | ZigBee roller shutters | |
+| Category | WHO | Thing Type IDs | Description | Status |
+| -------------------- | :----: | :-------------------------------: | :-------------------------------------------------------------------: | ------------------------------------ |
+| Gateway Management | `13` | `zb_gateway` | ZigBee USB Gateway (models: BTI-3578 / LG 088328) | Tested: BTI-3578 and LG 088328 |
+| Lighting | `1` | `zb_dimmer`, `zb_on_off_switch`, `zb_on_off_switch2u` | ZigBee dimmers, switches and 2-unit switches | Tested: BTI-4591, BTI-3584, BTI-4585 |
+| Automation | `2` | `zb_automation` | ZigBee roller shutters | |
## Discovery
#### Discovery by Activation
-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_ (spinning arrow in Inbox), 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).
### 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 discovery is started
-- ***IMPORTANT NOTE:*** As for other OH2 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:
+- 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
+- ***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:
```
$ sudo usermod -a -G dialout openhab
### Configuring Wireless ZigBee USB Gateway
-To add a ZigBee USB gateway manually using PaperUI: go to *Inbox > "+" > OpenWebNet > click `ADD MANUALLY`* and then select `ZigBee USB Gateway`.
+To add a ZigBee USB Gateway manually using PaperUI: go to *Inbox > "+" > OpenWebNet > click `ADD MANUALLY`* and then select `ZigBee USB Gateway`.
Configuration parameters are:
- `serialPort` : the serial port where the ZigBee USB Gateway is connected (`String`, *mandatory*)
- - Example: `COM3`
+ - Examples: `/dev/ttyUSB0` (Linux/RaPi), `COM3` (Windows)
### Configuring Devices
Devices can be also added manually from PaperUI. For each device it must be configured:
- the associated gateway (`Bridge Selection` menu)
-- the `WHERE` config parameter (`OpenWebNet Device Address`):
- - example for BUS/SCS: Point to Point `A=2 PL=4` --> `WHERE="24"`
- - example for BUS/SCS: Point to Point `A=6 PL=4` on local bus --> `WHERE="64#4#01"`
- - example for ZigBee devices: use decimal format address without the UNIT part and network: ZigBee `WHERE=414122201#9` --> `WHERE="4141222"`
+- 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=03 PL=11` on local bus --> `where="0311#4#01"`
+ - example for ZigBee devices: `where=765432101#9`. The ID of the device (ADDR part) is usually written in hexadecimal on the device itself, for example `ID 0074CBB1`: convert to decimal (`7654321`) and add `01#9` at the end to obtain `where=765432101#9`. For 2-unit switch devices (`zb_on_off_switch2u`), last part should be `00#9`.
## Channels
Devices support some of the following channels:
-| Channel Type ID (channel ID) | Item Type | Description | Read/Write |
-|--------------------------|---------------|-------------------------------------------------------------------------|:----------:|
-| `switch` | Switch | To switch the device `ON` and `OFF` | R/W |
-| `brightness` | Dimmer | To adjust the brightness value (Percent, `ON`, `OFF`) | R/W |
-| `shutter` | Rollershutter | To activate roller shutters (`UP`, `DOWN`, `STOP`, Percent - [see Shutter position](#shutter-position)) | R/W |
+| Channel Type ID (channel ID) | Item Type | Description | Read/Write |
+|------------------------------------------------|---------------|---------------------------------------------------------|:----------:|
+| `switch` or `switch_01`/`02` for ZigBee | Switch | To switch the device `ON` and `OFF` | R/W |
+| `brightness` | Dimmer | To adjust the brightness value (Percent, `ON`, `OFF`) | R/W |
+| `shutter` | Rollershutter | To activate roller shutters (`UP`, `DOWN`, `STOP`, Percent - [see Shutter position](#shutter-position)) | R/W |
### Notes on channels
### openwebnet.things:
+BUS gateway and things configuration:
+
```xtend
Bridge openwebnet:bus_gateway:mybridge "MyHOMEServer1" [ host="192.168.1.35", passwd="abcde", port=20000, discoveryByActivation=false ] {
- bus_on_off_switch LR_switch "Living Room Light" [ where="51" ]
- bus_dimmer LR_dimmer "Living Room Dimmer" [ where="25#4#01" ]
- bus_dimmer LR_dalidimmer "Living Room Dali-Dimmer" [ where="0311#4#01" ]
- bus_automation LR_shutter "Living Room Shutter" [ where="93", shutterRun="10050"]
+ bus_on_off_switch LR_switch "Living Room Light" [ where="51" ]
+ bus_dimmer LR_dimmer "Living Room Dimmer" [ where="0311#4#01" ]
+ bus_automation LR_shutter "Living Room Shutter" [ where="93", shutterRun="10050"]
}
-```
+```
+ZigBee USB Gateway and things configuration - for radio devices:
+
```xtend
-// ZigBee USB Gateway configuration for radio devices
Bridge openwebnet:zb_gateway:myZBgateway [serialPort="COM3"] {
- zb_dimmer myzigbeedimmer [ where="123456700#9"]
- zb_on_off_switch myzigbeeswitch [ where="765432200#9"]
+ zb_dimmer myZB_dimmer [ where="765432101#9"]
+ zb_on_off_switch myZB_switch [ where="765432201#9"]
+ zb_on_off_switch2u myZB_2U_switch [ where="765432300#9"]
}
```
### openwebnet.items:
-Items (Light, Dimmer, etc.) will be discovered by Google Assistant/Alexa/HomeKit if their tags are configured like in the example.
+Items (Light, Dimmer, etc.) will be discovered by Google Assistant/Alexa/HomeKit if their tags are configured like in the example:
```xtend
Switch iLR_switch "Light" <light> (gLivingRoom) [ "Lighting" ] { channel="openwebnet:bus_on_off_switch:mybridge:LR_switch:switch" }
Dimmer iLR_dimmer "Dimmer [%.0f %%]" <DimmableLight> (gLivingRoom) [ "Lighting" ] { channel="openwebnet:bus_dimmer:mybridge:LR_dimmer:brightness" }
-Dimmer iLR_dalidimmer "Dali-Dimmer [%.0f %%]" <DimmableLight> (gLivingRoom) [ "Lighting" ] { channel="openwebnet:bus_dimmer:mybridge:LR_dalidimmer:brightness" }
/* For Dimmers, use category DimmableLight to have Off/On switch in addition to the Percent slider in PaperUI */
Rollershutter iLR_shutter "Shutter [%.0f %%]" <rollershutter> (gShutters, gLivingRoom) [ "Blinds" ] { channel="openwebnet:bus_automation:mybridge:LR_shutter:shutter" }
```
+Example items linked to ZigBee devices:
+
+```xtend
+Dimmer iDimmer "Dimmer [%.0f %%]" <DimmableLight> (gKitchen) [ "Lighting" ] { channel="openwebnet:zb_dimmer:myZBgateway:myZB_dimmer:brightness" }
+Switch iSimpleSwitch "Kitchen Switch" <light> (gKitchen) [ "Lighting" ] { channel="openwebnet:zb_on_off_switch:myZBgateway:myZB_switch:switch_01" }
+Switch iSwitch_01 "2U first light" <light> (gKitchen) [ "Lighting" ] { channel="openwebnet:zb_on_off_switch2u:myZBgateway:myZB_2U_switch:switch_01" }
+Switch iSwitch_02 "2U second light" <light> (gKitchen) [ "Lighting" ] { channel="openwebnet:zb_on_off_switch2u:myZBgateway:myZB_2U_switch:switch_02" }
+```
+
### openwebnet.sitemap
```xtend
{
Default item=iLR_switch icon="light"
Default item=iLR_dimmer icon="light"
- Default item=iLR_dalidimmer icon="light"
Default item=iLR_shutter
}
}
<dependency>
<groupId>com.github.openwebnet4j</groupId>
<artifactId>openwebnet4j</artifactId>
- <version>0.3.1</version>
+ <version>0.3.2-1</version>
<scope>compile</scope>
</dependency>
updateMovingState(MOVING_STATE_STOPPED);
logger.debug("& {} & CALIBRATION - reached UP, now sending DOWN command...", deviceWhere);
calibrating = CALIBRATION_ACTIVATED;
- if (deviceWhere != null) {
- String w = deviceWhere.value();
+ Where dw = deviceWhere;
+ if (dw != null) {
+ String w = dw.value();
try {
send(Automation.requestMoveDown(w));
} catch (OWNException e) {
import org.openwebnet4j.message.GatewayMgmt;
import org.openwebnet4j.message.Lighting;
import org.openwebnet4j.message.OpenMessage;
+import org.openwebnet4j.message.What;
import org.openwebnet4j.message.Where;
+import org.openwebnet4j.message.WhereZigBee;
import org.openwebnet4j.message.Who;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// ConcurrentHashMap of devices registered to this BridgeHandler
// association is: ownId (String) -> OpenWebNetThingHandler, with ownId = WHO.WHERE
- private Map<String, OpenWebNetThingHandler> registeredDevices = new ConcurrentHashMap<>();
+ private Map<String, @Nullable OpenWebNetThingHandler> registeredDevices = new ConcurrentHashMap<>();
+ private Map<String, Long> discoveringDevices = new ConcurrentHashMap<>();
protected @Nullable OpenGateway gateway;
private boolean isBusGateway = false;
"Could not connect to gateway before " + GATEWAY_ONLINE_TIMEOUT_SEC + "s");
}
}, GATEWAY_ONLINE_TIMEOUT_SEC, TimeUnit.SECONDS);
+ logger.debug("bridge {} initialization completed", thing.getUID());
} catch (OWNException e) {
logger.debug("gw.connect() returned OWNException: {}", e.getMessage());
// status is updated by callback onConnectionError()
* Init a ZigBee gateway based on config
*/
private @Nullable OpenGateway initZigBeeGateway() {
- logger.debug("Initializing ZigBee USB gateway");
+ logger.debug("Initializing ZigBee USB Gateway");
OpenWebNetZigBeeBridgeConfig zbBridgeConfig = getConfigAs(OpenWebNetZigBeeBridgeConfig.class);
String serialPort = zbBridgeConfig.getSerialPort();
if (serialPort == null || serialPort.isEmpty()) {
- logger.warn("Cannot connect to gateway. No serial port has been provided in Bridge configuration.");
+ logger.info("Cannot connect ZigBee USB Gateway. No serial port has been provided in Bridge configuration.");
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.conf-error-no-serial-port");
return null;
OpenWebNetBusBridgeConfig busBridgeConfig = getConfigAs(OpenWebNetBusBridgeConfig.class);
String host = busBridgeConfig.getHost();
if (host == null || host.isEmpty()) {
- logger.warn("Cannot connect to gateway. No host/IP has been provided in Bridge configuration.");
+ logger.info("Cannot connect to BUS Gateway. No host/IP has been provided in Bridge configuration.");
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.conf-error-no-ip-address");
return null;
logger.debug("handleCommand (command={} - channel={})", command, channelUID);
OpenGateway gw = gateway;
if (gw != null && !gw.isConnected()) {
- logger.warn("Gateway is NOT connected, skipping command");
+ logger.info("Gateway is NOT connected, skipping command");
return;
} else {
logger.warn("Channel not supported: channel={}", channelUID);
if (gw != null) {
gw.closeConnection();
gw.unsubscribe(this);
- logger.debug("gateway {} connection closed and unsubscribed", gw.toString());
+ logger.debug("Gateway {} connection closed and unsubscribed", gw.toString());
gateway = null;
}
reconnecting = false;
}
private void discoverByActivation(BaseOpenMessage baseMsg) {
- logger.debug("BridgeHandler.discoverByActivation() msg={}", baseMsg);
+ logger.debug("discoverByActivation: msg={}", baseMsg);
OpenWebNetDeviceDiscoveryService discService = deviceDiscoveryService;
if (discService == null) {
logger.warn("discoverByActivation: null OpenWebNetDeviceDiscoveryService, ignoring msg={}", baseMsg);
return;
}
- if (baseMsg instanceof Lighting) {
+ if (baseMsg instanceof Lighting || baseMsg instanceof Automation) { // we support these types only
+ BaseOpenMessage bmsg = baseMsg;
+ if (baseMsg instanceof Lighting) {
+ What what = baseMsg.getWhat();
+ if (Lighting.WHAT.OFF.equals(what)) { // skipping OFF msg: cannot distinguish dimmer/switch
+ logger.debug("discoverByActivation: skipping OFF msg: cannot distinguish dimmer/switch");
+ return;
+ }
+ if (Lighting.WHAT.ON.equals(what)) { // if not already done just now, request light status to
+ // distinguish dimmer from switch
+ if (discoveringDevices.containsKey(ownIdFromMessage(baseMsg))) {
+ logger.debug(
+ "discoverByActivation: we just requested status for this device and it's ON -> it's a switch");
+ } else {
+ OpenGateway gw = gateway;
+ if (gw != null) {
+ try {
+ discoveringDevices.put(ownIdFromMessage(baseMsg),
+ Long.valueOf(System.currentTimeMillis()));
+ gw.send(Lighting.requestStatus(baseMsg.getWhere().value()));
+ return;
+
+ } catch (OWNException e) {
+ logger.warn("discoverByActivation: Exception while requesting light state: {}",
+ e.getMessage());
+ return;
+ }
+ }
+ }
+ }
+ discoveringDevices.remove(ownIdFromMessage(baseMsg));
+ }
OpenDeviceType type = null;
try {
- type = baseMsg.detectDeviceType();
+ type = bmsg.detectDeviceType();
} catch (FrameException e) {
logger.warn("Exception while detecting device type: {}", e.getMessage());
}
if (type != null) {
- discService.newDiscoveryResult(baseMsg.getWhere(), type, baseMsg);
+ discService.newDiscoveryResult(bmsg.getWhere(), type, bmsg);
} else {
- logger.debug("discoverByActivation: no device type detected from msg: {}", baseMsg);
+ logger.debug("discoverByActivation: no device type detected from msg: {}", bmsg);
}
}
}
// let's try to get the Thing associated with this message...
if (baseMsg instanceof Lighting || baseMsg instanceof Automation) {
String ownId = ownIdFromMessage(baseMsg);
- logger.debug("ownId={}", ownId);
+ logger.debug("ownIdFromMessage({}) --> {}", baseMsg, ownId);
OpenWebNetThingHandler deviceHandler = registeredDevices.get(ownId);
if (deviceHandler == null) {
OpenGateway gw = gateway;
return;
}
if (gw instanceof USBGateway) {
- logger.info("------------------- CONNECTED to USB (ZigBee) gateway - USB port: {}",
+ logger.info("------------------- CONNECTED to ZigBee USB gateway - USB port: {}",
((USBGateway) gw).getSerialPortName());
} else {
logger.info("------------------- CONNECTED to BUS gateway '{}' ({}:{})", thing.getUID(),
}
/**
- * Return a ownId string (=WHO.WHERE) from a deviceWhere thing config parameter (already normalized) and its
- * handler.
+ * Return a ownId string (=WHO.WHERE) from the device Where address and handler
*
- * @param deviceWhere the device WHERE config parameter
- * @param handler the thing handler
- * @return the ownId
+ * @param where the Where address (to be normalized)
+ * @param handler the device handler
+ * @return the ownId String
*/
- protected String ownIdFromDeviceWhere(@Nullable String deviceWhere, OpenWebNetThingHandler handler) {
- return handler.ownIdPrefix() + "." + deviceWhere;
+ protected String ownIdFromDeviceWhere(Where where, OpenWebNetThingHandler handler) {
+ return handler.ownIdPrefix() + "." + normalizeWhere(where);
}
/**
- * Returns a ownId string (=WHO.WHERE) from a Where address and Who
+ * Returns a ownId string (=WHO.WHERE) from a Who and Where address
*
- * @param where the Where address (to be normalized)
* @param who the Who
- * @return the ownId
+ * @param where the Where address (to be normalized)
+ * @return the ownId String
*/
- public String ownIdFromWhoWhere(Where where, Who who) {
+ public String ownIdFromWhoWhere(Who who, Where where) {
return who.value() + "." + normalizeWhere(where);
}
* @param baseMsg the BaseOpenMessage
* @return the ownId String
*/
- private String ownIdFromMessage(BaseOpenMessage baseMsg) {
+ public String ownIdFromMessage(BaseOpenMessage baseMsg) {
return baseMsg.getWho().value() + "." + normalizeWhere(baseMsg.getWhere());
}
/**
- * Transform a Where address into a Thing id string based on bridge type (BUS/USB ZigBee).
- * '#' in WHERE are changed to 'h'
+ * Transform a Where address into a Thing id string
*
* @param where the Where address
- * @return the thing Id
+ * @return the thing Id string
*/
public String thingIdFromWhere(Where where) {
- return normalizeWhere(where).replace('#', 'h'); // '#' cannot be used in ThingUID;
+ return normalizeWhere(where); // '#' cannot be used in ThingUID;
}
/**
- * Normalize a Where address for Thermo and Zigbee devices
+ * Normalize a Where address
*
* @param where the Where address
- * @return the normalized address
+ * @return the normalized address as String
*/
public String normalizeWhere(Where where) {
- String str = "";
- if (isBusGateway) {
- if (where.value().indexOf('#') < 0) { // no hash present
- str = where.value();
- } else if (where.value().indexOf("#4#") > 0) { // local bus: APL#4#bus
- str = where.value();
- } else if (where.value().indexOf('#') == 0) { // thermo zone via central unit: #0 or #Z (Z=[1-99]) --> Z
- str = where.value().substring(1);
- } else if (where.value().indexOf('#') > 0) { // thermo zone and actuator N: Z#N (Z=[1-99], N=[1-9]) -- > Z
- str = where.value().substring(0, where.value().indexOf('#'));
- } else {
- logger.warn("normalizeWhere() unexpected WHERE: {}", where);
- str = where.value();
- }
- return str;
+ String str = where.value();
+ if (where instanceof WhereZigBee) {
+ str = ((WhereZigBee) where).valueWithUnit(WhereZigBee.UNIT_ALL); // 76543210X#9 --> 765432100#9
} else {
- return where.value();
+ if (str.indexOf("#4#") > 0) { // local bus: APL#4#bus
+ // no change needed
+ } else if (str.indexOf('#') == 0) { // Thermo zone via central unit: #0 or #Z (Z=[1-99]) --> Z
+ str = str.substring(1);
+ } else if (str.indexOf('#') > 0) { // Thermo zone and actuator N: Z#N (Z=[1-99], N=[1-9]) --> Z
+ str = str.substring(0, str.indexOf('#'));
+ }
}
+ return str.replace('#', 'h');
}
}
if (!(deviceWhereConfig instanceof String)) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"WHERE parameter in configuration is null or invalid");
- return;
} else {
String deviceWhereStr = (String) getConfig().get(CONFIG_PROPERTY_WHERE);
Where w;
- if (brH.isBusGateway()) {
- w = new WhereLightAutom(deviceWhereStr);
- } else {
- w = new WhereZigBee(deviceWhereStr);
+ try {
+ if (brH.isBusGateway()) {
+ w = new WhereLightAutom(deviceWhereStr);
+ } else {
+ w = new WhereZigBee(deviceWhereStr);
+ }
+ } catch (IllegalArgumentException ia) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+ "WHERE parameter in configuration is invalid");
+ return;
}
deviceWhere = w;
- final String oid = brH.ownIdFromDeviceWhere(w.value(), this);
+ final String oid = brH.ownIdFromDeviceWhere(w, this);
ownId = oid;
Map<String, String> properties = editProperties();
properties.put(PROPERTY_OWNID, oid);
logger.debug("associated thing to bridge with ownId={}", ownId);
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, "waiting state update...");
}
- return;
}
+ } else {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+ "No bridge associated, please assign a bridge in thing configuration.");
}
- updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
- "No bridge associated, please assign a bridge in thing configuration.");
}
@Override
if (handler != null) {
OpenGateway gw = handler.gateway;
if (gw != null && !gw.isConnected()) {
- logger.info("Cannot handle command {}:{} for {}: gateway is not connected", channel, command,
- getThing().getUID());
+ logger.info("Cannot handle {} command for {}: gateway is not connected", command, getThing().getUID());
+ return;
+ }
+ if (deviceWhere == null) {
+ logger.info("Cannot handle {} command for {}: 'where' parameter is not configured or is invalid",
+ command, getThing().getUID());
return;
}
if (command instanceof RefreshType) {
}
}
- String ownId = bridgeHandler.ownIdFromWhoWhere(where, deviceWho);
+ String ownId = bridgeHandler.ownIdFromWhoWhere(deviceWho, where);
if (thingTypeUID == OpenWebNetBindingConstants.THING_TYPE_BUS_ON_OFF_SWITCH) {
if (bridgeHandler.getRegisteredDevice(ownId) != null) {
logger.debug("dimmer/switch with WHERE={} already registered, skipping this discovery result", where);
DiscoveryResult discoveryResult = null;
- String whereLabel = where.value();
+ String whereConfig = where.value();
if (where instanceof WhereZigBee && WhereZigBee.UNIT_02.equals(((WhereZigBee) where).getUnit())) {
- logger.debug("UNIT=02 found (WHERE={})", where);
- logger.debug("will remove previous result if exists");
+ logger.debug("UNIT=02 found (WHERE={}) -> will remove previous result if exists", where);
thingRemoved(thingUID); // remove previously discovered thing
// re-create thingUID with new type
thingTypeUID = OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH_2UNITS;
thingLabel = OpenWebNetBindingConstants.THING_LABEL_ZB_ON_OFF_SWITCH_2UNITS;
thingUID = new ThingUID(thingTypeUID, bridgeUID, tId);
- whereLabel = whereLabel.replace("02#", "00#"); // replace unit '02' with all unit '00'
+ whereConfig = ((WhereZigBee) where).valueWithUnit(WhereZigBee.UNIT_ALL); // replace unit '02' with '00'
logger.debug("UNIT=02, switching type from {} to {}",
OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH,
OpenWebNetBindingConstants.THING_TYPE_ZB_ON_OFF_SWITCH_2UNITS);
}
Map<String, Object> properties = new HashMap<>(2);
- properties.put(OpenWebNetBindingConstants.CONFIG_PROPERTY_WHERE, bridgeHandler.normalizeWhere(where));
+ properties.put(OpenWebNetBindingConstants.CONFIG_PROPERTY_WHERE, whereConfig);
properties.put(OpenWebNetBindingConstants.PROPERTY_OWNID, ownId);
if (thingTypeUID == OpenWebNetBindingConstants.THING_TYPE_GENERIC_DEVICE) {
- thingLabel = thingLabel + " (WHO=" + deviceWho + ", WHERE=" + whereLabel + ")";
+ thingLabel = thingLabel + " (WHO=" + deviceWho + ", WHERE=" + whereConfig + ")";
} else {
- thingLabel = thingLabel + " (WHERE=" + whereLabel + ")";
+ thingLabel = thingLabel + " (WHERE=" + whereConfig + ")";
}
discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(thingTypeUID).withProperties(properties)
.withRepresentationProperty(OpenWebNetBindingConstants.PROPERTY_OWNID).withBridge(bridgeUID)
</parameter>
<parameter name="where" type="text" required="true">
- <label>OpenWebNet Device Address (WHERE)</label>
- <description>Example: A/PL address: A=1 PL=3 --> WHERE=13. On local bus: WHERE=13#4#01</description>
+ <label>OpenWebNet Device Address (where)</label>
+ <description>Example: A/PL address: A=1 PL=3 --> where=13. On local bus: where=13#4#01</description>
</parameter>
</config-description>
</thing-type>
<config-description>
<parameter name="where" type="text" required="true">
- <label>OpenWebNet Device Address (WHERE)</label>
- <description>Example: A/PL address: A=1 PL=3 --> WHERE=13. On local bus: WHERE=13#4#01</description>
+ <label>OpenWebNet Device Address (where)</label>
+ <description>Example: A/PL address: A=1 PL=3 --> where=13. On local bus: where=13#4#01</description>
</parameter>
</config-description>
<config-description>
<parameter name="where" type="text" required="true">
- <label>OpenWebNet Device Address (WHERE)</label>
- <description>Example: A/PL address: A=1 PL=3 --> WHERE=13. On local bus: WHERE=13#4#01</description>
+ <label>OpenWebNet Device Address (where)</label>
+ <description>Example: A/PL address: A=1 PL=3 --> where=13. On local bus: where=13#4#01</description>
</parameter>
</config-description>
<config-description>
<parameter name="where" type="text" required="true">
- <label>OpenWebNet Device Address (WHERE)</label>
+ <label>OpenWebNet Device Address (where)</label>
<description>It identifies one OpenWebNet device</description>
</parameter>
</config-description>
<default>AUTO</default>
</parameter>
<parameter name="where" type="text">
- <label>OpenWebNet Device Address</label>
- <description>It identifies one ZigBee device. Use decimal format address without the UNIT part and network: ZigBee
- WHERE=414122201#9 -> OpenWebNet Device Address = 4141222</description>
+ <label>OpenWebNet Device Address (where)</label>
+ <description>It identifies one ZigBee device. Example: 765432101#9</description>
<required>true</required>
</parameter>
</config-description>
<config-description>
<parameter name="where" type="text" required="true">
- <label>OpenWebNet Device Address</label>
- <description>It identifies one ZigBee device. Use decimal format address without the UNIT part and network: ZigBee
- WHERE=414122201#9 -> OpenWebNet Device Address = 4141222</description>
+ <label>OpenWebNet Device Address (where)</label>
+ <description>It identifies one ZigBee device. Example: 765432101#9</description>
</parameter>
</config-description>
<config-description>
<parameter name="where" type="text" required="true">
- <label>OpenWebNet Device Address</label>
- <description>It identifies one ZigBee device. Use decimal format address without the UNIT part and network: ZigBee
- WHERE=414122201#9 -> OpenWebNet Device Address = 4141222</description>
+ <label>OpenWebNet Device Address (where)</label>
+ <description>It identifies one ZigBee device. Example: 765432101#9</description>
</parameter>
</config-description>
<config-description>
<parameter name="where" type="text" required="true">
- <label>OpenWebNet Device Address</label>
- <description>It identifies one ZigBee device. Use decimal format address without the UNIT part and network: ZigBee
- WHERE=414122201#9 -> OpenWebNet Device Address = 4141222</description>
+ <label>OpenWebNet Device Address (where)</label>
+ <description>It identifies one ZigBee device. Example: 765432100#9 (use unit=00 at the end)</description>
</parameter>
</config-description>
--- /dev/null
+/**
+ * Copyright (c) 2010-2020 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.handler;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.core.thing.Bridge;
+import org.openwebnet4j.message.Lighting;
+import org.openwebnet4j.message.Where;
+import org.openwebnet4j.message.WhereLightAutom;
+import org.openwebnet4j.message.WhereZigBee;
+import org.openwebnet4j.message.Who;
+
+/**
+ * Test class for {@link OpenWebNetBridgeHandler#ownID} and ThingID calculation using {@link OpenWebNetBridgeHandler}
+ * methods: normalizeWhere(), ownIdFromWhoWhere(), ownIdFromMessage(), thingIdFromWhere()
+ *
+ * @author Massimo Valla - Initial contribution
+ */
+@NonNullByDefault
+public class OwnIdTest {
+
+ // @formatter:off
+ /**
+ *
+ * deviceWhere
+ * (DevAddrParam)
+ * TYPE WHERE = normalizeWhere() ownId ThingID
+ * ---------------------------------------------------------------------------------
+ * Zigbee Switch 789309801#9 789309800h9 1.789309800h9 789309800h9
+ * Zigbee Switch_2u u1 789301201#9 789301200h9 1.789309800h9 789309800h9
+ * Zigbee Switch_2u u2 789301202#9 789301200h9 1.789309800h9 789309800h9
+ * BUS Switch 51 51 1.51 51
+ * BUS Local Bus 25#4#01 25h4h01 1.25h4h01 25h4h01
+ * BUS Autom 93 93 2.93 93
+ * BUS Thermo #1 or 1 1 4.1 1
+ * BUS TempSensor 500 500 4.500 500
+ * BUS Energy 51 51 18.51 51
+ * BUS CEN 51 51 15.51 51
+ * BUS CEN+ 212 212 25.212 212
+ * BUS DryContact 399 399 25.399 399
+ *
+ */
+// @formatter:on
+
+ public enum TEST {
+ zb_switch(new WhereZigBee("789309801#9"), Who.fromValue(1), "789309800h9", "1.789309800h9", "789309800h9"),
+ zb_switch_2u_1(new WhereZigBee("789301201#9"), Who.fromValue(1), "789301200h9", "1.789301200h9", "789301200h9"),
+ zb_switch_2u_2(new WhereZigBee("789301202#9"), Who.fromValue(1), "789301200h9", "1.789301200h9", "789301200h9"),
+ bus_switch(new WhereLightAutom("51"), Who.fromValue(1), "51", "1.51", "51"),
+ bus_localbus(new WhereLightAutom("25#4#01"), Who.fromValue(1), "25h4h01", "1.25h4h01", "25h4h01");
+ // bus_thermo("#1", "4", "1", "4.1", "1"),
+ // bus_tempSensor("500", "4", "500", "4.500", "500"),
+ // bus_energy("51", "18", "51", "18.51", "51");
+
+ public final Where where;
+ public final Who who;
+ public final String norm, ownId, thingId;
+
+ private TEST(Where where, Who who, String norm, String ownId, String thingId) {
+ this.where = where;
+ this.who = who;
+ this.norm = norm;
+ this.ownId = ownId;
+ this.thingId = thingId;
+ }
+ }
+
+ @Test
+ public void testOwnId() {
+ Bridge mockBridge = mock(Bridge.class);
+ OpenWebNetBridgeHandler brH = new OpenWebNetBridgeHandler(mockBridge);
+
+ for (int i = 0; i < TEST.values().length; i++) {
+ TEST test = TEST.values()[i];
+ // System.out.println("testing where=" + test.where);
+ assertEquals(test.norm, brH.normalizeWhere(test.where));
+ assertEquals(test.ownId, brH.ownIdFromWhoWhere(test.who, test.where));
+ assertEquals(test.ownId, brH.ownIdFromMessage(Lighting.requestTurnOn(test.where.value())));
+ assertEquals(test.thingId, brH.thingIdFromWhere(test.where));
+ }
+ }
+}