You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2022/07/22 10:39:49 UTC

[plc4x] 02/02: fix(cbus): fixed auxiliary levels on temperature and humidity

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 1041868caf1357003b2a163519a06a3df5b69e79
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Jul 22 12:39:40 2022 +0200

    fix(cbus): fixed auxiliary levels on temperature and humidity
---
 .../AirConditioningDataSetPlantHumidityLevel.go    | 61 ++++++++++++++--------
 .../model/AirConditioningDataSetPlantHvacLevel.go  | 61 ++++++++++++++--------
 .../AirConditioningDataSetZoneHumidityMode.go      | 61 ++++++++++++++--------
 .../model/AirConditioningDataSetZoneHvacMode.go    | 61 ++++++++++++++--------
 .../apache/plc4x/java/cbus/RandomPackagesTest.java | 46 ++++++++++------
 .../org/apache/plc4x/java/cbus/ReferenceTest.java  |  8 ++-
 .../src/main/resources/protocols/cbus/c-bus.mspec  | 16 +++---
 7 files changed, 197 insertions(+), 117 deletions(-)

diff --git a/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetPlantHumidityLevel.go b/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetPlantHumidityLevel.go
index 4ee3a7dba..1b1d6c180 100644
--- a/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetPlantHumidityLevel.go
+++ b/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetPlantHumidityLevel.go
@@ -184,8 +184,10 @@ func (m *_AirConditioningDataSetPlantHumidityLevel) GetLengthInBitsConditional(l
 		lengthInBits += m.RawLevel.GetLengthInBits()
 	}
 
-	// Simple field (auxLevel)
-	lengthInBits += m.AuxLevel.GetLengthInBits()
+	// Optional Field (auxLevel)
+	if m.AuxLevel != nil {
+		lengthInBits += m.AuxLevel.GetLengthInBits()
+	}
 
 	return lengthInBits
 }
@@ -293,17 +295,26 @@ func AirConditioningDataSetPlantHumidityLevelParse(readBuffer utils.ReadBuffer)
 		}
 	}
 
-	// Simple Field (auxLevel)
-	if pullErr := readBuffer.PullContext("auxLevel"); pullErr != nil {
-		return nil, errors.Wrap(pullErr, "Error pulling for auxLevel")
-	}
-	_auxLevel, _auxLevelErr := HVACAuxiliaryLevelParse(readBuffer)
-	if _auxLevelErr != nil {
-		return nil, errors.Wrap(_auxLevelErr, "Error parsing 'auxLevel' field of AirConditioningDataSetPlantHumidityLevel")
-	}
-	auxLevel := _auxLevel.(HVACAuxiliaryLevel)
-	if closeErr := readBuffer.CloseContext("auxLevel"); closeErr != nil {
-		return nil, errors.Wrap(closeErr, "Error closing for auxLevel")
+	// Optional Field (auxLevel) (Can be skipped, if a given expression evaluates to false)
+	var auxLevel HVACAuxiliaryLevel = nil
+	if humidityModeAndFlags.GetIsAuxLevelUsed() {
+		currentPos = positionAware.GetPos()
+		if pullErr := readBuffer.PullContext("auxLevel"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for auxLevel")
+		}
+		_val, _err := HVACAuxiliaryLevelParse(readBuffer)
+		switch {
+		case errors.Is(_err, utils.ParseAssertError{}) || errors.Is(_err, io.EOF):
+			log.Debug().Err(_err).Msg("Resetting position because optional threw an error")
+			readBuffer.Reset(currentPos)
+		case _err != nil:
+			return nil, errors.Wrap(_err, "Error parsing 'auxLevel' field of AirConditioningDataSetPlantHumidityLevel")
+		default:
+			auxLevel = _val.(HVACAuxiliaryLevel)
+			if closeErr := readBuffer.CloseContext("auxLevel"); closeErr != nil {
+				return nil, errors.Wrap(closeErr, "Error closing for auxLevel")
+			}
+		}
 	}
 
 	if closeErr := readBuffer.CloseContext("AirConditioningDataSetPlantHumidityLevel"); closeErr != nil {
@@ -408,16 +419,20 @@ func (m *_AirConditioningDataSetPlantHumidityLevel) Serialize(writeBuffer utils.
 			}
 		}
 
-		// Simple Field (auxLevel)
-		if pushErr := writeBuffer.PushContext("auxLevel"); pushErr != nil {
-			return errors.Wrap(pushErr, "Error pushing for auxLevel")
-		}
-		_auxLevelErr := writeBuffer.WriteSerializable(m.GetAuxLevel())
-		if popErr := writeBuffer.PopContext("auxLevel"); popErr != nil {
-			return errors.Wrap(popErr, "Error popping for auxLevel")
-		}
-		if _auxLevelErr != nil {
-			return errors.Wrap(_auxLevelErr, "Error serializing 'auxLevel' field")
+		// Optional Field (auxLevel) (Can be skipped, if the value is null)
+		var auxLevel HVACAuxiliaryLevel = nil
+		if m.GetAuxLevel() != nil {
+			if pushErr := writeBuffer.PushContext("auxLevel"); pushErr != nil {
+				return errors.Wrap(pushErr, "Error pushing for auxLevel")
+			}
+			auxLevel = m.GetAuxLevel()
+			_auxLevelErr := writeBuffer.WriteSerializable(auxLevel)
+			if popErr := writeBuffer.PopContext("auxLevel"); popErr != nil {
+				return errors.Wrap(popErr, "Error popping for auxLevel")
+			}
+			if _auxLevelErr != nil {
+				return errors.Wrap(_auxLevelErr, "Error serializing 'auxLevel' field")
+			}
 		}
 
 		if popErr := writeBuffer.PopContext("AirConditioningDataSetPlantHumidityLevel"); popErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetPlantHvacLevel.go b/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetPlantHvacLevel.go
index 18e3555e3..5ef4c4ec0 100644
--- a/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetPlantHvacLevel.go
+++ b/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetPlantHvacLevel.go
@@ -184,8 +184,10 @@ func (m *_AirConditioningDataSetPlantHvacLevel) GetLengthInBitsConditional(lastI
 		lengthInBits += m.RawLevel.GetLengthInBits()
 	}
 
-	// Simple field (auxLevel)
-	lengthInBits += m.AuxLevel.GetLengthInBits()
+	// Optional Field (auxLevel)
+	if m.AuxLevel != nil {
+		lengthInBits += m.AuxLevel.GetLengthInBits()
+	}
 
 	return lengthInBits
 }
@@ -293,17 +295,26 @@ func AirConditioningDataSetPlantHvacLevelParse(readBuffer utils.ReadBuffer) (Air
 		}
 	}
 
-	// Simple Field (auxLevel)
-	if pullErr := readBuffer.PullContext("auxLevel"); pullErr != nil {
-		return nil, errors.Wrap(pullErr, "Error pulling for auxLevel")
-	}
-	_auxLevel, _auxLevelErr := HVACAuxiliaryLevelParse(readBuffer)
-	if _auxLevelErr != nil {
-		return nil, errors.Wrap(_auxLevelErr, "Error parsing 'auxLevel' field of AirConditioningDataSetPlantHvacLevel")
-	}
-	auxLevel := _auxLevel.(HVACAuxiliaryLevel)
-	if closeErr := readBuffer.CloseContext("auxLevel"); closeErr != nil {
-		return nil, errors.Wrap(closeErr, "Error closing for auxLevel")
+	// Optional Field (auxLevel) (Can be skipped, if a given expression evaluates to false)
+	var auxLevel HVACAuxiliaryLevel = nil
+	if hvacModeAndFlags.GetIsAuxLevelUsed() {
+		currentPos = positionAware.GetPos()
+		if pullErr := readBuffer.PullContext("auxLevel"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for auxLevel")
+		}
+		_val, _err := HVACAuxiliaryLevelParse(readBuffer)
+		switch {
+		case errors.Is(_err, utils.ParseAssertError{}) || errors.Is(_err, io.EOF):
+			log.Debug().Err(_err).Msg("Resetting position because optional threw an error")
+			readBuffer.Reset(currentPos)
+		case _err != nil:
+			return nil, errors.Wrap(_err, "Error parsing 'auxLevel' field of AirConditioningDataSetPlantHvacLevel")
+		default:
+			auxLevel = _val.(HVACAuxiliaryLevel)
+			if closeErr := readBuffer.CloseContext("auxLevel"); closeErr != nil {
+				return nil, errors.Wrap(closeErr, "Error closing for auxLevel")
+			}
+		}
 	}
 
 	if closeErr := readBuffer.CloseContext("AirConditioningDataSetPlantHvacLevel"); closeErr != nil {
@@ -408,16 +419,20 @@ func (m *_AirConditioningDataSetPlantHvacLevel) Serialize(writeBuffer utils.Writ
 			}
 		}
 
-		// Simple Field (auxLevel)
-		if pushErr := writeBuffer.PushContext("auxLevel"); pushErr != nil {
-			return errors.Wrap(pushErr, "Error pushing for auxLevel")
-		}
-		_auxLevelErr := writeBuffer.WriteSerializable(m.GetAuxLevel())
-		if popErr := writeBuffer.PopContext("auxLevel"); popErr != nil {
-			return errors.Wrap(popErr, "Error popping for auxLevel")
-		}
-		if _auxLevelErr != nil {
-			return errors.Wrap(_auxLevelErr, "Error serializing 'auxLevel' field")
+		// Optional Field (auxLevel) (Can be skipped, if the value is null)
+		var auxLevel HVACAuxiliaryLevel = nil
+		if m.GetAuxLevel() != nil {
+			if pushErr := writeBuffer.PushContext("auxLevel"); pushErr != nil {
+				return errors.Wrap(pushErr, "Error pushing for auxLevel")
+			}
+			auxLevel = m.GetAuxLevel()
+			_auxLevelErr := writeBuffer.WriteSerializable(auxLevel)
+			if popErr := writeBuffer.PopContext("auxLevel"); popErr != nil {
+				return errors.Wrap(popErr, "Error popping for auxLevel")
+			}
+			if _auxLevelErr != nil {
+				return errors.Wrap(_auxLevelErr, "Error serializing 'auxLevel' field")
+			}
 		}
 
 		if popErr := writeBuffer.PopContext("AirConditioningDataSetPlantHvacLevel"); popErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetZoneHumidityMode.go b/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetZoneHumidityMode.go
index ff5b2ebb8..9d8d37791 100644
--- a/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetZoneHumidityMode.go
+++ b/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetZoneHumidityMode.go
@@ -184,8 +184,10 @@ func (m *_AirConditioningDataSetZoneHumidityMode) GetLengthInBitsConditional(las
 		lengthInBits += m.RawLevel.GetLengthInBits()
 	}
 
-	// Simple field (auxLevel)
-	lengthInBits += m.AuxLevel.GetLengthInBits()
+	// Optional Field (auxLevel)
+	if m.AuxLevel != nil {
+		lengthInBits += m.AuxLevel.GetLengthInBits()
+	}
 
 	return lengthInBits
 }
@@ -293,17 +295,26 @@ func AirConditioningDataSetZoneHumidityModeParse(readBuffer utils.ReadBuffer) (A
 		}
 	}
 
-	// Simple Field (auxLevel)
-	if pullErr := readBuffer.PullContext("auxLevel"); pullErr != nil {
-		return nil, errors.Wrap(pullErr, "Error pulling for auxLevel")
-	}
-	_auxLevel, _auxLevelErr := HVACAuxiliaryLevelParse(readBuffer)
-	if _auxLevelErr != nil {
-		return nil, errors.Wrap(_auxLevelErr, "Error parsing 'auxLevel' field of AirConditioningDataSetZoneHumidityMode")
-	}
-	auxLevel := _auxLevel.(HVACAuxiliaryLevel)
-	if closeErr := readBuffer.CloseContext("auxLevel"); closeErr != nil {
-		return nil, errors.Wrap(closeErr, "Error closing for auxLevel")
+	// Optional Field (auxLevel) (Can be skipped, if a given expression evaluates to false)
+	var auxLevel HVACAuxiliaryLevel = nil
+	if humidityModeAndFlags.GetIsAuxLevelUsed() {
+		currentPos = positionAware.GetPos()
+		if pullErr := readBuffer.PullContext("auxLevel"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for auxLevel")
+		}
+		_val, _err := HVACAuxiliaryLevelParse(readBuffer)
+		switch {
+		case errors.Is(_err, utils.ParseAssertError{}) || errors.Is(_err, io.EOF):
+			log.Debug().Err(_err).Msg("Resetting position because optional threw an error")
+			readBuffer.Reset(currentPos)
+		case _err != nil:
+			return nil, errors.Wrap(_err, "Error parsing 'auxLevel' field of AirConditioningDataSetZoneHumidityMode")
+		default:
+			auxLevel = _val.(HVACAuxiliaryLevel)
+			if closeErr := readBuffer.CloseContext("auxLevel"); closeErr != nil {
+				return nil, errors.Wrap(closeErr, "Error closing for auxLevel")
+			}
+		}
 	}
 
 	if closeErr := readBuffer.CloseContext("AirConditioningDataSetZoneHumidityMode"); closeErr != nil {
@@ -408,16 +419,20 @@ func (m *_AirConditioningDataSetZoneHumidityMode) Serialize(writeBuffer utils.Wr
 			}
 		}
 
-		// Simple Field (auxLevel)
-		if pushErr := writeBuffer.PushContext("auxLevel"); pushErr != nil {
-			return errors.Wrap(pushErr, "Error pushing for auxLevel")
-		}
-		_auxLevelErr := writeBuffer.WriteSerializable(m.GetAuxLevel())
-		if popErr := writeBuffer.PopContext("auxLevel"); popErr != nil {
-			return errors.Wrap(popErr, "Error popping for auxLevel")
-		}
-		if _auxLevelErr != nil {
-			return errors.Wrap(_auxLevelErr, "Error serializing 'auxLevel' field")
+		// Optional Field (auxLevel) (Can be skipped, if the value is null)
+		var auxLevel HVACAuxiliaryLevel = nil
+		if m.GetAuxLevel() != nil {
+			if pushErr := writeBuffer.PushContext("auxLevel"); pushErr != nil {
+				return errors.Wrap(pushErr, "Error pushing for auxLevel")
+			}
+			auxLevel = m.GetAuxLevel()
+			_auxLevelErr := writeBuffer.WriteSerializable(auxLevel)
+			if popErr := writeBuffer.PopContext("auxLevel"); popErr != nil {
+				return errors.Wrap(popErr, "Error popping for auxLevel")
+			}
+			if _auxLevelErr != nil {
+				return errors.Wrap(_auxLevelErr, "Error serializing 'auxLevel' field")
+			}
 		}
 
 		if popErr := writeBuffer.PopContext("AirConditioningDataSetZoneHumidityMode"); popErr != nil {
diff --git a/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetZoneHvacMode.go b/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetZoneHvacMode.go
index 11061ae4c..fae761a33 100644
--- a/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetZoneHvacMode.go
+++ b/plc4go/protocols/cbus/readwrite/model/AirConditioningDataSetZoneHvacMode.go
@@ -184,8 +184,10 @@ func (m *_AirConditioningDataSetZoneHvacMode) GetLengthInBitsConditional(lastIte
 		lengthInBits += m.RawLevel.GetLengthInBits()
 	}
 
-	// Simple field (auxLevel)
-	lengthInBits += m.AuxLevel.GetLengthInBits()
+	// Optional Field (auxLevel)
+	if m.AuxLevel != nil {
+		lengthInBits += m.AuxLevel.GetLengthInBits()
+	}
 
 	return lengthInBits
 }
@@ -293,17 +295,26 @@ func AirConditioningDataSetZoneHvacModeParse(readBuffer utils.ReadBuffer) (AirCo
 		}
 	}
 
-	// Simple Field (auxLevel)
-	if pullErr := readBuffer.PullContext("auxLevel"); pullErr != nil {
-		return nil, errors.Wrap(pullErr, "Error pulling for auxLevel")
-	}
-	_auxLevel, _auxLevelErr := HVACAuxiliaryLevelParse(readBuffer)
-	if _auxLevelErr != nil {
-		return nil, errors.Wrap(_auxLevelErr, "Error parsing 'auxLevel' field of AirConditioningDataSetZoneHvacMode")
-	}
-	auxLevel := _auxLevel.(HVACAuxiliaryLevel)
-	if closeErr := readBuffer.CloseContext("auxLevel"); closeErr != nil {
-		return nil, errors.Wrap(closeErr, "Error closing for auxLevel")
+	// Optional Field (auxLevel) (Can be skipped, if a given expression evaluates to false)
+	var auxLevel HVACAuxiliaryLevel = nil
+	if hvacModeAndFlags.GetIsAuxLevelUsed() {
+		currentPos = positionAware.GetPos()
+		if pullErr := readBuffer.PullContext("auxLevel"); pullErr != nil {
+			return nil, errors.Wrap(pullErr, "Error pulling for auxLevel")
+		}
+		_val, _err := HVACAuxiliaryLevelParse(readBuffer)
+		switch {
+		case errors.Is(_err, utils.ParseAssertError{}) || errors.Is(_err, io.EOF):
+			log.Debug().Err(_err).Msg("Resetting position because optional threw an error")
+			readBuffer.Reset(currentPos)
+		case _err != nil:
+			return nil, errors.Wrap(_err, "Error parsing 'auxLevel' field of AirConditioningDataSetZoneHvacMode")
+		default:
+			auxLevel = _val.(HVACAuxiliaryLevel)
+			if closeErr := readBuffer.CloseContext("auxLevel"); closeErr != nil {
+				return nil, errors.Wrap(closeErr, "Error closing for auxLevel")
+			}
+		}
 	}
 
 	if closeErr := readBuffer.CloseContext("AirConditioningDataSetZoneHvacMode"); closeErr != nil {
@@ -408,16 +419,20 @@ func (m *_AirConditioningDataSetZoneHvacMode) Serialize(writeBuffer utils.WriteB
 			}
 		}
 
-		// Simple Field (auxLevel)
-		if pushErr := writeBuffer.PushContext("auxLevel"); pushErr != nil {
-			return errors.Wrap(pushErr, "Error pushing for auxLevel")
-		}
-		_auxLevelErr := writeBuffer.WriteSerializable(m.GetAuxLevel())
-		if popErr := writeBuffer.PopContext("auxLevel"); popErr != nil {
-			return errors.Wrap(popErr, "Error popping for auxLevel")
-		}
-		if _auxLevelErr != nil {
-			return errors.Wrap(_auxLevelErr, "Error serializing 'auxLevel' field")
+		// Optional Field (auxLevel) (Can be skipped, if the value is null)
+		var auxLevel HVACAuxiliaryLevel = nil
+		if m.GetAuxLevel() != nil {
+			if pushErr := writeBuffer.PushContext("auxLevel"); pushErr != nil {
+				return errors.Wrap(pushErr, "Error pushing for auxLevel")
+			}
+			auxLevel = m.GetAuxLevel()
+			_auxLevelErr := writeBuffer.WriteSerializable(auxLevel)
+			if popErr := writeBuffer.PopContext("auxLevel"); popErr != nil {
+				return errors.Wrap(popErr, "Error popping for auxLevel")
+			}
+			if _auxLevelErr != nil {
+				return errors.Wrap(_auxLevelErr, "Error serializing 'auxLevel' field")
+			}
 		}
 
 		if popErr := writeBuffer.PopContext("AirConditioningDataSetZoneHvacMode"); popErr != nil {
diff --git a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
index 555567403..41a7e7be8 100644
--- a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
+++ b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/RandomPackagesTest.java
@@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 public class RandomPackagesTest {
 
+    public static final CBusOptions C_BUS_OPTIONS_WITH_SRCHK = new CBusOptions(false, false, false, false, false, false, false, false, true);
     RequestContext requestContext;
     CBusOptions cBusOptions;
 
@@ -46,7 +47,7 @@ public class RandomPackagesTest {
     void whatEverThisIs() throws Exception {
         byte[] bytes = "\\3436303230303231303167\r".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -83,7 +84,7 @@ public class RandomPackagesTest {
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
         // We know we send an identify command so we set the cal flag
         requestContext = new RequestContext(true, false, false);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -100,7 +101,7 @@ public class RandomPackagesTest {
         byte[] bytes = "nl.8220025C\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
         requestContext = new RequestContext(true, false, false);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -145,7 +146,7 @@ public class RandomPackagesTest {
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
         // We know we send an identify command so we set the cal flag
         requestContext = new RequestContext(true, false, true);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -180,7 +181,7 @@ public class RandomPackagesTest {
         byte[] bytes = "h.890150435F434E49454421\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
         requestContext = new RequestContext(true, false, true);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -197,7 +198,7 @@ public class RandomPackagesTest {
     void write30to9755() throws Exception {
         byte[] bytes = "A3309755s\r".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -211,7 +212,7 @@ public class RandomPackagesTest {
         byte[] bytes = "s.860202003230977D\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
         requestContext = new RequestContext(true, false, false);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -244,7 +245,7 @@ public class RandomPackagesTest {
     void wat() throws Exception {
         byte[] bytes = "D8FF0024000002000000000000000008000000000000000000\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         requestContext = new RequestContext(true, false, false);
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
@@ -276,7 +277,7 @@ public class RandomPackagesTest {
     void statusReply() throws Exception {
         byte[] bytes = "D8FF5800000000000000000000000000000000000000000000D1\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         requestContext = new RequestContext(false, true, false);
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
@@ -292,7 +293,7 @@ public class RandomPackagesTest {
     void identifyUnitSummary() throws Exception {
         byte[] bytes = "2110\r".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
@@ -305,7 +306,7 @@ public class RandomPackagesTest {
     void identifyUnitSummaryResponse() throws Exception {
         byte[] bytes = "o.8510020000FF6A\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         requestContext = new RequestContext(true, false, true);
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
@@ -319,7 +320,7 @@ public class RandomPackagesTest {
     void hvacAndCoolingSAL() throws Exception {
         byte[] bytes = "0531AC0079042F0401430316000011\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         requestContext = new RequestContext(false, false, false);
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
@@ -333,7 +334,7 @@ public class RandomPackagesTest {
     void calIdentifyReplyAndAnotherCal() throws Exception {
         byte[] bytes = "h.860102008902312E362E30302020832138FFAE\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         requestContext = new RequestContext(false, false, true);
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
@@ -347,7 +348,7 @@ public class RandomPackagesTest {
     void routedAcknowledge() throws Exception {
         byte[] bytes = "r.8631020100320041D3\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         requestContext = new RequestContext(false, false, true);
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
@@ -361,7 +362,7 @@ public class RandomPackagesTest {
     void gavValuesCurrentReply() throws Exception {
         byte[] bytes = "w.860C02008A08000000C8000000000012\r\n".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         requestContext = new RequestContext(false, false, true);
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
@@ -384,13 +385,26 @@ public class RandomPackagesTest {
         // TODO: apparently the set the first bit of AuxiliaryLevel to true wich is not valid according to the documentation
         //assertMessageMatches(bytes, msg);
     }
+    @Test
+    void salHvac() throws Exception {
+        byte[] bytes = "0531AC0036040142037F001F\r\n".getBytes(StandardCharsets.UTF_8);
+        ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
+        requestContext = new RequestContext(false, false, false);
+        CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, true, requestContext, cBusOptions, bytes.length);
+        assertThat(msg).isNotNull();
+        System.out.println(msg);
+        System.out.println(((ReplyEncodedReply) ((ReplyOrConfirmationReply) ((CBusMessageToClient) msg).getReply()).getReply()).getEncodedReply());
+
+        assertMessageMatches(bytes, msg);
+    }
 
     @Disabled("Not clear yet what this is")
     @Test
     void closestFitIsAStatusRequestButWeDonTHaveAnyBytesBeforeThat() throws Exception {
         byte[] bytes = "FAFF00r\r".getBytes(StandardCharsets.UTF_8);
         ReadBufferByteBased readBufferByteBased = new ReadBufferByteBased(bytes);
-        cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
+        cBusOptions = C_BUS_OPTIONS_WITH_SRCHK;
         CBusMessage msg = CBusMessage.staticParse(readBufferByteBased, false, requestContext, cBusOptions, bytes.length);
         assertThat(msg).isNotNull();
         System.out.println(msg);
diff --git a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/ReferenceTest.java b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/ReferenceTest.java
index fc5deb8b3..4c4426fe8 100644
--- a/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/ReferenceTest.java
+++ b/plc4j/drivers/c-bus/src/test/java/org/apache/plc4x/java/cbus/ReferenceTest.java
@@ -42,9 +42,15 @@ public class ReferenceTest {
         cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, false);
     }
 
+    // from: https://updates.clipsal.com/ClipsalSoftwareDownload/DL/downloads/OpenCBus/C-Bus%20Interface%20Requirements.pdf
+    @Nested
+    class InterfaceRequirementsTest {
+        // TODO: implement those
+    }
+
     // from: https://updates.clipsal.com/ClipsalSoftwareDownload/DL/downloads/OpenCBus/Serial%20Interface%20User%20Guide.pdf
     @Nested
-    class ReferenceDocumentationTest {
+    class SerialInterfaceGuideTest {
 
         // 3.4
         @Nested
diff --git a/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec b/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
index e74c3dc8f..177350c7a 100644
--- a/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
+++ b/protocols/c-bus/src/main/resources/protocols/cbus/c-bus.mspec
@@ -2713,7 +2713,7 @@
             [simple   HVACType            hvacType            ]
             [optional HVACTemperature     level     'hvacModeAndFlags.isLevelTemperature']
             [optional HVACRawLevels       rawLevel  'hvacModeAndFlags.isLevelRaw'        ]
-            [simple   HVACAuxiliaryLevel  auxLevel            ]
+            [optional HVACAuxiliaryLevel  auxLevel  'hvacModeAndFlags.isAuxLevelUsed'    ]
         ]
         ['SET_PLANT_HVAC_LEVEL'             *SetPlantHvacLevel
             [simple   byte                zoneGroup           ]
@@ -2722,25 +2722,25 @@
             [simple   HVACType            hvacType            ]
             [optional HVACTemperature     level     'hvacModeAndFlags.isLevelTemperature']
             [optional HVACRawLevels       rawLevel  'hvacModeAndFlags.isLevelRaw'        ]
-            [simple   HVACAuxiliaryLevel  auxLevel            ]
+            [optional HVACAuxiliaryLevel  auxLevel  'hvacModeAndFlags.isAuxLevelUsed'    ]
         ]
         ['SET_ZONE_HUMIDITY_MODE'           *SetZoneHumidityMode
             [simple   byte                      zoneGroup               ]
             [simple   HVACZoneList              zoneList                ]
             [simple   HVACHumidityModeAndFlags  humidityModeAndFlags    ]
             [simple   HVACHumidityType          humidityType            ]
-            [optional HVACHumidity              level   'humidityModeAndFlags.isLevelHumidity']
-            [optional HVACRawLevels             rawLevel 'humidityModeAndFlags.isLevelRaw'    ]
-            [simple   HVACAuxiliaryLevel        auxLevel            ]
+            [optional HVACHumidity              level    'humidityModeAndFlags.isLevelHumidity']
+            [optional HVACRawLevels             rawLevel 'humidityModeAndFlags.isLevelRaw'     ]
+            [optional HVACAuxiliaryLevel        auxLevel 'humidityModeAndFlags.isAuxLevelUsed' ]
         ]
         ['SET_PLANT_HUMIDITY_LEVEL'         *SetPlantHumidityLevel
             [simple   byte                      zoneGroup               ]
             [simple   HVACZoneList              zoneList                ]
             [simple   HVACHumidityModeAndFlags  humidityModeAndFlags    ]
             [simple   HVACHumidityType          humidityType            ]
-            [optional HVACHumidity              level   'humidityModeAndFlags.isLevelHumidity']
-            [optional HVACRawLevels             rawLevel 'humidityModeAndFlags.isLevelRaw'    ]
-            [simple   HVACAuxiliaryLevel        auxLevel            ]
+            [optional HVACHumidity              level    'humidityModeAndFlags.isLevelHumidity']
+            [optional HVACRawLevels             rawLevel 'humidityModeAndFlags.isLevelRaw'     ]
+            [optional HVACAuxiliaryLevel        auxLevel 'humidityModeAndFlags.isAuxLevelUsed' ]
         ]
         ['SET_HVAC_UPPER_GUARD_LIMIT'       *SetHvacUpperGuardLimit
             [simple   byte                zoneGroup           ]