This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC2530: UINT48 Reporting wrong after adding an INT24 to reportables

Part Number: CC2530


When using Read Attributes, the response is fine:

Command: Read Attributes Response (0x01)
Status Record, Uint: 500
Attribute: Client: Functional Notification Flags / Server: Current Summation Delivered (0x0000)
Status: Success (0x00)
Data Type: 48-Bit Unsigned Integer (0x25)
Uint48: 500 (0x00000000000001f4)

But when the same attribute is reported along with the Inlet temperature, "random" data gets added from the 5th byte upwards:

Command: Report Attributes (0x0a)
Attribute Field, Int24: 2358
Attribute: Inlet Temperature (0x0017)
Data Type: 24-Bit Signed Integer (0x2a)
Int24: 2358
Attribute Field, Uint: 17179869684
Attribute: Client: Functional Notification Flags / Server: Current Summation Delivered (0x0000)
Data Type: 48-Bit Unsigned Integer (0x25)
Uint48: 17179869684 (0x00000004000001f4)

Other unique invalid values over a short period of time are:

Uint48: 17179869684 (0x00000004000001f4)
Uint48: 390842024436 (0x0000005b000001f4)
Uint48: 880468296180 (0x000000cd000001f4)
Uint48: 93458488361460 (0x00005500000001f4)
Uint48: 94227287507444 (0x000055b3000001f4)
Uint48: 94373316395508 (0x000055d5000001f4)
Uint48: 94386201297396 (0x000055d8000001f4)

I inspected data memory where the 48 bit value is located (pointed to in the attribute definition), and it is always correcly showing the "500" value.

This value was reported with normal values prior to adding the Inlet temperature to the reportables.  I guess something is wrong in the BDB reporting code.

{
ZCL_CLUSTER_ID_SE_METERING, // Cluster IDs - defined in the foundation (ie. zcl.h) - Smart Energy (SE) Clusters
{ // Attribute record
ATTRID_SE_METERING_CURR_SUMM_DLVD, // 0x0000
ZCL_DATATYPE_UINT48,
ACCESS_CONTROL_READ | ACCESS_REPORTABLE,
(void *)&meterInfo.Wh_meter
}
},
{
ZCL_CLUSTER_ID_SE_METERING,
{ // Attribute record
ATTRID_SE_METERING_INLET_TEMP, // 0x0017
ZCL_DATATYPE_INT24, // Strangely enough int24, but as in ZCL
ACCESS_CONTROL_READ | ACCESS_REPORTABLE,
(void *)&inletTemperature
}
},

And, the following code is placed in appropriate locations to notify about changes:

uint8 status = bdb_RepChangedAttrValue(
APP_ENDPOINT,
ZCL_CLUSTER_ID_SE_METERING,
ATTRID_SE_METERING_INLET_TEMP
);

uint8 status = bdb_RepChangedAttrValue(
APP_ENDPOINT,
ZCL_CLUSTER_ID_SE_METERING,
ATTRID_SE_METERING_INST_DMD
);

And they are set up during initialisation:

bdb_RepAddAttrCfgRecordDefaultToList(APP_ENDPOINT, ZCL_CLUSTER_ID_SE_METERING, ATTRID_SE_METERING_INST_DMD, REP_INTERVAL_60S, REP_INTERVAL_5M, reportableChange1);
bdb_RepAddAttrCfgRecordDefaultToList(APP_ENDPOINT, ZCL_CLUSTER_ID_SE_METERING, ATTRID_SE_METERING_CURR_SUMM_DLVD, REP_INTERVAL_60S, REP_INTERVAL_5M, reportableChange50);
bdb_RepAddAttrCfgRecordDefaultToList(APP_ENDPOINT, ZCL_CLUSTER_ID_SE_METERING, ATTRID_SE_METERING_INLET_TEMP, REP_INTERVAL_60S, REP_INTERVAL_5M, reportableChange50);

What are your suggestions to fix this?

I am on the latest ZSTACK 3.0.2 with patches.

  • Hi Mario,

    Just to be clear, have you applied #22 from the Known Issues and Fixes E2E post?  Can you debug to determine the value of pReportCmd before zcl_StackSendReportCmd is called from bdb_RepReport?  If this value is as expected, then please provide a sniffer log of the attribute report.  If this is also structured correctly then there is an issue with the way it is being parsed by the destination during zclParseInReportCmd, at which point reportCmd will need to be debugged.

    Regards,
    Ryan

  • Thank you for your feedback.

    1. I used a diff tool to compare #22 and the version ov bdb_RepReport used: exactly the same code.

    2. Decoded using wireshark:

    Sniffer log with decoded ASCI - the secret key is in the .log file:

    bdb_reportIssue.zip

  • Couldn this just be because of  BDBREPORTING_MAX_ANALOG_ATTR_SIZE==4 .

  • Thanks for confirming that the issue exists on the reporting device.  The issue certainly can be due to BDBREPORTING_MAX_ANALOG_ATTR_SIZE, which you can change from bdb_interface.h and further test.  Please ensure that reportableChange50 is the correct size for each attribute as well.

    Regards,
    Ryan

  • I changed BDBREPORTING_MAX_ANALOG_ATTR_SIZE to 6 which is not a usual case and 'reportableChange50' was no longer defined because it depends ont this value.  I also had to add a case in the library.

    I has been running for 20 minutes or more and it seems to behave better, but I have no double reports yet.

    Because of these changes, I guess that there is no more reportable change detected for the inlet temperature, only for the consumption reporting which is reported as expected.

    I expect that htis is solved and will consider it is when I get a dual report with correct values as well.

  • I was looking at the wrong reports (my log filter was not working as expectec).

    I am currently investigating the issue in more detail and discovered a potential buffer overflow in the stack, as well as an optimisation.

    This could be leveraged on to detect that the BDBREPORTING_MAX_ANALOG_ATTR_SIZE is incorrect.

    If that constant is correct, then the memcpy can't theoretically brick the memory contents because it is required that the type in the report configuration is set to the attributes' type.

    .There could have been a check - at least with a debug setting - verifying that the reportable attributes are within limits.

    --- a/Components/stack/bdb/bdb_Reporting.c
    +++ b/Components/stack/bdb/bdb_Reporting.c
    @@ -559,7 +560,8 @@ uint8 bdb_ProcessInConfigReportCmd( zclIncomingMsg_t *pInMsg )
                   confchanged = BDBREPORTING_TRUE;^M
                   bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].minReportInt = bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].defaultMinReportInt;^M
                   bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].maxReportInt = bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].defaultMaxReportInt;^M
    -              osal_memset( bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].reportableChange, 0x00, BDBREPORTING_MAX_ANALOG_ATTR_SIZE );^M
    +              //YNA: Next in is useless, the memcpy replaces the content^M
    +              //osal_memset( bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].reportableChange, 0x00, BDBREPORTING_MAX_ANALOG_ATTR_SIZE );^M
                   osal_memcpy( bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].reportableChange, bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].defaultReportableChange, BDBREPORTING_MAX_ANALOG_ATTR_SIZE );^M
                   status = ZCL_STATUS_SUCCESS;  ^M
                 }^M
    @@ -570,10 +572,11 @@ uint8 bdb_ProcessInConfigReportCmd( zclIncomingMsg_t *pInMsg )
                   bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].minReportInt = reportRec->minReportInt;^M
                   bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].maxReportInt = reportRec->maxReportInt;^M
                   // For attributes of 'discrete' data types this field is omitted^M
    -              if ( zclAnalogDataType( reportRec->dataType ) )^M
    +              uint8_t len = zclAnalogDataType( reportRec->dataType );^M
    +              if ( len )^M
                   {^M
                     osal_memset( bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].reportableChange, 0x00, BDBREPORTING_MAX_ANALOG_ATTR_SIZE );^M
    -                osal_memcpy( bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].reportableChange, reportRec->reportableChange, zclGetDataTypeLength( reportRec->dataType ) );^M
    +                osal_memcpy( bdb_reportingAttrCfgRecordsArray[atrrCfgRecordIndex].reportableChange, reportRec->reportableChange, (len<=BDBREPORTING_MAX_ANALOG_ATTR_SIZE?len:BDBREPORTING_MAX_ANALOG_ATTR_SIZE));^M
                   }^M
                   status = ZCL_STATUS_SUCCESS;             ^M
                 }^M

  • Thank you for providing the suggested optimizations.

    Regards,
    Ryan

  • I discovered why I did not get any attribute reports - the change in attr_size has different requirements on NV storage, and as I was in debug mode keeping NV storage, all reporting related NV memory operations failed.

    A pity that there is no recovery from that in the stack which could also be an issue for OTA updates when the maximum reporting attribute size increases.