From 4104878f6b8a99fa1fd36fc62f956b5ed69415fa Mon Sep 17 00:00:00 2001 From: Jerry Johns Date: Thu, 2 Dec 2021 13:06:28 -0800 Subject: [PATCH] Handle IM error in Read (#12383) * Handle IM error in Read When handling the data returned on a read, we were proceeding to decode the data even if we had just received a status code. This resulted in confusing errors being delivered up to clients that seemed to indicate we couldn't decode the data when in fact, we never received any data at all and rather, just got a status code. * Test cluster server was missing the impl for the NullableStruct, resulting in some Cirque test failures * Add support for writing to the NullableStruct as well * Add writable version of NullableStruct too --- .../test-cluster-server.cpp | 19 ++++++++ .../python/chip/clusters/Attribute.py | 46 +++++++++++-------- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/app/clusters/test-cluster-server/test-cluster-server.cpp b/src/app/clusters/test-cluster-server/test-cluster-server.cpp index f2c48dacbcda05..2a4328b853283f 100644 --- a/src/app/clusters/test-cluster-server/test-cluster-server.cpp +++ b/src/app/clusters/test-cluster-server/test-cluster-server.cpp @@ -80,6 +80,8 @@ class TestAttrAccess : public AttributeAccessInterface CHIP_ERROR WriteListNullablesAndOptionalsStructAttribute(AttributeValueDecoder & aDecoder); CHIP_ERROR ReadStructAttribute(AttributeValueEncoder & aEncoder); CHIP_ERROR WriteStructAttribute(AttributeValueDecoder & aDecoder); + CHIP_ERROR ReadNullableStruct(AttributeValueEncoder & aEncoder); + CHIP_ERROR WriteNullableStruct(AttributeValueDecoder & aDecoder); }; TestAttrAccess gAttrAccess; @@ -90,6 +92,7 @@ Structs::TestListStructOctet::Type listStructOctetStringData[kAttributeListLengt Structs::SimpleStruct::Type gStructAttributeValue = { 0, false, SimpleEnum::kValueA, ByteSpan(), CharSpan(), BitFlags(), 0, 0 }; +NullableStruct::TypeInfo::Type gNullableStructAttributeValue; CHIP_ERROR TestAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) { @@ -110,6 +113,9 @@ CHIP_ERROR TestAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attribu case Struct::Id: { return ReadStructAttribute(aEncoder); } + case NullableStruct::Id: { + return ReadNullableStruct(aEncoder); + } default: { break; } @@ -137,6 +143,9 @@ CHIP_ERROR TestAttrAccess::Write(const ConcreteDataAttributePath & aPath, Attrib case Struct::Id: { return WriteStructAttribute(aDecoder); } + case NullableStruct::Id: { + return WriteNullableStruct(aDecoder); + } default: { break; } @@ -145,6 +154,16 @@ CHIP_ERROR TestAttrAccess::Write(const ConcreteDataAttributePath & aPath, Attrib return CHIP_NO_ERROR; } +CHIP_ERROR TestAttrAccess::ReadNullableStruct(AttributeValueEncoder & aEncoder) +{ + return aEncoder.Encode(gNullableStructAttributeValue); +} + +CHIP_ERROR TestAttrAccess::WriteNullableStruct(AttributeValueDecoder & aDecoder) +{ + return aDecoder.Decode(gNullableStructAttributeValue); +} + CHIP_ERROR TestAttrAccess::ReadListInt8uAttribute(AttributeValueEncoder & aEncoder) { return aEncoder.EncodeList([](const TagBoundEncoder & encoder) -> CHIP_ERROR { diff --git a/src/controller/python/chip/clusters/Attribute.py b/src/controller/python/chip/clusters/Attribute.py index a97f1e4ad9e985..dac73b3b5fae08 100644 --- a/src/controller/python/chip/clusters/Attribute.py +++ b/src/controller/python/chip/clusters/Attribute.py @@ -207,28 +207,36 @@ def _handleAttributeData(self, path: AttributePathWithListIndex, status: int, da imStatus = chip.interaction_model.Status(status) except: pass - attributeType = _AttributeIndex.get(str(AttributePath( - ClusterId=path.ClusterId, AttributeId=path.AttributeId)), None) - attributeValue = None - tlvData = chip.tlv.TLVReader(data).get().get("Any", {}) - if attributeType is None: + + if (imStatus != chip.interaction_model.Status.Success): + logging.error( + f"For path: Endpoint = {path.EndpointId}/Cluster = {path.ClusterId}/Attribute = {path.AttributeId}, got IM Error: {str(imStatus)}") attributeValue = ValueDecodeFailure( - tlvData, LookupError("attribute schema not found")) + None, chip.interaction_model.InteractionModelError(imStatus)) else: - try: - attributeValue = attributeType(attributeType.FromTLV(data)) - except Exception as ex: - logging.error( - f"Error convering TLV to Cluster Object for path: Endpoint = {path.EndpointId}/Cluster = {path.ClusterId}/Attribute = {path.AttributeId}") - logging.error( - f"Failed Cluster Object: {str(attributeType)}") - logging.error(ex) + attributeType = _AttributeIndex.get(str(AttributePath( + ClusterId=path.ClusterId, AttributeId=path.AttributeId)), None) + attributeValue = None + tlvData = chip.tlv.TLVReader(data).get().get("Any", {}) + if attributeType is None: attributeValue = ValueDecodeFailure( - tlvData, ex) - - # If we're in debug mode, raise the exception so that we can better debug what's happening. - if (builtins.enableDebugMode): - raise + tlvData, LookupError("attribute schema not found")) + else: + try: + attributeValue = attributeType( + attributeType.FromTLV(data)) + except Exception as ex: + logging.error( + f"Error convering TLV to Cluster Object for path: Endpoint = {path.EndpointId}/Cluster = {path.ClusterId}/Attribute = {path.AttributeId}") + logging.error( + f"Failed Cluster Object: {str(attributeType)}") + logging.error(ex) + attributeValue = ValueDecodeFailure( + tlvData, ex) + + # If we're in debug mode, raise the exception so that we can better debug what's happening. + if (builtins.enableDebugMode): + raise with self._resLock: self._res[path] = AttributeReadResult(