UNPKG

@lucavb/shellies-ds9

Version:

Handles communication with the next generation of Shelly devices

1,650 lines (1,615 loc) 81.7 kB
import EventEmitter from 'eventemitter3'; import mDNS from 'multicast-dns'; import { JSONRPCRequest, JSONRPCClient, SendRequest, JSONRPCResponse } from 'json-rpc-2.0'; import WebSocket from 'ws'; type RpcParams = Record<string, unknown>; /** * Describes a status update notification. */ interface RpcStatusNotification { /** * A UNIX timestamp. */ ts: number; /** * One or more components and its updated attributes. */ [component: string]: unknown; } interface RpcEvent { /** * The component that this event belongs to. */ component: string; /** * The instance ID of the component, if applicable. */ id?: number; /** * The name of the event. */ event: string; /** * A UNIX timestamp. */ ts: number; /** * Additional properties. */ [p: string]: unknown; } /** * Describes an event notification. */ interface RpcEventNotification { /** * A UNIX timestamp. */ ts: number; /** * A list of one or more events that have occurred. */ events: RpcEvent[]; } type RpcHandlerEvents = { /** * The 'connect' event is emitted when a connection has been established. */ connect: () => void; /** * The 'disconnect' event is emitted when a connection has been closed or an attempt to connect fails. */ disconnect: (code: number, reason: string, reconnectIn: number | null) => void; /** * The 'request' event is emitted when a new request is about to be sent. */ request: (method: string, params?: RpcParams) => void; /** * The 'statusUpdate' event is emitted when an update notification is received, * and contains updates to one or more device components. */ statusUpdate: (update: RpcStatusNotification) => void; /** * The 'event' event is emitted when an event notification is received. */ event: (events: RpcEventNotification) => void; /** * The 'error' event is emitted if an error occurs. */ error: (error: Error) => void; }; /** * Base class for all remote procedure call (RPC) handlers. */ declare abstract class RpcHandler extends EventEmitter<RpcHandlerEvents> { readonly protocol: string; /** * @param protocol - The protocol used to send RPCs. */ constructor(protocol: string); /** * Whether this handler is connected to its device. */ abstract get connected(): boolean; /** * Sends an RPC. * @param method - The method to call. * @param params - Parameters that the method takes (if any). * @returns A promise that will resolve once a response has been received from * the device. */ abstract request<T>(method: string, params?: RpcParams): PromiseLike<T>; /** * Closes the underlying connection, if applicable. * @returns A promise that resolves once the connection has been closed. */ abstract destroy(): PromiseLike<void>; } /** * Authentication challenge parameters sent by the server when a protected resource is requested. */ interface RpcAuthChallenge { auth_type: string; nonce: number; nc?: number; realm: string; algorithm: string; } /** * Authentication response parameters supplied with each authenticated request. */ interface RpcAuthResponse { realm: string; username: string; nonce: number; cnonce: number; response: string; algorithm: 'SHA-256'; } /** * A request with authentication response parameters. */ interface JSONRPCRequestWithAuth extends JSONRPCRequest { auth?: RpcAuthResponse; } /** * Extends JSONRPCClient to seamlessly handle authentication. */ declare class JSONRPCClientWithAuthentication<ClientParams = void> extends JSONRPCClient<ClientParams> { protected password?: string | undefined; /** * Holds the current request ID. This number is incremented for each new request. */ protected requestId: number; /** * Authentication response parameters sent with each request if the connection has been authenticated. */ protected auth?: RpcAuthResponse; /** * @param password - The password to authenticate with. */ constructor(send: SendRequest<ClientParams>, password?: string | undefined); requestAdvanced(request: JSONRPCRequest, clientParams: ClientParams): PromiseLike<JSONRPCResponse>; requestAdvanced(requests: JSONRPCRequest[], clientParams: ClientParams): PromiseLike<JSONRPCResponse[]>; /** * Handles 401 errors by parsing the authentication challenge, generating an authentication response * and supplying that response with each subsequent request. */ protected requestWithAuthentication(request: JSONRPCRequest, clientParams: ClientParams): Promise<JSONRPCResponse>; /** * Creates an authentication response based on the given challenge and the configured password. * @param params - Authentication challenge params. */ protected createAuthResponse(params: RpcAuthChallenge): RpcAuthResponse; } /** * Options for the WebSocket RPC handler. */ interface WebSocketRpcHandlerOptions { /** * A unique ID used to identify this client when communicating with the Shelly device. */ clientId: string; /** * The time, in seconds, to wait for a response before a request is aborted. */ requestTimeout: number; /** * The interval, in seconds, at which ping requests should be made to verify that the connection is open. * Set to `0` to disable. */ pingInterval: number; /** * The interval, in seconds, at which a connection attempt should be made after a socket has been closed. * If an array is specified, the first value of the array will be used for the first connection attempt, the second * value for the second attempt and so on. When the last item in the array has been reached, it will be used for * all subsequent connection attempts; unless the value is `0`, in which case no more attempts will be made. * Set to `0` or an empty array to disable. */ reconnectInterval: number | number[]; /** * The password to use if the Shelly device requires authentication. */ password?: string; } /** * Makes remote procedure calls (RPCs) over WebSockets. */ declare class WebSocketRpcHandler extends RpcHandler { readonly hostname: string; readonly options: WebSocketRpcHandlerOptions; /** * The underlying websocket. */ protected socket: WebSocket; /** * Handles parsing of JSON RPC requests and responses. */ protected readonly client: JSONRPCClientWithAuthentication; /** * Timeout used to schedule connection attempts and to send periodic ping requests. */ protected timeout: ReturnType<typeof setTimeout> | null; /** * Indicates which value in the `reconnectInterval` option is currently being used. */ protected reconnectIntervalIndex: number; /** * Event handlers bound to `this`. */ protected readonly openHandler: () => void; protected readonly closeHandler: (code: number, reason: Buffer) => void; protected readonly messageHandler: (data: Buffer) => void; protected readonly pongHandler: () => void; protected readonly errorHandler: (error: Error) => void; /** * @param hostname - The hostname of the Shelly device to connect to. * @param opts - Configuration options for this handler. */ constructor(hostname: string, options: WebSocketRpcHandlerOptions); get connected(): boolean; request<T>(method: string, params?: RpcParams): PromiseLike<T>; destroy(): PromiseLike<void>; /** * Creates a new websocket and registers event handlers. * @param url - The URL to connect to. */ protected createSocket(url: string): WebSocket; /** * Connects the websocket. * Creates a new socket if the current is closed. */ protected connect(): Promise<void>; /** * Returns a Promise that will be fulfilled once the socket is connected. */ protected awaitConnect(): Promise<void>; /** * Schedules a connection attempt after a time period specified by the `reconnectInterval` configuration option. * @return The time, in milliseconds, that the next connection attempt will be made in; or `null` if none has been scheduled. */ protected scheduleConnect(): number | null; /** * Disconnects the socket and unregisters event handlers. */ protected disconnect(): Promise<void>; /** * Returns a Promise that will be fulfilled once the socket is disconnected. */ protected awaitDisconnect(): Promise<void>; /** * Handles a request. * @param payload - The request payload. */ protected handleRequest(payload: RpcParams): Promise<void>; /** * Sends a request over the websocket. * @param payload - The request payload. */ protected sendRequest(payload: RpcParams): Promise<void>; /** * Sends a ping over the websocket. */ protected sendPing(): void; /** * Clears any currently pending timeout. */ protected clearTimeout(): void; /** * Handles 'open' events from the socket. */ protected handleOpen(): void; /** * Handles 'close' events from the socket. * @param code - A status code. * @param reason - A human-readable explanation why the connection was closed. */ protected handleClose(code: number, reason: Buffer): void; /** * Handles incoming messages. * @param data The message data, as a JSON encoded string. */ protected handleMessage(data: Buffer): void; /** * Handles pongs received from the device. */ protected handlePong(): void; /** * Handles errors from the websocket. * @param error - The error. */ protected handleError(error: Error): void; } /** * Factory class used to create `WebSocketRpcHandler` instances. */ declare class WebSocketRpcHandlerFactory { /** * Default `WebSocketRpcHandler` options. */ readonly defaultOptions: WebSocketRpcHandlerOptions; /** * Creates a new `WebSocketRpcHandler`. * @param hostname - The hostname of the Shelly device to connect to. * @param opts - Configuration options for the handler. */ create(hostname: string, opts?: Partial<WebSocketRpcHandlerOptions>): WebSocketRpcHandler; } declare abstract class Service { readonly name: string; readonly device: Device; /** * @param name - The name of this service. * @param device - The device that owns this service. */ constructor(name: string, device: Device); /** * Shorthand method for making an RPC. */ protected rpc<T>(method: string, params?: RpcParams): PromiseLike<T>; } interface HttpHeaders { [k: string]: string; } interface HttpResponse { code: number; message: string; headers: HttpHeaders; body?: string; body_b64?: string; } /** * The HTTP service enables sending HTTP requests from Shelly devices. */ declare class HttpService extends Service { constructor(device: Device); /** * Sends an HTTP GET request. * @param url - The URL to send the request to. * @param timeout - Timeout, in seconds. * @param ssl_ca - The certificate authority to use for HTTPS requests. */ get(url: string, timeout?: number, ssl_ca?: '*' | 'user_ca.pem' | '' | null): PromiseLike<HttpResponse>; /** * Sends an HTTP POST request. * Either `body` or `body_b64` must be specified. * @param url - The URL to send the request to. * @param body - The request body. * @param body_b64 - The request body (base64 encoded). * @param content_type - The type of content being sent. * @param timeout - Timeout, in seconds. * @param ssl_ca - The certificate authority to use for HTTPS requests. */ post(url: string, body?: string, body_b64?: string, content_type?: string, timeout?: number, ssl_ca?: '*' | 'user_ca.pem' | '' | null): PromiseLike<HttpResponse>; /** * Sends an HTTP request. * Either `body` or `body_b64` must be specified for POST and PUT requests. * @param method - The HTTP method to use. * @param url - The URL to send the request to. * @param body - The request body. * @param body_b64 - The request body (base64 encoded). * @param headers - User supplied request headers. * @param timeout - Timeout, in seconds. * @param ssl_ca - The certificate authority to use for HTTPS requests. */ request(method: 'GET' | 'POST' | 'PUT' | 'HEAD' | 'DELETE', url: string, body?: string, body_b64?: string, headers?: HttpHeaders, timeout?: number, ssl_ca?: '*' | 'user_ca.pem' | '' | null): PromiseLike<HttpResponse>; } type KvsValue = string | number | boolean | { [x: string]: KvsValue; } | Array<KvsValue>; interface KvsSetResponse { etag: string; rev: number; } interface KvsGetResponse { etag: string; value: KvsValue; } interface KvsGetManyResponse { items: { [key: string]: { etag: string; value: KvsValue; }; }; } interface KvsListResponse { keys: { [key: string]: { etag: string; }; }; rev: number; } interface KvsDeleteResponse { rev: number; } /** * The KVS (Key-Value Store) service provides a basic persistent storage of key-value pairs. */ declare class KvsService extends Service { constructor(device: Device); /** * Adds a new key-value pair to the store or updates an existing one. * @param key - The key to add or update. * @param value - Value for the key. * @param etag - Generated hash uniquely identifying the key-value pair. */ set(key: string, value: KvsValue, etag?: string): PromiseLike<KvsSetResponse>; /** * Returns the value stored and etag for a given key. * @param key - The key to lookup. */ get(key: string): PromiseLike<KvsGetResponse>; /** * Returns the full information stored for items in the store based on an optional key matching parameter. * @param match - Pattern against which keys are matched. */ getMany(match?: string): PromiseLike<KvsGetManyResponse>; /** * Returns a list of existing keys and etags based on an optional match parameter. * @param match - Pattern against which keys are matched. */ list(match?: string): PromiseLike<KvsListResponse>; /** * Deletes an existing key from the store. * @param key - The key to delete. * @param etag - Generated hash uniquely identifying the key-value pair. */ delete(key: string, etag?: string): PromiseLike<KvsDeleteResponse>; } interface ScheduleRpcCall { method: string; params?: Record<string, unknown>; } interface ScheduleJob { id?: number; enable: boolean; timespec: string; calls: ScheduleRpcCall[]; } interface ScheduleListResponse { jobs: ScheduleJob[]; rev: number; } interface ScheduleCreateResponse { id: number; rev: number; } interface ScheduleUpdateResponse { rev: number; } interface ScheduleDeleteResponse { rev: number; } /** * The Schedule service allows execution of RPC methods at fixes times or intervals. */ declare class ScheduleService extends Service { constructor(device: Device); /** * Lists all existing scheduled jobs. */ list(): PromiseLike<ScheduleListResponse>; /** * Creates a new scheduled job. * @param job - The job to add. */ create(job: ScheduleJob): PromiseLike<ScheduleCreateResponse>; /** * Updates an existing scheduled job. * @param job - The job to update. */ update(job: Partial<ScheduleJob>): PromiseLike<ScheduleUpdateResponse>; /** * Deletes a scheduled job. * @param id - ID of the job to delete. */ delete(id: number): PromiseLike<ScheduleDeleteResponse>; /** * Deletes all existing scheduled jobs. */ deleteAll(): PromiseLike<ScheduleDeleteResponse>; } interface ShellyStatus { sys?: SystemAttributes; wifi?: WiFiAttributes; eth?: EthernetAttributes; ble?: BluetoothLowEnergyAttributes; cloud?: CloudAttributes; mqtt?: MqttAttributes; ws?: OutboundWebSocketAttributes; 'cover:0'?: CoverAttributes; 'input:0'?: InputAttributes; 'input:1'?: InputAttributes; 'input:2'?: InputAttributes; 'input:3'?: InputAttributes; 'switch:0'?: SwitchAttributes; 'switch:1'?: SwitchAttributes; 'switch:2'?: SwitchAttributes; 'switch:3'?: SwitchAttributes; 'light:0'?: LightAttributes; 'devicepower:0'?: DevicePowerAttributes; 'humidity:0'?: HumidityAttributes; 'temperature:0'?: TemperatureAttributes; ui?: UiAttributes; } interface ShellyConfig { sys?: SystemConfig; wifi?: WiFiConfig; eth?: EthernetConfig; ble?: BluetoothLowEnergyConfig; cloud?: CloudConfig; mqtt?: MqttConfig; ws?: OutboundWebSocketConfig; 'cover:0'?: CoverConfig; 'input:0'?: InputConfig; 'input:1'?: InputConfig; 'input:2'?: InputConfig; 'input:3'?: InputConfig; 'switch:0'?: SwitchConfig; 'switch:1'?: SwitchConfig; 'switch:2'?: SwitchConfig; 'switch:3'?: SwitchConfig; 'light:0'?: LightConfig; 'devicepower:0'?: DevicePowerConfig; 'humidity:0'?: HumidityConfig; 'temperature:0'?: TemperatureConfig; ui?: UiConfig; } interface ShellyMethods { methods: string[]; } interface ShellyDeviceInfo { id: string; mac: string; model: string; gen: number; fw_id: string; ver: string; app: string; profile?: string; auth_en: boolean; auth_domain: string | null; discoverable: boolean; key?: string; batch?: string; fw_sbits?: string; } interface ShellyProfiles { profiles: Array<{ [name: string]: { components: Array<{ type: string; count: number; }>; }; }>; } interface ShellySetProfileResponse { profile_was: string; } interface ShellyTimezones { timezones: string[]; } interface ShellyLocation { tz: string | null; lat: number | null; lon: number | null; } interface ShellyFirmwareUpdate { stable?: { version: string; build_id: string; }; beta?: { version: string; build_id: string; }; } interface ShellyPutUserCaResponse { len: number; } /** * The common Shelly service that all devices have. */ declare class ShellyService extends Service { constructor(device: Device); /** * Retrieves the status of all of the components of the device. */ getStatus(): PromiseLike<ShellyStatus>; /** * Retrieves the configuration of all the components of the device. */ getConfig(): PromiseLike<ShellyConfig>; /** * Lists all available RPC methods. */ listMethods(): PromiseLike<ShellyMethods>; /** * Retrieves information about the device. */ getDeviceInfo(ident?: boolean): PromiseLike<ShellyDeviceInfo>; /** * Retrieves a list of all available profiles and the type/count of functional components exposed for each profile. */ listProfiles(): PromiseLike<ShellyProfiles>; /** * Sets the device profile. * @param name - Name of the device profile. */ setProfile(name: string): PromiseLike<ShellySetProfileResponse>; /** * Retrieves a list of all timezones. */ listTimezones(): PromiseLike<ShellyTimezones>; /** * Retrieves the location of the device. */ detectLocation(): PromiseLike<ShellyLocation>; /** * Checks for a new firmware version. */ checkForUpdate(): PromiseLike<ShellyFirmwareUpdate>; /** * Requests an update of the device firmware. * Either `stage` or `url` must be specified. * @param stage - The type of the new version. * @param url - URL of the update. */ update(stage?: 'stable' | 'beta', url?: string): PromiseLike<null>; /** * Requests a factory reset of the device. */ factoryReset(): PromiseLike<null>; /** * Requests that the device's WiFi configuration is reset. */ resetWiFiConfig(): PromiseLike<null>; /** * Requests a reboot of the device. * @param delay_ms - A delay until the device reboots, in milliseconds. The * minimum delay is 500 ms. */ reboot(delay_ms?: number): PromiseLike<null>; /** * Sets the authentication details (password) for the device. * @param password - The new password. Set to `null` to disable. */ setAuth(password: string | null): PromiseLike<null>; /** * Uploads a custom certificate authority (CA) PEM bundle. * @param data - Contents of the PEM file (`null` to remove the existing file). * @param append - Whether more data will be appended in a subsequent call. */ putUserCa(data: string | null, append: boolean): PromiseLike<ShellyPutUserCaResponse>; } interface WebhookEventType { attrs?: Array<{ name: string; type: 'boolean' | 'number' | 'string'; desc: string; }>; } interface WebhookSupportedResponse { hook_types?: string[]; types?: { [name: string]: WebhookEventType; }; } interface Webhook { id?: number; cid: number; enable: boolean; event: string; name: string | null; ssl_ca?: '*' | 'user_ca.pem' | '' | null; urls: string[]; active_between?: string[] | null; condition?: string | null; } interface WebhookListResponse { hooks: Webhook[]; rev: number; } interface WebhookCreateResponse { id: number; rev: number; } interface WebhookUpdateResponse { rev: number; } interface WebhookDeleteResponse { rev: number; } /** * The Webhook service allows Shelly devices to send HTTP requests triggered by events. */ declare class WebhookService extends Service { constructor(device: Device); /** * Lists all supported event types. */ listSupported(): PromiseLike<WebhookSupportedResponse>; /** * Lists all existing webhooks. */ list(): PromiseLike<WebhookListResponse>; /** * Creates a new webhook. * @param hook - The webhook to add. */ create(hook: Partial<Webhook>): PromiseLike<WebhookCreateResponse>; /** * Updates an existing webhook. * @param hook - The webhook to update. */ update(hook: Partial<Webhook>): PromiseLike<WebhookUpdateResponse>; /** * Deletes a webhook. * @param id - ID of the webhook to delete. */ delete(id: number): PromiseLike<WebhookDeleteResponse>; /** * Deletes all existing webhooks. */ deleteAll(): PromiseLike<WebhookDeleteResponse>; } type DeviceId = string; /** * Information about a device. */ interface DeviceInfo { /** * The device ID. */ id: DeviceId; /** * The MAC address of the device. */ mac: string; /** * The model designation of the device. */ model?: string; /** * Current firmware ID. */ fw_id?: string; /** * Current firmware version. */ ver?: string; /** * Current device profile. */ profile?: string; } /** * Information about the firmware that a device is running. */ interface DeviceFirmwareInfo { /** * The firmware ID. */ id?: string; /** * The firmware version. */ version?: string; } /** * Describes a device class and its static properties. */ interface DeviceClass { new (info: DeviceInfo, rpcHandler: RpcHandler): Device; /** * The model designation of the device. */ model: string; /** * A human-friendly name of the device model. */ modelName: string; } /** * Property decorator used to label properties as components. * @param target - The prototype of the device class that the property belongs to. * @param propertyName - The name of the property. */ declare const component: (target: any, propertyName: string) => void; /** * Base class for all devices. */ declare abstract class Device extends EventEmitter { readonly rpcHandler: RpcHandler; /** * Holds all registered subclasses. */ private static readonly subclasses; /** * Registers a device class, so that it can later be found based on its device model * using the `Device.getClass()` method. * @param cls - A subclass of `Device`. */ static registerClass(cls: DeviceClass): void; /** * Returns the device class for the given device model, if one has been registered. * @param model - The model designation to lookup. */ static getClass(model: string): DeviceClass | undefined; /** * The ID of this device. */ readonly id: DeviceId; /** * The MAC address of this device. */ readonly macAddress: string; /** * Information about the firmware that the device is running. */ readonly firmware: DeviceFirmwareInfo; /** * This device's Shelly service. */ readonly shelly: ShellyService; /** * This device's Schedule service. */ readonly schedule: ScheduleService; /** * This device's Webhook service. */ readonly webhook: WebhookService; /** * This device's HTTP service. */ readonly http: HttpService; /** * This device's KVS service. */ readonly kvs: KvsService; readonly system: System; /** * @param info - Information about this device. * @param rpcHandler - Used to make remote procedure calls. */ constructor(info: DeviceInfo, rpcHandler: RpcHandler); private _model; /** * The model designation of this device. */ get model(): string; /** * A human-friendly name of the device model. */ get modelName(): string; private _components; /** * Maps component keys to property names. */ protected get components(): Map<string, string>; /** * Determines whether this device has a component with a given key. * @param key - The component key. */ hasComponent(key: string): boolean; /** * Returns the component with the given key. * @param key - The component key. */ getComponent(key: string): ComponentLike | undefined; /** * Returns a new Iterator object that contains each of the device's * components. */ [Symbol.iterator](): IterableIterator<[string, ComponentLike]>; /** * Loads the status for all of the device's components and populates their characteristics. */ loadStatus(): Promise<void>; /** * Loads the condiguration for all of the device's components and populates their `config` properties. */ loadConfig(): Promise<void>; /** * Handles 'statusUpdate' events from our RPC handler. */ protected statusUpdateHandler(update: RpcStatusNotification): void; /** * Handles 'event' events from our RPC handler. */ protected eventHandler(events: RpcEventNotification): void; } /** * Base class for devices that have multiple profiles. */ declare abstract class MultiProfileDevice extends Device { readonly rpcHandler: RpcHandler; /** * The current device profile. */ readonly profile: string; /** * @param info - Information about this device. * @param rpcHandler - Used to make remote procedure calls. */ constructor(info: DeviceInfo, rpcHandler: RpcHandler); } declare class ShellyPlus1 extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly switch0: Switch; readonly script: Script; } declare class ShellyPlus1Ul extends ShellyPlus1 { static readonly model: string; } declare class ShellyPlus1Mini extends ShellyPlus1 { static readonly model: string; static readonly modelName: string; } declare class ShellyPlus1MiniV3 extends ShellyPlus1 { static readonly model: string; static readonly modelName: string; } declare class ShellyPlus1V3 extends ShellyPlus1 { static readonly model: string; } declare class ShellyPlusPmMini extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly script: Script; readonly pm1: Pm1; } declare class ShellyPlusPmMiniV3 extends ShellyPlusPmMini { static readonly model: string; } declare class ShellyPlus1Pm extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly switch0: Switch; readonly script: Script; } declare class ShellyPlus1PmUl extends ShellyPlus1Pm { static readonly model: string; } declare class ShellyPlus1PmMini extends ShellyPlus1Pm { static readonly model: string; static readonly modelName: string; } declare class ShellyPlus1PmMiniV3 extends ShellyPlus1Pm { static readonly model: string; static readonly modelName: string; } declare class ShellyPlus1PmV3 extends ShellyPlus1Pm { static readonly model: string; } declare class ShellyPlus2Pm extends MultiProfileDevice { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly cover0: Cover; readonly input0: Input; readonly input1: Input; readonly switch0: Switch; readonly switch1: Switch; readonly script: Script; } declare class ShellyPlus2PmRev1 extends ShellyPlus2Pm { static readonly model: string; } declare class ShellyPlusHt extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly temperature0: Temperature; readonly humidity0: Humidity; readonly devicePower0: DevicePower; readonly htUi: HtUi; } declare class ShellyPlusHtV3 extends ShellyPlusHt { static readonly model: string; } declare class ShellyPlusI4 extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly input2: Input; readonly input3: Input; readonly script: Script; } declare class ShellyPlusI4V3 extends ShellyPlusI4 { static readonly model: string; } declare class ShellyPlusPlugUs extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly switch0: Switch; readonly script: Script; } declare class ShellyPlusPlugEu extends ShellyPlusPlugUs { static readonly model: string; static readonly modelName: string; } declare class ShellyPlusPlugUk extends ShellyPlusPlugUs { static readonly model: string; static readonly modelName: string; } declare class ShellyPlusPlugIt extends ShellyPlusPlugUs { static readonly model: string; static readonly modelName: string; } declare class ShellyPlugSG3Eu extends ShellyPlusPlugUs { static readonly model: string; static readonly modelName: string; } declare class ShellyPro1 extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly switch0: Switch; readonly script: Script; } declare class ShellyPro1Rev1 extends ShellyPro1 { static readonly model: string; } declare class ShellyPro1Rev2 extends ShellyPro1Rev1 { static readonly model: string; } declare class ShellyPro1Pm extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly switch0: Switch; readonly script: Script; } declare class ShellyPro1PmRev1 extends ShellyPro1Pm { static readonly model: string; } declare class ShellyPro1PmRev2 extends ShellyPro1PmRev1 { static readonly model: string; } declare class ShellyPro2 extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly switch0: Switch; readonly switch1: Switch; readonly script: Script; } declare class ShellyPro2Rev1 extends ShellyPro2 { static readonly model: string; } declare class ShellyPro2Rev2 extends ShellyPro2Rev1 { static readonly model: string; } declare class ShellyPro2Pm extends MultiProfileDevice { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly cover0: Cover; readonly input0: Input; readonly input1: Input; readonly switch0: Switch; readonly switch1: Switch; readonly script: Script; } declare class ShellyPro2PmRev1 extends ShellyPro2Pm { static readonly model: string; } declare class ShellyPro2PmRev2 extends ShellyPro2PmRev1 { static readonly model: string; } declare class ShellyPro3 extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly ethernet: Ethernet; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly input2: Input; readonly switch0: Switch; readonly switch1: Switch; readonly switch2: Switch; readonly script: Script; } declare class ShellyPro4Pm extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly ethernet: Ethernet; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly input2: Input; readonly input3: Input; readonly switch0: Switch; readonly switch1: Switch; readonly switch2: Switch; readonly switch3: Switch; readonly script: Script; readonly ui: Ui; } declare class ShellyPro4PmV2 extends ShellyPro4Pm { static readonly model: string; } declare class ShellyProDimmer1Pm extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly ethernet: Ethernet; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly light0: Light; readonly script: Script; readonly ui: Ui; } declare class ShellyProDimmer1Pm2 extends ShellyProDimmer1Pm { static readonly model: string; static readonly modelName: string; } declare class ShellyDimmer extends ShellyProDimmer1Pm { static readonly model: string; static readonly modelName: string; } declare class ShellyProDimmer2Pm extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly ethernet: Ethernet; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly input2: Input; readonly input3: Input; readonly light0: Light; readonly light1: Light; readonly script: Script; readonly ui: Ui; } declare class ShellyProDualCoverPm extends MultiProfileDevice { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly cover0: Cover; readonly cover1: Cover; readonly input0: Input; readonly input1: Input; readonly input2: Input; readonly input3: Input; readonly script: Script; } declare class ShellyPlusPMDimmer extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly ethernet: Ethernet; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly light0: Light; readonly script: Script; readonly ui: Ui; } declare class ShellyPlusDimmer extends Device { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly ethernet: Ethernet; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly input0: Input; readonly input1: Input; readonly light0: Light; readonly script: Script; readonly ui: Ui; } declare class ShellyGen32Pm extends MultiProfileDevice { static readonly model: string; static readonly modelName: string; readonly wifi: WiFi; readonly bluetoothLowEnergy: BluetoothLowEnergy; readonly cloud: Cloud; readonly mqtt: Mqtt; readonly outboundWebSocket: OutboundWebSocket; readonly cover0: Cover; readonly input0: Input; readonly input1: Input; readonly switch0: Switch; readonly switch1: Switch; readonly script: Script; } type PrimitiveTypes = boolean | number | string; type CharacteristicValue = PrimitiveTypes | PrimitiveTypes[] | null | { [key: string]: PrimitiveTypes | PrimitiveTypes[] | null; }; /** * Interface used when passing around components, since the Component class is * generic. */ interface ComponentLike { name: string; key: string; device: Device; update(data: Record<string, unknown>): any; handleEvent(event: RpcEvent): any; } /** * Property decorator used to label properties as characteristics. * @param target - The prototype of the component class that the property belongs to. * @param propertyName - The name of the property. */ declare const characteristic: (target: any, propertyName: string) => void; /** * Base class for all device components. */ declare abstract class ComponentBase extends EventEmitter implements ComponentLike { readonly name: string; readonly device: Device; /** * The key used to identify the component in status updates etc. */ readonly key: string; /** * @param name - The name of this component. Used when making RPCs. * @param device - The device that owns this component. * @param key - The key used to identify the component in status updates etc. If `null`, the component name * in lower case letters will be used. */ constructor(name: string, device: Device, key?: string | null); private _characteristics; /** * A list of all characteristics. */ protected get characteristics(): Set<string>; /** * Updates the characteristics of the component. * This method will emit `change` events for all characteristics that are * updated. * @param data - A data object that contains characteristics and their values. */ update(data: Record<string | number | symbol, unknown>): void; /** * Handles events received from the device RPC handler. * Subclasses should override this method to handle their specific events. * @param event - The event that has occurred. */ handleEvent(event: RpcEvent): void; /** * Shorthand method for making an RPC. */ protected rpc<T>(method: string, params?: RpcParams): PromiseLike<T>; } /** * Defines the default response from a component's SetConfig RPC method. */ interface DefaultConfigResponse { restart_required: boolean; } /** * Defines a set of methods common for (almost) all device components. */ declare abstract class Component<Attributes, Config, ConfigResponse = DefaultConfigResponse> extends ComponentBase { /** * The confoguration options for this component. * Use the `getConfig()` method to load these options. * This property is automatically populated by the `Device.loadConfig()` method. */ config?: Config; /** * Retrieves the status of this component. */ getStatus(): PromiseLike<Attributes>; /** * Retrieves the configuration of this component. */ getConfig(): PromiseLike<Config>; /** * Requests changes in the configuration of this component. * @param config - The configuration options to set. */ setConfig(config: Partial<Config>): PromiseLike<ConfigResponse>; } /** * Base class for components with an ID. */ declare abstract class ComponentWithId<Attributes, Config, ConfigResponse = DefaultConfigResponse> extends Component<Attributes, Config, ConfigResponse> { readonly id: number; /** * @param name - The name of this component. Used when making RPCs. * @param device - The device that owns this component. * @param id - ID of this component. * @param key - The key used to identify the component in status updates etc. If `null`, the component name * in lower case letters will be used. The component ID will be appended to this key. */ constructor(name: string, device: Device, id?: number, key?: string | null); /** * Retrieves the status of this component. */ getStatus(): PromiseLike<Attributes>; /** * Retrieves the configuration of this component. */ getConfig(): PromiseLike<Config>; /** * Requests changes in the configuration of this component. * @param config - The configuration options to set. */ setConfig(config: Partial<Config>): PromiseLike<ConfigResponse>; } interface BluetoothLowEnergyAttributes { } interface BluetoothLowEnergyConfig { enable: boolean; } /** * Handles the Bluetooth services of a device. */ declare class BluetoothLowEnergy extends Component<BluetoothLowEnergyAttributes, BluetoothLowEnergyConfig> implements BluetoothLowEnergyAttributes { constructor(device: Device); } interface CloudAttributes { connected: boolean; } interface CloudConfig { enable: boolean; server: string | null; } /** * Handles the Cloud services of a device. */ declare class Cloud extends Component<CloudAttributes, CloudConfig> implements CloudAttributes { /** * Whether the device is connected to the Shelly cloud. */ readonly connected: boolean; constructor(device: Device); } interface CoverEnergyCounterAttributes { total: number; by_minute: number[]; minute_ts: number; } interface CoverTemperatureAttributes { tC: number | null; tF: number | null; } interface CoverAttributes { id: number; source: string; state: 'open' | 'closed' | 'opening' | 'closing' | 'stopped' | 'calibrating'; apower: number; voltage: number; current: number; pf: number; aenergy: CoverEnergyCounterAttributes; current_pos: number | null; target_pos: number | null; move_timeout?: number; move_started_at?: number; pos_control: boolean; temperature?: CoverTemperatureAttributes; errors?: string[]; } interface CoverAcMotorConfig { idle_power_thr: number; } interface CoverObstructionDetectionConfig { enable: boolean; direction: 'open' | 'close' | 'both'; action: 'stop' | 'reverse'; power_thr: number; holdoff: number; } interface CoverSafetySwitchConfig { enable: boolean; direction: 'open' | 'close' | 'both'; action: 'stop' | 'reverse' | 'pause'; allowed_move: 'reverse' | null; } interface CoverConfig { id: number; name: string | null; in_mode?: 'single' | 'dual' | 'detached'; initial_state: 'open' | 'closed' | 'stopped'; power_limit: number; voltage_limit: number; current_limit: number; motor?: CoverAcMotorConfig; maxtime_open: number; maxtime_close: number; swap_inputs?: boolean; invert_directions: boolean; obstruction_detection: CoverObstructionDetectionConfig; safety_switch?: CoverSafetySwitchConfig; } /** * Handles the operation of moorized garage doors, window blinds, roof skylights etc. */ declare class Cover extends ComponentWithId<CoverAttributes, CoverConfig> implements CoverAttributes { /** * Source of the last command. */ readonly source: string; /** * The current state. */ readonly state: 'open' | 'closed' | 'opening' | 'closing' | 'stopped' | 'calibrating'; /** * The current (last measured) instantaneous power delivered to the attached * load. */ readonly apower: number; /** * Last measured voltage (in Volts). */ readonly voltage: number; /** * Last measured current (in Amperes). */ readonly current: number; /** * Last measured power factor. */ readonly pf: number; /** * Information about the energy counter. */ readonly aenergy: CoverEnergyCounterAttributes; /** * The current position in percent, from `0` (fully closed) to `100` (fully open); or `null` if not calibrated. */ readonly current_pos: number | null; /** * The requested target position in percent, from `0` (fully closed) to `100` (fully open); or `null` if not calibrated * or not actively moving. */ readonly target_pos: number | null; /** * A timeout (in seconds) after which the cover will automatically stop moving; or `undefined` if not actively moving. */ readonly move_timeout: number | undefined; /** * The time at which the movement began; or `undefined` if not actively moving. */ readonly move_started_at: number | undefined; /** * Whether the cover has been calibrated. */ readonly pos_control: boolean; /** * Information about the temperature sensor (if applicable). */ readonly temperature: CoverTemperatureAttributes | undefined; /** * Any error conditions that have occurred. */ readonly errors: string[] | undefined; constructor(device: Device, id?: number); /** * Opens the cover. * @param duration - Move in open direction for the specified time (in seconds). */ open(duration?: number): PromiseLike<null>; /** * Closes the cover. * @param duration - Move in close direction for the specified time (in seconds). */ close(duration?: number): PromiseLike<null>; /** * Stops any ongoing movement. */ stop(): PromiseLike<null>; /** * Moves the cover to the given position. * One, but not both, of `pos` and `rel` must be specified. * @param pos - An absolute position (in percent). * @param rel - A relative position (in percent). */ goToPosition(pos?: number, rel?: number): PromiseLike<null>; /** * Starts the calibration procedure. */ calibrate(): PromiseLike<null>; } interface DevicePowerBatteryStatus { V: number | null; percent: number | null; } interface DevicePowerExternalSource { present: boolean; } interface DevicePowerAttributes { id: number; battery: DevicePowerBatteryStatus; external?: DevicePowerExternalSource; errors?: string[]; } interface DevicePowerConfig { } /** * Handles the monitoring of a device's battery charge. */ declare class DevicePower extends ComponentWithId<DevicePowerAttributes, DevicePowerConfig> implements DevicePowerAttributes { /** * Information about the battery charge. */ readonly battery: DevicePowerBatteryStatus; /** * Information about the external power source. */ readonly external: DevicePowerExternalSource | undefined; /** * Any error conditions that have occurred. */ readonly errors: string[] | undefined; constructor(device: Device, id?: number); } interface EthernetAttributes { ip: string | null; } interfac