We can split the properties in the twin into two categories:
- Properties that describe the state of a component on the device different from the device agent.
- Properties that describe how the device agent or one of its handlers should be behave.
When the propeties at hand describe how a handler should behave, such properties are embedded in the configuration group of that handler under the __meta
node.
Below is a description of node schema and programming model.
Sub-Group | Properties | ||
Deployment Id Desired: Optional Reported: Yes Indicates the source deployment id of the current configuration. |
`deploymentId` | Type | string |
Desired | Required | ||
Reported | Yes | ||
Description | This is a string selected by the operator to identify the deployment by. | ||
Deployment Status Desired: n/a Reported: Yes Indicates the current status of the deployment. |
`deploymentStatus` | Type | string |
Desired | n/a | ||
Reported | Yes | ||
Description | Indicates the status of the underlying configuration. Values are: - notStarted - succeeded - pending - failed |
||
Reporting Mode Desired: Optional Reported: Yes Indicates to the agent whether to report the current state of the group configuration (detailed|minimal) or not(none). |
`reportingMode` | Type | String |
Desired | Required | ||
Reported | Yes | ||
Description | `detailed` indicates the current component status should be reported in detail. `minimal` indicates the current component status should be reported at minimal. `none` indicates the current component status should not be reported to the device twin. If it has been reported in the past, it should be removed. |
||
Time Stamp Desired: n/a Reported: Yes Indicates the time of when the reported meta data was last updated. |
`time` | Type | string |
Desired | n/a | ||
Reported | Yes | ||
Description | time in ISO 8601 format (i.e. 2016-10-10T17:00:00Z). | ||
Service Interface Version Desired: Always Reported: n/a Indicates the interface version the service tries to communicate to the device handlers with. |
`serviceInterfaceVersion` | Type | string |
Desired | Required | ||
Reported | n/a | ||
Description | Indicates the interface version the service tries to communicate to the device handlers with. | ||
Device Interface Version Desired: n/a Reported: Always |
`deviceInterfaceVersion` | Type | string |
Desired | n/a | ||
Reported | Yes | ||
Description | Indicates the version of the interface the handler reports back to the cloud. |
{ "properties" : { "desired": { "<config-group-id>": { "__meta" : { "deploymentId": "unspecified", "reportingMode": "none|minimal|detailed", "serviceInterfaceVersion": "1.0.0" } } }, "reported": { "<config-group-id>": { "__meta" : { "deploymentId": "unspecified", "reportingMode": "none|minimal|detailed", "deploymentStatus": "notStarted|succeeded|pending|failed", "deviceInterfaceVersion": "1.0.0", "time": "<time>" } } } } }
The schema described above is implemented using the MetaData
class in the common library. The implementation provides an easy way to parse, validate, query, and update the underlying json.
The BaseHandler
class provide a data member _metaData
(of type MetaData
) to hold unto it. The author of the handler has to re-populate it during every invoke and use it to enforce policies (like reporting, etc).
For example, below is a common pattern of using the _metaData:
Invoke(...) { RunOperation(GetId(), errorList, [&]() { // Make sure this is not a transient state if (IsRefreshing(groupDesiredConfigJson)) { return; } // Processing Meta Data _metaData->FromJsonParentObject(groupDesiredConfigJson); // Apply new state SetSubGroup(...); // Report current state if (_metaData->GetReportingMode() == JsonReportingModeDetailed) { BuildReported(reportedObject, errorList); } else { EmptyReported(reportedObject); } }); FinalizeAndReport(reportedObject, errorList); return invokeResult; }