Skip to content

@mega-yfue/eufy-sdk / tuya / TuyaClient

Class: TuyaClient

Constructors

Constructor

ts
new TuyaClient(config?): TuyaClient;

Parameters

config?

TuyaClientConfig = {}

Returns

TuyaClient

Accessors

loggedIn

Get Signature

ts
get loggedIn(): boolean;

True once a login has populated a session id.

Returns

boolean

Methods

buildRequest()

ts
buildRequest(action): Record<string, string>;

Build the full signed param map for an action against the current session. Does not send. Requires a working signer (the sign step).

Parameters

action

TuyaAction

Returns

Record<string, string>


call()

ts
call<T>(action): Promise<TuyaEnvelope<T>>;

Build + POST an action, returning the parsed envelope. Requires a working signer.

Type Parameters

T

T = unknown

Parameters

action

TuyaAction

Returns

Promise<TuyaEnvelope<T>>


getDeviceDps()

ts
getDeviceDps<T>(devId, dpCacheType?): Promise<TuyaEnvelope<T>>;

READ/dump a device's cached data-points (thing.m.device.cache.dp.get). Builds the request without needing a working signer; the signer is only exercised on send.

Type Parameters

T

T = unknown

Parameters

devId

string

dpCacheType?

number

Returns

Promise<TuyaEnvelope<T>>


getSession()

ts
getSession(): Readonly<TuyaSession>;

The current per-install session identity (sid empty until login).

Returns

Readonly<TuyaSession>


login()

ts
login(eufyUserId, phoneCode?): Promise<TuyaLoginResult>;

Log into the Tuya cloud from a eufy user id (wire-confirmed from the eufy Security app).

Flow:

  1. smartlife.m.user.username.token.get{ token, publicKey, exponent } (RSA-2048 key). If this returns USER_NOT_EXIST the shadow account has never been provisioned — the vacuum must be added via the eufy Security app (com.oceanwing.battery.cam) at least once.
  2. Derive password: RSA/PKCS1-encrypt( MD5hex(aesPassword), serverKey ) → hex.
  3. smartlife.m.user.uid.password.login.reg{ sid, uid }. On USER_PASSWD_WRONG: re-fetch a token and retry once with the hardcoded fallback password "12345678" (wire-confirmed from the eufy Security app). ⚠️ Two failed attempts in a row can contribute to Tuya-side rate-limiting or lockout — do not add further retry loops on top of this one.

Parameters

eufyUserId

string

phoneCode?

string

Returns

Promise<TuyaLoginResult>


publishDps()

ts
publishDps<T>(
   devId, 
   gwId, 
   dps, 
   opts?
): Promise<TuyaEnvelope<T>>;

CONTROL: publish data-points to a device (thing.m.device.dp.publish). dps is { "<dpId>": <value> }. gwId is the gateway/parent id (equals devId for a standalone gw).

⚠️ UNVERIFIED write — refuses to send by default. The dp.publish param shape (buildPublishDpsAction) is derived, NOT pinned against a confirmed exchange, and the login round-trip that yields a real sid is unproven too. A wrong shape comes back as a generic Tuya error indistinguishable from a real device rejection, so blindly sending would hide that ambiguity. Pass { allowUnverified: true } to send anyway; the gate drops when the write is captured + confirmed against a device.

Type Parameters

T

T = unknown

Parameters

devId

string

gwId

string

dps

Record<string, unknown>

opts?
allowUnverified?

boolean

Returns

Promise<TuyaEnvelope<T>>

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.