aws-greengrass / aws-greengrass-shadow-manager

A GreengrassV2 Component that provides offline device shadow documents and optional synchronization to the IoT device shadow service.
Apache License 2.0
9 stars 5 forks source link

Shadow is not synchronized #198

Closed tomikpik closed 4 months ago

tomikpik commented 6 months ago

Hi there, I've experienced an issue while trying to synchronize the shadow between IoT core and shadow manager component. The problematic behaviour is following:

I have a following shadow document describing a rtsp stream that should be processed by EDGE device running Greengrass.

{
  "state": {
    "desired": {
      "state": "ENABLED",
      "uuid": "c65c7502-514c-41f8-af33-bbd58ad8afa9",
      "mode": "PERSON",
      "url": "rtsp://...."
      "configVersion": "1704190617045"
    },
    "reported": {
      "state": "ENABLED",
      "uuid": "c65c7502-514c-41f8-af33-bbd58ad8afa9",
      "mode": "PERSON",
      "url": "rtsp://...."
      "configVersion": "1704190617045"
    }
  }
}

The problem happens when I want to "clear" the shadow due to device reconfiguration. eg. i'd like to get to the following state:

{
  "state": {
    "desired": {
    },
    ....
  }
}

When our API updates the "desired" object the change is successfully saved in IoT core. Desired object written by our API:

{
  "state": {
    "desired": {
      "state": null,
      "uuid": null,
      "mode": null,
      "url": null,
      "configVersion": null
    },
    "reported": ...
  }
}

And that is when the problem happens. According to greengrass.log file the shadow synchronization is invoked, cloud version of shadow is incremented (it corresponds to iot core), but the local version stays the same.

I've dicovered that it is connected to the modification of the "state" property of the desired object. We're able to clear (by setting to null) one or more fields (and the change is successfully synchronized to the shadow manager as long as it does not include the "state" field. When the "state.desired.state" field is set to null the synchronization between IoT core and local shadow is not performed.

Please confirm if this is expected behaviour, eg. state is some protected field name that can't be used in child objects or if it is a bug.

Nucleus 2.12.1 Shadow manager 2.3.5

Thank you very much and have a happy new year! Tomas

MikeDombo commented 6 months ago

Hello,

What is the content of the shadow that you retrieve locally on Greengrass? You said what the value is in the IoT Shadow service, but not the local copy.

To truly clear the shadow state update with {"state": null}

Please also provide the configuration that you're using for shadow manager to synchronize the data.

tomikpik commented 6 months ago

Hi, the desired status read from our component stays un-updated. After we publish this from our API:

{
  "state": {
    "desired": {
      "state": null,
      "uuid": null,
      "mode": null,
      "url": null,
      "configVersion": null
    },
    "reported": ...
  }
}

The shadow manager adds a log to greengrass.log file that cloud version was incremented, but the local version of the shadow stayed the same.

This means that even after the update was published and has a correct value in aws iot core, the device still reads the original value (below):

{
  "state": {
    "desired": {
      "state": "ENABLED",
      "uuid": "c65c7502-514c-41f8-af33-bbd58ad8afa9",
      "mode": "PERSON",
      "url": "rtsp://...."
      "configVersion": "1704190617045"
    },
    "reported": {
      "state": "ENABLED",
      "uuid": "c65c7502-514c-41f8-af33-bbd58ad8afa9",
      "mode": "PERSON",
      "url": "rtsp://...."
      "configVersion": "1704190617045"
    }
  }
}

but when we publish this (omitting the state property of desired object):

{
  "state": {
    "desired": {
      "uuid": null,
      "mode": null,
      "url": null,
      "configVersion": null
    },
    "reported": ...
  }
}

The synchronization between the cloud and local copy is fine and our component reads this:

{
  "state": {
    "desired": {
      "state": "ENABLED",
    },
    "reported": {
       ....
    }
  }
}

Long story short, we're not able to clear the state propery by setting it to null and when it is set to null it also blocks the synchronization of other fields to local shadow copy.

Component configuration is below:

    config: {
      strategy: {
        type: 'realTime',
      },
      rateLimits: {
        maxOutboundSyncUpdatesPerSecond: 1000,
        maxTotalLocalRequestsRate: 1000,
        maxLocalRequestsPerSecondPerThing: 1000
      },
      synchronize: {
        coreThing: {
          classic: false,
          namedShadows: [
            'Attributes',
            'DetectorInfo',
            'DeviceInfo',
         ]
       }
    }
}
MikeDombo commented 6 months ago

Thank you for the details.

Yes this is a bug. You can avoid this by setting the entire state to null, rather than individual keys. You can also avoid this by not using a key named state.

We will work to address this shortly. The fix will not have keys which are set to null, instead they will be removed from the shadow document if they are null. To be specific an update of {"state": {"state":null} will result in {"state": {}}. If other keys were already in the shadow, then those keys will be preserved.

tomikpik commented 6 months ago

Thank you! 🤩

MikeDombo commented 4 months ago

@tomikpik,

This issue should now be fixed in Shadow Manager 2.3.6, please try out that version.

Closing the ticket now, but reopen it if needed.

Thank you again for reporting the problem

tomikpik commented 4 months ago

thank you @MikeDombo