MODBUS and System air

Tags: #<Tag:0x00007f8760109ac0>

(Gunnar Skjold) #61

I thought I’d update here with my current configuration including modbus cfg, items, rules and sitemap. Maybe someone can make use of it and also come up with some other ideas I haven’t thought of :slight_smile:
















Group Villavent

Group VillaventTemperatureGroup
Number VillaventTemperatureGroupGraph

Number VillaventNvm "Store NVM" (Villavent) { modbus="vvnvm:0" }

Number VillaventFan "Fan speed" <fan> (Villavent, Persist) { modbus="vvfan:0" }
Number VillaventSupplyFanRpm "Supply fan RPM [%d]" <fan> (Villavent, Persist) { modbus="vvfan:10" }
Number VillaventSupplyFanGraph (PersistAndRestore)
Number VillaventExtractFanRpm "Extract fan RPM [%d]" <fan> (Villavent, Persist) { modbus="vvfan:11" }
Number VillaventExtractFanGraph (PersistAndRestore)

Number VillaventFrostProtection "Frost protection level [%d]" <temperature> (Villavent, Persist) { modbus="vvhc:5" }
Number VillaventTempLvl "Temperature set point level [%d]" <heating> (Villavent, Persist) { modbus="vvhc:6" }
Number VillaventHeatSetpoint "Temperature set point (read only) [%d]" <heating> (Villavent, Persist) { modbus="vvhc:7" }

Number VillaventSupplyAirTemp "Supply air temperature [%.1f °C]" <temperature> (Villavent, VillaventTemperatureGroup, Temperature)
Number VillaventSupplyAirTemp_in "Supply air temperature [%d]" (Villavent) { modbus="vvhc:13" }
Number VillaventSupplyAirGraph (PersistAndRestore)

Number VillaventExtractAirTemp "Extract air temperature [%.1f °C]" <temperature> (Villavent, VillaventTemperatureGroup, Temperature)
Number VillaventExtractAirTemp_in "Extract air temperature [%d]" (Villavent) { modbus="vvhc:14" }
Number VillaventExtractAirGraph (PersistAndRestore)

Number VillaventExhaustAirTemp "Exhaust air temperature [%.1f °C]" <temperature> (Villavent)
Number VillaventExhaustAirTemp_in "Exhaust air temperature [%d]" (Villavent) { modbus="vvhc:15" }
Number VillaventExhaustAirGraph (PersistAndRestore)

Number VillaventProtectAirTemp "Overheating/Frosprotection temperature [%.1f °C]" <temperature> (Villavent, VillaventTemperatureGroup, Temperature)
Number VillaventProtectAirTemp_in "Overheating/Frosprotection temperature [%d]" (Villavent) { modbus="vvhc:16" }
Number VillaventProtectAirGraph (PersistAndRestore)

Number VillaventIntakeAirTemp "Intake air temperature [%.1f °C]" <temperature> (Villavent, VillaventTemperatureGroup, Temperature)
Number VillaventIntakeAirTemp_in "Intake air temperature [%d]" (Villavent) { modbus="vvhc:17" }
Number VillaventIntakeAirGraph (PersistAndRestore)

Number VillaventHeaterType "Heater type" <smoke> (Villavent, Persist) { modbus="vvhc:0" }
Number VillaventCoolerType "Cooler type" <climate> (Villavent, Persist) { modbus="vvhc:1" }
Number VillaventPreHeaterType "Pre-heater type" <smoke> (Villavent, Persist) { modbus="vvhc:19" }

Number VillaventFlowUnits "Fan speed flow unit" <pressure> (Villavent, Persist) { modbus="vvfan:7" }
Number VillaventFanControlType "Fan control" <flow> (Villavent, Persist) { modbus="vvfan:37" }
Number VillaventAllowFanStop "Control panel fan stop allowed" <switch> (Villavent, Persist) { modbus="vvfan:13" }

Number VillaventSupplyFanSystemCurve "Supply fan system curve [%d]" <line> (Villavent, Persist) { modbus="vvfan:35" }
Number VillaventSupplyFanSpeedLow "Supply fan speed for low [%d]" <fan> (Villavent, Persist) { modbus="vvfan:1" }
Number VillaventSupplyFanSpeedNom "Supply fan speed for nominal [%d]" <fan> (Villavent, Persist) { modbus="vvfan:3" }
Number VillaventSupplyFanSpeedHigh "Supply fan speed for high [%d]" <fan> (Villavent, Persist) { modbus="vvfan:5" }

Number VillaventExtractFanSystemCurve "Extract fan system curve [%d]" <line> (Villavent, Persist) { modbus="vvfan:36" }
Number VillaventExtractFanSpeedLow "Extract fan speed for low [%d]" <fan> (Villavent, Persist) { modbus="vvfan:2" }
Number VillaventExtractFanSpeedNom "Extract fan speed for nominal [%d]" <fan> (Villavent, Persist) { modbus="vvfan:4" }
Number VillaventExtractFanSpeedHigh "Extract fan speed for high [%d]" <fan> (Villavent, Persist) { modbus="vvfan:5" }

Number VillaventRotorState "Rotor state [MAP(]" <sun> (Villavent, Persist) { modbus="vvrot:0" }
Switch VillaventRotorRelayActive "Rotor relay [%s]" <switch> (Villavent, VillaventTemperatureGroup, Persist) { modbus="vvrot:1" }

Number VillaventDefrostState "Defrosting state [MAP(]" <rain> (Villavent, Persist) { modbus="vvdefr:0" }
Number VillaventDefrostMode "Defrosting mode [%d]" <qualityofservice> (Villavent, Persist) { modbus="vvdefr:1" }

Number VillaventFilterPeriod "Filter replace time [%d months]" <calendar> (Villavent, Persist) { modbus="vvfilter:0" }
Number VillaventFilterDays "Filter days since last replacement [%d days]" <time> (Villavent, Persist) { modbus="vvfilter:1" }

Number VillaventSystemType "System type [MAP(]" <contact> (Villavent, Persist) { modbus="vvsys:0" }

String VillaventProgVersion "Program version [%s]" <shield> (Villavent, Persist)
Number VillaventProgVH (Villavent) { modbus="vvsys:1" }
Number VillaventProgVM (Villavent) { modbus="vvsys:2" }
Number VillaventProgVL (Villavent) { modbus="vvsys:3" }
String VillaventBootVersion "Boot version [%s]" <shield> (Villavent, Persist)
Number VillaventBootVH (Villavent) { modbus="vvsys:4" }
Number VillaventBootVM (Villavent) { modbus="vvsys:5" }
Number VillaventBootVL (Villavent) { modbus="vvsys:6" }

DateTime VillaventClock "Clock [%s]" <time> (Villavent)
Number VillaventClockS "Clock seconds [%d]" (Villavent) { modbus="vvclock:0" }
Number VillaventClockM "Clock minutes [%d]" (Villavent) { modbus="vvclock:1" }
Number VillaventClockH "Clock hours [%d]" (Villavent) { modbus="vvclock:2" }
Number VillaventClockD "Clock day of month [%d]" (Villavent) { modbus="vvclock:3" }
Number VillaventClockMNTH "Clock month [%d]" (Villavent) { modbus="vvclock:4" }
Number VillaventClockY "Clock year [%d]" (Villavent) { modbus="vvclock:5" }

Switch VillaventSupplyAirTempFault "Supply air temperature sensor fault [%s]" <siren> (Villavent, Persist) { modbus="vvtsf:0" }
Switch VillaventExtractAirTempFault "Extract air temperature sensor fault [%s]" <siren> (Villavent, Persist) { modbus="vvtsf:0" }
Switch VillaventExhaustAirTempFault "Exhaust air temperature sensor fault [%s]" <siren> (Villavent, Persist) { modbus="vvtsf:0" }
Switch VillaventProtectAirTempFault "Overheating/Frostprotection temperature sensor fault [%s]" <siren> (Villavent, Persist) { modbus="vvtsf:0" }
Switch VillaventIntakeAirTempFault "Intake air temperature sensor fault [%s]" <siren> (Villavent, Persist) { modbus="vvtsf:0" }

Switch VillaventDigital1 "Digital input 1 [%s]" <switch> (Villavent, Persist) { modbus="vvdi:0" }
Number VillaventDigital1SF "Supply fan speed at DI1 [%s]" <fan> (Villavent, Persist) { modbus="vvdig:3" }
Number VillaventDigital1EF "Extract fan speed at DI1 [%s]" <fan> (Villavent, Persist) { modbus="vvdig:4" }
Switch VillaventDigital2 "Digital input 2 [%s]" <switch> (Villavent, Persist) { modbus="vvdi:1" }
Number VillaventDigital2SF "Supply fan speed at DI2 [%s]" <fan> (Villavent, Persist) { modbus="vvdig:5" }
Number VillaventDigital2EF "Extract fan speed at DI2 [%s]" <fan> (Villavent, Persist) { modbus="vvdig:6" }
Switch VillaventDigital3 "Digital input 3 [%s]" <switch> (Villavent, Persist) { modbus="vvdi:2" }
Number VillaventDigital3SF "Supply fan speed at DI3 [%s]" <fan> (Villavent, Persist) { modbus="vvdig:7" }
Number VillaventDigital3EF "Extract fan speed at DI3 [%s]" <fan> (Villavent, Persist) { modbus="vvdig:8" }
Switch VillaventDigital4 "Stop heat [%s]" <switch> (Villavent, Persist) { modbus="vvdi:3" }
Switch VillaventDigital5 "Extended run [%s]" <switch> (Villavent, Persist) { modbus="vvdi:4" }
Number VillaventDigital5Min "Extended running time [%d]" <time> (Villavent, Persist) { modbus="vvdig:1" }
Number VillaventDigital5Speed "Extended running speed [%d]" <fan> (Villavent, Persist) { modbus="vvdig:2" }
Switch VillaventDigital6 "Rotor top sensor [%s]" <switch> (Villavent, Persist) { modbus="vvdi:5" }
Switch VillaventDigital7 "Away [%s]" <switch> (Villavent, Persist) { modbus="vvdi:6" }

Switch VillaventFilterAlarm "Filter alarm [%s]" <siren> (Villavent, Persist) { modbus="vval:0" }
Switch VillaventFanAlarm "Fan alarm [%s]" <siren> (Villavent, Persist) { modbus="vval:1" }
Switch VillaventRotorAlarm "Rotor alarm [%s]" <siren> (Villavent, Persist) { modbus="vval:3" }
Switch VillaventFrostAlarm "Frost alarm [%s]" <siren> (Villavent, Persist) { modbus="vval:4" }
Switch VillaventPcuPbAlarm "PCU-PB alarm [%s]" <siren> (Villavent, Persist) { modbus="vval:5" }
Switch VillaventTempSensorAlarm "Temperature sensor alarm [%s]" <siren> (Villavent, Persist) { modbus="vval:6" }
Switch VillaventThermostatAlarm "Emergency thermostat alarm [%s]" <siren> (Villavent, Persist) { modbus="vval:7" }
Switch VillaventDamperAlarm "Damper alarm [%s]" <siren> (Villavent, Persist) { modbus="vval:8" }

Switch VillaventPreHeaterRelay "Preheater relay [%s]" <switch> (Villavent, Persist) { modbus="vvpcu:0" }
Switch VillaventHeaterRelay "Heater relay [%s]" <switch> (Villavent, Persist) { modbus="vvpcu:1" }
Switch VillaventCommonHeaterRelay "Common relay [%s]" <switch> (Villavent, Persist) { modbus="vvpcu:2" }


import java.math.BigDecimal
import java.util.Calendar

rule "Villavent home"
    Item PresenceState changed to HOME

rule "Villavent away"
    Item PresenceState changed to AWAY

rule "Correct supply air temp"
    Item VillaventSupplyAirTemp_in changed
    val BigDecimal ret = (VillaventSupplyAirTemp_in.state as DecimalType).toBigDecimal.movePointLeft(1)
    VillaventSupplyAirTemp.postUpdate(new DecimalType(ret))

rule "Correct extract air temp"
    Item VillaventExtractAirTemp_in changed
    val BigDecimal ret = (VillaventExtractAirTemp_in.state as DecimalType).toBigDecimal.movePointLeft(1)
    VillaventExtractAirTemp.postUpdate(new DecimalType(ret))

rule "Correct exhaust air temp"
    Item VillaventExhaustAirTemp_in changed
    val BigDecimal ret = (VillaventExhaustAirTemp_in.state as DecimalType).toBigDecimal.movePointLeft(1)
    VillaventExhaustAirTemp.postUpdate(new DecimalType(ret))

rule "Correct protect air temp"
    Item VillaventProtectAirTemp_in changed
    val BigDecimal ret = (VillaventProtectAirTemp_in.state as DecimalType).toBigDecimal.movePointLeft(1)
    VillaventProtectAirTemp.postUpdate(new DecimalType(ret))

rule "Correct intake air temp"
    Item VillaventIntakeAirTemp_in changed
    val BigDecimal ret = (VillaventIntakeAirTemp_in.state as DecimalType).toBigDecimal.movePointLeft(1)
    VillaventIntakeAirTemp.postUpdate(new DecimalType(ret))

rule "Filter alert"
    Item VillaventFilterDays changed
    if (((VillaventFilterDays.state as DecimalType).intValue % Math::round(((VillaventFilterPeriod.state as DecimalType).intValue * 30.5) - 30)) == 0) {
        pushover("WARN: Villavent filter replacement is due")
    } else {
        if ((VillaventFilterDays.state as DecimalType).intValue >= (VillaventFilterPeriod.state as DecimalType).intValue * 30.5) {
            pushover("ERROR: Villavent filter replacement overdue")

rule "VV read clock"
    Item VillaventClockS changed
    var Calendar cal = Calendar::getInstance()
    cal.set(Calendar::HOUR_OF_DAY, (VillaventClockH.state as DecimalType).intValue)
    cal.set(Calendar::MINUTE, (VillaventClockM.state as DecimalType).intValue)
    cal.set(Calendar::SECOND, (VillaventClockS.state as DecimalType).intValue)
    cal.set(Calendar::DAY_OF_MONTH, (VillaventClockD.state as DecimalType).intValue)
    cal.set(Calendar::MONTH, (VillaventClockMNTH.state as DecimalType).intValue)
    cal.set(Calendar::YEAR, (VillaventClockY.state as DecimalType).intValue+2000)
    VillaventClock.postUpdate(new DateTimeType(cal))

rule "VV write clock"
    System started or
    Time cron "0 0 6 * * ?"
    var Calendar cal = Calendar::getInstance()


rule "Write NVM"
    Time is midnight

rule "Villavent Program Version"
    System started or
    Item VillaventProgVH changed or
    Item VillaventProgVM changed or
    Item VillaventProgVL changed or
    Time is midnight
        (VillaventProgVH.state as DecimalType).intValue,
        (VillaventProgVM.state as DecimalType).intValue,
        (VillaventProgVL.state as DecimalType).intValue

rule "Villavent Boot Version"
    System started or
    Item VillaventBootVH changed or
    Item VillaventBootVM changed or
    Item VillaventBootVL changed or
    Time is midnight
        (VillaventBootVH.state as DecimalType).intValue,
        (VillaventBootVM.state as DecimalType).intValue,
        (VillaventBootVL.state as DecimalType).intValue

rule "Villavent filter alarm"
    Item VillaventFilterAlarm changed from OFF to ON
    pushover("ERROR: Villavent filter")

rule "Villavent filter ok"
    Item VillaventFilterAlarm changed from ON to OFF
    pushover("OK: Villavent filter")

rule "Villavent fan alarm"
    Item VillaventFanAlarm changed from OFF to ON
    pushover("ERROR: Villavent fan")

rule "Villavent fan ok"
    Item VillaventFanAlarm changed from ON to OFF
    pushover("OK: Villavent fan")

rule "Villavent rotor alarm"
    Item VillaventRotorAlarm changed from OFF to ON
    pushover("ERROR: Villavent rotor")

rule "Villavent rotor ok"
    Item VillaventRotorAlarm changed from ON to OFF
    pushover("OK: Villavent rotor")

rule "Villavent frost alarm"
    Item VillaventFrostAlarm changed from OFF to ON
    pushover("ERROR: Villavent frost")

rule "Villavent frost ok"
    Item VillaventFrostAlarm changed from ON to OFF
    pushover("OK: Villavent frost")

rule "Villavent PCU-PB alarm"
    Item VillaventPcuPbAlarm changed from OFF to ON
    pushover("ERROR: Villavent PCU-PB")

rule "Villavent PCU-PB ok"
    Item VillaventPcuPbAlarm changed from ON to OFF
    pushover("OK: Villavent PCU-PB")

rule "Villavent temp sensor alarm"
    Item VillaventTempSensorAlarm changed from OFF to ON
    pushover("ERROR: Villavent temp sensor")

rule "Villavent temp sensor ok"
    Item VillaventTempSensorAlarm changed from ON to OFF
    pushover("OK: Villavent temp sensor")

rule "Villavent thermostat alarm"
    Item VillaventThermostatAlarm changed from OFF to ON
    pushover("ERROR: Villavent emergency thermostat")

rule "Villavent thermostat ok"
    Item VillaventThermostatAlarm changed from ON to OFF
    pushover("OK: Villavent emergency thermostat")

rule "Villavent damper alarm"
    Item VillaventDamperAlarm changed from OFF to ON
    pushover("ERROR: Villavent damper")

rule "Villavent damper ok"
    Item VillaventDamperAlarm changed from ON to OFF
    pushover("OK: Villavent damper")


sitemap villavent label="Villavent" {
	Selection item=VillaventTempLvl mappings=[11="22 °C", 10="21 °C", 9="20 °C", 8="19 °C", 7="18 °C", 6="17 °C", 5="16 °C", 4="15 °C", 3="14 °C", 2="13 °C", 1="12° C", 0="Summer mode"]
	Selection item=VillaventFan icon=qualityofservice mappings=[4="Auto", 3="Max", 2="Normal", 1="Low", 0="Off"]
	Text item=VillaventSupplyAirTemp {
		Switch item=VillaventSupplyAirGraph label="Graph period" mappings=[1="Hour", 2="Day", 3="Week", 4="Month", 5="Year"]
		Chart item=VillaventSupplyAirTemp period=h refresh=30000 visibility=[VillaventSupplyAirGraph==1]
		Chart item=VillaventSupplyAirTemp period=D refresh=900000 visibility=[VillaventSupplyAirGraph==2]
		Chart item=VillaventSupplyAirTemp period=W refresh=3600000 visibility=[VillaventSupplyAirGraph==3]
		Chart item=VillaventSupplyAirTemp period=M refresh=3600000 visibility=[VillaventSupplyAirGraph==4]
		Chart item=VillaventSupplyAirTemp period=Y refresh=3600000 visibility=[VillaventSupplyAirGraph==5]
	Text item=VillaventSupplyFanRpm {
		Switch item=VillaventSupplyFanGraph label="Graph period" mappings=[1="Hour", 2="Day", 3="Week", 4="Month", 5="Year"]
		Chart item=VillaventSupplyFanRpm period=h refresh=30000 visibility=[VillaventSupplyFanGraph==1]
		Chart item=VillaventSupplyFanRpm period=D refresh=900000 visibility=[VillaventSupplyFanGraph==2]
		Chart item=VillaventSupplyFanRpm period=W refresh=3600000 visibility=[VillaventSupplyFanGraph==3]
		Chart item=VillaventSupplyFanRpm period=M refresh=3600000 visibility=[VillaventSupplyFanGraph==4]
		Chart item=VillaventSupplyFanRpm period=Y refresh=3600000 visibility=[VillaventSupplyFanGraph==5]
	Text item=VillaventExtractAirTemp {
		Switch item=VillaventExtractAirGraph label="Graph period" mappings=[1="Hour", 2="Day", 3="Week", 4="Month", 5="Year"]
		Chart item=VillaventExtractAirTemp period=h refresh=30000 visibility=[VillaventExtractAirGraph==1]
		Chart item=VillaventExtractAirTemp period=D refresh=900000 visibility=[VillaventExtractAirGraph==2]
		Chart item=VillaventExtractAirTemp period=W refresh=3600000 visibility=[VillaventExtractAirGraph==3]
		Chart item=VillaventExtractAirTemp period=M refresh=3600000 visibility=[VillaventExtractAirGraph==4]
		Chart item=VillaventExtractAirTemp period=Y refresh=3600000 visibility=[VillaventExtractAirGraph==5]
	Text item=VillaventExtractFanRpm {
		Switch item=VillaventExtractFanGraph label="Graph period" mappings=[1="Hour", 2="Day", 3="Week", 4="Month", 5="Year"]
		Chart item=VillaventExtractFanRpm period=h refresh=30000 visibility=[VillaventExtractFanGraph==1]
		Chart item=VillaventExtractFanRpm period=D refresh=900000 visibility=[VillaventExtractFanGraph==2]
		Chart item=VillaventExtractFanRpm period=W refresh=3600000 visibility=[VillaventExtractFanGraph==3]
		Chart item=VillaventExtractFanRpm period=M refresh=3600000 visibility=[VillaventExtractFanGraph==4]
		Chart item=VillaventExtractFanRpm period=Y refresh=3600000 visibility=[VillaventExtractFanGraph==5]
	Text item=VillaventIntakeAirTemp {
		Switch item=VillaventIntakeAirGraph label="Graph period" mappings=[1="Hour", 2="Day", 3="Week", 4="Month", 5="Year"]
		Chart item=VillaventIntakeAirTemp period=h refresh=30000 visibility=[VillaventIntakeAirGraph==1]
		Chart item=VillaventIntakeAirTemp period=D refresh=900000 visibility=[VillaventIntakeAirGraph==2]
		Chart item=VillaventIntakeAirTemp period=W refresh=3600000 visibility=[VillaventIntakeAirGraph==3]
		Chart item=VillaventIntakeAirTemp period=M refresh=3600000 visibility=[VillaventIntakeAirGraph==4]
		Chart item=VillaventIntakeAirTemp period=Y refresh=3600000 visibility=[VillaventIntakeAirGraph==5]
	Text item=Villavent label="Configuration" icon=settings {
		Frame label="Information" {
			Text item=VillaventSystemType
			Text item=VillaventClock
			Text item=VillaventProgVersion
			Text item=VillaventBootVersion
		Frame label="Fan" {
			Selection item=VillaventFanControlType mappings=[0="Air flow", 1="Speed"]
			Selection item=VillaventFlowUnits mappings=[0="l/s", 1="m3/h"]
			Setpoint item=VillaventSupplyFanSystemCurve minValue=0 maxValue=20 step=1
			Setpoint item=VillaventExtractFanSystemCurve minValue=0 maxValue=10 step=1
			Setpoint item=VillaventSupplyFanSpeedLow minValue=10 maxValue=100 step=1
			Setpoint item=VillaventExtractFanSpeedLow minValue=10 maxValue=100 step=1
			Setpoint item=VillaventSupplyFanSpeedNom minValue=10 maxValue=100 step=1
			Setpoint item=VillaventExtractFanSpeedNom minValue=10 maxValue=100 step=1
			Setpoint item=VillaventSupplyFanSpeedHigh minValue=10 maxValue=100 step=1
			Setpoint item=VillaventExtractFanSpeedHigh minValue=10 maxValue=100 step=1
			Switch item=VillaventAllowFanStop
		Frame label="Filter" {
			Setpoint item=VillaventFilterPeriod minValue=6 maxValue=12 step=1 label="Replace interval"
			Text item=VillaventFilterDays label="Days since last replace"
		Frame label="Heater and cooler" {
			Selection item=VillaventHeaterType mappings=[3="Contactor", 2="Electrical", 1="Water", 0="None"]
			Text item=VillaventHeaterRelay
			Selection item=VillaventPreHeaterType mappings=[1="Electrical", 0="None"]
			Text item=VillaventPreHeaterRelay
			Selection item=VillaventCoolerType mappings=[1="Water", 0="None"]
			Text item=VillaventCommonHeaterRelay
			Selection item=VillaventFrostProtection mappings=[120="12° C", 110="11° C", 100="10° C", 90="9° C", 80="8° C", 70="7° C"]
			Switch item=VillaventDigital4
			Text item=VillaventHeatSetpoint
		Frame label="Rotor" {
			Text item=VillaventRotorState label="State"
			Text item=VillaventRotorRelayActive label="Relay"
			Text item=VillaventDigital6 label="Rotation sensor"
		Frame label="Defrosting" {
			Text item=VillaventDefrostState label="State"
			Selection item=VillaventDefrostMode mappings=[0="0", 1="1", 2="2", 3="3", 4="4", 5="5"] label="Mode"
		Frame label="Digital inputs" {
			Switch item=VillaventDigital7
		Frame label="" {
			Switch item=VillaventDigital1
			Selection item=VillaventDigital1SF mappings=[3="Max", 2="Normal", 1="Low", 0="Off"]
			Selection item=VillaventDigital1EF mappings=[3="Max", 2="Normal", 1="Low", 0="Off"]
		Frame label="" {
			Switch item=VillaventDigital2
			Selection item=VillaventDigital2SF mappings=[3="Max", 2="Normal", 1="Low", 0="Off"]
			Selection item=VillaventDigital2EF mappings=[3="Max", 2="Normal", 1="Low", 0="Off"]
		Frame label="" {
			Switch item=VillaventDigital3
			Selection item=VillaventDigital3SF mappings=[3="Max", 2="Normal", 1="Low", 0="Off"]
			Selection item=VillaventDigital3EF mappings=[3="Max", 2="Normal", 1="Low", 0="Off"]
		Frame label="" {
			Switch item=VillaventDigital5
			Setpoint item=VillaventDigital5Min minValue=1 maxValue=60 step=1
			Selection item=VillaventDigital5Speed mappings=[3="Max", 2="Normal", 1="Low", 0="Off"]
		Frame label="Temperature sensors" {
			Text item=VillaventSupplyAirTemp
			Text item=VillaventSupplyAirTempFault
			Text item=VillaventExtractAirTemp
			Text item=VillaventExtractAirTempFault
			Text item=VillaventExhaustAirTemp
			Text item=VillaventExhaustAirTempFault
			Text item=VillaventProtectAirTemp
			Text item=VillaventProtectAirTempFault
			Text item=VillaventIntakeAirTemp
			Text item=VillaventIntakeAirTempFault
		Frame label="Alarms" {
			Text item=VillaventFilterAlarm
			Text item=VillaventFanAlarm
			Text item=VillaventRotorAlarm
			Text item=VillaventFrostAlarm
			Text item=VillaventPcuPbAlarm
			Text item=VillaventTempSensorAlarm
			Text item=VillaventThermostatAlarm
			Text item=VillaventDamperAlarm
	Text item=VillaventTemperatureGroup label="Temperature graph" icon=line {
		Switch item=VillaventTemperatureGroupGraph label="Graph period" mappings=[1="Hour", 2="Day", 3="Week", 4="Month", 5="Year"]
		Chart item=VillaventTemperatureGroup period=h refresh=30000 visibility=[VillaventTemperatureGroupGraph==1]
		Chart item=VillaventTemperatureGroup period=D refresh=900000 visibility=[VillaventTemperatureGroupGraph==2]
		Chart item=VillaventTemperatureGroup period=W refresh=3600000 visibility=[VillaventTemperatureGroupGraph==3]
		Chart item=VillaventTemperatureGroup period=M refresh=3600000 visibility=[VillaventTemperatureGroupGraph==4]
		Chart item=VillaventTemperatureGroup period=Y refresh=3600000 visibility=[VillaventTemperatureGroupGraph==5]

(Kim Skatun) #62

This is such a great write up, do you reckon you could turn it into a tutorial and also add some screenshots of the setup(both sitemaps and physical wiring). Great work Gunnar!

(Gunnar Skjold) #63

Thanks, I’ll see what I can do over a cold beer one weekend :slight_smile:

(Miha Mihalj) #64

Hi, please can you give some screenshots of wiring on Systemair ventilation?

(Gunnar Skjold) #65

My recommendation, buy something like a FTDI USB-RS485-PCBA and connect like attached image. Solid blue to B and striped blue to A from a standard T568 color coded RJ45 cable.


(Gunnar Skjold) #66

I have also edited the configuration in my previous comment to match the config I use today.

(Miha Mihalj) #67

OK so that it, just plug one side of the cable RJ-45 to board on Systemair HRV unit and other side with two wires like you mentioned to FTDI USB and then plug it to Raspberry pi…

Please send picture how does it look on OH dashboard…

(Gunnar Skjold) #68

Correct. According to the modbus document from Systemair, the following units use this registry set:
VR400, VR700, VR700DK, VR400DE, VTC300, VTC700, VTR150K, VTR200B, VSR300, VSR500, VSR150, VTR300, VTR500, VSR300DE, VTC200

There may be more that also use the same registry set, but these are at least mentioned in the document.

I have tested this on a Asus Tinkerboard, and the system totally crash when I run openhab with this setup. Without the RS485 USB connected it runs fine. I’m not sure if this is some issue isolated to Tinkerboard and the chipset it uses or if this would apply for Raspberry Pi as well. As far as I could tell when debugging it was related to chipset and IO. I did not use much time to try and fix it as it wasn’t important to me.

An alternative would be to find a modbus rs485 to tcp/ip adapter, but I have no suggestion on what hardware to use or how well it works.

Following is some screenshots from my openhab basicui:

Configuration menu:

Temperature graph:

(Kim Skatun) #69

I guess it would be nice to set up a usb rule, so that in case of shutdown and a new number get assigned it will still work. I am can not rember how to do this now, but it is explained somewhere on the forum here. Just a small tip. It looks awesome @gskjold, and something I will definitely implement over Xmas, are you running it on a RPI?

Do you have link to your dongle?

So which temperatures do you recommend to use? Some models have an optional heating element to preheat the incoming air(supply).

(Gunnar Skjold) #70

I have the followig in my /etc/udev/rules.d/99-usb-serial.rules

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", OWNER="openhab" SYMLINK="modbus"

This creates /dev/modbus as a device, but openhab does not work with this symlink for some reason. I have not chased this issue, so the solution may be simple. On reboot the device stays the same. Only replugging the device will change the identifier.

Not tried this setup on rpi yet. I use a HP G7 micro server.

My dongle is a FTDI USB-RS485-PCBA which you can find on ebay.

As for set temperatures I have 22° set in the winter. I use the electric heater in mine. I just feel this makes for more comfortable air in my house. My rules sets the away flag in the unit which switches off this heater when I am away. You can see it in the temperature graph. Looking at the blue and red line (which overlaps), you can see the ripples in the supply air when I am home, and how it is switched off when I am away. I also set the fan to low when I am away.

Temp graph:

Fan graph:

(Kim Skatun) #71

To your info I got it to work now. I will make some rules and keep you posted on the progress, thanks for the great work…

Some additional information to you.

  1. I am on openhabian, so I just issued system tweaks to get the serial device to work.
  2. Get last connected USB device
    dmesg | awk '/tty/ && /USB/ {print "/dev/"$10}'|tail -1```
  3. Get the device number
  4. Edit usb rules: sudo nano /etc/udev/rules.d/99-usb-serial.rules
    SUBSYSTEM=="tty", ATTRS{idVendor}=="XXX", ATTRS{idProduct}=="XXXX", OWNER="openhab" SYMLINK="modbus" however I could not get this to work either…
  5. Go to your fan panel and make sure the modbus settings are correct:
    Baudrate:19200, startIndex =1 Parity:None

So lets now move on to the rules:
So what I want to do with the fan is:

  1. Increase the speed if you go to the bathroom
  2. Switch it off when you are not home
  3. Adjust it automatically depending on CO2 level in the flat

The question is if we should adjust the rpm or do we only have the option to set fan speed to 1,2,3,4, what do you think @gskjold, can these be set dynamically:

Number VillaventSupplyFanRpm 
Number VillaventExtractFanRpm 

So my rule idea is shown below

val Functions.Function2 hvac= [ NumberItem setPoint,NumberItem co2Level ||

if manualOverride.state = OFF {
if((co2Level.state as Number)-100.0<(setPoint.state as Number) ) {

   VillaventFan.sendCommand( VillaventFan.state as Number -1)
if((co2Level.state as Number)+100.0>(setPoint.state as Number) ) {

   VillaventFan.sendCommand( VillaventFan.state as Number +1)

The bathroom rule:

rule "Turn up fan"
	Item bathroomLight changed  to ON

	sendCommand(manualOverride, ON)
 sendCommand(manualOverride, OFF)

(Håvard Berland) #72

Thanks for all the details in here, I will build something similar to replace my existing Z-wave unit attached to my VSR-300 (not working in OH2.4, and also with very limited feature set compared to the solution here).

My OpenHAB server is two floors away from the ventilation unit, so a direct connection is not possible. A Raspberry PI is a candidate, any recommendation on how to connect them? USB over TCP/IP, serial over TCP/IP (maybe the same thing?), or possibly write a MQTT service on the Pi?

(Rossko57) #73

There are off-the-shelf solutions like this.
openHAB talks to it as though it were a Modbus-TCP device, and it converts to/from serial Modbus-RTU

(Håvard Berland) #74

Thanks @gskjold for the detailed modbus configuration file and items file (the map-file is missing though).

I have it running with a one-dollar usb-485 adapter on a raspberry pi zero, which is running socat to my OpenHAB server in the basement.

I have already installed four temp+rh sensors in each of the chambers, and I compute efficiency factors continously . Some preliminary testing after some hours of operation reveals that there is additional effiency gain from ensuring that the heating set point is so high that the rotor is always on, but the heater is off. It also took me some time to figure out that I could not control the setpoint through the item VillaventHeatSetpoint, but through VillaventTempLvl (and the former can be subsequently read).

Has anyone converted the setup to the OpenHAB 2 Modbus binding? I think it is then possible to have different polling periods for different items. The VillaventDigital6 (Rotor Top Sensor) should be polled quite often (many times pr. second), it seems, to catch the event that the rotor passes the top, while most others items can be polled with many seconds apart.

(Gunnar Skjold) #75

I see that I’ve missed some posts here, sorry about that…

@skatun great to hear that you got it working! I love the idea of adjusting it for the fan speed based on CO2. What do you use for CO2 measuring?
Switching it off while you are not home is something I would be careful with due to condensation in the intake and exhaust. There is a reason why VillaventAllowFanStop is off as a default.

@berland did you find a good solution for physical connection between the unit and openhab? Personally I try to run everything over cable if I can.
How is the load on your rpi with this connected? I tried openhab on a Asus Tinker Board once, but it crashed as soon as I put the dongle in.
Do you have a device id for your dongle? You can find it using lsusb command in the terminal.
Sorry about my misconfiguration of the VillaventTempLvl adjustment in my setup. I noticed it as well this summer. I must have switched those two items in my sitemap at some point since I have used that dropdown in the sitemap before and seen it work.
Is the four sensors standalone, or have you added the fourth sensor to the unit? At least mine seems to be missing the exhaust air temperature sensor and shows no value on this register.
I have also seen that the efficiency factor is highest in this condition through the units menu. I’m annoyed that the unit does not report this value on the register.

I have recently converted my setup to 2x binding. I think it took me 3hrs to do so… In short, I’ve done:
Added modbus serial slave. Then added poller for each range of registers I need to read. Then added a thing for each item I needed to read from. You can set the poll interval for each poller. So for the digital input coil, you can set something lower.

As a side note, I think the modbus 2x binding has a really strange configuration structure, and I would be surprised if this doesn’t change in the future.

The most recent rules for my villavent is to set the fan to max while the fire alarm is going, and then set it back to normal when the fire alarm goes back to normal state. Any thoughts on how the ventilation should be set if there is a fire?

(Rossko57) #76

I wouldn’t hold your breath for that :slight_smile:
It was developed based on real OH users wrestling with weird and wonderful Modbus devices. The key thing is flexibility to cope with some maker’s truly weird interpretations of modbus ‘standard’.
This does of course make it look over-complicated for simple tasks.

What we do keep bandying about is a method to add-on a module or template from a library for known devices. This would hide complexity. To make it happen would require enough someones with device X, and skills and inclination.

In reality we each solve our own problem, and move on. Helpful folk can of course publish their solutions here, to give latecomers a head start :slight_smile:

(Gunnar Skjold) #77

Thanks @rossko57 for the input, but wouldn’t it be a lot easier to have the register values as dynamic channels on the poll thing? This would to me make a lot more sense and reduce the number of things drastically.

KNX 2x binding is made in that way:

(Rossko57) #78

I don’t really understand the question, not familiar with KNX.
But let me make an example. We want to read registers 5 and 7 say, but there is no register 6. Some devices let you read 5,6,7 in one efficient poll (in our terms, one poller thing with two data channels). Other devices insist you poll 5 and 7 separately (in our terms, two poller things with a data channel each).

There’s no way for the system to tell which is the correct solution, it must be manually configured by a user with understanding.

(Gunnar Skjold) #79

That makes sense, but what doesn’t make sense is that we need to configure a poller thing and then one thing per register with one channel per value type (number, switch etc). This could have been a dynamic channel on the poll thing where you configured the channel type. As an example, I have a “Villavent Digital input” poll thing and then 7 things (one per register) which could have been 7 dynamic channels on the poll thing instead, cleaning up the structure by making 8 things into one. Of course, in the example you have where you need to poll register 5 and 7 separately, you would end up with 2 things, but that would still be less than the 4 things you end up with now for that same example.

KNX is not that much different from modbus, having a bus with several devices which can be completely different in terms of configuration. My DALI gateway in the above example is a completely customizable unit where I have added 5 corresponding dimmer channels in OH manually. Regardless, dynamic channels is a core OH2 feature which in my opinion should have been used with modbus binding.

(Håvard Berland) #80

I am using socat between the Pi and the OpenHAB server. And a systemd service on each machine to ensure they are always running:

pi@systemairpi:~ $ cat /etc/systemd/system/socat.service 
Description=Socat serial port from systemair-pi

ExecStart=/home/pi/   # ensure executable bit is set
# contains: socat /dev/ttyUSB0,raw,echo=0 tcp-listen:8888,reuseaddr


And then on the openhab-server:
berland@ohserver:~$ cat /etc/systemd/system/socat.service

Description=Socat serial port from systemairpi
ExecStart=/home/berland/bin/  # ensure x-bit
# contains: "socat PTY,perm-late=777,raw,echo=0,link=/dev/ttVUSB0 tcp:systemairpi:8888"

Then the modbus binding is configured towards /dev/ttyVUSB0. Note that the VUSB0 device gets permissions 777, evaluate for yourself if that is acceptable.

These two services, once enabled and started, will make sure that the connection is always up and running, through socat crashes (not yet) and reboots. However, at least the Modbus 1 binding does not seem to be able to pick it up after /dev/ttyVUSB0 is reinstated, so I have yet another shell-script that checks a particular item for being expired (expire binding on the RPM), and if so, restarts the modbus bundle.

# Restart the modbus bundle if a certain item has expired. 
# You must configure expire on that particular item, AND ensure that the item is reset
# each time OpenHAB is started (otherwise, it might not expire as it should)
# (this script is not pretty!)
while : ; do
    rpm=`curl --silent http://192.168.x.x:8080/rest/items/VillaventSupplyFanRpm/state`
    if [ $rpm == 'UNDEF' ] ; then
        echo "Modbus maybe not working, restarting"
        bundleid=`echo "bundle:list" | openhab-cli console | grep  "ModbusTCP Master" | cut -f1 -d' '`
        echo "bundle:restart $bundleid" | openhab-cli console
        echo "all fine, waiting 10 sec" 
    sleep 10

And then make sure this script is also running as a service.