Sending commands from nRF Cloud to LTE Device

Hi!

In our project, we need to send cloud-to-device commands. By "command" I mean a request to do some short action, not a request to change device's configuration/state. We see two ways of sending such requests:

1. C2D messages

2. Device shadow

What are the pros and cons of each way?

Here I see a recommendation to use Device shadow for commands sending. But if we talk about commands in the sense I described above, would this recommendation be still actual?

If yes, is there a recommended way (or some sample) of Device shadow usage for sending such commands? I mean, which fields Device shadow should contain and some algorithm of updating desired and reported section during sending command and its execution.

In case of C2D messages, the main problem seems to be command delivery when the device is offline. Right? Or is there some mechanism for this case in nRF Cloud?

Thank you!

Parents
  • Hi,

    I will look into your questions and come back to you possibly in the first half of next week.

    Best regards,
    Dejan

  • Hi,

    C2D topic is best used as a return path for data requested by the device on a D2C channel rather than asynchronous commands for the device. If device is online, it will not receive messages on C2D or any other MQTT topic. For issuing commands by any means you wish, shadow would be appropriate to use. 

    We have an example using "config" section in multi-service sample. Using a section for commands would be the same process. You could create "cmd" section in your shadow. You can use built-in AWS shadow delta mechanism and/or newly added transform MQTT topic, with nrf_shadow_transform_request().

    Best regards,
    Dejan

  • Hi Dejan,

    I tried this, it doesn't seem to work as expected ... or maybe we are misunderstanding.

    From the cloud, we use the API devices/${deviceid}/state to send
    {
      "desired": {
        "cmd": "command"
      }
    }

    If the device is online then it receives the delta right away, as we expect:

    TOPIC: shadow/update/delta
    MESSAGE: {
      "state": {
        "nrfcloud_mqtt_topic_prefix": "prod/<tenant>/",
        "pairing": {
          "state": "paired",
          "topics": {
            "d2c": "prod/<tenant>/m/d/<deviceid>/d2c",
          }
        },
        "cmd": "command"
      }
    }

    If the device is offline then our understanding is the device would need to explicitly get the shadow via topic shadow/get/accepted when reconnecting . However, this is what the device gets (note that it does not contain the desired { "cmd": "command"} ):

    TOPIC: shadow/get/accepted
    MESSAGE: {
      "desired": {
        "pairing": {
          "state": "paired",
          "topics": {
            "d2c": "prod/<tenant>/m/d/<deviceid>/d2c",
          }
        },
        "nrfcloud_mqtt_topic_prefix": "prod/<tenant>/",
      },
      "reported": {
        "control": {
          "alertsEn": true,
           "logLvl": 3
         }
      },
      "config": {
        "activeMode": true,
        ...
      }
    }

    We also tried a shadow update with section
    {
      "desired": {
        "config": {
          "cmd": "command"
        }
      }
    }

    but get the same result: the delta contains the update, but the full shadow does not. 

    Could you please clarify where we would add the command and how the device gets that shadow change after it comes online?

    Thanks!

  • Hi  ,

    nRF Cloud library does not actually request the full shadow because it can be too large for modem to receive it. Topic ${deviceId}/shadow/get/accepted receives only trimmed shadow which contains only essential shadow data. You can find more information about shadow topics in the documentation. The reason that you do not receive your "cmd" section is due to trimmed shadow being received. 

    teba99 said:
    We also tried a shadow update with section
    {
      "desired": {
        "config": {
          "cmd": "command"
        }
      }
    }

    This is fine. In this case, reported config section is sent on trimmed shadow topic. The delta for "cmd" change in desired will come in on the delta topic.

    Best regards,
    Dejan

  • Hi   ,

    Thanks for the quick reply. You wrote:

    In this case, reported config section is sent on trimmed shadow topic. The delta for "cmd" change in desired will come in on the delta topic

    That is not what I am seeing. As I wrote above, when the device reconnects and retrieves the (trimmed) shadow, it does not contain the delta for "cmd" in desired. 

    Please compare the two screenshorts:

    1. shadow in the cloud

    2. device log  

    Note that I am using the device-simulator-v2, not a real device. But the device-simulator is suscribed to the correct deviceId shadow topic, so it shouldn't matter.

    What might be wrong?

    Thanks,

    -- Terrence

      

Reply
  • Hi   ,

    Thanks for the quick reply. You wrote:

    In this case, reported config section is sent on trimmed shadow topic. The delta for "cmd" change in desired will come in on the delta topic

    That is not what I am seeing. As I wrote above, when the device reconnects and retrieves the (trimmed) shadow, it does not contain the delta for "cmd" in desired. 

    Please compare the two screenshorts:

    1. shadow in the cloud

    2. device log  

    Note that I am using the device-simulator-v2, not a real device. But the device-simulator is suscribed to the correct deviceId shadow topic, so it shouldn't matter.

    What might be wrong?

    Thanks,

    -- Terrence

      

Children
  • Hi  ,

    Despite more experiments, I have not yet been able to retrieve the full shadow (including the cmd section) yet. Any advice is appreciated.

    In the meantime, I am now trying to at least have the device handle the delta message it receives while it is connected. Upon receiving the delta message (as per above) the device now publishes to $aws/things/<devceid>/shadow/update the following:

    {

      "reported": {

        "config": {

          "cmd": "command"

        }

      }

    }

    My expectation is that the "cmd" in "desired: config" in the shadow moves to "reported: config" or that "cmd" now is in both "desired" and "reported", indicating that the device has processed the shadow change. 

    But that is not what I am seeing. Instead, when I retrieve the full shadow via the cloud API the "cmd" is still present in the desired section, now also in the "delta" section as well, but not in "reported". It is as if the cloud hasn't processed the update message from the device and it is still pending in "delta".

    I have spent several hours on this topic now, and what I am seeing does not match the documentation or my understanding of AWS device shadow. https://docs.nordicsemi.com/bundle/nrf-cloud/page/Devices/Properties/Shadows.html#configuring-a-device provides a round-trip example, but  this is not what I am seeing.

    I would be very grateful if you could help clear this up.

    Thanks!

  • This issue has been notified to simulator and backend teams. 

    Do I understand correctly that you use the simulator V2 and have modified it.

    The simulator does not seem to have the report back functionality even a dummy one. It inits shadow with semi hardcoded JSON and subscribes shadow topics. But it does not seem to do anything based on received events.

    The device side would need to report the cmd being hendled. 

  • Hi  ,

    Thanks for the answer. Yes, I've added the necessary code to the device simulator. I subscribe to the appropriate topics to handle full and delta "desired" shadows, I handle the cmd, and I publish the device shadow "reported" update to the appropriate topic, as described above.

    To remove the device simulator from the equation I will try and replicate the problem with a desktop- or web-based MQTT client.

    Thanks,
    -- Terrence

  • In the meantime, I am now trying to at least have the device handle the delta message it receives while it is connected. Upon receiving the delta message (as per above) the device now publishes to $aws/things/<devceid>/shadow/update the following:

    Try the following:

    {
      "state": {
        "reported": {
          "config": {
            "cmd": "command"
          }
        }
      }
    }

  • Hi  ,

    Ah, thanks -- using "state" works as expected ... now the cmd is processed and appears in "reported: config: cmd" in the full shadow. I think that addresses my first problem. For my information, can you explain why "state" is necessary when sending a device update via MQTT but is not allowed when using the API (UpdateDevice)?

    However, the problem I still have is: When the device is online, it receives the delta update in the "desired: config: cmd" section (and can now process it, as above). But when the device is offline and then comes online, how should it retrieve the pending delta update? 

    Thanks,
    -- Terrence

Related