Skip to content

@mega-yfue/eufy-sdk / CommandContext

Interface: CommandContext ​

A capability module = property schema + detection + inbound decode + outbound commands. Written ONCE, reused by every device that lists the capability. This is how "extra bits" (a camera's light, pan-tilt, doorbell button) attach without subclassing. The full shape lives in capabilities/types.ts; re-exported here so existing ./types importers keep working.

Extends ​

Properties ​

accountName? ​

ts
accountName?: string;

The acting name a command attributes itself to — the lock cmd acting-username A4 field, and the user_name of the guard-mode and HomeBase-alarm writes. The logged-in account's display name (email local-part) unless the client pins a different label for it.


adminUserId? ​

ts
adminUserId?: string;

The lock owner's account id — the identity a lock command is authenticated against. Present on lock-family devices; absent elsewhere.


capabilities? ​

ts
capabilities?: ReadonlySet<Capability>;

The capability set the device was RESOLVED to have (from resolveDevice: curated row + codec baseline + per-module detection over the full, fresh record). buildCommand gates on this so the authorization matches exactly what device.has(cap) / buildActions saw — never a weaker re-detection from a partial context. Omit only in unit tests that pass evidence directly.

Overrides ​

AvailabilityContext.capabilities


category? ​

ts
category?: string;

API category string — e.g. "eufy_home", "eufy_home_tuya", "eufy_security". Primary transport discriminator for the clean line: "eufy_home_tuya" = ThingClips/Tuya Cloud, not Anker AIoT MQTT. Absent in unit-test contexts that build a minimal context without a real API.

Overrides ​

AvailabilityContext.category


channel ​

ts
channel: number;

Device channel (0 for standalone, device_channel on a HomeBase).


codec? ​

ts
codec?: Codec;

Resolved codec/family. Absent for a device outside the eufy device model entirely — the codecs are the eufy transport families, so an ecosystem with its own backend has no truthful value here and says so by omission rather than borrowing another family's. Every gate that reads it compares against a specific codec, so an absent one matches none.

Inherited from ​

AvailabilityContext.codec


deviceType? ​

ts
deviceType?: number;

eufy DeviceType, when known.

Overrides ​

AvailabilityContext.deviceType


dpCatalog? ​

ts
dpCatalog?: DpCatalog;

Parsed get_product_data_point catalog for this device's SKU — present for vacuum/mower devices, absent for all other codecs. Capabilities use it for per-model feature-availability and value-range data (e.g. which suction levels DP 158 admits). Absent means "catalog not fetched" — fall back to static defaults rather than treating the device as incapable.


firmwareSubVersion? ​

ts
firmwareSubVersion?: string;

Secondary/sub firmware version — the record's sec_sw_version (app label firmware_sub_version).


firmwareVersion? ​

ts
firmwareVersion?: string;

Firmware (main software) version — the device record's main_sw_version, the same field the v6 app maps to its firmware_main_version label. undefined when the record doesn't carry it.


hardwareVersion? ​

ts
hardwareVersion?: string;

Hardware version — the device record's main_hw_version (app label hardware_version). undefined when the record doesn't carry it.


hasP2p? ​

ts
hasP2p?: boolean;

Whether the device has a usable P2P endpoint (a non-empty p2p_did). A HomeBase-attached lock (T8531) is P2P-reachable; a standalone garage/lock (T85D0, p2p_did:"") is MQTT-only. The lock capability uses this to route lock/unlock to P2P vs. reject with a clear MQTT-not-wired error.

Overrides ​

AvailabilityContext.hasP2p


homeBaseAttached? ​

ts
homeBaseAttached?: boolean;

Whether the device hangs off a HomeBase (a parent_sn other than its own) rather than standing alone. A DEVICE fact, not a transport one — the same class of routing evidence as hasP2p — which is why it sits here rather than on CommandContext: it is as true of a described device as of a commanded one. The rtsp capability gates on it because a station serves an attached camera's stream itself and ignores that camera's authentication setting, so the write cannot do what its name promises there.

Inherited from ​

AvailabilityContext.homeBaseAttached


macAddress? ​

ts
macAddress?: string;

Wi-Fi MAC address — the record's wifi_mac (app label mac_address).


model? ​

ts
model?: string;

Model / T-code, when known.

Overrides ​

AvailabilityContext.model


name? ​

ts
name?: string;

Display name, when known — sourced from the device record by the facade (for info).


paramIds ​

ts
paramIds: ReadonlySet<number>;

The param_type / DP ids this device has actually reported (evidence for variant selection).

Overrides ​

AvailabilityContext.paramIds


serial? ​

ts
serial?: string;

Full device serial number, when known.


shortUserId? ​

ts
shortUserId?: string;

The acting member's short id (member.short_user_id, hex, e.g. "0003") — the lock cmd A5 field.


stationDeviceType? ​

ts
stationDeviceType?: number;

The vendor DeviceType of the station the device hangs off, when it is attached and the station's record states one. Answers which station family a command addressed to an attached device is carried through.

Inherited from ​

AvailabilityContext.stationDeviceType


stationSerial? ​

ts
stationSerial?: string;

Serial of the covering station, when the device record names one.

Inherited from ​

AvailabilityContext.stationSerial


timezone? ​

ts
timezone?: string;

Vendor-formatted timezone reported by the station; never inferred from the host.


updateAvailable? ​

ts
updateAvailable?: boolean;

Firmware-update-available flag — the record's needUpdate.

Independent and unofficial. Not affiliated with, endorsed by, or sponsored by Anker Innovations, Anker eufy, or eufy. "Anker eufy", "eufy" and "Anker" are trademarks of their respective owners. Use responsibly — rapid or failed logins can trigger captcha or temporary cooldowns.