Skip to content

Commit

Permalink
Handle IM error in Read (#12383)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
mrjerryjohns authored and pull[bot] committed May 12, 2022
1 parent fff3eb7 commit f78e381
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 19 deletions.
19 changes: 19 additions & 0 deletions src/app/clusters/test-cluster-server/test-cluster-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -90,6 +92,7 @@ Structs::TestListStructOctet::Type listStructOctetStringData[kAttributeListLengt
Structs::SimpleStruct::Type gStructAttributeValue = { 0, false, SimpleEnum::kValueA,
ByteSpan(), CharSpan(), BitFlags<SimpleBitmap>(),
0, 0 };
NullableStruct::TypeInfo::Type gNullableStructAttributeValue;

CHIP_ERROR TestAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand All @@ -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 {
Expand Down
46 changes: 27 additions & 19 deletions src/controller/python/chip/clusters/Attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit f78e381

Please sign in to comment.