[nikohomecontrol] Bug fixes and improvements to thermostats (#11963)

* Thermostat fixes and implement extra thermostat channels

Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
This commit is contained in:
Mark Herwege 2022-06-15 13:01:22 +02:00 committed by GitHub
parent 3349cf4945
commit f8bbb2b5a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 215 additions and 116 deletions

View File

@ -237,19 +237,25 @@ OnOff, IncreaseDecrease and Percent command types are supported.
Note that sending an ON command will switch the dimmer to the value stored when last turning the dimmer off, or 100% depending on the configuration in the Niko Home Control Controller.
This can be changed with the Niko Home Control programming software.
For thing type `blind` the supported channel is `rollershutter`. UpDown, StopMove and Percent command types are supported.
For thing type `blind` the supported channel is `rollershutter`.
UpDown, StopMove and Percent command types are supported.
For thing type `thermostat` the supported channels are `measured`, `mode`, `setpoint`, `overruletime` and `demand`.
For thing type `thermostat` the supported channels are `measured`, `heatingmode`, `mode`, `setpoint`, `overruletime`, `heatingdemand` and `demand`.
`measured` gives the current temperature in QuantityType<Temperature>, allowing for different temperature units.
This channel is read only.
`mode` can be set and shows the current thermostat mode.
Allowed values are 0 (day), 1 (night), 2 (eco), 3 (off), 4 (cool), 5 (prog 1), 6 (prog 2), 7 (prog 3).
If mode is set, the `setpoint` temperature will return to its standard value from the mode.
`setpoint` can be set and shows the current thermostat setpoint value in QuantityType<Temperature>.
`heatingmode` can be set and shows the current thermostat mode.
Allowed values are Day, Night, Eco, Off, Cool, Prog1, Prog2, Prog3.
As an alternative to `heatingmode` and for backward compatibility, the advanced channel `mode` is provided.
This channel has the same meaning, but with numeric values (0=Day, 1=Night, 2=Eco, 3=Off, 4=Cool, 5=Prog1, 6=Prog2, 7=Prog3) instead of string values.
If `heatingmode` or `mode` is set, the `setpoint` temperature will return to the standard value for the mode as defined in Niko Home Control.
`setpoint` shows the current thermostat setpoint value in QuantityType<Temperature>.
When updating `setpoint`, it will overrule the temperature setpoint defined by the thermostat mode for `overruletime` duration.
`overruletime` is used to set the total duration to apply the setpoint temperature set in the setpoint channel before the thermostat returns to the setting in its mode.
`demand` is a number indicating of the system is actively heating/cooling.
`overruletime` is used to set the total duration to apply the setpoint temperature set in the setpoint channel before the thermostat returns to the setting from its mode.
`heatingdemand` is a string indicating if the system is actively heating/cooling.
This channel will have value Heating, Cooling or None.
As an alternative to `heatingdemand`, the advanced channel `demand` is provided.
The value will be 1 for heating, -1 for cooling and 0 if not heating or cooling.
`heatingdemand` and `demand` are read only channels.
Note that cooling in NHC I is set by the binding, and will incorrectly show cooling demand when the system does not have cooling capabilities.
In NHC II, `measured` and `setpoint` temperatures will always report in 0.5°C increments due to a Niko Home Control II API restriction.
@ -310,12 +316,12 @@ Switch AllOff {channel="nikohomecontrol:onOff:nhc1:1:button"}
Switch LivingRoom {channel="nikohomecontrol:onOff:nhc1:2:switch"} # Switch for onOff type action
Dimmer TVRoom {channel="nikohomecontrol:dimmer:nhc1:3:brightness"} # Changing brightness dimmer type action
Rollershutter Kitchen {channel="nikohomecontrol:blind:nhc1:4:rollershutter"} # Controlling rollershutter or blind type action
Number:Temperature CurTemperature "[%.1f °F]" {channel="nikohomecontrol:thermostat:nhc1:5:measured"} # Getting measured temperature from thermostat in °F, read only
Number ThermostatMode {channel="nikohomecontrol:thermostat:nhc1:5:mode"} # Get and set thermostat mode
Number:Temperature SetTemperature "[%.1f °C]" {channel="nikohomecontrol:thermostat:nhc1:5:setpoint"} # Get and set target temperature in °C
Number OverruleDuration {channel="nikohomecontrol:thermostat:nhc1:5:overruletime"} # Get and set the overrule time
Number ThermostatDemand {channel="nikohomecontrol:thermostat:nhc1:5:demand"} # Get the current heating/cooling demand
Number:Power CurPower "[%.0f W]" {channel="nikohomecontrol:energyMeter:nhc2:6:power"} # Get current power consumption
Number:Temperature CurTemperature "[%.1f °F]" {channel="nikohomecontrol:thermostat:nhc1:5:measured"} # Getting measured temperature from thermostat in °F, read only
String ThermostatMode {channel="nikohomecontrol:thermostat:nhc1:5:heatingmode"} # Get and set thermostat mode
Number:Temperature SetTemperature "[%.1f °C]" {channel="nikohomecontrol:thermostat:nhc1:5:setpoint"} # Get and set target temperature in °C
Number OverruleDuration {channel="nikohomecontrol:thermostat:nhc1:5:overruletime"} # Get and set the overrule time
String ThermostatDemand {channel="nikohomecontrol:thermostat:nhc1:5:heatingdemand"} # Get the current heating/cooling demand
Number:Power CurPower "[%.0f W]" {channel="nikohomecontrol:energyMeter:nhc2:6:power"} # Get current power consumption
```
.sitemap:
@ -327,7 +333,7 @@ Slider item=TVRoom
Switch item=TVRoom # allows switching dimmer item off or on (with controller defined behavior)
Rollershutter item=Kitchen
Text item=CurTemperature
Selection item=ThermostatMode mappings=[0="day", 1="night", 2="eco", 3="off", 4="cool", 5="prog 1", 6="prog 2", 7="prog 3"]
Selection item=ThermostatMode mappings=[Day="day", Night="night", Eco="eco", Off="off", Prog1="Away"]
Setpoint item=SetTemperature minValue=0 maxValue=30
Slider item=OverruleDuration minValue=0 maxValue=120
Text item=Power

View File

@ -69,6 +69,8 @@ public class NikoHomeControlBindingConstants {
public static final String CHANNEL_OVERRULETIME = "overruletime";
public static final String CHANNEL_MODE = "mode";
public static final String CHANNEL_DEMAND = "demand";
public static final String CHANNEL_HEATING_MODE = "heatingmode";
public static final String CHANNEL_HEATING_DEMAND = "heatingdemand";
public static final String CHANNEL_POWER = "power";

View File

@ -21,6 +21,7 @@ import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridg
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler2;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlEnergyMeterHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlThermostatHandler;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.net.NetworkAddressService;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
@ -28,6 +29,7 @@ import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@ -42,7 +44,16 @@ import org.osgi.service.component.annotations.Reference;
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.nikohomecontrol")
public class NikoHomeControlHandlerFactory extends BaseThingHandlerFactory {
private @NonNullByDefault({}) NetworkAddressService networkAddressService;
private final NetworkAddressService networkAddressService;
private final TimeZoneProvider timeZoneProvider;
@Activate
public NikoHomeControlHandlerFactory(final @Reference NetworkAddressService networkAddressService,
final @Reference TimeZoneProvider timeZoneProvider) {
super();
this.networkAddressService = networkAddressService;
this.timeZoneProvider = timeZoneProvider;
}
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
@ -53,9 +64,9 @@ public class NikoHomeControlHandlerFactory extends BaseThingHandlerFactory {
protected @Nullable ThingHandler createHandler(Thing thing) {
if (BRIDGE_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
if (BRIDGEII_THING_TYPE.equals(thing.getThingTypeUID())) {
return new NikoHomeControlBridgeHandler2((Bridge) thing, networkAddressService);
return new NikoHomeControlBridgeHandler2((Bridge) thing, networkAddressService, timeZoneProvider);
} else {
return new NikoHomeControlBridgeHandler1((Bridge) thing);
return new NikoHomeControlBridgeHandler1((Bridge) thing, timeZoneProvider);
}
} else if (THING_TYPE_THERMOSTAT.equals(thing.getThingTypeUID())) {
return new NikoHomeControlThermostatHandler(thing);
@ -67,13 +78,4 @@ public class NikoHomeControlHandlerFactory extends BaseThingHandlerFactory {
return null;
}
@Reference
protected void setNetworkAddressService(NetworkAddressService networkAddressService) {
this.networkAddressService = networkAddressService;
}
protected void unsetNetworkAddressService(NetworkAddressService networkAddressService) {
this.networkAddressService = null;
}
}

View File

@ -16,6 +16,7 @@ import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindin
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.ZoneId;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
@ -29,6 +30,7 @@ import org.openhab.binding.nikohomecontrol.internal.discovery.NikoHomeControlDis
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcControllerEvent;
import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlCommunication;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingStatus;
@ -55,8 +57,11 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
private volatile @Nullable ScheduledFuture<?> refreshTimer;
public NikoHomeControlBridgeHandler(Bridge nikoHomeControlBridge) {
protected final TimeZoneProvider timeZoneProvider;
public NikoHomeControlBridgeHandler(Bridge nikoHomeControlBridge, TimeZoneProvider timeZoneProvider) {
super(nikoHomeControlBridge);
this.timeZoneProvider = timeZoneProvider;
}
@Override
@ -253,6 +258,11 @@ public abstract class NikoHomeControlBridgeHandler extends BaseBridgeHandler imp
return getConfig().as(NikoHomeControlBridgeConfig.class).port;
}
@Override
public ZoneId getTimeZone() {
return timeZoneProvider.getTimeZone();
}
@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Set.of(NikoHomeControlDiscoveryService.class);

View File

@ -20,6 +20,7 @@ import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.nikohomecontrol.internal.protocol.nhc1.NikoHomeControlCommunication1;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
@ -37,8 +38,8 @@ public class NikoHomeControlBridgeHandler1 extends NikoHomeControlBridgeHandler
private final Logger logger = LoggerFactory.getLogger(NikoHomeControlBridgeHandler1.class);
public NikoHomeControlBridgeHandler1(Bridge nikoHomeControlBridge) {
super(nikoHomeControlBridge);
public NikoHomeControlBridgeHandler1(Bridge nikoHomeControlBridge, TimeZoneProvider timeZoneProvider) {
super(nikoHomeControlBridge, timeZoneProvider);
}
@Override

View File

@ -24,6 +24,7 @@ import java.util.NoSuchElementException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.nikohomecontrol.internal.protocol.nhc2.NikoHomeControlCommunication2;
import org.openhab.core.i18n.TimeZoneProvider;
import org.openhab.core.net.NetworkAddressService;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ThingStatus;
@ -50,8 +51,9 @@ public class NikoHomeControlBridgeHandler2 extends NikoHomeControlBridgeHandler
NetworkAddressService networkAddressService;
public NikoHomeControlBridgeHandler2(Bridge nikoHomeControlBridge, NetworkAddressService networkAddressService) {
super(nikoHomeControlBridge);
public NikoHomeControlBridgeHandler2(Bridge nikoHomeControlBridge, NetworkAddressService networkAddressService,
TimeZoneProvider timeZoneProvider) {
super(nikoHomeControlBridge, timeZoneProvider);
this.networkAddressService = networkAddressService;
}

View File

@ -13,16 +13,16 @@
package org.openhab.binding.nikohomecontrol.internal.handler;
import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
import static org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlConstants.*;
import static org.openhab.core.library.unit.SIUnits.CELSIUS;
import static org.openhab.core.types.RefreshType.REFRESH;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import javax.measure.quantity.Temperature;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcThermostat;
@ -31,6 +31,7 @@ import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlComm
import org.openhab.binding.nikohomecontrol.internal.protocol.nhc2.NhcThermostat2;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
@ -105,33 +106,39 @@ public class NikoHomeControlThermostatHandler extends BaseThingHandler implement
switch (channelUID.getId()) {
case CHANNEL_MEASURED:
case CHANNEL_DEMAND:
case CHANNEL_HEATING_DEMAND:
updateStatus(ThingStatus.ONLINE);
break;
case CHANNEL_MODE:
if (command instanceof DecimalType) {
nhcThermostat.executeMode(((DecimalType) command).intValue());
}
updateStatus(ThingStatus.ONLINE);
break;
case CHANNEL_SETPOINT:
QuantityType<Temperature> setpoint = null;
if (command instanceof QuantityType) {
setpoint = ((QuantityType<Temperature>) command).toUnit(CELSIUS);
// Always set the new setpoint temperature as an overrule
// If no overrule time is given yet, set the overrule time to the configuration parameter
int time = nhcThermostat.getOverruletime();
if (time <= 0) {
time = overruleTime;
}
if (setpoint != null) {
nhcThermostat.executeOverrule(Math.round(setpoint.floatValue() * 10), time);
}
case CHANNEL_HEATING_MODE:
if (command instanceof StringType) {
nhcThermostat.executeMode(command.toString());
}
updateStatus(ThingStatus.ONLINE);
break;
case CHANNEL_SETPOINT:
// Always set the new setpoint temperature as an overrule
// If no overrule time is given yet, set the overrule time to the configuration parameter
int time = nhcThermostat.getOverruletime();
if (time <= 0) {
time = overruleTime;
}
if (command instanceof QuantityType<?>) {
QuantityType<?> setpoint = ((QuantityType<?>) command).toUnit(CELSIUS);
if (setpoint != null) {
nhcThermostat.executeOverrule(Math.round(setpoint.floatValue() * 10), time);
}
} else if (command instanceof DecimalType) {
BigDecimal setpoint = ((DecimalType) command).toBigDecimal();
nhcThermostat.executeOverrule(Math.round(setpoint.floatValue() * 10), time);
}
updateStatus(ThingStatus.ONLINE);
break;
case CHANNEL_OVERRULETIME:
if (command instanceof DecimalType) {
int overruletime = ((DecimalType) command).intValue();
@ -255,7 +262,7 @@ public class NikoHomeControlThermostatHandler extends BaseThingHandler implement
return;
}
updateState(CHANNEL_MEASURED, new QuantityType<>(nhcThermostat.getMeasured() / 10.0, CELSIUS));
updateState(CHANNEL_MEASURED, new QuantityType<>(measured / 10.0, CELSIUS));
int overruletime = nhcThermostat.getRemainingOverruletime();
updateState(CHANNEL_OVERRULETIME, new DecimalType(overruletime));
@ -271,8 +278,10 @@ public class NikoHomeControlThermostatHandler extends BaseThingHandler implement
}
updateState(CHANNEL_MODE, new DecimalType(mode));
updateState(CHANNEL_HEATING_MODE, new StringType(THERMOSTATMODES[mode]));
updateState(CHANNEL_DEMAND, new DecimalType(demand));
updateState(CHANNEL_HEATING_DEMAND, new StringType(THERMOSTATDEMAND[Math.abs(demand) <= 1 ? (demand + 1) : 0]));
updateStatus(ThingStatus.ONLINE);
}
@ -286,14 +295,14 @@ public class NikoHomeControlThermostatHandler extends BaseThingHandler implement
private void scheduleRefreshOverruletime(NhcThermostat nhcThermostat) {
cancelRefreshTimer();
if (nhcThermostat.getRemainingOverruletime() <= 0) {
if (nhcThermostat.getRemainingOverruletime() == 0) {
return;
}
refreshTimer = scheduler.scheduleWithFixedDelay(() -> {
int remainingTime = nhcThermostat.getRemainingOverruletime();
updateState(CHANNEL_OVERRULETIME, new DecimalType(remainingTime));
if (remainingTime <= 0) {
if (remainingTime == 0) {
cancelRefreshTimer();
}
}, 1, 1, TimeUnit.MINUTES);

View File

@ -13,6 +13,7 @@
package org.openhab.binding.nikohomecontrol.internal.protocol;
import java.net.InetAddress;
import java.time.ZoneId;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@ -64,6 +65,13 @@ public interface NhcControllerEvent {
return "";
}
/**
* Get the time zone ID of the Niko Home Control system.
*
* @return the zone ID
*/
public ZoneId getTimeZone();
/**
* Called to indicate the connection with the Niko Home Control Controller is offline.
*

View File

@ -20,10 +20,8 @@ import org.slf4j.LoggerFactory;
/**
* The {@link NhcEnergyMeter} class represents the energyMeters metering Niko Home Control communication object. It
* contains all
* fields representing a Niko Home Control energyMeters meter and has methods to receive energyMeters usage information.
* A specific
* implementation is {@link NhcEnergyMeter2}.
* contains all fields representing a Niko Home Control energyMeters meter and has methods to receive energyMeters usage
* information. A specific implementation is {@link NhcEnergyMeter2}.
*
* @author Mark Herwege - Initial Contribution
*/

View File

@ -12,8 +12,12 @@
*/
package org.openhab.binding.nikohomecontrol.internal.protocol;
import static org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlConstants.THERMOSTATMODES;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@ -47,7 +51,7 @@ public abstract class NhcThermostat {
protected volatile int ecosave;
protected volatile int demand;
private @Nullable LocalDateTime overruleStart;
private @Nullable volatile ZonedDateTime overruleStart;
private @Nullable NhcThermostatEvent eventHandler;
@ -84,33 +88,6 @@ public abstract class NhcThermostat {
updateChannels();
}
/**
* Update overrule values of the thermostat without touching the thermostat definition (id, name and location) and
* without changing the ThingHandler callback.
*
* @param overrule the overrule temperature in 0.1°C multiples
* @param overruletime in minutes
*/
public void updateState(int overrule, int overruletime) {
setOverrule(overrule);
setOverruletime(overruletime);
updateChannels();
}
/**
* Update overrule values of the thermostat without touching the thermostat definition (id, name and location) and
* without changing the ThingHandler callback.
*
* @param overrule the overrule temperature in 0.1°C multiples
* @param overruletime in minutes
*/
public void updateState(int mode) {
setMode(mode);
updateChannels();
}
/**
* Method called when thermostat is removed from the Niko Home Control Controller.
*/
@ -249,6 +226,9 @@ public abstract class NhcThermostat {
private void setOverrule(int overrule) {
this.overrule = overrule;
if (overrule <= 0) {
stopOverrule();
}
}
/**
@ -266,12 +246,14 @@ public abstract class NhcThermostat {
* @param overruletime the overruletime in minutes
*/
private void setOverruletime(int overruletime) {
if (overruletime <= 0) {
stopOverrule();
} else if (overruletime != this.overruletime) {
startOverrule();
if (overruletime != this.overruletime) {
if (overruletime <= 0) {
stopOverrule();
} else {
startOverrule();
}
this.overruletime = overruletime;
}
this.overruletime = overruletime;
}
/**
@ -289,7 +271,7 @@ public abstract class NhcThermostat {
}
/**
* @return the heating/cooling demand: 0 if no demand, >0 if heating, <0 if cooling
* @return the heating/cooling demand: 0 if no demand, 1 if heating, -1 if cooling
*/
public int getDemand() {
return demand;
@ -310,6 +292,20 @@ public abstract class NhcThermostat {
*/
public abstract void executeMode(int mode);
/**
* Sends thermostat mode to Niko Home Control.
*
* @param mode allowed values are Day, Night, Eco, Off, Cool, Prog1, Prog2, Prog3
*/
public void executeMode(String mode) {
int intMode = Arrays.asList(THERMOSTATMODES).indexOf(mode);
if (intMode < 0) { // if not recognized, default to Day
intMode = 0;
logger.debug("Thermostat mode {} not recognized, default to Day mode", mode);
}
executeMode(intMode);
};
/**
* Sends thermostat setpoint to Niko Home Control. This method is implemented in {@link NhcThermostat1} and
* {@link NhcThermostat2}.
@ -320,22 +316,24 @@ public abstract class NhcThermostat {
public abstract void executeOverrule(int overrule, int overruletime);
/**
* @return remaining overrule time in minutes
* @return remaining overrule time in minutes, 0 or positive
*/
public int getRemainingOverruletime() {
if (overruleStart == null) {
return 0;
} else {
int remainingTime = 0;
if (overruleStart != null) {
// overruletime time max 23h59min, therefore can safely cast to int
return overruletime - (int) ChronoUnit.MINUTES.between(overruleStart, LocalDateTime.now());
remainingTime = Math.max(0, overruletime - (int) ChronoUnit.MINUTES.between(overruleStart,
LocalDateTime.now().atZone(nhcComm.getTimeZone())));
}
logger.trace("Getting remaining overrule time, remaining: {}", remainingTime);
return remainingTime;
}
/**
* Start a new overrule, this method is used to be able to calculate the remaining overrule time
*/
private void startOverrule() {
overruleStart = LocalDateTime.now();
overruleStart = LocalDateTime.now().atZone(nhcComm.getTimeZone());
}
/**
@ -343,5 +341,7 @@ public abstract class NhcThermostat {
*/
private void stopOverrule() {
overruleStart = null;
overruletime = 0;
overrule = 0;
}
}

View File

@ -12,6 +12,7 @@
*/
package org.openhab.binding.nikohomecontrol.internal.protocol;
import java.time.ZoneId;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
@ -54,7 +55,7 @@ public abstract class NikoHomeControlCommunication {
// restart attempts
private volatile int delay = 0;
private volatile int attempt = 0;
protected @Nullable ScheduledFuture<?> scheduledRestart = null;
protected volatile @Nullable ScheduledFuture<?> scheduledRestart = null;
protected NikoHomeControlCommunication(NhcControllerEvent handler, ScheduledExecutorService scheduler) {
this.handler = handler;
@ -137,6 +138,15 @@ public abstract class NikoHomeControlCommunication {
*/
public abstract boolean communicationActive();
/**
* Return the timezone for the system.
*
* @return zoneId
*/
public ZoneId getTimeZone() {
return handler.getTimeZone();
}
/**
* Return all actions in the Niko Home Control Controller.
*

View File

@ -47,4 +47,5 @@ public class NikoHomeControlConstants {
// NhcII thermostat modes
public static final String[] THERMOSTATMODES = { "Day", "Night", "Eco", "Off", "Cool", "Prog1", "Prog2", "Prog3" };
public static final String[] THERMOSTATDEMAND = { "Cooling", "None", "Heating" };
}

View File

@ -569,11 +569,11 @@ public class NikoHomeControlCommunication2 extends NikoHomeControlCommunication
int measured = ambientTemperatureProperty.orElse(thermostat.getMeasured());
int setpoint = setpointTemperatureProperty.orElse(thermostat.getSetpoint());
int overrule = thermostat.getOverrule();
int overruletime = thermostat.getRemainingOverruletime();
if (overruleActiveProperty.orElse(false)) {
overrule = overruleSetpointProperty.orElse(0);
overruletime = overruleTimeProperty.orElse(0);
int overrule = 0;
int overruletime = 0;
if (overruleActiveProperty.orElse(true)) {
overrule = overruleSetpointProperty.orElse(thermostat.getOverrule());
overruletime = overruleTimeProperty.orElse(thermostat.getRemainingOverruletime());
}
int ecosave = thermostat.getEcosave();
@ -618,7 +618,7 @@ public class NikoHomeControlCommunication2 extends NikoHomeControlCommunication
energyMeter.setPower(power);
} catch (NumberFormatException e) {
energyMeter.setPower(null);
logger.trace("received empty energy meter {} power reading", energyMeter.getId());
logger.trace("wrong format in energy meter {} power reading", energyMeter.getId());
}
}

View File

@ -83,14 +83,20 @@ channelOverruletimeDescription = Time duration for overruling thermostat target
channelModeLabel = Mode
channelModeDescription = Thermostat mode
channelModeOption0 = day
channelModeOption1 = night
channelModeOption2 = eco
channelModeOption3 = off
channelModeOption4 = cool
channelModeOption5 = prog 1
channelModeOption6 = prog 2
channelModeOption7 = prog 3
channelModeOption0 = Day
channelModeOption1 = Night
channelModeOption2 = Eco
channelModeOption3 = Off
channelModeOption4 = Cool
channelModeOption5 = Program 1
channelModeOption6 = Program 2
channelModeOption7 = Program 3
channelDemandLabel = Demand
channelDemandDescription = Heating/cooling demand
channelDemand-1 = Cooling
channelDemand0 = None
channelDemand1 = Heating
channelPowerLabel = Power
channelPowerDescription = Momentary power consumption/production (positive is consumption)

View File

@ -161,13 +161,16 @@
<bridge-type-ref id="bridge"/>
<bridge-type-ref id="bridge2"/>
</supported-bridge-type-refs>
<label>@text/ThermostatLabel</label>
<description>@text/ThermostatDescription</description>
<label>@text/thermostatLabel</label>
<description>@text/thermostatDescription</description>
<channels>
<channel id="measured" typeId="measured"/>
<channel id="heatingmode" typeId="heatingmode"/>
<channel id="mode" typeId="mode"/>
<channel id="setpoint" typeId="setpoint"/>
<channel id="overruletime" typeId="overruletime"/>
<channel id="heatingdemand" typeId="heatingdemand"/>
<channel id="demand" typeId="demand"/>
</channels>
<config-description>
<parameter name="thermostatId" type="text" required="true">
@ -244,11 +247,27 @@
<category>Number</category>
<state min="0" max="1440" step="5"/>
</channel-type>
<channel-type id="mode">
<channel-type id="heatingmode">
<item-type>String</item-type>
<label>@text/channelModeLabel</label>
<description>@text/channelModeDescription</description>
<state>
<options>
<option value="Day">@text/channelModeOption0</option>
<option value="Night">@text/channelModeOption1</option>
<option value="Eco">@text/channelModeOption2</option>
<option value="Off">@text/channelModeOption3</option>
<option value="Cool">@text/channelModeOption4</option>
<option value="Prog1">@text/channelModeOption5</option>
<option value="Prog2">@text/channelModeOption6</option>
<option value="Prog3">@text/channelModeOption7</option>
</options>
</state>
</channel-type>
<channel-type id="mode" advanced="true">
<item-type>Number</item-type>
<label>@text/channelModeLabel</label>
<description>@text/channelModeDescription</description>
<category>Number</category>
<state>
<options>
<option value="0">@text/channelModeOption0</option>
@ -262,6 +281,31 @@
</options>
</state>
</channel-type>
<channel-type id="heatingdemand">
<item-type>String</item-type>
<label>@text/channelDemandLabel</label>
<description>@text/channelDemandDescription</description>
<state readOnly="true">
<options>
<option value="Cooling">@text/channelDemand-1</option>
<option value="None">@text/channelDemand0</option>
<option value="Heating">@text/channelDemand1</option>
</options>
</state>
</channel-type>
<channel-type id="demand" advanced="true">
<item-type>Number</item-type>
<label>@text/channelDemandLabel</label>
<description>@text/channelDemandDescription</description>
<state readOnly="true">
<options>
<option value="-1">@text/channelDemand-1</option>
<option value="0">@text/channelDemand0</option>
<option value="1">@text/channelDemand1</option>
</options>
</state>
</channel-type>
<channel-type id="power">
<item-type>Number:Power</item-type>
<label>@text/channelPowerLabel</label>