mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[nikohomecontrol] Discovery improvements (#12855)
* Add discovery representation properties * Recognized device types improvements * Move discovery to thingHandlerService * Discover multiple bridges in network * Made device property names constants Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
This commit is contained in:
parent
43e44ea39a
commit
651fa295e7
@ -90,4 +90,9 @@ public class NikoHomeControlBindingConstants {
|
|||||||
public static final String CONFIG_OVERRULETIME = "overruleTime";
|
public static final String CONFIG_OVERRULETIME = "overruleTime";
|
||||||
|
|
||||||
public static final String CONFIG_ENERGYMETER_ID = "energyMeterId";
|
public static final String CONFIG_ENERGYMETER_ID = "energyMeterId";
|
||||||
|
|
||||||
|
// Thing properties
|
||||||
|
public static final String PROPERTY_DEVICE_TYPE = "deviceType";
|
||||||
|
public static final String PROPERTY_DEVICE_TECHNOLOGY = "deviceTechnology";
|
||||||
|
public static final String PROPERTY_DEVICE_MODEL = "deviceModel";
|
||||||
}
|
}
|
||||||
|
@ -14,29 +14,20 @@ package org.openhab.binding.nikohomecontrol.internal;
|
|||||||
|
|
||||||
import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
|
import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.binding.nikohomecontrol.internal.discovery.NikoHomeControlDiscoveryService;
|
|
||||||
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlActionHandler;
|
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlActionHandler;
|
||||||
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler;
|
|
||||||
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler1;
|
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler1;
|
||||||
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler2;
|
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler2;
|
||||||
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlEnergyMeterHandler;
|
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlEnergyMeterHandler;
|
||||||
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlThermostatHandler;
|
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlThermostatHandler;
|
||||||
import org.openhab.core.config.discovery.DiscoveryService;
|
|
||||||
import org.openhab.core.net.NetworkAddressService;
|
import org.openhab.core.net.NetworkAddressService;
|
||||||
import org.openhab.core.thing.Bridge;
|
import org.openhab.core.thing.Bridge;
|
||||||
import org.openhab.core.thing.Thing;
|
import org.openhab.core.thing.Thing;
|
||||||
import org.openhab.core.thing.ThingTypeUID;
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
import org.openhab.core.thing.ThingUID;
|
|
||||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
import org.openhab.core.thing.binding.ThingHandler;
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
import org.osgi.framework.ServiceRegistration;
|
|
||||||
import org.osgi.service.component.annotations.Component;
|
import org.osgi.service.component.annotations.Component;
|
||||||
import org.osgi.service.component.annotations.Reference;
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
@ -47,14 +38,12 @@ import org.osgi.service.component.annotations.Reference;
|
|||||||
* @author Mark Herwege - Initial Contribution
|
* @author Mark Herwege - Initial Contribution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.nikohomecontrol")
|
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
|
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.nikohomecontrol")
|
||||||
public class NikoHomeControlHandlerFactory extends BaseThingHandlerFactory {
|
public class NikoHomeControlHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
|
||||||
private @NonNullByDefault({}) NetworkAddressService networkAddressService;
|
private @NonNullByDefault({}) NetworkAddressService networkAddressService;
|
||||||
|
|
||||||
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID) || BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID);
|
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID) || BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||||
@ -63,14 +52,11 @@ public class NikoHomeControlHandlerFactory extends BaseThingHandlerFactory {
|
|||||||
@Override
|
@Override
|
||||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||||
if (BRIDGE_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
|
if (BRIDGE_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
|
||||||
NikoHomeControlBridgeHandler handler;
|
|
||||||
if (BRIDGEII_THING_TYPE.equals(thing.getThingTypeUID())) {
|
if (BRIDGEII_THING_TYPE.equals(thing.getThingTypeUID())) {
|
||||||
handler = new NikoHomeControlBridgeHandler2((Bridge) thing, networkAddressService);
|
return new NikoHomeControlBridgeHandler2((Bridge) thing, networkAddressService);
|
||||||
} else {
|
} else {
|
||||||
handler = new NikoHomeControlBridgeHandler1((Bridge) thing);
|
return new NikoHomeControlBridgeHandler1((Bridge) thing);
|
||||||
}
|
}
|
||||||
registerNikoHomeControlDiscoveryService(handler);
|
|
||||||
return handler;
|
|
||||||
} else if (THING_TYPE_THERMOSTAT.equals(thing.getThingTypeUID())) {
|
} else if (THING_TYPE_THERMOSTAT.equals(thing.getThingTypeUID())) {
|
||||||
return new NikoHomeControlThermostatHandler(thing);
|
return new NikoHomeControlThermostatHandler(thing);
|
||||||
} else if (THING_TYPE_ENERGYMETER.equals(thing.getThingTypeUID())) {
|
} else if (THING_TYPE_ENERGYMETER.equals(thing.getThingTypeUID())) {
|
||||||
@ -82,29 +68,6 @@ public class NikoHomeControlHandlerFactory extends BaseThingHandlerFactory {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void registerNikoHomeControlDiscoveryService(NikoHomeControlBridgeHandler bridgeHandler) {
|
|
||||||
NikoHomeControlDiscoveryService nhcDiscoveryService = new NikoHomeControlDiscoveryService(bridgeHandler);
|
|
||||||
discoveryServiceRegs.put(bridgeHandler.getThing().getUID(), bundleContext
|
|
||||||
.registerService(DiscoveryService.class.getName(), nhcDiscoveryService, new Hashtable<>()));
|
|
||||||
nhcDiscoveryService.activate();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected synchronized void removeHandler(ThingHandler thingHandler) {
|
|
||||||
if (thingHandler instanceof NikoHomeControlBridgeHandler) {
|
|
||||||
ServiceRegistration<?> serviceReg = discoveryServiceRegs.remove(thingHandler.getThing().getUID());
|
|
||||||
if (serviceReg != null) {
|
|
||||||
// remove discovery service, if bridge handler is removed
|
|
||||||
NikoHomeControlDiscoveryService service = (NikoHomeControlDiscoveryService) bundleContext
|
|
||||||
.getService(serviceReg.getReference());
|
|
||||||
serviceReg.unregister();
|
|
||||||
if (service != null) {
|
|
||||||
service.deactivate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Reference
|
@Reference
|
||||||
protected void setNetworkAddressService(NetworkAddressService networkAddressService) {
|
protected void setNetworkAddressService(NetworkAddressService networkAddressService) {
|
||||||
this.networkAddressService = networkAddressService;
|
this.networkAddressService = networkAddressService;
|
||||||
|
@ -40,8 +40,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
*
|
*
|
||||||
* @author Mark Herwege - Initial Contribution
|
* @author Mark Herwege - Initial Contribution
|
||||||
*/
|
*/
|
||||||
@Component(service = DiscoveryService.class, configurationPid = "discovery.nikohomecontrol")
|
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
|
@Component(service = DiscoveryService.class, configurationPid = "discovery.nikohomecontrol")
|
||||||
public class NikoHomeControlBridgeDiscoveryService extends AbstractDiscoveryService {
|
public class NikoHomeControlBridgeDiscoveryService extends AbstractDiscoveryService {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlBridgeDiscoveryService.class);
|
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlBridgeDiscoveryService.class);
|
||||||
@ -50,11 +50,11 @@ public class NikoHomeControlBridgeDiscoveryService extends AbstractDiscoveryServ
|
|||||||
|
|
||||||
private @NonNullByDefault({}) NetworkAddressService networkAddressService;
|
private @NonNullByDefault({}) NetworkAddressService networkAddressService;
|
||||||
|
|
||||||
private static final int TIMEOUT = 5;
|
private static final int TIMOUT_S = 5;
|
||||||
private static final int REFRESH_INTERVAL = 60;
|
private static final int REFRESH_INTERVAL_S = 60;
|
||||||
|
|
||||||
public NikoHomeControlBridgeDiscoveryService() {
|
public NikoHomeControlBridgeDiscoveryService() {
|
||||||
super(NikoHomeControlBindingConstants.BRIDGE_THING_TYPES_UIDS, TIMEOUT);
|
super(NikoHomeControlBindingConstants.BRIDGE_THING_TYPES_UIDS, TIMOUT_S);
|
||||||
logger.debug("bridge discovery service started");
|
logger.debug("bridge discovery service started");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,13 +70,18 @@ public class NikoHomeControlBridgeDiscoveryService extends AbstractDiscoveryServ
|
|||||||
}
|
}
|
||||||
logger.debug("discovery broadcast on {}", broadcastAddr);
|
logger.debug("discovery broadcast on {}", broadcastAddr);
|
||||||
NikoHomeControlDiscover nhcDiscover = new NikoHomeControlDiscover(broadcastAddr);
|
NikoHomeControlDiscover nhcDiscover = new NikoHomeControlDiscover(broadcastAddr);
|
||||||
if (nhcDiscover.isNhcII()) {
|
for (String nhcController : nhcDiscover.getNhcBridgeIds()) {
|
||||||
addNhcIIBridge(nhcDiscover.getAddr(), nhcDiscover.getNhcBridgeId());
|
InetAddress addr = nhcDiscover.getAddr(nhcController);
|
||||||
} else {
|
if (addr != null) {
|
||||||
addNhcIBridge(nhcDiscover.getAddr(), nhcDiscover.getNhcBridgeId());
|
if (nhcDiscover.isNhcII(nhcController)) {
|
||||||
|
addNhcIIBridge(addr, nhcController);
|
||||||
|
} else {
|
||||||
|
addNhcIBridge(addr, nhcController);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.debug("no bridge found.");
|
logger.debug("bridge discovery IO exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +92,8 @@ public class NikoHomeControlBridgeDiscoveryService extends AbstractDiscoveryServ
|
|||||||
ThingUID uid = new ThingUID(BINDING_ID, "bridge", bridgeId);
|
ThingUID uid = new ThingUID(BINDING_ID, "bridge", bridgeId);
|
||||||
|
|
||||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(uid).withLabel(bridgeName)
|
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(uid).withLabel(bridgeName)
|
||||||
.withProperty(CONFIG_HOST_NAME, addr.getHostAddress()).build();
|
.withProperty(CONFIG_HOST_NAME, addr.getHostAddress()).withRepresentationProperty(CONFIG_HOST_NAME)
|
||||||
|
.build();
|
||||||
thingDiscovered(discoveryResult);
|
thingDiscovered(discoveryResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +104,8 @@ public class NikoHomeControlBridgeDiscoveryService extends AbstractDiscoveryServ
|
|||||||
ThingUID uid = new ThingUID(BINDING_ID, "bridge2", bridgeId);
|
ThingUID uid = new ThingUID(BINDING_ID, "bridge2", bridgeId);
|
||||||
|
|
||||||
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(uid).withLabel(bridgeName)
|
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(uid).withLabel(bridgeName)
|
||||||
.withProperty(CONFIG_HOST_NAME, addr.getHostAddress()).build();
|
.withProperty(CONFIG_HOST_NAME, addr.getHostAddress()).withRepresentationProperty(CONFIG_HOST_NAME)
|
||||||
|
.build();
|
||||||
thingDiscovered(discoveryResult);
|
thingDiscovered(discoveryResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,10 +122,10 @@ public class NikoHomeControlBridgeDiscoveryService extends AbstractDiscoveryServ
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void startBackgroundDiscovery() {
|
protected void startBackgroundDiscovery() {
|
||||||
logger.debug("Start background bridge discovery");
|
logger.debug("Start bridge background discovery");
|
||||||
ScheduledFuture<?> job = nhcDiscoveryJob;
|
ScheduledFuture<?> job = nhcDiscoveryJob;
|
||||||
if (job == null || job.isCancelled()) {
|
if (job == null || job.isCancelled()) {
|
||||||
nhcDiscoveryJob = scheduler.scheduleWithFixedDelay(this::discoverBridge, 0, REFRESH_INTERVAL,
|
nhcDiscoveryJob = scheduler.scheduleWithFixedDelay(this::discoverBridge, 0, REFRESH_INTERVAL_S,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,8 +14,10 @@ package org.openhab.binding.nikohomecontrol.internal.discovery;
|
|||||||
|
|
||||||
import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
|
import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.time.Instant;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
@ -27,6 +29,8 @@ import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlComm
|
|||||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||||
import org.openhab.core.thing.ThingUID;
|
import org.openhab.core.thing.ThingUID;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -37,43 +41,52 @@ import org.slf4j.LoggerFactory;
|
|||||||
* @author Mark Herwege - Initial Contribution
|
* @author Mark Herwege - Initial Contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public class NikoHomeControlDiscoveryService extends AbstractDiscoveryService {
|
public class NikoHomeControlDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlDiscoveryService.class);
|
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlDiscoveryService.class);
|
||||||
|
|
||||||
private static final int TIMEOUT = 5;
|
private volatile @Nullable ScheduledFuture<?> nhcDiscoveryJob;
|
||||||
|
|
||||||
private ThingUID bridgeUID;
|
private static final int TIMEOUT_S = 5;
|
||||||
private NikoHomeControlBridgeHandler handler;
|
private static final int INITIAL_DELAY_S = 5; // initial delay for polling to allow time for initial request to NHC
|
||||||
|
// controller to complete
|
||||||
|
private static final int REFRESH_INTERVAL_S = 60;
|
||||||
|
|
||||||
public NikoHomeControlDiscoveryService(NikoHomeControlBridgeHandler handler) {
|
private @Nullable ThingUID bridgeUID;
|
||||||
super(SUPPORTED_THING_TYPES_UIDS, TIMEOUT, false);
|
private @Nullable NikoHomeControlBridgeHandler handler;
|
||||||
logger.debug("discovery service {}", handler);
|
|
||||||
bridgeUID = handler.getThing().getUID();
|
public NikoHomeControlDiscoveryService() {
|
||||||
this.handler = handler;
|
super(SUPPORTED_THING_TYPES_UIDS, TIMEOUT_S, true);
|
||||||
|
logger.debug("device discovery service started");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void activate() {
|
public void activate() {
|
||||||
handler.setNhcDiscovery(this);
|
startBackgroundDiscovery();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deactivate() {
|
public void deactivate() {
|
||||||
removeOlderResults(new Date().getTime());
|
removeOlderResults(Instant.now().toEpochMilli());
|
||||||
handler.setNhcDiscovery(null);
|
super.deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discovers devices connected to a Niko Home Control controller
|
* Discovers devices connected to a Niko Home Control controller
|
||||||
*/
|
*/
|
||||||
public void discoverDevices() {
|
public void discoverDevices() {
|
||||||
NikoHomeControlCommunication nhcComm = handler.getCommunication();
|
NikoHomeControlBridgeHandler bridgeHandler = handler;
|
||||||
|
if (bridgeHandler == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NikoHomeControlCommunication nhcComm = bridgeHandler.getCommunication();
|
||||||
|
|
||||||
if ((nhcComm == null) || !nhcComm.communicationActive()) {
|
if ((nhcComm == null) || !nhcComm.communicationActive()) {
|
||||||
logger.warn("not connected");
|
logger.warn("not connected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.debug("getting devices on {}", handler.getThing().getUID().getId());
|
logger.debug("getting devices on {}", bridgeHandler.getThing().getUID().getId());
|
||||||
|
|
||||||
Map<String, NhcAction> actions = nhcComm.getActions();
|
Map<String, NhcAction> actions = nhcComm.getActions();
|
||||||
|
|
||||||
@ -83,20 +96,21 @@ public class NikoHomeControlDiscoveryService extends AbstractDiscoveryService {
|
|||||||
|
|
||||||
switch (nhcAction.getType()) {
|
switch (nhcAction.getType()) {
|
||||||
case TRIGGER:
|
case TRIGGER:
|
||||||
addActionDevice(new ThingUID(THING_TYPE_PUSHBUTTON, handler.getThing().getUID(), actionId),
|
addActionDevice(new ThingUID(THING_TYPE_PUSHBUTTON, bridgeHandler.getThing().getUID(), actionId),
|
||||||
actionId, thingName, thingLocation);
|
actionId, thingName, thingLocation);
|
||||||
break;
|
break;
|
||||||
case RELAY:
|
case RELAY:
|
||||||
addActionDevice(new ThingUID(THING_TYPE_ON_OFF_LIGHT, handler.getThing().getUID(), actionId),
|
addActionDevice(new ThingUID(THING_TYPE_ON_OFF_LIGHT, bridgeHandler.getThing().getUID(), actionId),
|
||||||
actionId, thingName, thingLocation);
|
actionId, thingName, thingLocation);
|
||||||
break;
|
break;
|
||||||
case DIMMER:
|
case DIMMER:
|
||||||
addActionDevice(new ThingUID(THING_TYPE_DIMMABLE_LIGHT, handler.getThing().getUID(), actionId),
|
addActionDevice(
|
||||||
|
new ThingUID(THING_TYPE_DIMMABLE_LIGHT, bridgeHandler.getThing().getUID(), actionId),
|
||||||
actionId, thingName, thingLocation);
|
actionId, thingName, thingLocation);
|
||||||
break;
|
break;
|
||||||
case ROLLERSHUTTER:
|
case ROLLERSHUTTER:
|
||||||
addActionDevice(new ThingUID(THING_TYPE_BLIND, handler.getThing().getUID(), actionId), actionId,
|
addActionDevice(new ThingUID(THING_TYPE_BLIND, bridgeHandler.getThing().getUID(), actionId),
|
||||||
thingName, thingLocation);
|
actionId, thingName, thingLocation);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.debug("unrecognized action type {} for {} {}", nhcAction.getType(), actionId, thingName);
|
logger.debug("unrecognized action type {} for {} {}", nhcAction.getType(), actionId, thingName);
|
||||||
@ -108,7 +122,7 @@ public class NikoHomeControlDiscoveryService extends AbstractDiscoveryService {
|
|||||||
thermostats.forEach((thermostatId, nhcThermostat) -> {
|
thermostats.forEach((thermostatId, nhcThermostat) -> {
|
||||||
String thingName = nhcThermostat.getName();
|
String thingName = nhcThermostat.getName();
|
||||||
String thingLocation = nhcThermostat.getLocation();
|
String thingLocation = nhcThermostat.getLocation();
|
||||||
addThermostatDevice(new ThingUID(THING_TYPE_THERMOSTAT, handler.getThing().getUID(), thermostatId),
|
addThermostatDevice(new ThingUID(THING_TYPE_THERMOSTAT, bridgeHandler.getThing().getUID(), thermostatId),
|
||||||
thermostatId, thingName, thingLocation);
|
thermostatId, thingName, thingLocation);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -116,14 +130,16 @@ public class NikoHomeControlDiscoveryService extends AbstractDiscoveryService {
|
|||||||
|
|
||||||
energyMeters.forEach((energyMeterId, nhcEnergyMeter) -> {
|
energyMeters.forEach((energyMeterId, nhcEnergyMeter) -> {
|
||||||
String thingName = nhcEnergyMeter.getName();
|
String thingName = nhcEnergyMeter.getName();
|
||||||
addEnergyMeterDevice(new ThingUID(THING_TYPE_ENERGYMETER, handler.getThing().getUID(), energyMeterId),
|
String thingLocation = nhcEnergyMeter.getLocation();
|
||||||
energyMeterId, thingName);
|
addEnergyMeterDevice(new ThingUID(THING_TYPE_ENERGYMETER, bridgeHandler.getThing().getUID(), energyMeterId),
|
||||||
|
energyMeterId, thingName, thingLocation);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addActionDevice(ThingUID uid, String actionId, String thingName, @Nullable String thingLocation) {
|
private void addActionDevice(ThingUID uid, String actionId, String thingName, @Nullable String thingLocation) {
|
||||||
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
|
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
|
||||||
.withLabel(thingName).withProperty(CONFIG_ACTION_ID, actionId);
|
.withLabel(thingName).withProperty(CONFIG_ACTION_ID, actionId)
|
||||||
|
.withRepresentationProperty(CONFIG_ACTION_ID);
|
||||||
if (thingLocation != null) {
|
if (thingLocation != null) {
|
||||||
discoveryResultBuilder.withProperty("Location", thingLocation);
|
discoveryResultBuilder.withProperty("Location", thingLocation);
|
||||||
}
|
}
|
||||||
@ -133,16 +149,22 @@ public class NikoHomeControlDiscoveryService extends AbstractDiscoveryService {
|
|||||||
private void addThermostatDevice(ThingUID uid, String thermostatId, String thingName,
|
private void addThermostatDevice(ThingUID uid, String thermostatId, String thingName,
|
||||||
@Nullable String thingLocation) {
|
@Nullable String thingLocation) {
|
||||||
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
|
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
|
||||||
.withLabel(thingName).withProperty(CONFIG_THERMOSTAT_ID, thermostatId);
|
.withLabel(thingName).withProperty(CONFIG_THERMOSTAT_ID, thermostatId)
|
||||||
|
.withRepresentationProperty(CONFIG_THERMOSTAT_ID);
|
||||||
if (thingLocation != null) {
|
if (thingLocation != null) {
|
||||||
discoveryResultBuilder.withProperty("Location", thingLocation);
|
discoveryResultBuilder.withProperty("Location", thingLocation);
|
||||||
}
|
}
|
||||||
thingDiscovered(discoveryResultBuilder.build());
|
thingDiscovered(discoveryResultBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addEnergyMeterDevice(ThingUID uid, String energyMeterId, String thingName) {
|
private void addEnergyMeterDevice(ThingUID uid, String energyMeterId, String thingName,
|
||||||
|
@Nullable String thingLocation) {
|
||||||
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
|
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
|
||||||
.withLabel(thingName).withProperty(CONFIG_ENERGYMETER_ID, energyMeterId);
|
.withLabel(thingName).withProperty(CONFIG_ENERGYMETER_ID, energyMeterId)
|
||||||
|
.withRepresentationProperty(CONFIG_ENERGYMETER_ID);
|
||||||
|
if (thingLocation != null) {
|
||||||
|
discoveryResultBuilder.withProperty("Location", thingLocation);
|
||||||
|
}
|
||||||
thingDiscovered(discoveryResultBuilder.build());
|
thingDiscovered(discoveryResultBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,4 +178,37 @@ public class NikoHomeControlDiscoveryService extends AbstractDiscoveryService {
|
|||||||
super.stopScan();
|
super.stopScan();
|
||||||
removeOlderResults(getTimestampOfLastScan());
|
removeOlderResults(getTimestampOfLastScan());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startBackgroundDiscovery() {
|
||||||
|
logger.debug("Start device background discovery");
|
||||||
|
ScheduledFuture<?> job = nhcDiscoveryJob;
|
||||||
|
if (job == null || job.isCancelled()) {
|
||||||
|
nhcDiscoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, INITIAL_DELAY_S,
|
||||||
|
REFRESH_INTERVAL_S, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void stopBackgroundDiscovery() {
|
||||||
|
logger.debug("Stop device background discovery");
|
||||||
|
ScheduledFuture<?> job = nhcDiscoveryJob;
|
||||||
|
if (job != null && !job.isCancelled()) {
|
||||||
|
job.cancel(true);
|
||||||
|
nhcDiscoveryJob = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setThingHandler(@Nullable ThingHandler handler) {
|
||||||
|
if (handler instanceof NikoHomeControlBridgeHandler) {
|
||||||
|
this.handler = (NikoHomeControlBridgeHandler) handler;
|
||||||
|
bridgeUID = handler.getThing().getUID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ThingHandler getThingHandler() {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +238,7 @@ public class NikoHomeControlActionHandler extends BaseThingHandler implements Nh
|
|||||||
|
|
||||||
nhcAction.setEventHandler(this);
|
nhcAction.setEventHandler(this);
|
||||||
|
|
||||||
updateProperties();
|
updateProperties(nhcAction);
|
||||||
|
|
||||||
String actionLocation = nhcAction.getLocation();
|
String actionLocation = nhcAction.getLocation();
|
||||||
if (thing.getLocation() == null) {
|
if (thing.getLocation() == null) {
|
||||||
@ -260,14 +260,9 @@ public class NikoHomeControlActionHandler extends BaseThingHandler implements Nh
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateProperties() {
|
private void updateProperties(NhcAction nhcAction) {
|
||||||
NhcAction nhcAction = this.nhcAction;
|
|
||||||
if (nhcAction == null) {
|
|
||||||
logger.debug("action with ID {} not initialized", actionId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
|
||||||
properties.put("type", String.valueOf(nhcAction.getType()));
|
properties.put("type", String.valueOf(nhcAction.getType()));
|
||||||
if (getThing().getThingTypeUID() == THING_TYPE_BLIND) {
|
if (getThing().getThingTypeUID() == THING_TYPE_BLIND) {
|
||||||
properties.put("timeToOpen", String.valueOf(nhcAction.getOpenTime()));
|
properties.put("timeToOpen", String.valueOf(nhcAction.getOpenTime()));
|
||||||
@ -276,8 +271,9 @@ public class NikoHomeControlActionHandler extends BaseThingHandler implements Nh
|
|||||||
|
|
||||||
if (nhcAction instanceof NhcAction2) {
|
if (nhcAction instanceof NhcAction2) {
|
||||||
NhcAction2 action = (NhcAction2) nhcAction;
|
NhcAction2 action = (NhcAction2) nhcAction;
|
||||||
properties.put("model", action.getModel());
|
properties.put(PROPERTY_DEVICE_TYPE, action.getDeviceType());
|
||||||
properties.put("technology", action.getTechnology());
|
properties.put(PROPERTY_DEVICE_TECHNOLOGY, action.getDeviceTechnology());
|
||||||
|
properties.put(PROPERTY_DEVICE_MODEL, action.getDeviceModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
thing.setProperties(properties);
|
thing.setProperties(properties);
|
||||||
|
@ -16,8 +16,10 @@ import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindin
|
|||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -32,6 +34,7 @@ import org.openhab.core.thing.ChannelUID;
|
|||||||
import org.openhab.core.thing.ThingStatus;
|
import org.openhab.core.thing.ThingStatus;
|
||||||
import org.openhab.core.thing.ThingStatusDetail;
|
import org.openhab.core.thing.ThingStatusDetail;
|
||||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||||
import org.openhab.core.types.Command;
|
import org.openhab.core.types.Command;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -39,8 +42,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
/**
|
/**
|
||||||
* {@link NikoHomeControlBridgeHandler} is an abstract class representing a handler to all different interfaces to the
|
* {@link NikoHomeControlBridgeHandler} is an abstract class representing a handler to all different interfaces to the
|
||||||
* Niko Home Control System. {@link NikoHomeControlBridgeHandler1} or {@link NikoHomeControlBridgeHandler2} should be
|
* Niko Home Control System. {@link NikoHomeControlBridgeHandler1} or {@link NikoHomeControlBridgeHandler2} should be
|
||||||
* used for the respective
|
* used for the respective version of Niko Home Control.
|
||||||
* version of Niko Home Control.
|
|
||||||
*
|
*
|
||||||
* @author Mark Herwege - Initial Contribution
|
* @author Mark Herwege - Initial Contribution
|
||||||
*/
|
*/
|
||||||
@ -49,14 +51,10 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
|
|||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlBridgeHandler.class);
|
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlBridgeHandler.class);
|
||||||
|
|
||||||
protected @NonNullByDefault({}) NikoHomeControlBridgeConfig config;
|
|
||||||
|
|
||||||
protected @Nullable NikoHomeControlCommunication nhcComm;
|
protected @Nullable NikoHomeControlCommunication nhcComm;
|
||||||
|
|
||||||
private volatile @Nullable ScheduledFuture<?> refreshTimer;
|
private volatile @Nullable ScheduledFuture<?> refreshTimer;
|
||||||
|
|
||||||
protected volatile @Nullable NikoHomeControlDiscoveryService nhcDiscovery;
|
|
||||||
|
|
||||||
public NikoHomeControlBridgeHandler(Bridge nikoHomeControlBridge) {
|
public NikoHomeControlBridgeHandler(Bridge nikoHomeControlBridge) {
|
||||||
super(nikoHomeControlBridge);
|
super(nikoHomeControlBridge);
|
||||||
}
|
}
|
||||||
@ -90,22 +88,15 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
|
|||||||
|
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
|
||||||
int refreshInterval = config.refresh;
|
int refreshInterval = getConfig().as(NikoHomeControlBridgeConfig.class).refresh;
|
||||||
setupRefreshTimer(refreshInterval);
|
setupRefreshTimer(refreshInterval);
|
||||||
|
|
||||||
NikoHomeControlDiscoveryService discovery = nhcDiscovery;
|
|
||||||
if (discovery != null) {
|
|
||||||
discovery.discoverDevices();
|
|
||||||
} else {
|
|
||||||
logger.debug("cannot discover devices, discovery service not started");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule future communication refresh.
|
* Schedule future communication refresh.
|
||||||
*
|
*
|
||||||
* @param interval_config Time before refresh in minutes.
|
* @param refreshInterval Time before refresh in minutes.
|
||||||
*/
|
*/
|
||||||
private void setupRefreshTimer(int refreshInterval) {
|
private void setupRefreshTimer(int refreshInterval) {
|
||||||
ScheduledFuture<?> timer = refreshTimer;
|
ScheduledFuture<?> timer = refreshTimer;
|
||||||
@ -163,7 +154,7 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
|
|||||||
public void controllerOnline() {
|
public void controllerOnline() {
|
||||||
bridgeOnline();
|
bridgeOnline();
|
||||||
|
|
||||||
int refreshInterval = config.refresh;
|
int refreshInterval = getConfig().as(NikoHomeControlBridgeConfig.class).refresh;
|
||||||
if (refreshTimer == null) {
|
if (refreshTimer == null) {
|
||||||
setupRefreshTimer(refreshInterval);
|
setupRefreshTimer(refreshInterval);
|
||||||
}
|
}
|
||||||
@ -199,13 +190,11 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
|
|||||||
}
|
}
|
||||||
|
|
||||||
Configuration configuration = editConfiguration();
|
Configuration configuration = editConfiguration();
|
||||||
for (Entry<String, Object> configurationParmeter : configurationParameters.entrySet()) {
|
for (Entry<String, Object> configurationParameter : configurationParameters.entrySet()) {
|
||||||
configuration.put(configurationParmeter.getKey(), configurationParmeter.getValue());
|
configuration.put(configurationParameter.getKey(), configurationParameter.getValue());
|
||||||
}
|
}
|
||||||
updateConfiguration(configuration);
|
updateConfiguration(configuration);
|
||||||
|
|
||||||
setConfig();
|
|
||||||
|
|
||||||
scheduler.submit(() -> {
|
scheduler.submit(() -> {
|
||||||
comm.restartCommunication();
|
comm.restartCommunication();
|
||||||
if (!comm.communicationActive()) {
|
if (!comm.communicationActive()) {
|
||||||
@ -217,20 +206,11 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
|
|||||||
|
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
|
||||||
int refreshInterval = config.refresh;
|
int refreshInterval = getConfig().as(NikoHomeControlBridgeConfig.class).refresh;
|
||||||
setupRefreshTimer(refreshInterval);
|
setupRefreshTimer(refreshInterval);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set discovery service handler to be able to start discovery after bridge initialization.
|
|
||||||
*
|
|
||||||
* @param nhcDiscovery
|
|
||||||
*/
|
|
||||||
public void setNhcDiscovery(@Nullable NikoHomeControlDiscoveryService nhcDiscovery) {
|
|
||||||
this.nhcDiscovery = nhcDiscovery;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void alarmEvent(String alarmText) {
|
public void alarmEvent(String alarmText) {
|
||||||
logger.debug("triggering alarm channel with {}", alarmText);
|
logger.debug("triggering alarm channel with {}", alarmText);
|
||||||
@ -262,6 +242,7 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
|
|||||||
@Override
|
@Override
|
||||||
public @Nullable InetAddress getAddr() {
|
public @Nullable InetAddress getAddr() {
|
||||||
InetAddress addr = null;
|
InetAddress addr = null;
|
||||||
|
NikoHomeControlBridgeConfig config = getConfig().as(NikoHomeControlBridgeConfig.class);
|
||||||
try {
|
try {
|
||||||
addr = InetAddress.getByName(config.addr);
|
addr = InetAddress.getByName(config.addr);
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
@ -272,10 +253,11 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPort() {
|
public int getPort() {
|
||||||
return config.port;
|
return getConfig().as(NikoHomeControlBridgeConfig.class).port;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected synchronized void setConfig() {
|
@Override
|
||||||
config = getConfig().as(NikoHomeControlBridgeConfig.class);
|
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||||
|
return Set.of(NikoHomeControlDiscoveryService.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,6 @@ public class NikoHomeControlBridgeHandler1 extends NikoHomeControlBridgeHandler
|
|||||||
public void initialize() {
|
public void initialize() {
|
||||||
logger.debug("initializing bridge handler");
|
logger.debug("initializing bridge handler");
|
||||||
|
|
||||||
setConfig();
|
|
||||||
InetAddress addr = getAddr();
|
InetAddress addr = getAddr();
|
||||||
int port = getPort();
|
int port = getPort();
|
||||||
|
|
||||||
|
@ -59,8 +59,6 @@ public class NikoHomeControlBridgeHandler2 extends NikoHomeControlBridgeHandler
|
|||||||
public void initialize() {
|
public void initialize() {
|
||||||
logger.debug("initializing NHC II bridge handler");
|
logger.debug("initializing NHC II bridge handler");
|
||||||
|
|
||||||
setConfig();
|
|
||||||
|
|
||||||
Date expiryDate = getTokenExpiryDate();
|
Date expiryDate = getTokenExpiryDate();
|
||||||
if (expiryDate == null) {
|
if (expiryDate == null) {
|
||||||
if (getToken().isEmpty()) {
|
if (getToken().isEmpty()) {
|
||||||
@ -161,12 +159,12 @@ public class NikoHomeControlBridgeHandler2 extends NikoHomeControlBridgeHandler
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getProfile() {
|
public String getProfile() {
|
||||||
return ((NikoHomeControlBridgeConfig2) config).profile;
|
return getConfig().as(NikoHomeControlBridgeConfig2.class).profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getToken() {
|
public String getToken() {
|
||||||
String token = ((NikoHomeControlBridgeConfig2) config).password;
|
String token = getConfig().as(NikoHomeControlBridgeConfig2.class).password;
|
||||||
if (token.isEmpty()) {
|
if (token.isEmpty()) {
|
||||||
logger.debug("no JWT token set.");
|
logger.debug("no JWT token set.");
|
||||||
}
|
}
|
||||||
@ -227,9 +225,4 @@ public class NikoHomeControlBridgeHandler2 extends NikoHomeControlBridgeHandler
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected synchronized void setConfig() {
|
|
||||||
config = getConfig().as(NikoHomeControlBridgeConfig2.class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.nikohomecontrol.internal.handler;
|
package org.openhab.binding.nikohomecontrol.internal.handler;
|
||||||
|
|
||||||
import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.CHANNEL_POWER;
|
import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
|
||||||
import static org.openhab.core.types.RefreshType.REFRESH;
|
import static org.openhab.core.types.RefreshType.REFRESH;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -102,7 +102,12 @@ public class NikoHomeControlEnergyMeterHandler extends BaseThingHandler implemen
|
|||||||
|
|
||||||
nhcEnergyMeter.setEventHandler(this);
|
nhcEnergyMeter.setEventHandler(this);
|
||||||
|
|
||||||
updateProperties();
|
updateProperties(nhcEnergyMeter);
|
||||||
|
|
||||||
|
String location = nhcEnergyMeter.getLocation();
|
||||||
|
if (thing.getLocation() == null) {
|
||||||
|
thing.setLocation(location);
|
||||||
|
}
|
||||||
|
|
||||||
// Subscribing to power readings starts an intensive data flow, therefore only do it when there is an item
|
// Subscribing to power readings starts an intensive data flow, therefore only do it when there is an item
|
||||||
// linked to the channel
|
// linked to the channel
|
||||||
@ -132,13 +137,14 @@ public class NikoHomeControlEnergyMeterHandler extends BaseThingHandler implemen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateProperties() {
|
private void updateProperties(NhcEnergyMeter nhcEnergyMeter) {
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
|
||||||
if (nhcEnergyMeter instanceof NhcEnergyMeter2) {
|
if (nhcEnergyMeter instanceof NhcEnergyMeter2) {
|
||||||
NhcEnergyMeter2 energyMeter = (NhcEnergyMeter2) nhcEnergyMeter;
|
NhcEnergyMeter2 energyMeter = (NhcEnergyMeter2) nhcEnergyMeter;
|
||||||
properties.put("model", energyMeter.getModel());
|
properties.put(PROPERTY_DEVICE_TYPE, energyMeter.getDeviceType());
|
||||||
properties.put("technology", energyMeter.getTechnology());
|
properties.put(PROPERTY_DEVICE_TECHNOLOGY, energyMeter.getDeviceTechnology());
|
||||||
|
properties.put(PROPERTY_DEVICE_MODEL, energyMeter.getDeviceModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
thing.setProperties(properties);
|
thing.setProperties(properties);
|
||||||
|
@ -181,7 +181,7 @@ public class NikoHomeControlThermostatHandler extends BaseThingHandler implement
|
|||||||
|
|
||||||
nhcThermostat.setEventHandler(this);
|
nhcThermostat.setEventHandler(this);
|
||||||
|
|
||||||
updateProperties();
|
updateProperties(nhcThermostat);
|
||||||
|
|
||||||
String thermostatLocation = nhcThermostat.getLocation();
|
String thermostatLocation = nhcThermostat.getLocation();
|
||||||
if (thing.getLocation() == null) {
|
if (thing.getLocation() == null) {
|
||||||
@ -204,13 +204,14 @@ public class NikoHomeControlThermostatHandler extends BaseThingHandler implement
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateProperties() {
|
private void updateProperties(NhcThermostat nhcThermostat) {
|
||||||
Map<String, String> properties = new HashMap<>();
|
Map<String, String> properties = new HashMap<>();
|
||||||
|
|
||||||
if (nhcThermostat instanceof NhcThermostat2) {
|
if (nhcThermostat instanceof NhcThermostat2) {
|
||||||
NhcThermostat2 thermostat = (NhcThermostat2) nhcThermostat;
|
NhcThermostat2 thermostat = (NhcThermostat2) nhcThermostat;
|
||||||
properties.put("model", thermostat.getModel());
|
properties.put(PROPERTY_DEVICE_TYPE, thermostat.getDeviceType());
|
||||||
properties.put("technology", thermostat.getTechnology());
|
properties.put(PROPERTY_DEVICE_TECHNOLOGY, thermostat.getDeviceTechnology());
|
||||||
|
properties.put(PROPERTY_DEVICE_MODEL, thermostat.getDeviceModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
thing.setProperties(properties);
|
thing.setProperties(properties);
|
||||||
|
@ -66,9 +66,9 @@ public abstract class NhcAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the id of the action.
|
* Get id of action.
|
||||||
*
|
*
|
||||||
* @return the id
|
* @return id
|
||||||
*/
|
*/
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
@ -83,6 +83,15 @@ public abstract class NhcAction {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set name of action.
|
||||||
|
*
|
||||||
|
* @param name action name
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get type of action identified.
|
* Get type of action identified.
|
||||||
* <p>
|
* <p>
|
||||||
@ -103,6 +112,15 @@ public abstract class NhcAction {
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set location name of action.
|
||||||
|
*
|
||||||
|
* @param location action location name
|
||||||
|
*/
|
||||||
|
public void setLocation(@Nullable String location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get state of action.
|
* Get state of action.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -36,14 +36,16 @@ public abstract class NhcEnergyMeter {
|
|||||||
|
|
||||||
protected String id;
|
protected String id;
|
||||||
protected String name;
|
protected String name;
|
||||||
|
protected @Nullable String location;
|
||||||
// This can be null as long as we do not receive power readings
|
// This can be null as long as we do not receive power readings
|
||||||
protected volatile @Nullable Integer power = null;
|
protected volatile @Nullable Integer power = null;
|
||||||
|
|
||||||
private @Nullable NhcEnergyMeterEvent eventHandler;
|
private @Nullable NhcEnergyMeterEvent eventHandler;
|
||||||
|
|
||||||
protected NhcEnergyMeter(String id, String name, NikoHomeControlCommunication nhcComm) {
|
protected NhcEnergyMeter(String id, String name, @Nullable String location, NikoHomeControlCommunication nhcComm) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.location = location;
|
||||||
this.nhcComm = nhcComm;
|
this.nhcComm = nhcComm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,23 +86,50 @@ public abstract class NhcEnergyMeter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the id of the energyMeters meter.
|
* Get id of meter.
|
||||||
*
|
*
|
||||||
* @return the id
|
* @return id
|
||||||
*/
|
*/
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get name of the energyMeters meter.
|
* Get name of meter.
|
||||||
*
|
*
|
||||||
* @return energyMeters meter name
|
* @return energyMeter name
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set name of meter.
|
||||||
|
*
|
||||||
|
* @param name meter name
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get location name of meter.
|
||||||
|
*
|
||||||
|
* @return location energyMeter location
|
||||||
|
*/
|
||||||
|
public @Nullable String getLocation() {
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set location name of meter.
|
||||||
|
*
|
||||||
|
* @param location meter location name
|
||||||
|
*/
|
||||||
|
public void setLocation(@Nullable String location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the power in W (positive for consumption, negative for production), return null if no reading received
|
* @return the power in W (positive for consumption, negative for production), return null if no reading received
|
||||||
* yet
|
* yet
|
||||||
|
@ -142,9 +142,9 @@ public abstract class NhcThermostat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the id of the thermostat.
|
* Get id of the thermostat.
|
||||||
*
|
*
|
||||||
* @return the id
|
* @return id
|
||||||
*/
|
*/
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
@ -160,7 +160,16 @@ public abstract class NhcThermostat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get location name of action.
|
* Set name of thermostat.
|
||||||
|
*
|
||||||
|
* @param name thermostat name
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get location name of thermostat.
|
||||||
*
|
*
|
||||||
* @return location name
|
* @return location name
|
||||||
*/
|
*/
|
||||||
@ -168,6 +177,15 @@ public abstract class NhcThermostat {
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set location name of thermostat.
|
||||||
|
*
|
||||||
|
* @param location thermostat location name
|
||||||
|
*/
|
||||||
|
public void setLocation(@Nullable String location) {
|
||||||
|
this.location = location;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get measured temperature.
|
* Get measured temperature.
|
||||||
*
|
*
|
||||||
|
@ -16,9 +16,15 @@ import java.io.IOException;
|
|||||||
import java.net.DatagramPacket;
|
import java.net.DatagramPacket;
|
||||||
import java.net.DatagramSocket;
|
import java.net.DatagramSocket;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.util.HexUtils;
|
import org.openhab.core.util.HexUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -43,13 +49,13 @@ public final class NikoHomeControlDiscover {
|
|||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlDiscover.class);
|
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlDiscover.class);
|
||||||
|
|
||||||
private InetAddress addr;
|
private List<String> nhcBridgeIds = new ArrayList<>();
|
||||||
private String nhcBridgeId = "";
|
private Map<String, InetAddress> addr = new HashMap<>();
|
||||||
private boolean isNhcII;
|
private Map<String, Boolean> isNhcII = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Discover a Niko Home Control IP interface by broadcasting UDP packet 0x44 to port 10000. The IP interface will
|
* Discover the list of Niko Home Control IP interfaces by broadcasting UDP packet 0x44 to port 10000. The IP
|
||||||
* reply. The address of the IP interface is than derived from that response.
|
* interface will reply. The address of the IP interface is than derived from that response.
|
||||||
*
|
*
|
||||||
* @param broadcast Broadcast address of the network
|
* @param broadcast Broadcast address of the network
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
@ -68,33 +74,37 @@ public final class NikoHomeControlDiscover {
|
|||||||
datagramSocket.setBroadcast(true);
|
datagramSocket.setBroadcast(true);
|
||||||
datagramSocket.setSoTimeout(500);
|
datagramSocket.setSoTimeout(500);
|
||||||
datagramSocket.send(discoveryPacket);
|
datagramSocket.send(discoveryPacket);
|
||||||
while (true) {
|
try {
|
||||||
datagramSocket.receive(packet);
|
while (true) {
|
||||||
logger.trace("bridge discovery response {}",
|
datagramSocket.receive(packet);
|
||||||
HexUtils.bytesToHex(Arrays.copyOf(packet.getData(), packet.getLength())));
|
logger.trace("bridge discovery response {}",
|
||||||
if (isNhc(packet)) {
|
HexUtils.bytesToHex(Arrays.copyOf(packet.getData(), packet.getLength())));
|
||||||
break;
|
if (isNhcController(packet)) {
|
||||||
|
String bridgeId = setNhcBridgeId(packet);
|
||||||
|
setIsNhcII(bridgeId, packet);
|
||||||
|
setAddr(bridgeId, packet);
|
||||||
|
logger.debug("IP address is {}, unique ID is {}", addr, bridgeId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} catch (SocketTimeoutException e) {
|
||||||
|
// all received, continue
|
||||||
}
|
}
|
||||||
addr = packet.getAddress();
|
|
||||||
setNhcBridgeId(packet);
|
|
||||||
setIsNhcII(packet);
|
|
||||||
logger.debug("IP address is {}, unique ID is {}", addr, nhcBridgeId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the addr
|
* @return the discovered nhcBridgeIds
|
||||||
*/
|
*/
|
||||||
public InetAddress getAddr() {
|
public List<String> getNhcBridgeIds() {
|
||||||
return addr;
|
return nhcBridgeIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the nhcBridgeId
|
* @param bridgeId discovered bridgeId
|
||||||
|
* @return the addr, null if not in the list of discovered bridgeId's
|
||||||
*/
|
*/
|
||||||
public String getNhcBridgeId() {
|
public @Nullable InetAddress getAddr(String bridgeId) {
|
||||||
return nhcBridgeId;
|
return addr.get(bridgeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,9 +113,15 @@ public final class NikoHomeControlDiscover {
|
|||||||
* @param packet
|
* @param packet
|
||||||
* @return true if packet is from a Niko Home Control controller
|
* @return true if packet is from a Niko Home Control controller
|
||||||
*/
|
*/
|
||||||
private boolean isNhc(DatagramPacket packet) {
|
private boolean isNhcController(DatagramPacket packet) {
|
||||||
byte[] packetData = packet.getData();
|
byte[] packetData = packet.getData();
|
||||||
return ((packet.getLength() > 2) && (packetData[0] == 0x44));
|
boolean isNhc = (packet.getLength() > 2) && (packetData[0] == 0x44);
|
||||||
|
// filter response from Gen1 touchscreens
|
||||||
|
boolean isController = isNhc && (packetData[1] == 0x3b) || (packetData[1] == 0x0c) || (packetData[1] == 0x0e);
|
||||||
|
if (!isController) {
|
||||||
|
logger.trace("not a NHC controller");
|
||||||
|
}
|
||||||
|
return isController;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,7 +129,7 @@ public final class NikoHomeControlDiscover {
|
|||||||
*
|
*
|
||||||
* @param packet
|
* @param packet
|
||||||
*/
|
*/
|
||||||
private void setNhcBridgeId(DatagramPacket packet) {
|
private String setNhcBridgeId(DatagramPacket packet) {
|
||||||
byte[] packetData = packet.getData();
|
byte[] packetData = packet.getData();
|
||||||
int packetLength = packet.getLength();
|
int packetLength = packet.getLength();
|
||||||
packetLength = packetLength > 6 ? 6 : packetLength;
|
packetLength = packetLength > 6 ? 6 : packetLength;
|
||||||
@ -121,31 +137,45 @@ public final class NikoHomeControlDiscover {
|
|||||||
for (int i = 0; i < packetLength; i++) {
|
for (int i = 0; i < packetLength; i++) {
|
||||||
sb.append(String.format("%02x", packetData[i]));
|
sb.append(String.format("%02x", packetData[i]));
|
||||||
}
|
}
|
||||||
nhcBridgeId = sb.toString();
|
String bridgeId = sb.toString();
|
||||||
|
nhcBridgeIds.add(bridgeId);
|
||||||
|
return bridgeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this is a NHC II Connected Controller
|
* Checks if this is a NHC II Connected Controller
|
||||||
*
|
*
|
||||||
|
* @param bridgeId
|
||||||
* @param packet
|
* @param packet
|
||||||
*/
|
*/
|
||||||
private void setIsNhcII(DatagramPacket packet) {
|
private void setIsNhcII(String bridgeId, DatagramPacket packet) {
|
||||||
byte[] packetData = packet.getData();
|
byte[] packetData = packet.getData();
|
||||||
int packetLength = packet.getLength();
|
int packetLength = packet.getLength();
|
||||||
// The 16th byte in the packet is 2 for a NHC II Connected Controller
|
// The 16th byte in the packet is 2 for a NHC II Connected Controller
|
||||||
if ((packetLength >= 16) && (packetData[15] >= 2)) {
|
if ((packetLength >= 16) && (packetData[15] >= 2)) {
|
||||||
isNhcII = true;
|
isNhcII.put(bridgeId, true);
|
||||||
} else {
|
} else {
|
||||||
isNhcII = false;
|
isNhcII.put(bridgeId, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the IP address retrieved from the packet response
|
||||||
|
*
|
||||||
|
* @param bridgeId
|
||||||
|
* @param packet
|
||||||
|
*/
|
||||||
|
private void setAddr(String bridgeId, DatagramPacket packet) {
|
||||||
|
addr.put(bridgeId, packet.getAddress());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if the installation is a Niko Home Control II installation
|
* Test if the installation is a Niko Home Control II installation
|
||||||
*
|
*
|
||||||
|
* @param bridgeId
|
||||||
* @return true if this is a Niko Home Control II installation
|
* @return true if this is a Niko Home Control II installation
|
||||||
*/
|
*/
|
||||||
public boolean isNhcII() {
|
public boolean isNhcII(String bridgeId) {
|
||||||
return isNhcII;
|
return isNhcII.getOrDefault(bridgeId, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,38 +364,38 @@ public class NikoHomeControlCommunication1 extends NikoHomeControlCommunication
|
|||||||
String value3 = action.get("value3");
|
String value3 = action.get("value3");
|
||||||
int openTime = ((value3 == null) || value3.isEmpty() ? 0 : Integer.parseInt(value3));
|
int openTime = ((value3 == null) || value3.isEmpty() ? 0 : Integer.parseInt(value3));
|
||||||
|
|
||||||
|
String name = action.get("name");
|
||||||
|
if (name == null) {
|
||||||
|
logger.debug("name not found in action {}", action);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String type = Optional.ofNullable(action.get("type")).orElse("");
|
||||||
|
ActionType actionType = ActionType.GENERIC;
|
||||||
|
switch (type) {
|
||||||
|
case "0":
|
||||||
|
actionType = ActionType.TRIGGER;
|
||||||
|
break;
|
||||||
|
case "1":
|
||||||
|
actionType = ActionType.RELAY;
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
actionType = ActionType.DIMMER;
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
case "5":
|
||||||
|
actionType = ActionType.ROLLERSHUTTER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.debug("unknown action type {} for action {}", type, id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String locationId = action.get("location");
|
||||||
|
String location = "";
|
||||||
|
if (locationId != null && !locationId.isEmpty()) {
|
||||||
|
location = locations.getOrDefault(locationId, new NhcLocation1("")).getName();
|
||||||
|
}
|
||||||
if (!actions.containsKey(id)) {
|
if (!actions.containsKey(id)) {
|
||||||
// Initial instantiation of NhcAction class for action object
|
// Initial instantiation of NhcAction class for action object
|
||||||
String name = action.get("name");
|
|
||||||
if (name == null) {
|
|
||||||
logger.debug("name not found in action {}", action);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String type = Optional.ofNullable(action.get("type")).orElse("");
|
|
||||||
ActionType actionType = ActionType.GENERIC;
|
|
||||||
switch (type) {
|
|
||||||
case "0":
|
|
||||||
actionType = ActionType.TRIGGER;
|
|
||||||
break;
|
|
||||||
case "1":
|
|
||||||
actionType = ActionType.RELAY;
|
|
||||||
break;
|
|
||||||
case "2":
|
|
||||||
actionType = ActionType.DIMMER;
|
|
||||||
break;
|
|
||||||
case "4":
|
|
||||||
case "5":
|
|
||||||
actionType = ActionType.ROLLERSHUTTER;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
logger.debug("unknown action type {} for action {}", type, id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String locationId = action.get("location");
|
|
||||||
String location = "";
|
|
||||||
if (locationId != null && !locationId.isEmpty()) {
|
|
||||||
location = locations.getOrDefault(locationId, new NhcLocation1("")).getName();
|
|
||||||
}
|
|
||||||
NhcAction nhcAction = new NhcAction1(id, name, actionType, location, this, scheduler);
|
NhcAction nhcAction = new NhcAction1(id, name, actionType, location, this, scheduler);
|
||||||
if (actionType == ActionType.ROLLERSHUTTER) {
|
if (actionType == ActionType.ROLLERSHUTTER) {
|
||||||
nhcAction.setShutterTimes(openTime, closeTime);
|
nhcAction.setShutterTimes(openTime, closeTime);
|
||||||
@ -403,11 +403,13 @@ public class NikoHomeControlCommunication1 extends NikoHomeControlCommunication
|
|||||||
nhcAction.setState(state);
|
nhcAction.setState(state);
|
||||||
actions.put(id, nhcAction);
|
actions.put(id, nhcAction);
|
||||||
} else {
|
} else {
|
||||||
// Action object already exists, so only update state.
|
// Action object already exists, so only update state, name and location.
|
||||||
// If we would re-instantiate action, we would lose pointer back from action to thing handler that was
|
// If we would re-instantiate action, we would lose pointer back from action to thing handler that was
|
||||||
// set in thing handler initialize().
|
// set in thing handler initialize().
|
||||||
NhcAction nhcAction = actions.get(id);
|
NhcAction nhcAction = actions.get(id);
|
||||||
if (nhcAction != null) {
|
if (nhcAction != null) {
|
||||||
|
nhcAction.setName(name);
|
||||||
|
nhcAction.setLocation(location);
|
||||||
nhcAction.setState(state);
|
nhcAction.setState(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,23 +454,25 @@ public class NikoHomeControlCommunication1 extends NikoHomeControlCommunication
|
|||||||
// measured
|
// measured
|
||||||
int demand = (mode != 3) ? (setpoint > measured ? 1 : (setpoint < measured ? -1 : 0)) : 0;
|
int demand = (mode != 3) ? (setpoint > measured ? 1 : (setpoint < measured ? -1 : 0)) : 0;
|
||||||
|
|
||||||
|
String name = thermostat.get("name");
|
||||||
|
String locationId = thermostat.get("location");
|
||||||
|
NhcLocation1 nhcLocation = null;
|
||||||
|
if (!((locationId == null) || locationId.isEmpty())) {
|
||||||
|
nhcLocation = locations.get(locationId);
|
||||||
|
}
|
||||||
|
String location = (nhcLocation != null) ? nhcLocation.getName() : null;
|
||||||
NhcThermostat t = thermostats.computeIfAbsent(id, i -> {
|
NhcThermostat t = thermostats.computeIfAbsent(id, i -> {
|
||||||
// Initial instantiation of NhcThermostat class for thermostat object
|
// Initial instantiation of NhcThermostat class for thermostat object
|
||||||
String name = thermostat.get("name");
|
|
||||||
String locationId = thermostat.get("location");
|
|
||||||
String location = "";
|
|
||||||
if (!((locationId == null) || locationId.isEmpty())) {
|
|
||||||
NhcLocation1 nhcLocation = locations.get(locationId);
|
|
||||||
if (nhcLocation != null) {
|
|
||||||
location = nhcLocation.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
return new NhcThermostat1(i, name, location, this);
|
return new NhcThermostat1(i, name, location, this);
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
});
|
});
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
|
if (name != null) {
|
||||||
|
t.setName(name);
|
||||||
|
}
|
||||||
|
t.setLocation(location);
|
||||||
t.updateState(measured, setpoint, mode, overrule, overruletime, ecosave, demand);
|
t.updateState(measured, setpoint, mode, overrule, overruletime, ecosave, demand);
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
|
@ -35,14 +35,16 @@ public class NhcAction2 extends NhcAction {
|
|||||||
private final Logger logger = LoggerFactory.getLogger(NhcAction2.class);
|
private final Logger logger = LoggerFactory.getLogger(NhcAction2.class);
|
||||||
|
|
||||||
private volatile boolean booleanState;
|
private volatile boolean booleanState;
|
||||||
private String model;
|
private String deviceType;
|
||||||
private String technology;
|
private String deviceTechnology;
|
||||||
|
private String deviceModel;
|
||||||
|
|
||||||
NhcAction2(String id, String name, String model, String technology, ActionType type, @Nullable String location,
|
NhcAction2(String id, String name, String deviceType, String deviceTechnology, String deviceModel,
|
||||||
NikoHomeControlCommunication nhcComm) {
|
@Nullable String location, ActionType type, NikoHomeControlCommunication nhcComm) {
|
||||||
super(id, name, type, location, nhcComm);
|
super(id, name, type, location, nhcComm);
|
||||||
this.model = model;
|
this.deviceType = deviceType;
|
||||||
this.technology = technology;
|
this.deviceTechnology = deviceTechnology;
|
||||||
|
this.deviceModel = deviceModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,7 +122,7 @@ public class NhcAction2 extends NhcAction {
|
|||||||
logger.debug("execute action {} of type {} for {}", command, type, id);
|
logger.debug("execute action {} of type {} for {}", command, type, id);
|
||||||
|
|
||||||
String cmd;
|
String cmd;
|
||||||
if ("flag".equals(model)) {
|
if ("flag".equals(deviceModel)) {
|
||||||
cmd = NHCON.equals(command) ? NHCTRUE : NHCFALSE;
|
cmd = NHCON.equals(command) ? NHCTRUE : NHCFALSE;
|
||||||
} else {
|
} else {
|
||||||
cmd = command;
|
cmd = command;
|
||||||
@ -130,16 +132,23 @@ public class NhcAction2 extends NhcAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return model as returned from Niko Home Control
|
* @return type as returned from Niko Home Control
|
||||||
*/
|
*/
|
||||||
public String getModel() {
|
public String getDeviceType() {
|
||||||
return model;
|
return deviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return technology as returned from Niko Home Control
|
* @return technology as returned from Niko Home Control
|
||||||
*/
|
*/
|
||||||
public String getTechnology() {
|
public String getDeviceTechnology() {
|
||||||
return technology;
|
return deviceTechnology;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return model as returned from Niko Home Control
|
||||||
|
*/
|
||||||
|
public String getDeviceModel() {
|
||||||
|
return deviceModel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,18 @@ class NhcDevice2 {
|
|||||||
@Nullable
|
@Nullable
|
||||||
String electricalPower;
|
String electricalPower;
|
||||||
@Nullable
|
@Nullable
|
||||||
|
String electricalPowerToGrid;
|
||||||
|
@Nullable
|
||||||
|
String electricalPowerFromGrid;
|
||||||
|
@Nullable
|
||||||
|
String electricalPowerProduction;
|
||||||
|
@Nullable
|
||||||
|
String electricalPowerSelfConsumption;
|
||||||
|
@Nullable
|
||||||
|
String electricalPowerConsumption;
|
||||||
|
@Nullable
|
||||||
|
String electricalPowerProductionThresholdExceeded;
|
||||||
|
@Nullable
|
||||||
String reportInstantUsage;
|
String reportInstantUsage;
|
||||||
// fields for access control
|
// fields for access control
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -34,14 +34,16 @@ public class NhcEnergyMeter2 extends NhcEnergyMeter {
|
|||||||
private ScheduledExecutorService scheduler;
|
private ScheduledExecutorService scheduler;
|
||||||
private volatile @Nullable ScheduledFuture<?> restartTimer;
|
private volatile @Nullable ScheduledFuture<?> restartTimer;
|
||||||
|
|
||||||
private String model;
|
private String deviceType;
|
||||||
private String technology;
|
private String deviceTechnology;
|
||||||
|
private String deviceModel;
|
||||||
|
|
||||||
protected NhcEnergyMeter2(String id, String name, String model, String technology,
|
protected NhcEnergyMeter2(String id, String name, String deviceType, String deviceTechnology, String deviceModel,
|
||||||
NikoHomeControlCommunication nhcComm, ScheduledExecutorService scheduler) {
|
@Nullable String location, NikoHomeControlCommunication nhcComm, ScheduledExecutorService scheduler) {
|
||||||
super(id, name, nhcComm);
|
super(id, name, location, nhcComm);
|
||||||
this.model = model;
|
this.deviceType = deviceType;
|
||||||
this.technology = technology;
|
this.deviceTechnology = deviceTechnology;
|
||||||
|
this.deviceModel = deviceModel;
|
||||||
|
|
||||||
this.scheduler = scheduler;
|
this.scheduler = scheduler;
|
||||||
}
|
}
|
||||||
@ -75,16 +77,23 @@ public class NhcEnergyMeter2 extends NhcEnergyMeter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return model as returned from Niko Home Control
|
* @return type as returned from Niko Home Control
|
||||||
*/
|
*/
|
||||||
public String getModel() {
|
public String getDeviceType() {
|
||||||
return model;
|
return deviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return technology as returned from Niko Home Control
|
* @return technology as returned from Niko Home Control
|
||||||
*/
|
*/
|
||||||
public String getTechnology() {
|
public String getDeviceTechnology() {
|
||||||
return technology;
|
return deviceTechnology;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return model as returned from Niko Home Control
|
||||||
|
*/
|
||||||
|
public String getDeviceModel() {
|
||||||
|
return deviceModel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,14 +33,16 @@ public class NhcThermostat2 extends NhcThermostat {
|
|||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(NhcThermostat2.class);
|
private final Logger logger = LoggerFactory.getLogger(NhcThermostat2.class);
|
||||||
|
|
||||||
private String model;
|
private String deviceType;
|
||||||
private String technology;
|
private String deviceTechnology;
|
||||||
|
private String deviceModel;
|
||||||
|
|
||||||
protected NhcThermostat2(String id, String name, String model, String technology, @Nullable String location,
|
protected NhcThermostat2(String id, String name, String deviceType, String deviceTechnology, String deviceModel,
|
||||||
NikoHomeControlCommunication nhcComm) {
|
@Nullable String location, NikoHomeControlCommunication nhcComm) {
|
||||||
super(id, name, location, nhcComm);
|
super(id, name, location, nhcComm);
|
||||||
this.model = model;
|
this.deviceType = deviceType;
|
||||||
this.technology = technology;
|
this.deviceTechnology = deviceTechnology;
|
||||||
|
this.deviceModel = deviceModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -59,16 +61,23 @@ public class NhcThermostat2 extends NhcThermostat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return model as returned from Niko Home Control
|
* @return type as returned from Niko Home Control
|
||||||
*/
|
*/
|
||||||
public String getModel() {
|
public String getDeviceType() {
|
||||||
return model;
|
return deviceType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return technology as returned from Niko Home Control
|
* @return technology as returned from Niko Home Control
|
||||||
*/
|
*/
|
||||||
public String getTechnology() {
|
public String getDeviceTechnology() {
|
||||||
return technology;
|
return deviceTechnology;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return model as returned from Niko Home Control
|
||||||
|
*/
|
||||||
|
public String getDeviceModel() {
|
||||||
|
return deviceModel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,63 +364,77 @@ public class NikoHomeControlCommunication2 extends NikoHomeControlCommunication
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("action".equals(device.type) || "virtual".equals(device.type)) {
|
if ("action".equals(device.type) || "virtual".equals(device.type)) {
|
||||||
if (!actions.containsKey(device.uuid)) {
|
ActionType actionType;
|
||||||
logger.debug("adding action device {}, {}", device.uuid, device.name);
|
switch (device.model) {
|
||||||
|
case "generic":
|
||||||
ActionType actionType;
|
case "pir":
|
||||||
switch (device.model) {
|
case "simulation":
|
||||||
case "generic":
|
case "comfort":
|
||||||
case "pir":
|
case "alarms":
|
||||||
case "simulation":
|
case "alloff":
|
||||||
case "comfort":
|
case "overallcomfort":
|
||||||
case "alarms":
|
case "garagedoor":
|
||||||
case "alloff":
|
actionType = ActionType.TRIGGER;
|
||||||
case "overallcomfort":
|
break;
|
||||||
case "garagedoor":
|
case "light":
|
||||||
actionType = ActionType.TRIGGER;
|
case "socket":
|
||||||
break;
|
case "switched-generic":
|
||||||
case "light":
|
case "switched-fan":
|
||||||
case "socket":
|
case "flag":
|
||||||
case "switched-generic":
|
actionType = ActionType.RELAY;
|
||||||
case "switched-fan":
|
break;
|
||||||
case "flag":
|
case "dimmer":
|
||||||
actionType = ActionType.RELAY;
|
actionType = ActionType.DIMMER;
|
||||||
break;
|
break;
|
||||||
case "dimmer":
|
case "rolldownshutter":
|
||||||
actionType = ActionType.DIMMER;
|
case "sunblind":
|
||||||
break;
|
case "venetianblind":
|
||||||
case "rolldownshutter":
|
case "gate":
|
||||||
case "sunblind":
|
actionType = ActionType.ROLLERSHUTTER;
|
||||||
case "venetianblind":
|
break;
|
||||||
case "gate":
|
default:
|
||||||
actionType = ActionType.ROLLERSHUTTER;
|
actionType = ActionType.GENERIC;
|
||||||
break;
|
logger.debug("device type {} and model {} not recognised for {}, {}, ignoring", device.type,
|
||||||
default:
|
device.model, device.uuid, device.name);
|
||||||
actionType = ActionType.GENERIC;
|
return;
|
||||||
logger.debug("device model {} not recognised, default to GENERIC action", device.model);
|
|
||||||
}
|
|
||||||
|
|
||||||
NhcAction2 nhcAction = new NhcAction2(device.uuid, device.name, device.model, device.technology,
|
|
||||||
actionType, location, this);
|
|
||||||
actions.put(device.uuid, nhcAction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NhcAction nhcAction = actions.get(device.uuid);
|
||||||
|
if (nhcAction != null) {
|
||||||
|
// update name and location so discovery will see updated name and location
|
||||||
|
nhcAction.setName(device.name);
|
||||||
|
nhcAction.setLocation(location);
|
||||||
|
} else {
|
||||||
|
logger.debug("adding action device {} model {}, {}", device.uuid, device.model, device.name);
|
||||||
|
nhcAction = new NhcAction2(device.uuid, device.name, device.type, device.technology, device.model,
|
||||||
|
location, actionType, this);
|
||||||
|
}
|
||||||
|
actions.put(device.uuid, nhcAction);
|
||||||
} else if ("thermostat".equals(device.type)) {
|
} else if ("thermostat".equals(device.type)) {
|
||||||
if (!thermostats.containsKey(device.uuid)) {
|
NhcThermostat nhcThermostat = thermostats.get(device.uuid);
|
||||||
logger.debug("adding thermostat device {}, {}", device.uuid, device.name);
|
if (nhcThermostat != null) {
|
||||||
|
nhcThermostat.setName(device.name);
|
||||||
NhcThermostat2 nhcThermostat = new NhcThermostat2(device.uuid, device.name, device.model,
|
nhcThermostat.setLocation(location);
|
||||||
device.technology, location, this);
|
} else {
|
||||||
thermostats.put(device.uuid, nhcThermostat);
|
logger.debug("adding thermostat device {} model {}, {}", device.uuid, device.model, device.name);
|
||||||
|
nhcThermostat = new NhcThermostat2(device.uuid, device.name, device.type, device.technology,
|
||||||
|
device.model, location, this);
|
||||||
}
|
}
|
||||||
} else if ("centralmeter".equals(device.type)) {
|
thermostats.put(device.uuid, nhcThermostat);
|
||||||
if (!energyMeters.containsKey(device.uuid)) {
|
} else if ("centralmeter".equals(device.type) || "energyhome".equals(device.type)) {
|
||||||
logger.debug("adding centralmeter device {}, {}", device.uuid, device.name);
|
NhcEnergyMeter nhcEnergyMeter = energyMeters.get(device.uuid);
|
||||||
NhcEnergyMeter2 nhcEnergyMeter = new NhcEnergyMeter2(device.uuid, device.name, device.model,
|
if (nhcEnergyMeter != null) {
|
||||||
device.technology, this, scheduler);
|
nhcEnergyMeter.setName(device.name);
|
||||||
energyMeters.put(device.uuid, nhcEnergyMeter);
|
nhcEnergyMeter.setLocation(location);
|
||||||
|
} else {
|
||||||
|
logger.debug("adding energy meter device {} model {}, {}", device.uuid, device.model, device.name);
|
||||||
|
nhcEnergyMeter = new NhcEnergyMeter2(device.uuid, device.name, device.type, device.technology,
|
||||||
|
device.model, location, this, scheduler);
|
||||||
}
|
}
|
||||||
|
energyMeters.put(device.uuid, nhcEnergyMeter);
|
||||||
} else {
|
} else {
|
||||||
logger.debug("device type {} not supported for {}, {}", device.type, device.uuid, device.name);
|
logger.debug("device type {} and model {} not supported for {}, {}", device.type, device.model, device.uuid,
|
||||||
|
device.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,18 +594,23 @@ public class NikoHomeControlCommunication2 extends NikoHomeControlCommunication
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateEnergyMeterState(NhcEnergyMeter2 energyMeter, List<NhcProperty> deviceProperties) {
|
private void updateEnergyMeterState(NhcEnergyMeter2 energyMeter, List<NhcProperty> deviceProperties) {
|
||||||
deviceProperties.stream().map(p -> p.electricalPower).filter(Objects::nonNull).findFirst()
|
try {
|
||||||
.ifPresent(electricalPower -> {
|
Optional<Integer> electricalPower = deviceProperties.stream().map(p -> p.electricalPower)
|
||||||
try {
|
.map(s -> (!((s == null) || s.isEmpty())) ? Math.round(Float.parseFloat(s)) : null)
|
||||||
// Sometimes API sends a fractional part, although API should only send whole units in W,
|
.filter(Objects::nonNull).findFirst();
|
||||||
// therefore drop fractional part
|
Optional<Integer> powerFromGrid = deviceProperties.stream().map(p -> p.electricalPowerFromGrid)
|
||||||
energyMeter.setPower((int) Double.parseDouble(electricalPower));
|
.map(s -> (!((s == null) || s.isEmpty())) ? Math.round(Float.parseFloat(s)) : null)
|
||||||
logger.trace("setting energy meter {} power to {}", energyMeter.getId(), electricalPower);
|
.filter(Objects::nonNull).findFirst();
|
||||||
} catch (NumberFormatException e) {
|
Optional<Integer> powerToGrid = deviceProperties.stream().map(p -> p.electricalPowerToGrid)
|
||||||
energyMeter.setPower(null);
|
.map(s -> (!((s == null) || s.isEmpty())) ? Math.round(Float.parseFloat(s)) : null)
|
||||||
logger.trace("received empty energy meter {} power reading", energyMeter.getId());
|
.filter(Objects::nonNull).findFirst();
|
||||||
}
|
int power = electricalPower.orElse(powerFromGrid.orElse(0) - powerToGrid.orElse(0));
|
||||||
});
|
logger.trace("setting energy meter {} power to {}", energyMeter.getId(), electricalPower);
|
||||||
|
energyMeter.setPower(power);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
energyMeter.setPower(null);
|
||||||
|
logger.trace("received empty energy meter {} power reading", energyMeter.getId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -876,7 +895,7 @@ public class NikoHomeControlCommunication2 extends NikoHomeControlCommunication
|
|||||||
@Override
|
@Override
|
||||||
public void connectionStateChanged(MqttConnectionState state, @Nullable Throwable error) {
|
public void connectionStateChanged(MqttConnectionState state, @Nullable Throwable error) {
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
logger.debug("Connection state: {}", state, error);
|
logger.debug("Connection state: {}, error", state, error);
|
||||||
String message = error.getLocalizedMessage();
|
String message = error.getLocalizedMessage();
|
||||||
message = (message != null) ? message : "@text/offline.communication-error";
|
message = (message != null) ? message : "@text/offline.communication-error";
|
||||||
if (!MqttConnectionState.CONNECTING.equals(state)) {
|
if (!MqttConnectionState.CONNECTING.equals(state)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user