[danfossairunit] Add filter period channel (#11371)
* Add filter period channel. Fixes #11310 Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> * Round remaining filter life percentage to one decimal. Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> * Improve and extend example configuration. Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> * Mark filter period channel as advanced due to Link CC/Air Dial conflicts. Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> * Add comment about value getting overwritten. Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> * Remove redundant parentheses. Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> * Fix SCA report: First javadoc author should have 'Initial contribution' contribution description. Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk> * Fix SCA issue: NoEmptyLineSeparatorCheck Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>pull/11434/head
parent
5eb004e378
commit
d4c9d6ef77
|
@ -41,6 +41,7 @@ These are the available configuration parameters:
|
||||||
| exhaust_temp | recuperator | Number | RO | Temperature of the air when pushed outside |
|
| exhaust_temp | recuperator | Number | RO | Temperature of the air when pushed outside |
|
||||||
| battery_life | service | Number | RO | Remaining Air Dial Battery Level (percentage) |
|
| battery_life | service | Number | RO | Remaining Air Dial Battery Level (percentage) |
|
||||||
| filter_life | service | Number | RO | Remaining life of filter until exchange is necessary (percentage) |
|
| filter_life | service | Number | RO | Remaining life of filter until exchange is necessary (percentage) |
|
||||||
|
| filter_period | service | Number | RW | Number of months between filter replacements (between 3 and 12). This value affects calculation of filter_life by the unit, and might get overwritten by Air Dial or Link CC Controller. |
|
||||||
|
|
||||||
|
|
||||||
## Full Example
|
## Full Example
|
||||||
|
@ -63,21 +64,47 @@ updateUnchangedValuesEveryMillis=30000]
|
||||||
### Items
|
### Items
|
||||||
|
|
||||||
```
|
```
|
||||||
Dimmer Lueftung_Drehzahl_Manuell "Drehzahl Lüftung %" (All,Lueftung) {channel = "danfossairunit:airunit:myairunit:main#manual_fan_speed"}
|
Dimmer DanfossHRV_ManualFanStep "Manual Fan Step [%s]" {channel = "danfossairunit:airunit:myairunit:main#manual_fan_step"}
|
||||||
Number Lueftung_Drehzahl_Supply "Drehzahl Lüftung Zuluft (rpm)" (All,Lueftung) {channel = "danfossairunit:airunit:myairunit:main#supply_fan_speed"}
|
Number DanfossHRV_SupplyFanSpeed "Supply Fan Speed" {channel = "danfossairunit:airunit:myairunit:main#supply_fan_speed"}
|
||||||
Number Lueftung_Drehzahl_Extract "Drehzahl Lüftung Abluft (rpm)" (All,Lueftung) {channel = "danfossairunit:airunit:myairunit:main#extract_fan_speed"}
|
Number DanfossHRV_ExtractFanSpeed "Extract Fan Speed" {channel = "danfossairunit:airunit:myairunit:main#extract_fan_speed"}
|
||||||
String Lueftung_Mode "Betriebsart Lüftung" (All,Lueftung) {channel = "danfossairunit:airunit:myairunit:main#mode"}
|
String DanfossHRV_Mode "Operation Mode" {channel = "danfossairunit:airunit:myairunit:main#mode"}
|
||||||
Switch Lueftung_Boost "Stoßlüftung" (All,Lueftung) {channel = "danfossairunit:airunit:myairunit:main#boost"}
|
Switch DanfossHRV_Boost "Boost" {channel = "danfossairunit:airunit:myairunit:main#boost"}
|
||||||
Switch Lueftung_Bypass "Lüftung Bypass" (All,Lueftung) {channel = "danfossairunit:airunit:myairunit:recuperator#bypass"}
|
Switch DanfossHRV_Bypass "Bypass" {channel = "danfossairunit:airunit:myairunit:recuperator#bypass"}
|
||||||
|
Number:Dimensionless DanfossHRV_Humidity "Relative humidity" <humidity> { channel = "danfossairunit:airunit:myairunit:humidity#humidity" }
|
||||||
|
Number:Temperature DanfossHRV_RoomTemperature "Room air temperatuyre" <temperature> { channel = "danfossairunit:airunit:myairunit:temps#room_temp" }
|
||||||
|
Number:Temperature DanfossHRV_OutdoorTemperature "Outdoor air temperature" <temperature> { channel = "danfossairunit:airunit:myairunit:temps#outdoor_temp" }
|
||||||
|
Number:Temperature DanfossHRV_SupplyAirTemperature "Supply air temperature" <temperature> { channel = "danfossairunit:airunit:myairunit:recuperator#supply_temp" }
|
||||||
|
Number:Temperature DanfossHRV_ExtractAirTemperature "Extract air temperature" <temperature> { channel = "danfossairunit:airunit:myairunit:recuperator#extract_temp" }
|
||||||
|
Number:Temperature DanfossHRV_ExhaustAirTemperature "Exhaust air temperature" <temperature> { channel = "danfossairunit:airunit:myairunit:recuperator#exhaust_temp" }
|
||||||
|
Number DanfossHRV_RemainingFilterLife "Remaining filter life" { channel = "danfossairunit:airunit:myairunit:service#filter_life" }
|
||||||
|
Number DanfossHRV_FilterPeriod "Filter period" { channel = "danfossairunit:airunit:myairunit:service#filter_period" }
|
||||||
```
|
```
|
||||||
|
|
||||||
### Sitemap
|
### Sitemap
|
||||||
|
|
||||||
```
|
```
|
||||||
Slider item=Lueftung_Drehzahl_Manuell
|
sitemap danfoss label="Danfoss" {
|
||||||
Text item=Lueftung_Drehzahl_Supply
|
Frame label="Control" {
|
||||||
Text item=Lueftung_Drehzahl_Extract
|
Selection item=DanfossHRV_Mode mappings=[DEMAND="Demand", OFF="Off", PROGRAM="Program", MANUAL="Manual"]
|
||||||
Selection item=Lueftung_Mode mappings=[DEMAND="Bedarfslüftung", OFF="Aus", PROGRAM="Programm", MANUAL="manuell"]
|
Slider item=DanfossHRV_ManualFanStep step=10 visibility=[DanfossHRV_Mode=="MANUAL"]
|
||||||
Switch item=Lueftung_Boost
|
Switch item=DanfossHRV_Bypass
|
||||||
Switch item=Lueftung_Bypass
|
Switch item=DanfossHRV_Boost
|
||||||
|
}
|
||||||
|
Frame label="Measurements" {
|
||||||
|
Text item=DanfossHRV_Humidity
|
||||||
|
Text item=DanfossHRV_RoomTemperature
|
||||||
|
Text item=DanfossHRV_OutdoorTemperature
|
||||||
|
Text item=DanfossHRV_SupplyAirTemperature
|
||||||
|
Text item=DanfossHRV_ExtractAirTemperature
|
||||||
|
Text item=DanfossHRV_ExhaustAirTemperature
|
||||||
|
}
|
||||||
|
Frame label="Fan" {
|
||||||
|
Text item=DanfossHRV_SupplyFanSpeed
|
||||||
|
Text item=DanfossHRV_ExtractFanSpeed
|
||||||
|
}
|
||||||
|
Frame label="Filter" {
|
||||||
|
Text item=DanfossHRV_RemainingFilterLife
|
||||||
|
Slider item=DanfossHRV_FilterPeriod minValue=3 maxValue=12
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -59,7 +59,9 @@ public enum Channel {
|
||||||
|
|
||||||
// service channels
|
// service channels
|
||||||
CHANNEL_BATTERY_LIFE("battery_life", ChannelGroup.SERVICE, DanfossAirUnit::getBatteryLife),
|
CHANNEL_BATTERY_LIFE("battery_life", ChannelGroup.SERVICE, DanfossAirUnit::getBatteryLife),
|
||||||
CHANNEL_FILTER_LIFE("filter_life", ChannelGroup.SERVICE, DanfossAirUnit::getFilterLife);
|
CHANNEL_FILTER_LIFE("filter_life", ChannelGroup.SERVICE, DanfossAirUnit::getFilterLife),
|
||||||
|
CHANNEL_FILTER_PERIOD("filter_period", ChannelGroup.SERVICE, DanfossAirUnit::getFilterPeriod,
|
||||||
|
DanfossAirUnit::setFilterPeriod);
|
||||||
|
|
||||||
private final String channelName;
|
private final String channelName;
|
||||||
private final ChannelGroup group;
|
private final ChannelGroup group;
|
||||||
|
|
|
@ -57,6 +57,7 @@ public class Commands {
|
||||||
public static byte[] EXHAUST_TEMPERATURE = { 0x14, 0x75 };
|
public static byte[] EXHAUST_TEMPERATURE = { 0x14, 0x75 };
|
||||||
public static byte[] BATTERY_LIFE = { 0x03, 0x0f };
|
public static byte[] BATTERY_LIFE = { 0x03, 0x0f };
|
||||||
public static byte[] FILTER_LIFE = { 0x14, 0x6a };
|
public static byte[] FILTER_LIFE = { 0x14, 0x6a };
|
||||||
|
public static byte[] FILTER_PERIOD = { 0x14, 0x69 };
|
||||||
public static byte[] CURRENT_TIME = { 0x15, (byte) 0xe0 };
|
public static byte[] CURRENT_TIME = { 0x15, (byte) 0xe0 };
|
||||||
public static byte[] AWAY_TO = { 0x15, 0x20 };
|
public static byte[] AWAY_TO = { 0x15, 0x20 };
|
||||||
public static byte[] AWAY_FROM = { 0x15, 0x21 };
|
public static byte[] AWAY_FROM = { 0x15, 0x21 };
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
/**
|
/**
|
||||||
* This interface defines a communication controller that can be used to send requests to the Danfoss Air Unit.
|
* This interface defines a communication controller that can be used to send requests to the Danfoss Air Unit.
|
||||||
*
|
*
|
||||||
* @author Jacob Laursen - Refactoring, bugfixes and enhancements
|
* @author Jacob Laursen - Initial contribution
|
||||||
*/
|
*/
|
||||||
@NonNullByDefault
|
@NonNullByDefault
|
||||||
public interface CommunicationController {
|
public interface CommunicationController {
|
||||||
|
|
|
@ -213,7 +213,16 @@ public class DanfossAirUnit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public DecimalType getFilterLife() throws IOException {
|
public DecimalType getFilterLife() throws IOException {
|
||||||
return new DecimalType(BigDecimal.valueOf(asPercentByte(getByte(REGISTER_1_READ, FILTER_LIFE))));
|
BigDecimal value = BigDecimal.valueOf(asPercentByte(getByte(REGISTER_1_READ, FILTER_LIFE)));
|
||||||
|
return new DecimalType(value.setScale(1, RoundingMode.HALF_UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecimalType getFilterPeriod() throws IOException {
|
||||||
|
return new DecimalType(BigDecimal.valueOf(getByte(REGISTER_1_READ, FILTER_PERIOD)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DecimalType setFilterPeriod(Command cmd) throws IOException {
|
||||||
|
return setNumberTypeRegister(cmd, FILTER_PERIOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DateTimeType getCurrentTime() throws IOException, UnexpectedResponseValueException {
|
public DateTimeType getCurrentTime() throws IOException, UnexpectedResponseValueException {
|
||||||
|
@ -225,6 +234,14 @@ public class DanfossAirUnit {
|
||||||
return setPercentTypeRegister(cmd, MANUAL_FAN_SPEED_STEP);
|
return setPercentTypeRegister(cmd, MANUAL_FAN_SPEED_STEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DecimalType setNumberTypeRegister(Command cmd, byte[] register) throws IOException {
|
||||||
|
if (cmd instanceof DecimalType) {
|
||||||
|
byte value = (byte) ((DecimalType) cmd).intValue();
|
||||||
|
set(REGISTER_1_WRITE, register, value);
|
||||||
|
}
|
||||||
|
return new DecimalType(BigDecimal.valueOf(getByte(REGISTER_1_READ, register)));
|
||||||
|
}
|
||||||
|
|
||||||
private PercentType setPercentTypeRegister(Command cmd, byte[] register) throws IOException {
|
private PercentType setPercentTypeRegister(Command cmd, byte[] register) throws IOException {
|
||||||
if (cmd instanceof PercentType) {
|
if (cmd instanceof PercentType) {
|
||||||
byte value = (byte) ((((PercentType) cmd).intValue() + 5) / 10);
|
byte value = (byte) ((((PercentType) cmd).intValue() + 5) / 10);
|
||||||
|
|
|
@ -80,7 +80,6 @@ public class DanfossAirUnitDiscoveryService extends AbstractDiscoveryService {
|
||||||
logger.debug("Try to discover all Danfoss Air CCM devices");
|
logger.debug("Try to discover all Danfoss Air CCM devices");
|
||||||
|
|
||||||
try (DatagramSocket socket = new DatagramSocket()) {
|
try (DatagramSocket socket = new DatagramSocket()) {
|
||||||
|
|
||||||
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||||
while (interfaces.hasMoreElements()) {
|
while (interfaces.hasMoreElements()) {
|
||||||
NetworkInterface networkInterface = interfaces.nextElement();
|
NetworkInterface networkInterface = interfaces.nextElement();
|
||||||
|
@ -96,7 +95,6 @@ public class DanfossAirUnitDiscoveryService extends AbstractDiscoveryService {
|
||||||
sendBroadcastToDiscoverThing(socket, interfaceAddress.getBroadcast());
|
sendBroadcastToDiscoverThing(socket, interfaceAddress.getBroadcast());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.debug("No Danfoss Air CCM device found. Diagnostic: {}", e.getMessage());
|
logger.debug("No Danfoss Air CCM device found. Diagnostic: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@
|
||||||
<label>Remaining Filter Life</label>
|
<label>Remaining Filter Life</label>
|
||||||
<description>Remaining life of filter until exchange is necessary</description>
|
<description>Remaining life of filter until exchange is necessary</description>
|
||||||
</channel>
|
</channel>
|
||||||
|
<channel id="filter_period" typeId="filterPeriod"/>
|
||||||
</channels>
|
</channels>
|
||||||
</channel-group-type>
|
</channel-group-type>
|
||||||
|
|
||||||
|
@ -190,6 +191,12 @@
|
||||||
<category>Fan</category>
|
<category>Fan</category>
|
||||||
<state step="10" min="0" max="100" readOnly="true"/>
|
<state step="10" min="0" max="100" readOnly="true"/>
|
||||||
</channel-type>
|
</channel-type>
|
||||||
|
<channel-type id="filterPeriod" advanced="true">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>Filter Period</label>
|
||||||
|
<description>Number of months between filter replacements</description>
|
||||||
|
<state pattern="%d" min="3" max="12"/>
|
||||||
|
</channel-type>
|
||||||
<channel-type id="percentage">
|
<channel-type id="percentage">
|
||||||
<item-type>Number</item-type>
|
<item-type>Number</item-type>
|
||||||
<label>Percentage</label>
|
<label>Percentage</label>
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.time.ZonedDateTime;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.openhab.core.library.types.DateTimeType;
|
import org.openhab.core.library.types.DateTimeType;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
import org.openhab.core.library.types.PercentType;
|
import org.openhab.core.library.types.PercentType;
|
||||||
import org.openhab.core.library.types.QuantityType;
|
import org.openhab.core.library.types.QuantityType;
|
||||||
|
@ -31,7 +32,7 @@ import org.openhab.core.test.java.JavaTest;
|
||||||
/**
|
/**
|
||||||
* This class provides test cases for {@link DanfossAirUnit}
|
* This class provides test cases for {@link DanfossAirUnit}
|
||||||
*
|
*
|
||||||
* @author Jacob Laursen - Refactoring, bugfixes and enhancements
|
* @author Jacob Laursen - Initial contribution
|
||||||
*/
|
*/
|
||||||
public class DanfossAirUnitTest extends JavaTest {
|
public class DanfossAirUnitTest extends JavaTest {
|
||||||
|
|
||||||
|
@ -153,4 +154,12 @@ public class DanfossAirUnitTest extends JavaTest {
|
||||||
var airUnit = new DanfossAirUnit(communicationController);
|
var airUnit = new DanfossAirUnit(communicationController);
|
||||||
assertThrows(UnexpectedResponseValueException.class, () -> airUnit.getManualFanStep());
|
assertThrows(UnexpectedResponseValueException.class, () -> airUnit.getManualFanStep());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFilterLifeWhenNearestNeighborIsBelowRoundsDown() throws IOException {
|
||||||
|
byte[] response = new byte[] { (byte) 0xf0 };
|
||||||
|
when(this.communicationController.sendRobustRequest(REGISTER_1_READ, FILTER_LIFE)).thenReturn(response);
|
||||||
|
var airUnit = new DanfossAirUnit(communicationController);
|
||||||
|
assertEquals(new DecimalType("94.1"), airUnit.getFilterLife());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue