@lucavb/shellies-ds9
Version:
Handles communication with the next generation of Shelly devices
1,650 lines (1,615 loc) • 81.7 kB
TypeScript
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