Skip to main content

Entities

CDF entities are the stable, app-facing objects your UI calls. Each entity wraps SDK calls in operations, keeps the original SDK object in _raw, and emits operation events that drive store updates.

Use entity pages for task-oriented workflows (control a param, run a scene, share a group). Use domain stores for store maps, pagination, and session bootstrap.

tip

Do not construct entities in UI code — adaptors create them and stores hold observable instances.


Common Workflows

Subscribe to operation events on an entity

import { initCDF } from "@espressif/rainmaker-base-cdf";

const espCDF = await initCDF({ sdkAdaptorRegistry });
const node = espCDF.nodeStore.getNodeById("node-id");

const unsubscribe = node?.subscribe((n, op, success, _, err) => {
if (!success) console.error({ nodeId: n.id, op, err });
});

// Clean up when the screen unmounts
unsubscribe?.();

Per-entity guides are in the catalog below.


Entity Catalog

CDF entity classes are the objects your UI and feature code call. Observable fields are updated after successful operations; methods delegate to injected operations and emit on the entity event bus.

EntityRole
ESPCDFUserAuthenticated user; groups, nodes, provisioning, Matter, and push helpers.
ESPCDFGroupRoom / home / fabric; nodes, scenes, schedules, automations, sharing.
ESPCDFNodeOne backend node; connectivity, config tree, OTA, property-change sync.
ESPCDFNodeConfigNode configuration snapshot (devices, version, info).
ESPCDFDeviceDevice model under a node (Light, Fan, …).
ESPCDFDeviceParamSingle device parameter (read/write value).
ESPCDFServiceOptional service slice on a node (params).
ESPCDFServiceParamParameter on a service.
ESPCDFSceneScene definition and lifecycle.
ESPCDFScheduleSchedule with triggers, action, enable flags, sync metadata.
ESPCDFAutomationAutomation (events → actions); uses operationsEvents for op bus.
ESPCDFGroupSharingRequestIncoming/outgoing group share workflow.
ESPCDFProvisioningDeviceEphemeral provisioned peer (no operation event emitter).

Advanced Concepts

Unified entity wrapper

Every CDF entity (ESPCDFNode, ESPCDFGroup, ESPCDFUser, …) is a pure SDK wrapper:

An entity is constructed by an adaptor transformer with three injected pieces:

PropertyWho provides itPurpose
operationsAdaptor transformerObject whose methods call the underlying SDK
_rawAdaptor transformerOriginal SDK entity; excluded from MobX observation
eventsEntity constructorOperationEventEmitter instance; used internally for event emission

The critical rule: Entities delegate to operations and emit events. They never update their own observable properties. All observable mutations go through synchronizers. Exception: ESPCDFAutomation uses operationsEvents as the operation bus name (see ESPCDFAutomation).

Entity method pattern

Every entity method follows the runAndEmit pattern — delegate the SDK call, then emit success or failure:

// ESPCDFGroup.delete() — representative of all entity operations
async delete(): Promise<ESPCDFAPIResponse> {
return this.runAndEmit(
"delete", // operation name
() => this.operations.delete(), // SDK call
() => this, // data to include in success event
);
}

// runAndEmit is a shared helper on every entity:
private async runAndEmit<T>(
operation: OperationType,
execute: () => Promise<T>,
getData?: (result: T) => unknown,
): Promise<T> {
let succeeded = false;
let result!: T;
let error: unknown;
try {
result = await execute();
succeeded = true;
return result;
} catch (e) {
error = e;
throw e;
} finally {
this.emit(operation, succeeded, succeeded ? getData?.(result) : undefined, error);
}
}

On failure the error is re-thrown (so the caller can handle it), and the failure event is still emitted so synchronizers can log without applying partial state patches.

OperationEventEmitter

Every entity holds a typed OperationEventEmitter. The entity uses it internally; synchronizers subscribe to it.

// Type signature (illustrative)
class ESPCDFOperationEventEmitter<TEntity, TOperation extends string> {
subscribe(
listener: (
entity: TEntity,
operation: TOperation,
success: boolean,
data?: unknown,
error?: unknown,
) => void,
): () => void; // returns unsubscribe function

emit(
entity: TEntity,
operation: TOperation,
success: boolean,
data?: unknown,
error?: unknown,
): void;

dispose(): void; // removes all listeners
}

On this page