node-red-contrib-tplink-tapo-connect-api
Version:
This unofficial node-RED node allows connection to TP-Link Tapo devices. This project has been enhanced with AI support to enable new features. Starting with v0.50, we have added support for the KLAP protocol. To prioritize the operation of this node, we
200 lines • 7.45 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseDevice = void 0;
const connection_manager_1 = require("../core/connection-manager");
const session_manager_1 = require("../core/session-manager");
const protocol_selector_1 = require("../core/protocol-selector");
const request_manager_1 = require("../core/request-manager");
const device_controller_1 = require("../controllers/device-controller");
const energy_controller_1 = require("../controllers/energy-controller");
const lighting_controller_1 = require("../controllers/lighting-controller");
/**
* Base device class using composition pattern
* Single responsibility: Device lifecycle and controller coordination
*/
class BaseDevice {
constructor(ip, credentials, deviceModel) {
this.ip = ip;
this.credentials = credentials;
this.deviceModel = deviceModel;
this.isInitialized = false;
// Initialize core managers
this.connectionManager = new connection_manager_1.ConnectionManager(ip, credentials);
this.sessionManager = new session_manager_1.SessionManager();
this.protocolSelector = new protocol_selector_1.ProtocolSelector(ip, credentials);
this.requestManager = new request_manager_1.RequestManager();
// Initialize controllers
this.deviceController = new device_controller_1.DeviceController(this.sendRequest.bind(this));
// Determine capabilities based on device model
this.capabilities = this.determineCapabilities(deviceModel);
// Initialize feature controllers based on capabilities
if (this.capabilities.hasEnergyMonitoring) {
this.energyController = new energy_controller_1.EnergyController(this.sendRequest.bind(this));
}
if (this.capabilities.hasBrightnessControl || this.capabilities.hasColorControl) {
this.lightingController = new lighting_controller_1.LightingController(this.sendRequest.bind(this));
}
}
/**
* Connect to the device
*/
async connect() {
if (this.isInitialized) {
return;
}
try {
// Select best protocol
const protocol = await this.protocolSelector.selectProtocol();
// Establish connection
await this.connectionManager.connect();
// Initialize session based on protocol
await this.initializeSession(protocol);
this.isInitialized = true;
}
catch (error) {
await this.cleanup();
throw error;
}
}
/**
* Disconnect from the device
*/
async disconnect() {
await this.cleanup();
this.isInitialized = false;
}
/**
* Send request through the request manager
*/
async sendRequest(request) {
if (!this.isInitialized) {
throw new Error('Device not connected. Call connect() first.');
}
return this.requestManager.queueRequest(request);
}
/**
* Configure request executor for the request manager
*/
setRequestExecutor(executor) {
this.requestManager.setRequestExecutor(executor);
}
// Device Controller Methods (delegation)
async turnOn() {
return this.deviceController.turnOn();
}
async turnOff() {
return this.deviceController.turnOff();
}
async getDeviceInfo() {
return this.deviceController.getDeviceInfo();
}
async setAlias(alias) {
return this.deviceController.setAlias(alias);
}
async ping() {
return this.deviceController.ping();
}
// Energy Controller Methods (if supported)
async getEnergyUsage() {
if (!this.energyController) {
throw new Error('Energy monitoring not supported by this device');
}
return this.energyController.getEnergyUsage();
}
async getCurrentPower() {
if (!this.energyController) {
throw new Error('Energy monitoring not supported by this device');
}
return this.energyController.getCurrentPower();
}
// Lighting Controller Methods (if supported)
async setBrightness(brightness) {
if (!this.lightingController) {
throw new Error('Brightness control not supported by this device');
}
return this.lightingController.setBrightness(brightness);
}
async setColorHSV(hue, saturation, brightness) {
if (!this.lightingController) {
throw new Error('Color control not supported by this device');
}
return this.lightingController.setColorHSV(hue, saturation, brightness);
}
async setColorRGB(red, green, blue, brightness) {
if (!this.lightingController) {
throw new Error('Color control not supported by this device');
}
return this.lightingController.setColorRGB(red, green, blue, brightness);
}
async setNamedColor(colorName, brightness) {
if (!this.lightingController) {
throw new Error('Color control not supported by this device');
}
return this.lightingController.setNamedColor(colorName, brightness);
}
async setColorTemperature(temperature, brightness) {
if (!this.lightingController) {
throw new Error('Color temperature control not supported by this device');
}
return this.lightingController.setColorTemperature(temperature, brightness);
}
// Utility Methods
getCapabilities() {
return { ...this.capabilities };
}
isConnected() {
return this.isInitialized && this.connectionManager.isConnected();
}
getDeviceModel() {
return this.deviceModel;
}
getDeviceIP() {
return this.ip;
}
/**
* Determine device capabilities based on model
*/
determineCapabilities(deviceModel) {
return {
hasEnergyMonitoring: energy_controller_1.EnergyController.supportsEnergyMonitoring(deviceModel),
hasBrightnessControl: lighting_controller_1.LightingController.supportsBrightnessControl(deviceModel),
hasColorControl: lighting_controller_1.LightingController.supportsColorControl(deviceModel),
hasColorTemperature: lighting_controller_1.LightingController.supportsColorTemperature(deviceModel),
hasLightEffects: this.supportsLightEffects(deviceModel)
};
}
/**
* Check if device supports light effects
*/
supportsLightEffects(deviceModel) {
const supportedModels = ['L530', 'L535', 'L630', 'L920', 'L930'];
return supportedModels.some(model => deviceModel.toUpperCase().includes(model.toUpperCase()));
}
/**
* Cleanup resources
*/
async cleanup() {
try {
// Clear request queue
this.requestManager.clearQueue();
// Invalidate session
this.sessionManager.invalidateSession();
// Disconnect
await this.connectionManager.disconnect();
}
catch (error) {
// Ignore cleanup errors
}
}
/**
* Handle session refresh
*/
async refreshSession() {
const protocol = this.protocolSelector.getActiveProtocol();
if (protocol) {
await this.initializeSession(protocol);
}
}
}
exports.BaseDevice = BaseDevice;
//# sourceMappingURL=base-device.js.map