RPC vs. Shadow - help and opinions needed

I’ve been looking at remotely setting some device variables, and reading through the RPC (mos and mdash) and Shadow (mos and mdash) docs. I’m only looking at mDash as the backend mechanism for all of this.

First off not sure if I’m missing something but the Shadow docs seemed to omit basic examples of the expected flow from desireddeltareported for mDash.
For C the smart light example on github really made it clear.

I wanted to clarify my understanding and ask for opinions on a few things:

  1. Online/Offline
    RPC only works if the device is online and can accept/respond to the request.
    Shadow allows the variable to be set independently and then picked up when the device when it comes online.

  2. Security
    From this mDash diagram it looks as though the auth mechanism is the same for both RPC and Shadow (TLS 1.2), but reading the RPC docs auth section makes me feel as though Shadow might be more secure by default:

    Mongoose OS RPC authentication is quite basic, and is vulnerable to replay attacks as the TC field is not incremented. However it enforces basic authentication that is not plaintext, and the intention is you’re communicating via a secure TLS channel like MQTT or HTTPS.

  3. ACL
    Both RPC and Shadow have the ability to be limited when used with customers using ACL on the device.

Based on this it feels like I should be using shadow where possible.

Would love to hear some opinions or experience around the above comments.
Thanks.

The shadow is a means to keep the state of a device and/or modify it when it is not online. Apps can change the state of your device without actually connecting to it, decouples your device from the rest of the world.
RPC (Remote Procedural Call) is a mechanism to send messages to a device and request something, to send commands, to obtain data from it. You need to somehow “connect” to the device, it must be online and you must be able to reach to the device somehow.

Some stuff you can do almost indistinctly with any of these; some stuff is more suited to one of them. For example, if you want to send something on the serial port, I would use RPC. If you want to change the state of an output in a manner it will stay that way even after a reboot, I would use the shadow.

AFAIK, RPC authentication is on top of whatever mechanism you use for connecting to the device (plain/TLS). I think what the docs say is that as the auth mechanism itself is basic, you need to add an extra layer of security to avoid someone sniffing the network and replaying your commands; if you are on top of TLS then your traffic is encrypted.
Shadow messages are just messages; the only authentication you may have is at the connection level; for example if mutual authentication is used by your MQTT broker provider. I guess mDash has something for this, I don’t use it so I don’t know. I’ve only used the shadow through AWS so I might be biased and forgetting something.

My 2 cents, YMMV.

Thanks for your opinion @scaprile.
Sounds like Shadow is worth the time to get right, seems like a good general way forward.

On my shadow journey I’ve been playing around with some code samples to get/set/update states using shadows and I’m struggling to work out a way in mos to handle events like “B is updated but not A and C”. With RPC I would have handled this by breaking down the RPC endpoints to the smallest chunk and processing what comes in.

Since shadow events come in as a single event with potentially a number of changes at once I’m stuck doing something like:

if (json_scanf(delta->p, delta->len, "{a: %d}", &a) == 1)
{
  do_a_action(a);
}

if (json_scanf(delta->p, delta->len, "{b: %lf}", &b) == 1)
{
  do_b_action(b);
}

if (json_scanf(delta->p, delta->len, "{message: %s, timestamp: %s}", &message, &timestamp) == 2)
{
  do_message_action(message, timestamp);
}

Is there a nicer way to do this for a large set of potential shadow values that isn’t always sent in a single batch?

Instead of reinventing the wheel I would look at how AWS solved it.
They have different subtopics and either send deltas or the whole device shadow.
You have a local copy and you can calculate your deltas yourself.
In my opinion, changes that are not permanent and or have a higher frequency would be better handled by other means. Google, for example, has a different topic for ‘commands’.
You can run RPC on a MQTT topic in AWS (or any other MQTT broker except Google, which has fixed topics and requires the use of a special library).