Skip to content

Commit

Permalink
NHCI energy meters and NHCII access control
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
  • Loading branch information
mherwege committed Jun 15, 2022
1 parent f8bbb2b commit 01e674d
Show file tree
Hide file tree
Showing 45 changed files with 3,767 additions and 1,273 deletions.
259 changes: 105 additions & 154 deletions bundles/org.openhab.binding.nikohomecontrol/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,33 @@ public class NikoHomeControlBindingConstants {
public static final ThingTypeUID THING_TYPE_DIMMABLE_LIGHT = new ThingTypeUID(BINDING_ID, "dimmer");
public static final ThingTypeUID THING_TYPE_BLIND = new ThingTypeUID(BINDING_ID, "blind");
public static final ThingTypeUID THING_TYPE_THERMOSTAT = new ThingTypeUID(BINDING_ID, "thermostat");
public static final ThingTypeUID THING_TYPE_ENERGYMETER_LIVE = new ThingTypeUID(BINDING_ID, "energyMeterLive");
public static final ThingTypeUID THING_TYPE_ENERGYMETER = new ThingTypeUID(BINDING_ID, "energyMeter");
public static final ThingTypeUID THING_TYPE_GASMETER = new ThingTypeUID(BINDING_ID, "gasMeter");
public static final ThingTypeUID THING_TYPE_WATERMETER = new ThingTypeUID(BINDING_ID, "waterMeter");
public static final ThingTypeUID THING_TYPE_ACCESS = new ThingTypeUID(BINDING_ID, "access");
public static final ThingTypeUID THING_TYPE_ACCESS_RINGANDCOMEIN = new ThingTypeUID(BINDING_ID,
"accessRingAndComeIn");

// thing type sets
public static final Set<ThingTypeUID> BRIDGE_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(BRIDGEI_THING_TYPE, BRIDGEII_THING_TYPE).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> ACTION_THING_TYPES_UIDS = Collections.unmodifiableSet(
Stream.of(THING_TYPE_PUSHBUTTON, THING_TYPE_ON_OFF_LIGHT, THING_TYPE_DIMMABLE_LIGHT, THING_TYPE_BLIND)
.collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_PUSHBUTTON, THING_TYPE_ON_OFF_LIGHT, THING_TYPE_DIMMABLE_LIGHT,
THING_TYPE_BLIND, THING_TYPE_THERMOSTAT, THING_TYPE_ENERGYMETER).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> THERMOSTAT_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_THERMOSTAT).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> METER_THING_TYPES_UIDS = Collections.unmodifiableSet(
Stream.of(THING_TYPE_ENERGYMETER_LIVE, THING_TYPE_ENERGYMETER, THING_TYPE_GASMETER, THING_TYPE_WATERMETER)
.collect(Collectors.toSet()));
public static final Set<ThingTypeUID> ACCESS_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_ACCESS, THING_TYPE_ACCESS_RINGANDCOMEIN).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream
.concat(BRIDGE_THING_TYPES_UIDS.stream(),
Stream.concat(ACTION_THING_TYPES_UIDS.stream(),
Stream.concat(THERMOSTAT_THING_TYPES_UIDS.stream(),
Stream.concat(METER_THING_TYPES_UIDS.stream(), ACCESS_THING_TYPES_UIDS.stream()))))
.collect(Collectors.toSet());

// List of all Channel ids
public static final String CHANNEL_BUTTON = "button";
Expand All @@ -73,6 +89,19 @@ public class NikoHomeControlBindingConstants {
public static final String CHANNEL_HEATING_DEMAND = "heatingdemand";

public static final String CHANNEL_POWER = "power";
public static final String CHANNEL_ENERGY = "energy";
public static final String CHANNEL_GAS = "gas";
public static final String CHANNEL_WATER = "water";
public static final String CHANNEL_ENERGY_DAY = "energyday";
public static final String CHANNEL_GAS_DAY = "gasday";
public static final String CHANNEL_WATER_DAY = "waterday";
public static final String CHANNEL_ENERGY_LAST = "energylast";
public static final String CHANNEL_GAS_LAST = "gaslast";
public static final String CHANNEL_WATER_LAST = "waterlast";

public static final String CHANNEL_BELL_BUTTON = "bellbutton";
public static final String CHANNEL_RING_AND_COME_IN = "ringandcomein";
public static final String CHANNEL_LOCK = "lock";

public static final String CHANNEL_ALARM = "alarm";
public static final String CHANNEL_NOTICE = "notice";
Expand All @@ -87,11 +116,15 @@ public class NikoHomeControlBindingConstants {
// Thing config properties
public static final String CONFIG_ACTION_ID = "actionId";
public static final String CONFIG_STEP_VALUE = "step";
public static final String CONFIG_INVERT = "invert";

public static final String CONFIG_THERMOSTAT_ID = "thermostatId";
public static final String CONFIG_OVERRULETIME = "overruleTime";

public static final String CONFIG_ENERGYMETER_ID = "energyMeterId";
public static final String METER_ID = "meterId";
public static final String CONFIG_METER_REFRESH = "refresh";

public static final String CONFIG_ACCESS_ID = "accessId";

// Thing properties
public static final String PROPERTY_DEVICE_TYPE = "deviceType";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlAccessHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlActionHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler1;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler2;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlEnergyMeterHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlMeterHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlThermostatHandler;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.net.NetworkAddressService;
Expand Down Expand Up @@ -68,12 +69,14 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
} else {
return new NikoHomeControlBridgeHandler1((Bridge) thing, timeZoneProvider);
}
} else if (THING_TYPE_THERMOSTAT.equals(thing.getThingTypeUID())) {
return new NikoHomeControlThermostatHandler(thing);
} else if (THING_TYPE_ENERGYMETER.equals(thing.getThingTypeUID())) {
return new NikoHomeControlEnergyMeterHandler(thing);
} else if (ACTION_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
return new NikoHomeControlActionHandler(thing);
} else if (THERMOSTAT_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
return new NikoHomeControlThermostatHandler(thing);
} else if (METER_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
return new NikoHomeControlMeterHandler(thing);
} else if (ACCESS_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
return new NikoHomeControlAccessHandler(thing);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler2;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAccess;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAction;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcEnergyMeter;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcMeter;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcThermostat;
import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlCommunication;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
Expand Down Expand Up @@ -88,80 +90,121 @@ public void discoverDevices() {
}
logger.debug("getting devices on {}", bridgeHandler.getThing().getUID().getId());

discoverActionDevices(bridgeHandler, nhcComm);
discoverThermostatDevices(bridgeHandler, nhcComm);
discoverMeterDevices(bridgeHandler, nhcComm);
discoverAccessDevices(bridgeHandler, nhcComm);
}

private void discoverActionDevices(NikoHomeControlBridgeHandler bridgeHandler,
NikoHomeControlCommunication nhcComm) {
Map<String, NhcAction> actions = nhcComm.getActions();

actions.forEach((actionId, nhcAction) -> {
actions.forEach((deviceId, nhcAction) -> {
String thingName = nhcAction.getName();
String thingLocation = nhcAction.getLocation();

switch (nhcAction.getType()) {
case TRIGGER:
addActionDevice(new ThingUID(THING_TYPE_PUSHBUTTON, bridgeHandler.getThing().getUID(), actionId),
actionId, thingName, thingLocation);
addDevice(new ThingUID(THING_TYPE_PUSHBUTTON, bridgeHandler.getThing().getUID(), deviceId),
CONFIG_ACTION_ID, deviceId, thingName, thingLocation);
break;
case RELAY:
addActionDevice(new ThingUID(THING_TYPE_ON_OFF_LIGHT, bridgeHandler.getThing().getUID(), actionId),
actionId, thingName, thingLocation);
addDevice(new ThingUID(THING_TYPE_ON_OFF_LIGHT, bridgeHandler.getThing().getUID(), deviceId),
CONFIG_ACTION_ID, deviceId, thingName, thingLocation);
break;
case DIMMER:
addActionDevice(
new ThingUID(THING_TYPE_DIMMABLE_LIGHT, bridgeHandler.getThing().getUID(), actionId),
actionId, thingName, thingLocation);
addDevice(new ThingUID(THING_TYPE_DIMMABLE_LIGHT, bridgeHandler.getThing().getUID(), deviceId),
CONFIG_ACTION_ID, deviceId, thingName, thingLocation);
break;
case ROLLERSHUTTER:
addActionDevice(new ThingUID(THING_TYPE_BLIND, bridgeHandler.getThing().getUID(), actionId),
actionId, thingName, thingLocation);
addDevice(new ThingUID(THING_TYPE_BLIND, bridgeHandler.getThing().getUID(), deviceId),
CONFIG_ACTION_ID, deviceId, thingName, thingLocation);
break;
default:
logger.debug("unrecognized action type {} for {} {}", nhcAction.getType(), actionId, thingName);
logger.debug("unrecognized action type {} for {} {}", nhcAction.getType(), deviceId, thingName);
}
});
}

private void discoverThermostatDevices(NikoHomeControlBridgeHandler bridgeHandler,
NikoHomeControlCommunication nhcComm) {
Map<String, NhcThermostat> thermostats = nhcComm.getThermostats();

thermostats.forEach((thermostatId, nhcThermostat) -> {
thermostats.forEach((deviceId, nhcThermostat) -> {
String thingName = nhcThermostat.getName();
String thingLocation = nhcThermostat.getLocation();
addThermostatDevice(new ThingUID(THING_TYPE_THERMOSTAT, bridgeHandler.getThing().getUID(), thermostatId),
thermostatId, thingName, thingLocation);
addDevice(new ThingUID(THING_TYPE_THERMOSTAT, bridgeHandler.getThing().getUID(), deviceId),
CONFIG_THERMOSTAT_ID, deviceId, thingName, thingLocation);
});
}

private void discoverMeterDevices(NikoHomeControlBridgeHandler bridgeHandler,
NikoHomeControlCommunication nhcComm) {
if (bridgeHandler instanceof NikoHomeControlBridgeHandler2) {
// disable discovery of NHC II energy meters to avoid overload in Niko Home Control cloud, can be removed
// when Niko solves their issue with the controller sending all live power data to their cloud
return;
}

Map<String, NhcMeter> meters = nhcComm.getMeters();

Map<String, NhcEnergyMeter> energyMeters = nhcComm.getEnergyMeters();
meters.forEach((deviceId, nhcMeter) -> {
String thingName = nhcMeter.getName();
String thingLocation = nhcMeter.getLocation();

energyMeters.forEach((energyMeterId, nhcEnergyMeter) -> {
String thingName = nhcEnergyMeter.getName();
String thingLocation = nhcEnergyMeter.getLocation();
addEnergyMeterDevice(new ThingUID(THING_TYPE_ENERGYMETER, bridgeHandler.getThing().getUID(), energyMeterId),
energyMeterId, thingName, thingLocation);
switch (nhcMeter.getType()) {
case ENERGY_LIVE:
addDevice(new ThingUID(THING_TYPE_ENERGYMETER_LIVE, bridgeHandler.getThing().getUID(), deviceId),
METER_ID, deviceId, thingName, thingLocation);
break;
case ENERGY:
addDevice(new ThingUID(THING_TYPE_ENERGYMETER, bridgeHandler.getThing().getUID(), deviceId),
METER_ID, deviceId, thingName, thingLocation);
break;
case GAS:
addDevice(new ThingUID(THING_TYPE_GASMETER, bridgeHandler.getThing().getUID(), deviceId), deviceId,
METER_ID, thingName, thingLocation);
break;
case WATER:
addDevice(new ThingUID(THING_TYPE_WATERMETER, bridgeHandler.getThing().getUID(), deviceId),
METER_ID, deviceId, thingName, thingLocation);
break;
default:
logger.debug("unrecognized meter type {} for {} {}", nhcMeter.getType(), deviceId, thingName);
}
});
}

private void addActionDevice(ThingUID uid, String actionId, String thingName, @Nullable String thingLocation) {
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
.withLabel(thingName).withProperty(CONFIG_ACTION_ID, actionId)
.withRepresentationProperty(CONFIG_ACTION_ID);
if (thingLocation != null) {
discoveryResultBuilder.withProperty("Location", thingLocation);
}
thingDiscovered(discoveryResultBuilder.build());
}
private void discoverAccessDevices(NikoHomeControlBridgeHandler bridgeHandler,
NikoHomeControlCommunication nhcComm) {
Map<String, NhcAccess> accessDevices = nhcComm.getAccessDevices();

private void addThermostatDevice(ThingUID uid, String thermostatId, String thingName,
@Nullable String thingLocation) {
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
.withLabel(thingName).withProperty(CONFIG_THERMOSTAT_ID, thermostatId)
.withRepresentationProperty(CONFIG_THERMOSTAT_ID);
if (thingLocation != null) {
discoveryResultBuilder.withProperty("Location", thingLocation);
}
thingDiscovered(discoveryResultBuilder.build());
accessDevices.forEach((deviceId, nhcAccess) -> {
String thingName = nhcAccess.getName();
String thingLocation = nhcAccess.getLocation();

switch (nhcAccess.getType()) {
case BASE:
case BELLBUTTON:
addDevice(new ThingUID(THING_TYPE_ACCESS, bridgeHandler.getThing().getUID(), deviceId),
CONFIG_ACCESS_ID, deviceId, thingName, thingLocation);
break;
case RINGANDCOMEIN:
addDevice(
new ThingUID(THING_TYPE_ACCESS_RINGANDCOMEIN, bridgeHandler.getThing().getUID(), deviceId),
CONFIG_ACCESS_ID, deviceId, thingName, thingLocation);
break;
default:
logger.debug("unrecognized access type {} for {} {}", nhcAccess.getType(), deviceId, thingName);
}
});
}

private void addEnergyMeterDevice(ThingUID uid, String energyMeterId, String thingName,
private void addDevice(ThingUID uid, String deviceIdKey, String deviceId, String thingName,
@Nullable String thingLocation) {
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
.withLabel(thingName).withProperty(CONFIG_ENERGYMETER_ID, energyMeterId)
.withRepresentationProperty(CONFIG_ENERGYMETER_ID);
.withLabel(thingName).withProperty(deviceIdKey, deviceId).withRepresentationProperty(deviceIdKey);
if (thingLocation != null) {
discoveryResultBuilder.withProperty("Location", thingLocation);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* {@link NikoHomeControlEnergyMeterConfig} is the config class for Niko Home Control Thermostats.
* {@link NikoHomeControlAccessConfig} is the general config class for Niko Home Control Door Locks.
*
* @author Mark Herwege - Initial Contribution
*/
@NonNullByDefault
public class NikoHomeControlEnergyMeterConfig {
public String energyMeterId = "";
public class NikoHomeControlAccessConfig {
public String accessId = "";
}
Loading

0 comments on commit 01e674d

Please sign in to comment.