UNPKG

@lucavb/shellies-ds9

Version:

Handles communication with the next generation of Shelly devices

1,961 lines (1,923 loc) 88.9 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __decorateClass = (decorators, target, key, kind) => { var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result; if (kind && result) __defProp(target, key, result); return result; }; // src/components/base.ts import equal from "fast-deep-equal"; import EventEmitter from "eventemitter3"; var characteristic = (target, propertyName) => { if (!Object.prototype.hasOwnProperty.call(target, "_characteristicProps")) { target._characteristicProps = new Array(); } const props = target._characteristicProps; props.push(propertyName); }; var ComponentBase = class extends EventEmitter { /** * @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, device, key = null) { super(); this.name = name; this.device = device; this._characteristics = null; this.key = key !== null ? key : name.toLowerCase(); } /** * A list of all characteristics. */ get characteristics() { if (this._characteristics === null) { const props = new Array(); let proto = Object.getPrototypeOf(this); while (proto !== null) { if (Object.prototype.hasOwnProperty.call(proto, "_characteristicProps")) { props.push(...proto._characteristicProps); } proto = Object.getPrototypeOf(proto); } this._characteristics = new Set(props); } return this._characteristics; } /** * 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) { const cs = this.characteristics; const changed = /* @__PURE__ */ new Set(); if (!cs) { return; } for (const c of cs) { if (!Object.prototype.hasOwnProperty.call(data, c)) { continue; } if (typeof data[c] === "object" && this[c]) { if (equal(data[c], this[c])) { continue; } Object.assign(this[c], data[c]); } else { if (data[c] === this[c]) { continue; } this[c] = data[c]; } changed.add(c); } for (const c of changed) { this.emit("change", c, this[c]); this.emit("change:" + c, this[c]); } } /** * 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) { if (event.event === "config_changed") { this.emit("configChange", event.cfg_rev, event.restart_required); } } /** * Shorthand method for making an RPC. */ rpc(method, params) { return this.device.rpcHandler.request(`${this.name}.${method}`, params); } }; var Component = class extends ComponentBase { /** * Retrieves the status of this component. */ getStatus() { return this.rpc("GetStatus"); } /** * Retrieves the configuration of this component. */ getConfig() { return this.rpc("GetConfig"); } /** * Requests changes in the configuration of this component. * @param config - The configuration options to set. */ setConfig(config) { return this.rpc("SetConfig", { config }); } }; var ComponentWithId = class extends Component { /** * @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, device, id = 0, key = null) { super(name, device, (key !== null ? key : name.toLowerCase()) + ":" + id); this.id = id; } /** * Retrieves the status of this component. */ getStatus() { return this.rpc("GetStatus", { id: this.id }); } /** * Retrieves the configuration of this component. */ getConfig() { return this.rpc("GetConfig", { id: this.id }); } /** * Requests changes in the configuration of this component. * @param config - The configuration options to set. */ setConfig(config) { return this.rpc("SetConfig", { id: this.id, config }); } }; // src/components/bluetooth-low-energy.ts var BluetoothLowEnergy = class extends Component { constructor(device) { super("BLE", device); } }; // src/components/cloud.ts var Cloud = class extends Component { constructor(device) { super("Cloud", device); this.connected = false; } }; __decorateClass([ characteristic ], Cloud.prototype, "connected", 2); // src/components/cover.ts var Cover = class extends ComponentWithId { constructor(device, id = 0) { super("Cover", device, id); this.source = ""; this.state = "stopped"; this.apower = 0; this.voltage = 0; this.current = 0; this.pf = 0; this.aenergy = { total: 0, by_minute: [], minute_ts: 0 }; this.current_pos = null; this.target_pos = null; this.pos_control = false; } /** * Opens the cover. * @param duration - Move in open direction for the specified time (in seconds). */ open(duration) { return this.rpc("Open", { id: this.id, duration }); } /** * Closes the cover. * @param duration - Move in close direction for the specified time (in seconds). */ close(duration) { return this.rpc("Close", { id: this.id, duration }); } /** * Stops any ongoing movement. */ stop() { return this.rpc("Stop", { id: this.id }); } /** * 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, rel) { return this.rpc("GoToPosition", { id: this.id, pos, rel }); } /** * Starts the calibration procedure. */ calibrate() { return this.rpc("Calibrate", { id: this.id }); } }; __decorateClass([ characteristic ], Cover.prototype, "source", 2); __decorateClass([ characteristic ], Cover.prototype, "state", 2); __decorateClass([ characteristic ], Cover.prototype, "apower", 2); __decorateClass([ characteristic ], Cover.prototype, "voltage", 2); __decorateClass([ characteristic ], Cover.prototype, "current", 2); __decorateClass([ characteristic ], Cover.prototype, "pf", 2); __decorateClass([ characteristic ], Cover.prototype, "aenergy", 2); __decorateClass([ characteristic ], Cover.prototype, "current_pos", 2); __decorateClass([ characteristic ], Cover.prototype, "target_pos", 2); __decorateClass([ characteristic ], Cover.prototype, "move_timeout", 2); __decorateClass([ characteristic ], Cover.prototype, "move_started_at", 2); __decorateClass([ characteristic ], Cover.prototype, "pos_control", 2); __decorateClass([ characteristic ], Cover.prototype, "temperature", 2); __decorateClass([ characteristic ], Cover.prototype, "errors", 2); // src/components/device-power.ts var DevicePower = class extends ComponentWithId { constructor(device, id = 0) { super("DevicePower", device, id); this.battery = { V: null, percent: null }; } }; __decorateClass([ characteristic ], DevicePower.prototype, "battery", 2); __decorateClass([ characteristic ], DevicePower.prototype, "external", 2); __decorateClass([ characteristic ], DevicePower.prototype, "errors", 2); // src/components/ethernet.ts var Ethernet = class extends Component { constructor(device) { super("Eth", device); this.ip = null; } }; __decorateClass([ characteristic ], Ethernet.prototype, "ip", 2); // src/components/ht-ui.ts var HtUi = class extends Component { constructor(device) { super("HT_UI", device); } }; // src/components/humidity.ts var Humidity = class extends ComponentWithId { constructor(device, id = 0) { super("Humidity", device, id); this.rh = null; } }; __decorateClass([ characteristic ], Humidity.prototype, "rh", 2); __decorateClass([ characteristic ], Humidity.prototype, "errors", 2); // src/components/input.ts var Input = class extends ComponentWithId { constructor(device, id = 0) { super("Input", device, id); this.state = null; } handleEvent(event) { switch (event.event) { case "btn_down": this.emit("buttonDown"); break; case "btn_up": this.emit("buttonUp"); break; case "single_push": this.emit("singlePush"); break; case "double_push": this.emit("doublePush"); break; case "long_push": this.emit("longPush"); break; default: super.handleEvent(event); } } }; __decorateClass([ characteristic ], Input.prototype, "state", 2); // src/components/light.ts var Light = class extends ComponentWithId { constructor(device, id = 0) { super("Light", device, id); this.source = ""; this.output = false; this.brightness = 0; } /** * Toggles the output state. */ toggle() { return this.rpc("Toggle", { id: this.id }); } /** * Sets the output and brightness level of the light. * At least one of `on` and `brightness` must be specified. * @param on - Whether to switch on or off. * @param brightness - Brightness level. * @param toggle_after - Flip-back timer, in seconds. */ set(on, brightness, toggle_after) { return this.rpc("Set", { id: this.id, on, brightness, toggle_after }); } }; __decorateClass([ characteristic ], Light.prototype, "source", 2); __decorateClass([ characteristic ], Light.prototype, "output", 2); __decorateClass([ characteristic ], Light.prototype, "brightness", 2); __decorateClass([ characteristic ], Light.prototype, "timer_started_at", 2); __decorateClass([ characteristic ], Light.prototype, "timer_duration", 2); // src/components/mqtt.ts var Mqtt = class extends Component { constructor(device) { super("MQTT", device); this.connected = false; } }; __decorateClass([ characteristic ], Mqtt.prototype, "connected", 2); // src/components/outbound-websocket.ts var OutboundWebSocket = class extends Component { constructor(device) { super("Ws", device); this.connected = false; } }; __decorateClass([ characteristic ], OutboundWebSocket.prototype, "connected", 2); // src/components/script.ts var Script = class extends ComponentBase { constructor(device) { super("Script", device); } /** * Retrieves the status of a script. * @param id - The script ID. */ getStatus(id) { return this.rpc("GetStatus", { id }); } /** * Retrieves the configuration of a script. * @param id - The script ID. */ getConfig(id) { return this.rpc("GetConfig", { id }); } /** * Requests changes in the configuration of a script. * @param id - The script ID. * @param config - The configuration options to set. */ setConfig(id, config) { return this.rpc("SetConfig", { id, config }); } /** * Lists all scripts. */ list() { return this.rpc("List"); } /** * Creates a new script. * @param name - The name of the script. */ create(name) { return this.rpc("Create", { name }); } /** * Removes a script. * @param id - The script ID. */ delete(id) { return this.rpc("Delete", { id }); } /** * Runs a script. * @param id - The script ID. */ start(id) { return this.rpc("Start", { id }); } /** * Stops the execution of a script. * @param id - The script ID. */ stop(id) { return this.rpc("Stop", { id }); } /** * Uploads code to a script. * @param id - The script ID. * @param code - The code to upload. * @param append - Whether the code should be appended to the script or overwrite any existing code. */ putCode(id, code, append = false) { return this.rpc("PutCode", { id, code, append }); } /** * Downloads code from a script. * @param id - The script ID. * @param offset - The byte offset from the beginning. * @param len - The number of bytes to download. */ getCode(id, offset = 0, len) { return this.rpc("GetCode", { id, offset, len }); } /** * Evaluates or executes code inside of a script. * @param id - The script ID. * @param code - The code to evaluate. */ eval(id, code) { return this.rpc("Eval", { id, code }); } }; // src/components/switch.ts var Switch = class extends ComponentWithId { constructor(device, id = 0) { super("Switch", device, id); this.source = ""; this.output = false; this.temperature = { tC: null, tF: null }; } /** * Toggles the switch. */ toggle() { return this.rpc("Toggle", { id: this.id }); } /** * Sets the output of the switch. * @param on - Whether to switch on or off. * @param toggle_after - Flip-back timer, in seconds. */ set(on, toggle_after) { return this.rpc("Set", { id: this.id, on, toggle_after }); } }; __decorateClass([ characteristic ], Switch.prototype, "source", 2); __decorateClass([ characteristic ], Switch.prototype, "output", 2); __decorateClass([ characteristic ], Switch.prototype, "timer_started_at", 2); __decorateClass([ characteristic ], Switch.prototype, "timer_duration", 2); __decorateClass([ characteristic ], Switch.prototype, "apower", 2); __decorateClass([ characteristic ], Switch.prototype, "voltage", 2); __decorateClass([ characteristic ], Switch.prototype, "current", 2); __decorateClass([ characteristic ], Switch.prototype, "pf", 2); __decorateClass([ characteristic ], Switch.prototype, "aenergy", 2); __decorateClass([ characteristic ], Switch.prototype, "temperature", 2); __decorateClass([ characteristic ], Switch.prototype, "errors", 2); // src/components/system.ts var System = class extends Component { constructor(device) { super("Sys", device); this.mac = ""; this.restart_required = false; this.time = ""; this.unixtime = 0; this.uptime = 0; this.ram_size = 0; this.ram_free = 0; this.fs_size = 0; this.fs_free = 0; this.cfg_rev = 0; this.kvs_rev = 0; this.available_updates = {}; } handleEvent(event) { switch (event.event) { case "ota_begin": this.emit("otaBegin", event.msg); break; case "ota_progress": this.emit("otaProgress", event.progress_percent, event.msg); break; case "ota_success": this.emit("otaSuccess", event.msg); break; case "ota_error": this.emit("otaError", event.msg); break; case "sleep": this.emit("sleep"); break; default: super.handleEvent(event); } } }; __decorateClass([ characteristic ], System.prototype, "mac", 2); __decorateClass([ characteristic ], System.prototype, "restart_required", 2); __decorateClass([ characteristic ], System.prototype, "time", 2); __decorateClass([ characteristic ], System.prototype, "unixtime", 2); __decorateClass([ characteristic ], System.prototype, "uptime", 2); __decorateClass([ characteristic ], System.prototype, "ram_size", 2); __decorateClass([ characteristic ], System.prototype, "ram_free", 2); __decorateClass([ characteristic ], System.prototype, "fs_size", 2); __decorateClass([ characteristic ], System.prototype, "fs_free", 2); __decorateClass([ characteristic ], System.prototype, "cfg_rev", 2); __decorateClass([ characteristic ], System.prototype, "kvs_rev", 2); __decorateClass([ characteristic ], System.prototype, "schedule_rev", 2); __decorateClass([ characteristic ], System.prototype, "webhook_rev", 2); __decorateClass([ characteristic ], System.prototype, "available_updates", 2); __decorateClass([ characteristic ], System.prototype, "wakeup_reason", 2); // src/components/temperature.ts var Temperature = class extends ComponentWithId { constructor(device, id = 0) { super("Temperature", device, id); this.tC = null; this.tF = null; } }; __decorateClass([ characteristic ], Temperature.prototype, "tC", 2); __decorateClass([ characteristic ], Temperature.prototype, "tF", 2); __decorateClass([ characteristic ], Temperature.prototype, "errors", 2); // src/components/ui.ts var Ui = class extends Component { constructor(device) { super("UI", device); } }; // src/components/wifi.ts var WiFi = class extends Component { constructor(device) { super("WiFi", device); this.sta_ip = null; this.status = "disconnected"; this.ssid = null; this.rssi = 0; } /** * Retrieves a list of available networks. */ scan() { return this.rpc("Scan"); } /** * Returns a list of clients currently connected to the device's access point. */ listApClients() { return this.rpc("ListAPClients"); } handleEvent(event) { switch (event.event) { case "sta_connect_fail": this.emit("connectionError", event.reason); break; case "sta_disconnected": this.emit("disconnect", event.reason, event.ssid, event.sta_ip); break; default: super.handleEvent(event); } } }; __decorateClass([ characteristic ], WiFi.prototype, "sta_ip", 2); __decorateClass([ characteristic ], WiFi.prototype, "status", 2); __decorateClass([ characteristic ], WiFi.prototype, "ssid", 2); __decorateClass([ characteristic ], WiFi.prototype, "rssi", 2); __decorateClass([ characteristic ], WiFi.prototype, "ap_client_count", 2); // src/components/pm1.ts var Pm1 = class extends ComponentWithId { constructor(device, id = 0) { super("Pm1", device, id); this.output = false; } }; __decorateClass([ characteristic ], Pm1.prototype, "output", 2); __decorateClass([ characteristic ], Pm1.prototype, "voltage", 2); __decorateClass([ characteristic ], Pm1.prototype, "current", 2); __decorateClass([ characteristic ], Pm1.prototype, "apower", 2); __decorateClass([ characteristic ], Pm1.prototype, "aprtpower", 2); __decorateClass([ characteristic ], Pm1.prototype, "pf", 2); __decorateClass([ characteristic ], Pm1.prototype, "freq", 2); __decorateClass([ characteristic ], Pm1.prototype, "aenergy", 2); __decorateClass([ characteristic ], Pm1.prototype, "ret_aenergy", 2); __decorateClass([ characteristic ], Pm1.prototype, "errors", 2); // src/devices/base.ts import EventEmitter2 from "eventemitter3"; // src/services/base.ts var Service = class { /** * @param name - The name of this service. * @param device - The device that owns this service. */ constructor(name, device) { this.name = name; this.device = device; } /** * Shorthand method for making an RPC. */ rpc(method, params) { return this.device.rpcHandler.request(`${this.name}.${method}`, params); } }; // src/services/http.ts var HttpService = class extends Service { constructor(device) { super("HTTP", 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, timeout, ssl_ca) { return this.rpc("GET", { url, timeout, ssl_ca }); } /** * 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, body, body_b64, content_type = "application/json", timeout, ssl_ca) { return this.rpc("POST", { url, body, body_b64, content_type, timeout, ssl_ca }); } /** * 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, url, body, body_b64, headers, timeout, ssl_ca) { return this.rpc("Request", { method, url, body, body_b64, headers, timeout, ssl_ca }); } }; // src/services/kvs.ts var KvsService = class extends Service { constructor(device) { super("KVS", 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, value, etag) { return this.rpc("Set", { key, value, etag }); } /** * Returns the value stored and etag for a given key. * @param key - The key to lookup. */ get(key) { return this.rpc("Get", { key }); } /** * 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) { return this.rpc("GetMany", { match }); } /** * Returns a list of existing keys and etags based on an optional match parameter. * @param match - Pattern against which keys are matched. */ list(match) { return this.rpc("List", { match }); } /** * 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, etag) { return this.rpc("Delete", { key, etag }); } }; // src/services/schedule.ts var ScheduleService = class extends Service { constructor(device) { super("Schedule", device); } /** * Lists all existing scheduled jobs. */ list() { return this.rpc("List"); } /** * Creates a new scheduled job. * @param job - The job to add. */ create(job) { return this.rpc("Create", { ...job }); } /** * Updates an existing scheduled job. * @param job - The job to update. */ update(job) { return this.rpc("Update", { ...job }); } /** * Deletes a scheduled job. * @param id - ID of the job to delete. */ delete(id) { return this.rpc("Delete", { id }); } /** * Deletes all existing scheduled jobs. */ deleteAll() { return this.rpc("DeleteAll"); } }; // src/services/shelly.ts import crypto from "crypto"; var ShellyService = class extends Service { constructor(device) { super("Shelly", device); } /** * Retrieves the status of all of the components of the device. */ getStatus() { return this.rpc("GetStatus"); } /** * Retrieves the configuration of all the components of the device. */ getConfig() { return this.rpc("GetConfig"); } /** * Lists all available RPC methods. */ listMethods() { return this.rpc("ListMethods"); } /** * Retrieves information about the device. */ getDeviceInfo(ident) { return this.rpc("GetDeviceInfo", { ident }); } /** * Retrieves a list of all available profiles and the type/count of functional components exposed for each profile. */ listProfiles() { return this.rpc("ListProfiles"); } /** * Sets the device profile. * @param name - Name of the device profile. */ setProfile(name) { return this.rpc("SetProfile", { name }); } /** * Retrieves a list of all timezones. */ listTimezones() { return this.rpc("ListTimezones"); } /** * Retrieves the location of the device. */ detectLocation() { return this.rpc("DetectLocation"); } /** * Checks for a new firmware version. */ checkForUpdate() { return this.rpc("CheckForUpdate"); } /** * 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, url) { return this.rpc("Update", { stage, url }); } /** * Requests a factory reset of the device. */ factoryReset() { return this.rpc("FactoryReset"); } /** * Requests that the device's WiFi configuration is reset. */ resetWiFiConfig() { return this.rpc("ResetWiFiConfig"); } /** * 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) { return this.rpc("Reboot", { delay_ms }); } /** * Sets the authentication details (password) for the device. * @param password - The new password. Set to `null` to disable. */ setAuth(password) { const user = "admin"; const hash = password === null ? null : crypto.createHash("sha256").update(`${user}:${this.device.id}:${password}`).digest("hex"); return this.rpc("SetAuth", { user, realm: this.device.id, ha1: hash }); } /** * 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, append) { return this.rpc("PutUserCA", { data, append }); } }; // src/services/webhook.ts var WebhookService = class extends Service { constructor(device) { super("Webhook", device); } /** * Lists all supported event types. */ listSupported() { return this.rpc("ListSupported"); } /** * Lists all existing webhooks. */ list() { return this.rpc("List"); } /** * Creates a new webhook. * @param hook - The webhook to add. */ create(hook) { return this.rpc("Create", { ...hook }); } /** * Updates an existing webhook. * @param hook - The webhook to update. */ update(hook) { return this.rpc("Update", { ...hook }); } /** * Deletes a webhook. * @param id - ID of the webhook to delete. */ delete(id) { return this.rpc("Delete", { id }); } /** * Deletes all existing webhooks. */ deleteAll() { return this.rpc("DeleteAll"); } }; // src/devices/base.ts var component = (target, propertyName) => { if (!Object.prototype.hasOwnProperty.call(target, "_componentProps")) { target._componentProps = new Array(); } const props = target._componentProps; props.push(propertyName); }; var _Device = class _Device extends EventEmitter2 { /** * @param info - Information about this device. * @param rpcHandler - Used to make remote procedure calls. */ constructor(info, rpcHandler) { super(); this.rpcHandler = rpcHandler; /** * This device's Shelly service. */ this.shelly = new ShellyService(this); /** * This device's Schedule service. */ this.schedule = new ScheduleService(this); /** * This device's Webhook service. */ this.webhook = new WebhookService(this); /** * This device's HTTP service. */ this.http = new HttpService(this); /** * This device's KVS service. */ this.kvs = new KvsService(this); this.system = new System(this); this._components = null; this.id = info.id; this.macAddress = info.mac; this.firmware = { id: info.fw_id, version: info.ver }; this._model = info.model; rpcHandler.on("statusUpdate", this.statusUpdateHandler, this); rpcHandler.on("event", this.eventHandler, this); } /** * 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) { const model = cls.model.toUpperCase(); if (_Device.subclasses.has(model)) { throw new Error(`A device class for ${model} has already been registered`); } _Device.subclasses.set(model, cls); } /** * Returns the device class for the given device model, if one has been registered. * @param model - The model designation to lookup. */ static getClass(model) { return _Device.subclasses.get(model.toUpperCase()); } /** * The model designation of this device. */ get model() { return this._model || this.constructor.model; } /** * A human-friendly name of the device model. */ get modelName() { return this.constructor.modelName; } /** * Maps component keys to property names. */ get components() { if (this._components === null) { this._components = /* @__PURE__ */ new Map(); const props = new Array(); let proto = Object.getPrototypeOf(this); while (proto !== null) { if (Object.prototype.hasOwnProperty.call(proto, "_componentProps")) { props.push(...proto._componentProps); } proto = Object.getPrototypeOf(proto); } for (const p of props) { const cmpnt = this[p]; if (!cmpnt) { continue; } this._components.set(cmpnt.key, p); } } return this._components; } /** * Determines whether this device has a component with a given key. * @param key - The component key. */ hasComponent(key) { return this.components.has(key); } /** * Returns the component with the given key. * @param key - The component key. */ getComponent(key) { const prop = this.components.get(key); if (prop) { return this[prop]; } return void 0; } /** * Returns a new Iterator object that contains each of the device's * components. */ *[Symbol.iterator]() { for (const [key, prop] of this.components.entries()) { yield [key, this[prop]]; } } /** * Loads the status for all of the device's components and populates their characteristics. */ async loadStatus() { const status = await this.shelly.getStatus(); for (const cmpnt in status) { if (Object.prototype.hasOwnProperty.call(status, cmpnt) && typeof status[cmpnt] === "object") { this.getComponent(cmpnt)?.update(status[cmpnt]); } } } /** * Loads the condiguration for all of the device's components and populates their `config` properties. */ async loadConfig() { const config = await this.shelly.getConfig(); for (const cmpnt in config) { if (Object.prototype.hasOwnProperty.call(config, cmpnt) && typeof config[cmpnt] === "object") { const c = this.getComponent(cmpnt); if (c && c instanceof Component) { c.config = config[cmpnt]; } } } } /** * Handles 'statusUpdate' events from our RPC handler. */ statusUpdateHandler(update) { for (const cmpnt in update) { if (cmpnt !== "ts" && Object.prototype.hasOwnProperty.call(update, cmpnt) && typeof update[cmpnt] === "object") { this.getComponent(cmpnt)?.update(update[cmpnt]); } } } /** * Handles 'event' events from our RPC handler. */ eventHandler(events) { for (const event of events.events) { this.getComponent(event.component)?.handleEvent(event); } } }; /** * Holds all registered subclasses. */ _Device.subclasses = /* @__PURE__ */ new Map(); __decorateClass([ component ], _Device.prototype, "system", 2); var Device = _Device; var MultiProfileDevice = class extends Device { /** * @param info - Information about this device. * @param rpcHandler - Used to make remote procedure calls. */ constructor(info, rpcHandler) { super(info, rpcHandler); this.rpcHandler = rpcHandler; this.profile = info.profile ?? ""; } }; // src/devices/shelly-plus-1.ts var ShellyPlus1 = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.input0 = new Input(this, 0); this.switch0 = new Switch(this, 0); this.script = new Script(this); } }; ShellyPlus1.model = "SNSW-001X16EU"; ShellyPlus1.modelName = "Shelly Plus 1"; __decorateClass([ component ], ShellyPlus1.prototype, "wifi", 2); __decorateClass([ component ], ShellyPlus1.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPlus1.prototype, "cloud", 2); __decorateClass([ component ], ShellyPlus1.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPlus1.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPlus1.prototype, "input0", 2); __decorateClass([ component ], ShellyPlus1.prototype, "switch0", 2); __decorateClass([ component ], ShellyPlus1.prototype, "script", 2); Device.registerClass(ShellyPlus1); var ShellyPlus1Ul = class extends ShellyPlus1 { }; ShellyPlus1Ul.model = "SNSW-001X15UL"; Device.registerClass(ShellyPlus1Ul); var ShellyPlus1Mini = class extends ShellyPlus1 { }; ShellyPlus1Mini.model = "SNSW-001X8EU"; ShellyPlus1Mini.modelName = "Shelly Plus 1 Mini"; Device.registerClass(ShellyPlus1Mini); var ShellyPlus1MiniV3 = class extends ShellyPlus1 { }; ShellyPlus1MiniV3.model = "S3SW-001X8EU"; ShellyPlus1MiniV3.modelName = "Shelly Plus 1 Mini"; Device.registerClass(ShellyPlus1MiniV3); var ShellyPlus1V3 = class extends ShellyPlus1 { }; ShellyPlus1V3.model = "S3SW-001X16EU"; Device.registerClass(ShellyPlus1V3); // src/devices/shelly-plus-pm.ts var ShellyPlusPmMini = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.script = new Script(this); this.pm1 = new Pm1(this); } }; ShellyPlusPmMini.model = "SNPM-001PCEU16"; ShellyPlusPmMini.modelName = "Shelly Plus PM Mini"; __decorateClass([ component ], ShellyPlusPmMini.prototype, "wifi", 2); __decorateClass([ component ], ShellyPlusPmMini.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPlusPmMini.prototype, "cloud", 2); __decorateClass([ component ], ShellyPlusPmMini.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPlusPmMini.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPlusPmMini.prototype, "script", 2); __decorateClass([ component ], ShellyPlusPmMini.prototype, "pm1", 2); Device.registerClass(ShellyPlusPmMini); var ShellyPlusPmMiniV3 = class extends ShellyPlusPmMini { }; ShellyPlusPmMiniV3.model = "S3PM-001PCEU16"; Device.registerClass(ShellyPlusPmMiniV3); // src/devices/shelly-plus-1-pm.ts var ShellyPlus1Pm = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.input0 = new Input(this, 0); this.switch0 = new Switch(this, 0); this.script = new Script(this); } }; ShellyPlus1Pm.model = "SNSW-001P16EU"; ShellyPlus1Pm.modelName = "Shelly Plus 1 PM"; __decorateClass([ component ], ShellyPlus1Pm.prototype, "wifi", 2); __decorateClass([ component ], ShellyPlus1Pm.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPlus1Pm.prototype, "cloud", 2); __decorateClass([ component ], ShellyPlus1Pm.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPlus1Pm.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPlus1Pm.prototype, "input0", 2); __decorateClass([ component ], ShellyPlus1Pm.prototype, "switch0", 2); __decorateClass([ component ], ShellyPlus1Pm.prototype, "script", 2); Device.registerClass(ShellyPlus1Pm); var ShellyPlus1PmUl = class extends ShellyPlus1Pm { }; ShellyPlus1PmUl.model = "SNSW-001P15UL"; Device.registerClass(ShellyPlus1PmUl); var ShellyPlus1PmMini = class extends ShellyPlus1Pm { }; ShellyPlus1PmMini.model = "SNSW-001P8EU"; ShellyPlus1PmMini.modelName = "Shelly Plus 1 PM Mini"; Device.registerClass(ShellyPlus1PmMini); var ShellyPlus1PmMiniV3 = class extends ShellyPlus1Pm { }; ShellyPlus1PmMiniV3.model = "S3SW-001P8EU"; ShellyPlus1PmMiniV3.modelName = "Shelly Plus 1 PM Mini"; Device.registerClass(ShellyPlus1PmMiniV3); var ShellyPlus1PmV3 = class extends ShellyPlus1Pm { }; ShellyPlus1PmV3.model = "S3SW-001P16EU"; Device.registerClass(ShellyPlus1PmV3); // src/devices/shelly-plus-2-pm.ts var ShellyPlus2Pm = class extends MultiProfileDevice { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.cover0 = new Cover(this, 0); this.input0 = new Input(this, 0); this.input1 = new Input(this, 1); this.switch0 = new Switch(this, 0); this.switch1 = new Switch(this, 1); this.script = new Script(this); } }; ShellyPlus2Pm.model = "SNSW-002P16EU"; ShellyPlus2Pm.modelName = "Shelly Plus 2 PM"; __decorateClass([ component ], ShellyPlus2Pm.prototype, "wifi", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "cloud", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "cover0", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "input0", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "input1", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "switch0", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "switch1", 2); __decorateClass([ component ], ShellyPlus2Pm.prototype, "script", 2); Device.registerClass(ShellyPlus2Pm); var ShellyPlus2PmRev1 = class extends ShellyPlus2Pm { }; ShellyPlus2PmRev1.model = "SNSW-102P16EU"; Device.registerClass(ShellyPlus2PmRev1); // src/devices/shelly-plus-ht.ts var ShellyPlusHt = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.temperature0 = new Temperature(this, 0); this.humidity0 = new Humidity(this, 0); this.devicePower0 = new DevicePower(this, 0); this.htUi = new HtUi(this); } }; ShellyPlusHt.model = "SNSN-0013A"; ShellyPlusHt.modelName = "Shelly Plus H&T"; __decorateClass([ component ], ShellyPlusHt.prototype, "wifi", 2); __decorateClass([ component ], ShellyPlusHt.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPlusHt.prototype, "cloud", 2); __decorateClass([ component ], ShellyPlusHt.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPlusHt.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPlusHt.prototype, "temperature0", 2); __decorateClass([ component ], ShellyPlusHt.prototype, "humidity0", 2); __decorateClass([ component ], ShellyPlusHt.prototype, "devicePower0", 2); __decorateClass([ component ], ShellyPlusHt.prototype, "htUi", 2); Device.registerClass(ShellyPlusHt); var ShellyPlusHtV3 = class extends ShellyPlusHt { }; ShellyPlusHtV3.model = "S3SN-0U12A"; Device.registerClass(ShellyPlusHtV3); // src/devices/shelly-plus-i4.ts var ShellyPlusI4 = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.input0 = new Input(this, 0); this.input1 = new Input(this, 1); this.input2 = new Input(this, 2); this.input3 = new Input(this, 3); this.script = new Script(this); } }; ShellyPlusI4.model = "SNSN-0024X"; ShellyPlusI4.modelName = "Shelly Plus I4"; __decorateClass([ component ], ShellyPlusI4.prototype, "wifi", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "cloud", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "input0", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "input1", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "input2", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "input3", 2); __decorateClass([ component ], ShellyPlusI4.prototype, "script", 2); Device.registerClass(ShellyPlusI4); var ShellyPlusI4V3 = class extends ShellyPlusI4 { }; ShellyPlusI4V3.model = "S3SN-0024X"; Device.registerClass(ShellyPlusI4V3); // src/devices/shelly-plus-plug.ts var ShellyPlusPlugUs = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.switch0 = new Switch(this, 0); this.script = new Script(this); } }; ShellyPlusPlugUs.model = "SNPL-00116US"; ShellyPlusPlugUs.modelName = "Shelly Plus Plug US"; __decorateClass([ component ], ShellyPlusPlugUs.prototype, "wifi", 2); __decorateClass([ component ], ShellyPlusPlugUs.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPlusPlugUs.prototype, "cloud", 2); __decorateClass([ component ], ShellyPlusPlugUs.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPlusPlugUs.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPlusPlugUs.prototype, "switch0", 2); __decorateClass([ component ], ShellyPlusPlugUs.prototype, "script", 2); Device.registerClass(ShellyPlusPlugUs); var ShellyPlusPlugEu = class extends ShellyPlusPlugUs { }; ShellyPlusPlugEu.model = "SNPL-00112EU"; ShellyPlusPlugEu.modelName = "Shelly Plus Plug EU"; Device.registerClass(ShellyPlusPlugEu); var ShellyPlusPlugUk = class extends ShellyPlusPlugUs { }; ShellyPlusPlugUk.model = "SNPL-00112UK"; ShellyPlusPlugUk.modelName = "Shelly Plus Plug UK"; Device.registerClass(ShellyPlusPlugUk); var ShellyPlusPlugIt = class extends ShellyPlusPlugUs { }; ShellyPlusPlugIt.model = "SNPL-00110IT"; ShellyPlusPlugIt.modelName = "Shelly Plus Plug IT"; Device.registerClass(ShellyPlusPlugIt); var ShellyPlugSG3Eu = class extends ShellyPlusPlugUs { }; ShellyPlugSG3Eu.model = "S3PL-00112EU"; ShellyPlugSG3Eu.modelName = "Shelly Plug S Gen3"; Device.registerClass(ShellyPlugSG3Eu); // src/devices/shelly-pro-1.ts var ShellyPro1 = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.input0 = new Input(this, 0); this.input1 = new Input(this, 1); this.switch0 = new Switch(this, 0); this.script = new Script(this); } }; ShellyPro1.model = "SPSW-001XE16EU"; ShellyPro1.modelName = "Shelly Pro 1"; __decorateClass([ component ], ShellyPro1.prototype, "wifi", 2); __decorateClass([ component ], ShellyPro1.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPro1.prototype, "cloud", 2); __decorateClass([ component ], ShellyPro1.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPro1.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPro1.prototype, "input0", 2); __decorateClass([ component ], ShellyPro1.prototype, "input1", 2); __decorateClass([ component ], ShellyPro1.prototype, "switch0", 2); __decorateClass([ component ], ShellyPro1.prototype, "script", 2); Device.registerClass(ShellyPro1); var ShellyPro1Rev1 = class extends ShellyPro1 { }; ShellyPro1Rev1.model = "SPSW-101XE16EU"; Device.registerClass(ShellyPro1Rev1); var ShellyPro1Rev2 = class extends ShellyPro1Rev1 { }; ShellyPro1Rev2.model = "SPSW-201XE16EU"; Device.registerClass(ShellyPro1Rev2); // src/devices/shelly-pro-1-pm.ts var ShellyPro1Pm = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.input0 = new Input(this, 0); this.input1 = new Input(this, 1); this.switch0 = new Switch(this, 0); this.script = new Script(this); } }; ShellyPro1Pm.model = "SPSW-001PE16EU"; ShellyPro1Pm.modelName = "Shelly Pro 1 PM"; __decorateClass([ component ], ShellyPro1Pm.prototype, "wifi", 2); __decorateClass([ component ], ShellyPro1Pm.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPro1Pm.prototype, "cloud", 2); __decorateClass([ component ], ShellyPro1Pm.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPro1Pm.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPro1Pm.prototype, "input0", 2); __decorateClass([ component ], ShellyPro1Pm.prototype, "input1", 2); __decorateClass([ component ], ShellyPro1Pm.prototype, "switch0", 2); __decorateClass([ component ], ShellyPro1Pm.prototype, "script", 2); Device.registerClass(ShellyPro1Pm); var ShellyPro1PmRev1 = class extends ShellyPro1Pm { }; ShellyPro1PmRev1.model = "SPSW-101PE16EU"; Device.registerClass(ShellyPro1PmRev1); var ShellyPro1PmRev2 = class extends ShellyPro1PmRev1 { }; ShellyPro1PmRev2.model = "SPSW-201PE16EU"; Device.registerClass(ShellyPro1PmRev2); // src/devices/shelly-pro-2.ts var ShellyPro2 = class extends Device { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.input0 = new Input(this, 0); this.input1 = new Input(this, 1); this.switch0 = new Switch(this, 0); this.switch1 = new Switch(this, 1); this.script = new Script(this); } }; ShellyPro2.model = "SPSW-002XE16EU"; ShellyPro2.modelName = "Shelly Pro 2"; __decorateClass([ component ], ShellyPro2.prototype, "wifi", 2); __decorateClass([ component ], ShellyPro2.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPro2.prototype, "cloud", 2); __decorateClass([ component ], ShellyPro2.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPro2.prototype, "outboundWebSocket", 2); __decorateClass([ component ], ShellyPro2.prototype, "input0", 2); __decorateClass([ component ], ShellyPro2.prototype, "input1", 2); __decorateClass([ component ], ShellyPro2.prototype, "switch0", 2); __decorateClass([ component ], ShellyPro2.prototype, "switch1", 2); __decorateClass([ component ], ShellyPro2.prototype, "script", 2); Device.registerClass(ShellyPro2); var ShellyPro2Rev1 = class extends ShellyPro2 { }; ShellyPro2Rev1.model = "SPSW-102XE16EU"; Device.registerClass(ShellyPro2Rev1); var ShellyPro2Rev2 = class extends ShellyPro2Rev1 { }; ShellyPro2Rev2.model = "SPSW-202XE16EU"; Device.registerClass(ShellyPro2Rev2); // src/devices/shelly-pro-2-pm.ts var ShellyPro2Pm = class extends MultiProfileDevice { constructor() { super(...arguments); this.wifi = new WiFi(this); this.bluetoothLowEnergy = new BluetoothLowEnergy(this); this.cloud = new Cloud(this); this.mqtt = new Mqtt(this); this.outboundWebSocket = new OutboundWebSocket(this); this.cover0 = new Cover(this, 0); this.input0 = new Input(this, 0); this.input1 = new Input(this, 1); this.switch0 = new Switch(this, 0); this.switch1 = new Switch(this, 1); this.script = new Script(this); } }; ShellyPro2Pm.model = "SPSW-002PE16EU"; ShellyPro2Pm.modelName = "Shelly Pro 2 PM"; __decorateClass([ component ], ShellyPro2Pm.prototype, "wifi", 2); __decorateClass([ component ], ShellyPro2Pm.prototype, "bluetoothLowEnergy", 2); __decorateClass([ component ], ShellyPro2Pm.prototype, "cloud", 2); __decorateClass([ component ], ShellyPro2Pm.prototype, "mqtt", 2); __decorateClass([ component ], ShellyPro2Pm.prototype, "outboundWebSoc