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.

CCS/LAUNCHXL-CC1310: How to properly kick a sensor in non-beacon mode

Part Number: LAUNCHXL-CC1310
Other Parts Discussed in Thread: CC1310

Tool/software: Code Composer Studio

Hey guys,

we use sensor/collector 15.4 stack and i went through the user guide, which tells me that in non beacon mode with security on, the collector waits for the sleepy sensor to poll to kick it. Therefore, only Cllc_sendDisassociationRequest() has to be called. However, this is not working, i can see in the sniffer, that no disassociation request is send when the collector is in pollIndCb(). Only if I remove the device from the list and I change the code within pollIndCb() as follows, a disassociation message is triggered.

static void pollIndCB(ApiMac_mlmePollInd_t *pPollInd)
{
    ApiMac_sAddr_t addr;

    addr.addrMode = ApiMac_addrType_short;
    if (pPollInd->srcAddr.addrMode == ApiMac_addrType_short)
    {
        addr.addr.shortAddr = pPollInd->srcAddr.addr.shortAddr;
    }
    else
    {
        addr.addr.shortAddr = Csf_getDeviceShort(
                        &pPollInd->srcAddr.addr.extAddr);
    }
__________MY CHANGE START____________
#ifdef SMART_DIS
   if (findDevice(&pPollInd->srcAddr) == NULL &&
           pPollInd->srcAddr.addrMode == ApiMac_addrType_short)
   {
       Cllc_sendDisassociationRequest(addr.addr.shortAddr, false);
       System_printf("disD 0x%02x\r\n", addr.addr.shortAddr);
   }
#endif
_________MY CHANGE END______________
    processDataRetry(&addr);
}

  1. Why is that?
  2. Why is there no highLevel Callback function like disassociateCnfCb() on the collector side? this could help debugging and I guess at some point the device has to be removed from the NV, too, why not at this point?
  3. What would be a correct disassociation sequence in the code?

I.e. (which does not work, because no disassociation message is send according to the sniffer, not during the call nor in pollindcb())

                        if(Csf_getDevice(&devAddr, &item))
                        {
                            Cllc_sendDisassociationRequest(devAddr.addr.shortAddr, false);
                            Cllc_removeDevice(&item.devInfo.extAddress);
                        }

Besides, if I call Cllc_sendDisassociationRequest() in pollindcb() and the sensor gets disconnected, it tries to join again (which is desired). This works, however, every time an already in use short address is assigned. Checking whats in the NV memory, there are two entries with the same short and ext. address. Furthermore, the newly joined sensor can report data which is acknowledged and printed via uart. Note that the wrong assignment is not happening if I add a completely new sensor which was not connected before..

So why is this happening during association?!

EDIT!!! - Note that I kick the sensors via a UART message, for some reason I have to press the reset button after calling the 2nd code snippet because the application crashes. I think this is the reason  that the short addresses are not assigned correctly. could this be the reason? The issue with Cllc_sendDisassociationRequest() has nothing to do with the reset, because also without reset, calling this function only works within pollindCb().

kind regards

Slev1n

  • Hey Slev1n,

    Please allow me some time to reproduce your issue.

    Off the top of my head, here are some answers to some of your questions.

    Slev1n said:
    Why is there no highLevel Callback function like disassociateCnfCb() on the collector side? this could help debugging and I guess at some point the device has to be removed from the NV, too, why not at this point?

    There is the ability to enable the mac callback for a Disassociate confirmation (see Collector_macCallbacks in collector.c). You'll have to enable the callback as it's not provided out of the box. There are examples in the struct for your reference. I would assume the disassociated sensor should only be removed from NV when it has successfully disassociated, so doing so in the pollIndCb is likely too early.

    Slev1n said:
    What would be a correct disassociation sequence in the code?

    The correct disassociation sequence is outlined here: http://dev.ti.com/tirex/content/simplelink_cc13x0_sdk_3_20_00_23/docs/ti154stack/html/ti154stack/non-beacon-mode.html#disassociating. I'm sure you've seen and tested this already, so allow me some time to reproduce your issue if it still persists.

  • Ammar N said:
    I would assume the disassociated sensor should only be removed from NV when it has successfully disassociated, so doing so in the pollIndCb is likely too early.

    Hmm, I am already removing it before entering pollIndCb, because all sensor information has to removed in order to trigger the if-loop presented in my first post (at the end of my first code snippet). As I mentioned before, calling Cllc_sendDisassociationRequest once is not enough, it has to called during pollIndCb again to trigger a disassociate message from the collector.

    Ammar N said:
    I'm sure you've seen and tested this already, so allow me some time to reproduce your issue if it still persists.

    Yes, I checked this diagram and it was helpful to understand the stack behavior, however, I was not able to reproduce the disassociation behavior as depicted in your link. I am looking forward to hear some updates from your side making our code more robust.

  • Hey Slev1n,

    Sorry for the delay. I tested the out of box code, sdk 3.20 with a CC1310 as collector and sensor. FEATURE_MAC_SECURITY was defined by default.

    I defined TEST_REMOVE_DEVICE to quickly test the disassociate sequence. I did modify the removeTheFirstDevice() function by removing the block of code that adds the device to the blacklist to allow a rejoin. By doing this, I was able to disassociate by clicking the left button.

    The proper disassociate sequence should be to call:

    /* Send a disassociate to the device */
    Cllc_sendDisassociationRequest(item.devInfo.shortAddress,
                                                       item.capInfo.rxOnWhenIdle);
    /* remove device from the NV list */
    Cllc_removeDevice(&item.devInfo.extAddress);
    
    /* Remove it from the Device list */
    Csf_removeDeviceListItem(&item.devInfo.extAddress);
  • Hey Ammar,

    first of all thank you for your time, I really appreciate.

    Ammar N said:
    The proper disassociate sequence should be to call:

    Ok, so  that is what I am doing. First call Cllc_sendDisassociationRequest() and then Cllc_removeDevice(), the Csf_removeDeviceListItem() is already inside the Cllc_removeDevice() function and I dont have to call it twice.

    EDIT: I just checked and you are right, I dont have to call Cllc_sendDisassociationRequest() within pollIndCb() again to remove the sensor. Seems to be working now, since I've shifted this disassociation sequence into a collector_event.

    kind regards

    Slev1n

  • Glad to hear!

  • Note, if a sensor is kicked using

    /* Send a disassociate to the device */
    Cllc_sendDisassociationRequest(item.devInfo.shortAddress,
                                                       item.capInfo.rxOnWhenIdle);
    /* remove device from the NV list */
    Cllc_removeDevice(&item.devInfo.extAddress);
    
    /* Remove it from the Device list */
    Csf_removeDeviceListItem(&item.devInfo.extAddress);

    and the collector device is reset, before the disassociation message could be send to the sensor, the sensor is removed from the NV, however, the collector forgets about sending the disassociation request to the sensor node. This leads to the following scenario. The sensor can send messages and receives an ack but the collector is not further processing it. hence, the sensor thinks everything is fine. To still be able to kick the sensor, use the following code within pollIndCb()

        
    ApiMac_sAddr_t addr;
    if (findDevice(&pPollInd->srcAddr) == NULL &&
           pPollInd->srcAddr.addrMode == ApiMac_addrType_short)
        {
            Cllc_sendDisassociationRequest(addr.addr.shortAddr, false);
    
        }
  • Hey Ammar,

    is the queued disassociation request for sleepy sensors send before pollIndCb() is entered or after? Because if the latter one is the case, than I think the best way would be to check if a dis request is currently pending for the device where findDevice() returns NULL within pollIndCb(). Than, the collector could send the request if it has been lost due to a power cycle, but would not send the disassociation request twice if the message is still queued.

    Waiting for your comment on that.

  • Hey Slev1n,

    Happy Holidays, I apologize for the delayed response.

    I think the disassociation request is queued and the collector device waits for a poll from the sensor to send the request. I do follow your logic. I would test it out to confirm in your setup that it operates as you desire.

  • Hey Ammar,

    I just noticed that you wanted to figure out if the queued dis request is send before the collector enters pollIndCb or after.

    Best wishes

    Slev1n

  • Hey Slev1n,

    The collector sends the disassociation request before pollIndCb is entered. I did a quick test and saw the disassociation sent to the sensor, then the sensor wakes up to disassociate and sends the response back to the collector in the next polling message. 

    Does this make sense?

  • Ammar N said:
    Does this make sense?

    I think I noticed this behavior comparing UART prints with sniffer output and timings, so yes, I agree with you. Thanks for testing this.