mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[openwebnet] Fixed handling of ZigBee USB gateway and devices (fixes #8915 #8917 #8962) (2.5.x) (#9141)
Signed-off-by: Massimo Valla <mvcode00@gmail.com>
This commit is contained in:
parent
ed798b7ad7
commit
00a02158aa
@ -9,7 +9,7 @@ The binding supports:
|
||||
- commands from openHAB and feedback (events) from BUS/SCS and wireless network
|
||||
|
||||
![F454 Gateway](doc/F454_gateway.png)
|
||||
![USB ZigBee Gateway](doc/USB_gateway.jpg)
|
||||
![ZigBee USB Gateway](doc/USB_gateway.jpg)
|
||||
|
||||
## Supported Things
|
||||
|
||||
@ -35,19 +35,19 @@ The following Things and OpenWebNet `WHOs` are supported:
|
||||
|
||||
### 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
|
||||
|
||||
@ -64,15 +64,15 @@ For other gateways you can add them manually, see [Thing Configuration](#thing-c
|
||||
|
||||
#### 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
|
||||
@ -105,12 +105,12 @@ Alternatively the BUS/SCS Gateway thing can be configured using the `.things` fi
|
||||
|
||||
### 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
|
||||
|
||||
@ -119,20 +119,20 @@ Devices can be discovered automatically from Inbox after a gateway has been conf
|
||||
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
|
||||
|
||||
@ -151,36 +151,47 @@ It's possible to enter a value manually or set `shutterRun=AUTO` (default) to ca
|
||||
|
||||
### 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
|
||||
@ -190,7 +201,6 @@ sitemap openwebnet label="OpenWebNet Binding Example Sitemap"
|
||||
{
|
||||
Default item=iLR_switch icon="light"
|
||||
Default item=iLR_dimmer icon="light"
|
||||
Default item=iLR_dalidimmer icon="light"
|
||||
Default item=iLR_shutter
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.openwebnet4j</groupId>
|
||||
<artifactId>openwebnet4j</artifactId>
|
||||
<version>0.3.1</version>
|
||||
<version>0.3.2-1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -329,8 +329,9 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
|
||||
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) {
|
||||
|
@ -49,7 +49,9 @@ import org.openwebnet4j.message.FrameException;
|
||||
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;
|
||||
@ -71,6 +73,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
// ConcurrentHashMap of devices registered to this BridgeHandler
|
||||
// association is: ownId (String) -> OpenWebNetThingHandler, with ownId = WHO.WHERE
|
||||
private Map<String, @Nullable OpenWebNetThingHandler> registeredDevices = new ConcurrentHashMap<>();
|
||||
private Map<String, Long> discoveringDevices = new ConcurrentHashMap<>();
|
||||
|
||||
protected @Nullable OpenGateway gateway;
|
||||
private boolean isBusGateway = false;
|
||||
@ -119,6 +122,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
"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()
|
||||
@ -131,11 +135,11 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
* 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.warn("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;
|
||||
@ -152,7 +156,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
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.warn("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;
|
||||
@ -206,7 +210,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
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;
|
||||
@ -276,23 +280,54 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -354,7 +389,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
// 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;
|
||||
@ -384,7 +419,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
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(),
|
||||
@ -482,25 +517,24 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
@ -510,45 +544,39 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|
||||
* @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');
|
||||
}
|
||||
}
|
||||
|
@ -72,17 +72,22 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
|
||||
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);
|
||||
@ -91,11 +96,11 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
|
||||
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
|
||||
@ -105,8 +110,12 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
|
||||
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) {
|
||||
|
@ -81,6 +81,7 @@ public class BusGatewayUpnpDiscovery implements UpnpDiscoveryParticipant {
|
||||
/**
|
||||
* DeviceInfo bean to store device useful info (and log them)
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class DeviceInfo {
|
||||
@Nullable
|
||||
private String friendlyName;
|
||||
|
@ -139,7 +139,7 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractDiscoveryService
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@ -152,27 +152,26 @@ public class OpenWebNetDeviceDiscoveryService extends AbstractDiscoveryService
|
||||
|
||||
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)
|
||||
|
@ -38,8 +38,8 @@
|
||||
</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>
|
||||
|
@ -27,8 +27,8 @@
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -27,8 +27,8 @@
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
<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>
|
||||
|
@ -38,9 +38,8 @@
|
||||
<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>
|
||||
|
@ -27,9 +27,8 @@
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -27,9 +27,8 @@
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -28,9 +28,8 @@
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* 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.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.smarthome.core.thing.Bridge;
|
||||
import org.junit.Test;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user