UDMI / Docs / Specs / Sequences / Writeback
This file documents UDMI’s specification for cloud to device control i.e. writeback. At a high level, the cloud controls a device by writing to the pointset block in the device config. After receiving the config, the device updates its state to reflect the status of the writeback attempt e.g. success, failure, etc.
Generated using <https://sequencediagram.org>
participant Device
participant Broker
entryspacing 0.1
Broker->Device: CONFIG MESSAGE\npointset.points.subject.set_value = X
note left of Device: point `subject`\n set to X
Device->Broker: STATE MESSAGE\npointset.points.subject.value_state = applied
space -2
To write to a point, the cloud sets three fields in the device config:
set_value
, which specifies the value for a given point in the device’s current units.state_etag
value which uniquely represents the state. Specifically, state_etag
is used to avoid race conditions where the incoming config is based off an obsolete state.set_value_expiry
, which contains the RFC 3339 timestamp at which all set_value
values expire.After receiving the config message, the device attempts to write the value to the point. Depending
on the status of the write, the device should populate the value_state
value_state
The value_state
field is an enumeration within a state message representing
the status of a point’s writeback attempt.
Possible states for value_state
:
value_state
field is missing from this point. This means one of two things:
set_value
, the config misspelled as , which isn’t a valid field in UDMI, and is ignored by the device.value_state
set to updating.
While the system should never abort trying to reconcile the config, after 1 minute of attempting to reconcile, the system should set value_state
to failure.state_etag
on the device doesn’t match the state_etag
from the incoming configIn the case of any of the error states (failure, invalid, overridden), the status field for the point should be populated to provide additional debugging information about the error.
state_etag
The state_etag
field is meant to prevent a race condition where the device could apply a config
change based off an obsolete device state. The state_etag
is a hash value of point units, config
set values echo and value_states in the points block. The state_etag
must be updated to reflect
any updates in the pointset block. The specific calculation of state_etag
is left up to
implementation, but the value should be a unique hash of the state’s pointset. The state_etag
should be included by state and config. When the device receives a new config with a valid
state_etag
, regardless of update success or failure.
An example of how the state_etag
works and the race condition this field prevents:
1) The device is in state A. For example, it specifies units Fahrenheit for some writable point P.
2) The cloud sends a config update to write the value 70 to point P.
3) The device state changes state B, where point P is now using units Celsius. This change can happen manually through the BMS, or through other mechanisms.
4) The device receives the cloud’s config update, and sets the value of point P to 70 Celsius, instead of the intended 70 Fahrenheit.
state_etag
prevents this race condition by ensuring that the device state doesn’t change between when the config was sent and received. i.e. in the previous example, the cloud’s config update would include a state_etag
uniquely representing state A. Upon receiving the update, the device would detect that the current state_etag
(uniquely representing state B) is not the same as the one in the config, and therefore set the value_state
as invalid.
When the device receives a config, it should check that set_value_expiry
exists and is greater than the timestamp field in the config, sending an invalid value_state
if not.
If the set_value_expiry
has already passed, then there’s no write to perform, so the state of the device shouldn’t change (i.e. this is a no-op)
If the config passes these checks, then the device should
1) perform the write
2) set a timer to trigger at the given set_value_expiry
, overwriting any existing timer.
When the timer expires, the device reverts to its base state (as if no set values have been indicated), and sends a state update to notify the cloud of the state change.