eufy-mega / client/eufy-mega / EufyMega
Class: EufyMega
The package entry point — one client per eufy account. Handles the login state machine (captcha/2FA/persistence), resolves the account's devices (getDevices/getDevice → capability-driven Devices), auto-manages the realtime channels (FCM push + secure MQTT start on login; P2P opens on demand per station and idle-detaches battery cameras), and fans every transport's traffic into one typed semantic event stream (eufy.on("motion", …)). Construct it with an EufyMegaOptions (email/password + optional session/push stores), then drive login() to completion — no connect* call needed (set autoRealtime:false to opt out). Call disconnect to tear the realtime channels down.
Extends
EventEmitter
Constructors
Constructor
new EufyMega(opts): EufyMega;Parameters
opts
Returns
EufyMega
Accessors
api
Get Signature
get api(): MegaHttpClient;Raw mega HTTP client, for endpoints not yet wrapped.
Returns
MegaHttpClient
loggedIn
Get Signature
get loggedIn(): boolean;True if a usable session (restored from store or freshly logged in) is held.
Returns
boolean
Methods
clearSession()
clearSession(): void;Forget the persisted session (forces a fresh login + 2FA next time).
Returns
void
deviceState()
deviceState(sn): DeviceState;The liveness facts for one device — see DeviceState. Facts, not an online verdict: "how long is too long" is a threshold that belongs to the caller, and it differs per device class.
Pair it with the deviceState event to be told when a device reports in, rather than polling this.
Parameters
sn
string
Returns
disconnect()
disconnect(): Promise<void>;Tear down every realtime channel: close the secure-MQTT transport, all P2P sessions, and the FCM push socket. Idempotent — safe to call when nothing is connected. Leaves the login session intact (call login again to reconnect without re-authenticating).
Returns
Promise<void>
emit()
emit<E>(event, ...args): boolean;Type Parameters
E
E extends | "error" | "p2p" | "connect" | "disconnect" | "message" | "push" | "event" | keyof DeviceEventMap | "deviceAdded" | "deviceRemoved" | "deviceCapabilities" | "deviceState" | "p2pConnect" | "p2pClose" | "p2pLevel2Ready" | "pushConnect" | "pushDisconnect" | "pushRaw" | "commandAck"
Parameters
event
E
args
...EufyMegaEventMap[E]
Returns
boolean
getDevice()
getDevice(sn): Promise<Device>;Build a live Device model object for one serial: the resolved codec/capabilities with its current param values applied (named via the param dictionary; unknown ids kept as unknown_<pt>). This is the device primitive a host reads — dev.getProperties(), dev.has(cap), etc. Prefers fresh get_device_param_list, falls back to the device-list params. Under auto-realtime the returned Device is wired with a read-through freshness cache (see Device.setFreshnessPolicy), so a host that reuses it (e.g. a periodic polling loop) serves repeat reads from cache instead of re-fetching, and realtime updates keep values fresh.
Parameters
sn
string
Returns
Promise<Device>
Example
const dev = await eufy.getDevice(sn);
if (dev.has("camera")) await dev.camera()?.snapshot();
console.log(dev.getProperty("battery"));getDeviceParamList()
getDeviceParamList<T>(deviceSn): Promise<T>;Live param list for one owned device. See MegaHttpClient.getDeviceParamList.
Type Parameters
T
T = unknown
Parameters
deviceSn
string
Returns
Promise<T>
getDevices()
getDevices(): Promise<EufyDevice[]>;List + classify devices across all houses (mega API). Each device is tagged with its API backend
- realtime transport. Camera/HomeBase records still appear here for inventory; driving them is P2P. Delegates to
DeviceRegistry(the house-scoped merge/dedupe lives there).
Returns
Promise<EufyDevice[]>
getMqttDevices()
getMqttDevices(): EufyDevice[];Devices that this client drives over MQTT (transport ≠ p2p).
Returns
EufyDevice[]
getP2pDevices()
getP2pDevices(): EufyDevice[];Devices that require P2P (cameras/HomeBases).
Returns
EufyDevice[]
getP2pSessions()
getP2pSessions(): Map<string, P2PSession>;Stations with a live P2P session. P2P is auto-managed: wired stations are warmed at login, battery stations open on demand (command / stream / doorbell pre-warm) and idle-detach — so this map grows and shrinks over time. p2pConnect(stationSn) / p2pClose(stationSn) events track the changes.
Returns
Map<string, P2PSession>
getProductDataPoint()
getProductDataPoint<T>(code): Promise<T>;Per-SKU data-point (param) schema from the mega things service — the authoritative param_type catalogue for a product code (the same call the v6 app uses). Works for ANY SKU, not just owned devices. See MegaHttpClient.getProductDataPoint.
Type Parameters
T
T = unknown
Parameters
code
string
Returns
Promise<T>
getUserMqttInfo()
getUserMqttInfo(appName?): Promise<SecureMqttCredentials>;Fetch the per-user secure-MQTT credentials for realtime appliance control. Pass appName to request a specific capability scope on the current session without re-logging in — security devices (locks/garage) need the eufy_security scope, which the default scope can't reach.
Parameters
appName?
string
Returns
Promise<SecureMqttCredentials>
inspectAllDevices()
inspectAllDevices(): Promise<DeviceInspection[]>;Inspect every owned device (the bulk enrichment export).
Returns
Promise<DeviceInspection[]>
inspectDevice()
inspectDevice(sn): Promise<DeviceInspection>;Inspect one device by serial: resolve its codec/capabilities, cross-reference every reported param_type against the param dictionary, and emit a paste-ready registry.ts row plus dictionary snippets for anything unknown. The enrichment tool — run it on a new/unconfirmed device and send back the export to grow the device catalog. Loads the device list if needed; prefers the live get_device_param_list for freshest params, falling back to the device-list params.
Parameters
sn
string
Returns
Promise<DeviceInspection>
login()
login(opts?): Promise<LoginResult>;Begin (or resume) login. Returns a LoginResult — switch on status:
ok→ authenticated (result.session).captcha→ showresult.image, then solveCaptcha(answer).2fa→ a code was sent; submitVerifyCode(code).
A restored session resolves straight to ok. No exceptions for the expected captcha/2FA flow.
Parameters
opts?
messageType?
number
Returns
Promise<LoginResult>
Example
const res = await eufy.login();
if (res.status === "captcha") await eufy.solveCaptcha(await ask(res.image));
else if (res.status === "2fa") await eufy.submitVerifyCode(await ask());off()
off<E>(event, listener): this;Type Parameters
E
E extends | "error" | "p2p" | "connect" | "disconnect" | "message" | "push" | "event" | keyof DeviceEventMap | "deviceAdded" | "deviceRemoved" | "deviceCapabilities" | "deviceState" | "p2pConnect" | "p2pClose" | "p2pLevel2Ready" | "pushConnect" | "pushDisconnect" | "pushRaw" | "commandAck"
Parameters
event
E
listener
(...args) => void
Returns
this
on()
on<E>(event, listener): this;Type Parameters
E
E extends | "error" | "p2p" | "connect" | "disconnect" | "message" | "push" | "event" | keyof DeviceEventMap | "deviceAdded" | "deviceRemoved" | "deviceCapabilities" | "deviceState" | "p2pConnect" | "p2pClose" | "p2pLevel2Ready" | "pushConnect" | "pushDisconnect" | "pushRaw" | "commandAck"
Parameters
event
E
listener
(...args) => void
Returns
this
once()
once<E>(event, listener): this;Type Parameters
E
E extends | "error" | "p2p" | "connect" | "disconnect" | "message" | "push" | "event" | keyof DeviceEventMap | "deviceAdded" | "deviceRemoved" | "deviceCapabilities" | "deviceState" | "p2pConnect" | "p2pClose" | "p2pLevel2Ready" | "pushConnect" | "pushDisconnect" | "pushRaw" | "commandAck"
Parameters
event
E
listener
(...args) => void
Returns
this
renameDevice()
renameDevice(sn, name): Promise<void>;Rename a device (or station). The new name propagates to the eufy cloud automatically, so no separate HTTP update is needed. Fire-and-forget; re-read with getDevice to confirm the new name. ASCII names only for now.
Parameters
sn
string
name
string
Returns
Promise<void>
setProperty()
setProperty(
sn,
name,
value): Promise<void>;Write a device property. Asks the capability modules to build the command for this (name, value) — the module owns how THIS device applies it. No (name, value) recipe → the device doesn't support the property, so we throw CapabilityNotSupportedError rather than a silent no-op. On success the device echoes the new state back as a param update — read it with getDevice to confirm.
Parameters
sn
string
device serial.
name
string
property name (e.g. "light", "brightness", "enabled").
value
string | number | boolean
desired value.
Returns
Promise<void>
Example
await eufy.setProperty(sn, "brightness", 50);
await eufy.setProperty(sn, "light", true);solveCaptcha()
solveCaptcha(answer, opts?): Promise<LoginResult>;Continue a {status:"captcha"} login with the solved answer. See login.
Parameters
answer
string
opts?
messageType?
number
Returns
Promise<LoginResult>
submitVerifyCode()
submitVerifyCode(code): Promise<LoginResult>;Continue a {status:"2fa"} login with the verify code that was sent. See login.
Parameters
code
string
Returns
Promise<LoginResult>