Function Call Patterns¶
How to call function methods from adapter code. Getting this wrong is the most common source of confusion when writing event routing and command handlers.
Things implement function interfaces directly¶
The source generator implements each function interface on the Thing class itself, forwarding to the underlying function instance. Call methods directly on the Thing - no intermediate property needed.
var timestamp = evt.Timestamp;
// correct
await partition.Armed(timestamp, personId);
await zone.Alarm(timestamp);
await output.Activated(timestamp);
// wrong - do not navigate through Functions for method calls
await partition.Functions.Partition.Armed(timestamp, personId);
This works for any typed variable: local variables, method parameters, field references.
StatusBatch selects the function from the state enum type¶
During status polling, StatusBatch.Set(state) reports current state. The state enum's type selects the target function at compile time — pass only the value, no function reference. Do not use action methods for status snapshots; they publish events.
// correct use - StatusBatch in PollStatus handler
using var batch = thing.StatusBatch();
batch.Set(PqState.Partition.Armed);
batch.Set(PqState.IntrusionDetector.Normal);
await batch.Commit(ct);
// wrong use - calling an action method during polling
await thing.Armed(timestamp, personId); // publishes an event, not a status snapshot
Commit scopes to exactly the functions you Set(...); sibling functions are never cleared.
Use DeviceTimestamp for all function method calls¶
All function action methods take a DeviceTimestamp as their first parameter. Use the timestamp from the device event payload when available. Use an adapter-generated timestamp only for events created by the adapter itself, such as timers and command responses.
// device-reported timestamp from event payload
await zone.Alarm(evt.Timestamp);
// parse a protocol-specific timestamp when the event object does not already expose one
await partition.Armed(DeviceTimestamp.FromUnixSeconds(evt.Timestamp), personId);
await partition.Armed(DeviceTimestamp.FromDateTime(evt.DateTime), personId);
// adapter-generated event, e.g. timer expiry
var timerTimestamp = DeviceTimestamp.FromDateTime(timeProvider.GetUtcNow().UtcDateTime);
await zone.Cleared(timerTimestamp);
// wrong - do not use DateTimeOffset directly
await zone.Alarm(DateTimeOffset.UtcNow); // does not compile - wrong type
Function method signatures are defined by the framework function taxonomy and exposed through generated code.
Common examples¶
Partition.Armed¶
// user armed
await partition.Armed(timestamp, personId);
// schedule arm (no user)
await partition.ArmedSchedule(timestamp, Guid.Empty);
// remote arm (API/integration)
await partition.ArmedRemote(timestamp);
// disarm
await partition.Disarmed(timestamp, personId);
IntrusionDetector.Alarm¶
// zone tripped
await zone.Alarm(timestamp);
// zone restored
await zone.Cleared(timestamp);
// zone bypassed
await zone.Bypassed(timestamp, personId, $"Zone {zone.Address}");
// zone fault / restore
await zone.Fault(timestamp);
await zone.FaultRestored(timestamp);
Output.Activated¶
// output relay energised
await output.Activated(timestamp);
// output relay de-energised
await output.Deactivated(timestamp);
See Also¶
- Source of truth: Functions Registry - documented function definitions, actions, and signatures
- Status polling: Status Polling Pattern - StatusBatch pattern
- Generated API: Generated Code API - full method listings per function