Skip to content

Commit

Permalink
Added address as parameter and not using id anymore + updated readme. (
Browse files Browse the repository at this point in the history
…openhab#6284)

Signed-off-by: Boris Krivonog <boris.krivonog@inova.si>
  • Loading branch information
crnjan authored and hww3 committed Jan 25, 2020
1 parent 15aacb3 commit 19218a0
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 43 deletions.
70 changes: 61 additions & 9 deletions bundles/org.openhab.binding.nikobus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ In order to be able to read the status of a Nikobus module channel or to switch
#### switch-module

```
Thing switch-module BC00
Thing switch-module s1 [ address = "BC00" ]
```

Defines a `switch-module` with address `BC00`.
Expand All @@ -98,7 +98,7 @@ Defines a `switch-module` with address `BC00`.
#### dimmer-module

```
Thing dimmer-module D969
Thing dimmer-module d1 [ address = "D969" ]
```

Defines a `dimmer-module` with address `D969`.
Expand All @@ -121,7 +121,7 @@ Defines a `dimmer-module` with address `D969`.
#### rollershutter-module

```
Thing rollershutter-module 4C6C
Thing rollershutter-module r1 [ address = "4C6C" ]
```

Defines a `rollershutter-module` with address `4C6C`.
Expand All @@ -144,7 +144,7 @@ This means one could also define virtual buttons in openHAB with non-existing ad
To configure an item for a button in openHAB with address `28092A`, use the following format:

```
Thing push-button 28092A
Thing push-button pb1 [ address = "28092A" ]
```

Since all the channels in the entire channel group are switched to their new state, it is important that openHAB knows the current state of all the channels in that group.
Expand All @@ -156,22 +156,74 @@ When configured, the status of the channel groups to which the button is linked,
Every status query takes between ~300 ms, so to get the best performance, only add the affected channel groups in the configuration, which has the following format:

```
Thing push-button <address> [ impactedModules = "<moduleAddress>-<channelGroup>, <moduleAddress>-<channelGroup>, ..." ]
Thing push-button <id> [ address = "<address>", impactedModules = "<moduleType>:<moduleId>:<channelGroup>, <moduleType>:<moduleId>:<channelGroup>, ..." ]
```

where:

* `moduleAddress` represents the address of the switch module,
* `channelGroup` represents the first or second channel group in the module.
* `moduleType` represents module's type,
* `moduleId` represents module's id,
* `channelGroup` represents the first (1) or second (2) channel group in the module.

Example configurations may look like:

```
Thing push-button 28092A [ impactedModules = "4C6C-2" ]
Thing switch-module s1 [ address = "FF2A" ]
Thing push-button pb1 [ address = "28092A", impactedModules = "switch-module:s1:1" ]
```

In addition to the status requests triggered by button presses, there is also a scheduled status update interval defined by the `refreshInterval` parameter and explained above.

## Full Example

t.b.d.
### nikobus.things

```
Bridge nikobus:pc-link:mypclink [ port = "/dev/ttyUSB0", refreshInterval = 10 ] {
Thing dimmer-module d1 [ address = "0700" ]
Thing dimmer-module d2 [ address = "6B00" ]
Thing switch-module s1 [ address = "FF2A" ]
Thing switch-module s2 [ address = "4C6C" ]
Thing switch-module s3 [ address = "A063" ]
Thing rollershutter-module r1 [ address = "D769" ]
Thing push-button 92092A "S_2_1_2A" [ address = "92092A", impactedModules = "switch-module:s1:1" ]
Thing push-button D2092A "S_2_1_2B" [ address = "D2092A", impactedModules = "switch-module:s1:1" ]
Thing push-button 12092A "S_2_1_2C" [ address = "12092A", impactedModules = "dimmer-module:d1:1" ]
Thing push-button 52092A "S_2_1_2D" [ address = "52092A", impactedModules = "dimmer-module:d1:1" ]
Thing push-button 1EE5F2 "S_2_3_A" [ address = "1EE5F2", impactedModules = "dimmer-module:d1:2" ]
Thing push-button 5EE5F2 "S_2_3_B" [ address = "5EE5F2", impactedModules = "dimmer-module:d1:2" ]
Thing push-button 0C274A "S_2_4_A" [ address = "0C274A", impactedModules = "dimmer-module:d1:2" ]
Thing push-button 4C274A "S_2_4_B" [ address = "4C274A", impactedModules = "dimmer-module:d1:2" ]
Thing push-button 1D1FF2 "S_2_5_A" [ address = "1D1FF2", impactedModules = "switch-module:s1:1" ]
Thing push-button 5D1FF2 "S_2_5_B" [ address = "5D1FF2", impactedModules = "switch-module:s1:1" ]
}
```

### nikobus.items

```
Dimmer Light_FF_Gallery_Ceiling "Ceiling" (FF_Gallery, Lights) [ "Lighting" ] { channel="nikobus:dimmer-module:mypclink:d1:output-1" }
Dimmer Light_FF_Bed_Ceiling "Ceiling" (FF_Bed, Lights) [ "Lighting" ] { channel="nikobus:dimmer-module:mypclink:d1:output-7" }
Dimmer Light_FF_Child_Ceiling "Ceiling" (FF_Child, Lights) [ "Lighting" ] { channel="nikobus:dimmer-module:mypclink:d2:output-10" }
Dimmer Light_FF_Child_Wall_Left "Wall Left" (FF_Child, Lights) [ "Lighting" ] { channel="nikobus:dimmer-module:mypclink:d1:output-11" }
Dimmer Light_FF_Child_Wall_Right "Wall Right" (FF_Child, Lights) [ "Lighting" ] { channel="nikobus:dimmer-module:mypclink:d1:output-12" }
Dimmer Light_FF_PlayRoom_Ceiling "Ceiling" (FF_PlayRoom, Lights) [ "Lighting" ] { channel="nikobus:dimmer-module:mypclink:d1:output-6" }
Dimmer Light_FF_PlayRoom_Wall "Wall" (FF_PlayRoom, Lights) [ "Lighting" ] { channel="nikobus:dimmer-module:mypclink:d1:output-4" }
Switch Light_FF_Gallery_Wall "Wall" (FF_Gallery, Lights) [ "Lighting" ] { channel="nikobus:switch-module:mypclink:s1:output-4" }
Switch Light_FF_Bath_Ceiling "Ceiling" (FF_Bath, Lights) [ "Lighting" ] { channel="nikobus:switch-module:mypclink:s3:output-2" }
Switch Light_FF_Wardrobe_Ceiling "Ceiling" (FF_Wardrobe, Lights) [ "Lighting" ] { channel="nikobus:switch-module:mypclink:s1:output-1" }
Switch Light_FF_Corridor_Ceiling "Ceiling" (FF_Corridor, Lights) [ "Lighting" ] { channel="nikobus:switch-module:mypclink:s2:output-3" }
Rollershutter Shutter_GF_Corridor "Corridor" (GF_Corridor, gShuttersGF) { channel="nikobus:rollershutter-module:mypclink:r1:output-1" }
Rollershutter Shutter_GF_Bed "Bedroom" (GF_Bed, gShuttersGF) { channel="nikobus:rollershutter-module:mypclink:r1:output-3" }
Rollershutter Shutter_GF_Bath "Bathroom" (GF_Bath, gShuttersGF) { channel="nikobus:rollershutter-module:mypclink:r1:output-2" }
Rollershutter Shutter_FF_Child "Child's room" (FF_Child, gShuttersFF) { channel="nikobus:rollershutter-module:mypclink:r1:output-4" }
Rollershutter Shutter_FF_Gallery "Gallery" (FF_Gallery, gShuttersFF) { channel="nikobus:rollershutter-module:mypclink:r1:output-5" }
```
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class NikobusBindingConstants {
// Configuration parameters
public static final String CONFIG_REFRESH_INTERVAL = "refreshInterval";
public static final String CONFIG_IMPACTED_MODULES = "impactedModules";

public static final String CONFIG_ADDRESS = "address";
public static final String CONFIG_PORT_NAME = "port";

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.thing.Bridge;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
import org.openhab.binding.nikobus.internal.NikobusBindingConstants;

/**
* The {@link NikobusBaseThingHandler} class defines utility logic to be consumed by Nikobus thing(s).
Expand All @@ -25,11 +28,23 @@
*/
@NonNullByDefault
abstract class NikobusBaseThingHandler extends BaseThingHandler {
private @Nullable String address;

protected NikobusBaseThingHandler(Thing thing) {
super(thing);
}

@Override
public void initialize() {
address = (String) getConfig().get(NikobusBindingConstants.CONFIG_ADDRESS);
if (address == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, "Address must be set!");
return;
}

updateStatus(ThingStatus.UNKNOWN);
}

protected @Nullable NikobusPcLinkHandler getPcLink() {
Bridge bridge = getBridge();
if (bridge != null) {
Expand All @@ -39,6 +54,10 @@ protected NikobusBaseThingHandler(Thing thing) {
}

protected String getAddress() {
return thing.getUID().getId();
String address = this.address;
if (address == null) {
throw new IllegalStateException();
}
return address;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ protected NikobusModuleHandler(Thing thing) {
super(thing);
}

@Override
public void initialize() {
updateStatus(ThingStatus.UNKNOWN);
}

@Override
public void dispose() {
super.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,16 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.common.AbstractUID;
import org.eclipse.smarthome.core.library.types.OnOffType;
import org.eclipse.smarthome.core.thing.Bridge;
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.eclipse.smarthome.core.thing.binding.ThingHandler;
import org.eclipse.smarthome.core.types.Command;
import org.openhab.binding.nikobus.internal.protocol.NikobusCommand;
import org.openhab.binding.nikobus.internal.protocol.SwitchModuleGroup;
Expand All @@ -44,16 +48,16 @@
@NonNullByDefault
public class NikobusPushButtonHandler extends NikobusBaseThingHandler {
private static class ImpactedModule {
private final String address;
private final ThingUID thingUID;
private final SwitchModuleGroup group;

ImpactedModule(String address, SwitchModuleGroup group) {
this.address = address;
ImpactedModule(ThingUID thingUID, SwitchModuleGroup group) {
this.thingUID = thingUID;
this.group = group;
}

public String getAddress() {
return address;
public ThingUID getThingUID() {
return thingUID;
}

public SwitchModuleGroup getGroup() {
Expand All @@ -62,12 +66,41 @@ public SwitchModuleGroup getGroup() {

@Override
public String toString() {
return "'" + address + "'-" + group;
return "'" + thingUID + "'-" + group;
}
}

private static class ImpactedModuleUID extends AbstractUID {
ImpactedModuleUID(String uid) {
super(uid);
}

String getThingTypeId() {
return getSegment(0);
}

String getThingId() {
return getSegment(1);
}

SwitchModuleGroup getGroup() {
if (getSegment(2).equals("1")) {
return FIRST;
}
if (getSegment(2).equals("2")) {
return SECOND;
}
throw new IllegalArgumentException("Unexpected group found " + getSegment(2));
}

@Override
protected int getMinimalNumberOfSegments() {
return 3;
}

}

private static final String END_OF_TRANSMISSION = "\r#E1";
private static final String MODULE_CHANNEL_PATTERN = "^[A-Z0-9]{4}-[12]$";
private final Logger logger = LoggerFactory.getLogger(NikobusPushButtonHandler.class);
private final List<ImpactedModule> impactedModules = Collections.synchronizedList(new ArrayList<>());
private @Nullable Future<?> requestUpdateFuture;
Expand All @@ -78,27 +111,35 @@ public NikobusPushButtonHandler(Thing thing) {

@Override
public void initialize() {
super.initialize();

if (thing.getStatus() == ThingStatus.OFFLINE) {
return;
}

impactedModules.clear();

String[] impactedModulesString = getConfig().get(CONFIG_IMPACTED_MODULES).toString().split(",");
for (String impactedModuleString : impactedModulesString) {
impactedModuleString = impactedModuleString.trim();
if (!impactedModuleString.matches(MODULE_CHANNEL_PATTERN)) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"Unexpected impactedModules format found '" + impactedModuleString + "'");
return;
try {
ThingUID bridgeUID = thing.getBridgeUID();
if (bridgeUID == null) {
throw new IllegalArgumentException("Bridge does not exist!");
}

String[] moduleInfo = impactedModuleString.split("-");
SwitchModuleGroup group = moduleInfo[1].equals("1") ? FIRST : SECOND;

impactedModules.add(new ImpactedModule(moduleInfo[0], group));
String[] impactedModulesString = getConfig().get(CONFIG_IMPACTED_MODULES).toString().split(",");
for (String impactedModuleString : impactedModulesString) {
ImpactedModuleUID impactedModuleUID = new ImpactedModuleUID(impactedModuleString.trim());
ThingTypeUID thingTypeUID = new ThingTypeUID(bridgeUID.getBindingId(),
impactedModuleUID.getThingTypeId());
ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, impactedModuleUID.getThingId());
impactedModules.add(new ImpactedModule(thingUID, impactedModuleUID.getGroup()));
}
} catch (RuntimeException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
return;
}

logger.debug("Impacted modules for {} = {}", thing.getUID(), impactedModules);

updateStatus(ThingStatus.UNKNOWN);

NikobusPcLinkHandler pcLink = getPcLink();
if (pcLink != null) {
pcLink.addListener(getAddress(), this::commandReceived);
Expand Down Expand Up @@ -149,25 +190,28 @@ private void commandReceived() {

private void update() {
for (ImpactedModule module : impactedModules) {
NikobusSwitchModuleHandler switchModule = getSwitchModuleWithId(module.getAddress());
NikobusModuleHandler switchModule = getModuleWithId(module.getThingUID());
if (switchModule != null) {
switchModule.requestStatus(module.getGroup());
}
}
}

private @Nullable NikobusSwitchModuleHandler getSwitchModuleWithId(String id) {
private @Nullable NikobusModuleHandler getModuleWithId(ThingUID thingUID) {
Bridge bridge = getBridge();
if (bridge == null) {
return null;
}

for (Thing thing : bridge.getThings()) {
if (thing.getUID().getId().equals(id)) {
return (NikobusSwitchModuleHandler) thing.getHandler();
}
Thing thing = bridge.getThing(thingUID);
if (thing == null) {
return null;
}

ThingHandler thingHandler = thing.getHandler();
if (thingHandler instanceof NikobusModuleHandler) {
return (NikobusModuleHandler) thingHandler;
}
return null;
}

Expand Down
Loading

0 comments on commit 19218a0

Please sign in to comment.