homebridge-kasa-python 1.0.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +21 -6
  2. package/config.schema.json +2 -33
  3. package/dist/accessoryInformation.d.ts +1 -1
  4. package/dist/accessoryInformation.js +14 -18
  5. package/dist/accessoryInformation.js.map +1 -1
  6. package/dist/categoriesParse.d.ts +8 -0
  7. package/dist/categoriesParse.js +44 -0
  8. package/dist/categoriesParse.js.map +1 -0
  9. package/dist/config.d.ts +12 -155
  10. package/dist/config.js +52 -100
  11. package/dist/config.js.map +1 -1
  12. package/dist/devices/create.d.ts +3 -9
  13. package/dist/devices/create.js +6 -7
  14. package/dist/devices/create.js.map +1 -1
  15. package/dist/devices/deviceManager.d.ts +6 -8
  16. package/dist/devices/deviceManager.js +47 -126
  17. package/dist/devices/deviceManager.js.map +1 -1
  18. package/dist/devices/homekitPlug.d.ts +10 -16
  19. package/dist/devices/homekitPlug.js +93 -74
  20. package/dist/devices/homekitPlug.js.map +1 -1
  21. package/dist/devices/homekitPowerstrip.d.ts +11 -17
  22. package/dist/devices/homekitPowerstrip.js +106 -73
  23. package/dist/devices/homekitPowerstrip.js.map +1 -1
  24. package/dist/devices/index.d.ts +12 -19
  25. package/dist/devices/index.js +44 -71
  26. package/dist/devices/index.js.map +1 -1
  27. package/dist/devices/kasaDevices.d.ts +4 -5
  28. package/dist/platform.d.ts +22 -29
  29. package/dist/platform.js +127 -131
  30. package/dist/platform.js.map +1 -1
  31. package/dist/python/kasaApi.py +109 -0
  32. package/dist/python/pythonChecker.d.ts +2 -2
  33. package/dist/python/pythonChecker.js +24 -89
  34. package/dist/python/pythonChecker.js.map +1 -1
  35. package/dist/utils.d.ts +3 -18
  36. package/dist/utils.js +72 -116
  37. package/dist/utils.js.map +1 -1
  38. package/package.json +23 -15
  39. package/requirements.txt +4 -1
  40. package/dist/python/discover.py +0 -38
  41. package/dist/python/getSysInfo.py +0 -39
  42. package/dist/python/turnOff.py +0 -20
  43. package/dist/python/turnOffChild.py +0 -22
  44. package/dist/python/turnOn.py +0 -20
  45. package/dist/python/turnOnChild.py +0 -22
@@ -1,57 +1,50 @@
1
1
  import { Categories } from 'homebridge';
2
2
  import type { API, Characteristic, DynamicPlatformPlugin, Logging, PlatformAccessory, PlatformConfig, Service, WithUUID } from 'homebridge';
3
+ import DeviceManager from './devices/deviceManager.js';
3
4
  import type { KasaPythonConfig } from './config.js';
4
- import type { KasaDevice } from './utils.js';
5
+ import type { KasaDevice } from './devices/kasaDevices.js';
5
6
  export type KasaPythonAccessoryContext = {
6
7
  deviceId?: string;
7
8
  };
8
9
  export default class KasaPythonPlatform implements DynamicPlatformPlugin {
9
10
  readonly log: Logging;
10
11
  readonly api: API;
11
- readonly Service: typeof Service;
12
12
  readonly Characteristic: typeof Characteristic;
13
- config: KasaPythonConfig;
14
- private readonly configuredAccessories;
15
- private readonly homekitDevicesById;
13
+ readonly configuredAccessories: Map<string, PlatformAccessory<KasaPythonAccessoryContext>>;
14
+ readonly Service: typeof Service;
16
15
  readonly storagePath: string;
17
16
  readonly venvPythonExecutable: string;
18
- private deviceManager;
17
+ config: KasaPythonConfig;
18
+ deviceManager: DeviceManager | undefined;
19
+ port: number;
20
+ private readonly categories;
21
+ private readonly homekitDevicesById;
22
+ private kasaProcess;
23
+ private platformInitialization;
19
24
  constructor(log: Logging, config: PlatformConfig, api: API);
20
- /**
21
- * Function invoked when checking python environment.
22
- */
25
+ private createHomekitDevice;
26
+ private initializeCategories;
27
+ initializePlatform(): Promise<void>;
28
+ private logInitializationDetails;
29
+ private verifyEnvironment;
30
+ private didFinishLaunching;
23
31
  private checkPython;
24
- /**
25
- * Return string representation of Service/Characteristic for logging
26
- *
27
- * @internal
28
- */
32
+ private startKasaApi;
33
+ private stopKasaApi;
29
34
  lsc(serviceOrCharacteristic: Service | Characteristic | {
30
35
  UUID: string;
31
36
  }, characteristic?: Characteristic | {
32
37
  UUID: string;
33
38
  }): string;
34
- private createHomekitDevice;
35
- getCategoryName(category: Categories): string | undefined;
36
39
  getServiceName(service: {
37
40
  UUID: string;
38
41
  }): string | undefined;
39
42
  getCharacteristicName(characteristic: WithUUID<{
40
- name?: string;
41
- displayName?: string;
43
+ name?: string | null;
44
+ displayName?: string | null;
42
45
  }>): string | undefined;
43
- /**
44
- * Registers a Homebridge PlatformAccessory.
45
- *
46
- * Calls {@link external:homebridge.API#registerPlatformAccessories}
47
- */
46
+ getCategoryName(category: Categories): string;
48
47
  registerPlatformAccessory(platformAccessory: PlatformAccessory<KasaPythonAccessoryContext>): void;
49
- /**
50
- * Function invoked when homebridge tries to restore cached accessory
51
- */
52
48
  configureAccessory(accessory: PlatformAccessory<KasaPythonAccessoryContext>): void;
53
- /**
54
- * Adds a new device.
55
- */
56
49
  foundDevice(device: KasaDevice): void;
57
50
  }
package/dist/platform.js CHANGED
@@ -1,182 +1,178 @@
1
- import chalk from 'chalk';
2
- import { promises as fs } from 'fs';
3
- import path from 'path';
1
+ import getPort from 'get-port';
2
+ import path from 'node:path';
3
+ import { promises as fs } from 'node:fs';
4
4
  import { satisfies } from 'semver';
5
- import { fileURLToPath } from 'url';
6
- import { parseConfig } from './config.js';
7
- import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
8
- import { lookup, lookupCharacteristicNameByUUID, isObjectLike } from './utils.js';
5
+ import { fileURLToPath } from 'node:url';
9
6
  import create from './devices/create.js';
10
7
  import DeviceManager from './devices/deviceManager.js';
11
8
  import PythonChecker from './python/pythonChecker.js';
9
+ import { EnumParser } from './categoriesParse.js';
10
+ import { parseConfig } from './config.js';
11
+ import { runCommand } from './utils.js';
12
+ import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
13
+ import { isObjectLike, lookup, lookupCharacteristicNameByUUID, prefixLogger } from './utils.js';
12
14
  let packageConfig;
13
- try {
15
+ async function loadPackageConfig(logger) {
14
16
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
17
  const packageConfigPath = path.join(__dirname, '..', 'package.json');
16
- const packageConfigData = await fs.readFile(packageConfigPath, 'utf8');
17
- packageConfig = JSON.parse(packageConfigData);
18
- }
19
- catch (error) {
20
- // eslint-disable-next-line no-console
21
- console.error('Error reading package.json: %s', error);
18
+ const log = prefixLogger(logger, '[Package Config]');
19
+ try {
20
+ const packageConfigData = await fs.readFile(packageConfigPath, 'utf8');
21
+ packageConfig = JSON.parse(packageConfigData);
22
+ }
23
+ catch (error) {
24
+ log.error(`Error reading package.json: ${error}`);
25
+ throw error;
26
+ }
22
27
  }
23
28
  export default class KasaPythonPlatform {
24
29
  log;
25
30
  api;
26
- Service;
27
31
  Characteristic;
28
- config;
29
32
  configuredAccessories = new Map();
30
- homekitDevicesById = new Map();
33
+ Service;
31
34
  storagePath;
32
35
  venvPythonExecutable;
36
+ config;
33
37
  deviceManager;
38
+ port = 0;
39
+ categories;
40
+ homekitDevicesById = new Map();
41
+ kasaProcess = null;
42
+ platformInitialization;
34
43
  constructor(log, config, api) {
35
44
  this.log = log;
36
45
  this.api = api;
37
- this.api = api;
46
+ this.Service = this.api.hap.Service;
47
+ this.Characteristic = this.api.hap.Characteristic;
38
48
  this.storagePath = this.api.user.storagePath();
39
49
  this.venvPythonExecutable = path.join(this.storagePath, 'kasa-python', '.venv', 'bin', 'python3');
40
- this.deviceManager = new DeviceManager(this);
41
- this.log.info('%s v%s, node %s, homebridge v%s, api v%s Initializing...', packageConfig.name, packageConfig.version, process.version, this.api.serverVersion, this.api.version);
50
+ this.config = parseConfig(config);
51
+ this.categories = this.initializeCategories();
52
+ this.platformInitialization = this.initializePlatform().catch((error) => {
53
+ this.log.error('Platform initialization failed:', error);
54
+ });
55
+ this.api.on('didFinishLaunching', async () => {
56
+ await this.platformInitialization;
57
+ await this.didFinishLaunching();
58
+ });
59
+ this.api.on('shutdown', () => {
60
+ this.stopKasaApi();
61
+ });
62
+ }
63
+ createHomekitDevice(kasaDevice) {
64
+ return create(this, kasaDevice);
65
+ }
66
+ initializeCategories() {
67
+ return new EnumParser(this).parse();
68
+ }
69
+ async initializePlatform() {
70
+ await loadPackageConfig(this.log);
71
+ this.logInitializationDetails();
72
+ await this.verifyEnvironment();
73
+ }
74
+ logInitializationDetails() {
75
+ this.log.info(`${packageConfig.name} v${packageConfig.version}, node ${process.version}, ` +
76
+ `homebridge v${this.api.serverVersion}, api v${this.api.version} Initializing...`);
77
+ }
78
+ async verifyEnvironment() {
42
79
  if (!satisfies(process.version, packageConfig.engines.node)) {
43
- this.log.error('Error: not using minimum node version %s', packageConfig.engines.node);
80
+ this.log.error(`Error: not using minimum node version ${packageConfig.engines.node}`);
44
81
  }
45
- else {
46
- this.log.debug('Using minimum node version or better: %s', packageConfig.engines.node);
82
+ if (this.api.versionGreaterOrEqual && !this.api.versionGreaterOrEqual('1.8.4')) {
83
+ throw new Error(`homebridge-kasa-python requires homebridge >= 1.8.4. Currently running: ${this.api.serverVersion}`);
47
84
  }
48
- if (this.api.versionGreaterOrEqual === null ||
49
- !this.api.versionGreaterOrEqual('1.8.3')) {
50
- this.log.error(`homebridge-kasa-python requires homebridge >= 1.8.3. Currently running: ${this.api.serverVersion}`);
51
- throw new Error(`homebridge-kasa-python requires homebridge >= 1.8.3. Currently running: ${this.api.serverVersion}`);
85
+ }
86
+ async didFinishLaunching() {
87
+ this.log.debug('Did Finish Launching Event Received');
88
+ try {
89
+ await this.checkPython();
90
+ this.port = await getPort();
91
+ this.deviceManager = new DeviceManager(this);
92
+ await this.startKasaApi();
93
+ await this.deviceManager.discoverDevices();
52
94
  }
53
- else {
54
- this.log.debug('Using minimum homebridge version or better: %s', this.api.serverVersion);
95
+ catch (error) {
96
+ this.log.error('An error occurred during startup:', error);
55
97
  }
56
- this.Service = this.api.hap.Service;
57
- this.Characteristic = this.api.hap.Characteristic;
58
- this.log.debug('config.json: %j', config);
59
- this.config = parseConfig(config);
60
- this.log.debug('config: %j', this.config);
61
- this.log.info('%s v%s, node %s, homebridge v%s, api v%s Finished Initializing.', packageConfig.name, packageConfig.version, process.version, this.api.serverVersion, this.api.version);
62
- this.api.on('didFinishLaunching', async () => {
63
- this.log.info('Did Finish Launching Event Received');
64
- try {
65
- await this.checkPython().catch(error => {
66
- this.log.error('Error checking python environment: %s', error);
67
- });
68
- await this.deviceManager.discoverDevices().catch(error => {
69
- this.log.error('Error discovering devices: %s', error);
70
- });
71
- }
72
- catch (error) {
73
- this.log.error('An error occurred during startup: %s', error);
74
- }
75
- });
76
98
  }
77
- /**
78
- * Function invoked when checking python environment.
79
- */
80
99
  async checkPython() {
81
- this.log.info('Executing Python Checker...');
82
- await new PythonChecker(this, this.storagePath, this.config.pythonExecutable)
83
- .allInOne(this.config.forceVenvRecreate).catch((error) => {
84
- this.log.error('Error checking python environment: %s', error);
85
- });
86
- this.log.info('Python Checker finished, environment is ready.');
87
- }
88
- /**
89
- * Return string representation of Service/Characteristic for logging
90
- *
91
- * @internal
92
- */
93
- lsc(serviceOrCharacteristic, characteristic) {
94
- let serviceName;
95
- let characteristicName;
96
- if (serviceOrCharacteristic instanceof this.api.hap.Service) {
97
- serviceName = this.getServiceName(serviceOrCharacteristic);
98
- }
99
- else if (serviceOrCharacteristic instanceof this.api.hap.Characteristic ||
100
- ('UUID' in serviceOrCharacteristic &&
101
- typeof serviceOrCharacteristic.UUID === 'string')) {
102
- characteristicName = this.getCharacteristicName(serviceOrCharacteristic);
100
+ try {
101
+ await new PythonChecker(this).allInOne();
103
102
  }
104
- if (characteristic instanceof this.api.hap.Characteristic) {
105
- characteristicName = this.getCharacteristicName(characteristic);
103
+ catch (error) {
104
+ this.log.error('Error checking python environment:', error);
106
105
  }
107
- if (serviceName !== null && characteristicName !== null) {
108
- return `[${chalk.yellow(serviceName)}.${chalk.green(characteristicName)}]`;
106
+ }
107
+ async startKasaApi() {
108
+ const scriptPath = `${this.storagePath}/node_modules/homebridge-kasa-python/dist/python/kasaApi.py`;
109
+ try {
110
+ const [, stderr, , process] = await runCommand(this.log, this.venvPythonExecutable, [scriptPath, this.port.toString()], undefined, true, true, true);
111
+ this.kasaProcess = process;
112
+ if (stderr) {
113
+ this.log.debug(`kasaApi.py process started: ${stderr}`);
114
+ }
109
115
  }
110
- if (serviceName !== undefined) {
111
- return `[${chalk.yellow(serviceName)}]`;
116
+ catch (error) {
117
+ if (error instanceof Error) {
118
+ this.log.error(`Error starting kasaApi.py process: ${error.message}`);
119
+ }
120
+ else {
121
+ this.log.error('An unknown error occurred during startup');
122
+ }
112
123
  }
113
- return `[${chalk.green(characteristicName)}]`;
114
124
  }
115
- createHomekitDevice(accessory, kasaDevice) {
116
- return create(this, this.config, accessory, kasaDevice);
125
+ stopKasaApi() {
126
+ if (this.kasaProcess) {
127
+ this.kasaProcess.kill();
128
+ this.kasaProcess = null;
129
+ this.log.debug('kasaApi.py process terminated');
130
+ }
117
131
  }
118
- getCategoryName(category) {
119
- // @ts-expect-error: this should work
120
- return this.api.hap.Accessory.Categories[category];
132
+ lsc(serviceOrCharacteristic, characteristic) {
133
+ const serviceName = serviceOrCharacteristic instanceof this.api.hap.Service
134
+ ? this.getServiceName(serviceOrCharacteristic)
135
+ : undefined;
136
+ const characteristicName = characteristic instanceof this.api.hap.Characteristic
137
+ ? this.getCharacteristicName(characteristic)
138
+ : serviceOrCharacteristic instanceof this.api.hap.Characteristic || 'UUID' in serviceOrCharacteristic
139
+ ? this.getCharacteristicName(serviceOrCharacteristic)
140
+ : undefined;
141
+ return `[${serviceName ? serviceName : ''}` +
142
+ `${serviceName && characteristicName ? '.' : ''}` +
143
+ `${characteristicName ? characteristicName : ''}]`;
121
144
  }
122
145
  getServiceName(service) {
123
- return lookup(this.api.hap.Service, (thisKeyValue, value) => isObjectLike(thisKeyValue) &&
124
- 'UUID' in thisKeyValue &&
125
- thisKeyValue.UUID === value, service.UUID);
146
+ return lookup(this.api.hap.Service, (thisKeyValue, value) => isObjectLike(thisKeyValue) && 'UUID' in thisKeyValue && thisKeyValue.UUID === value, service.UUID);
126
147
  }
127
148
  getCharacteristicName(characteristic) {
128
- if ('name' in characteristic && characteristic.name !== undefined) {
129
- return characteristic.name;
130
- }
131
- if ('displayName' in characteristic &&
132
- characteristic.displayName !== undefined) {
133
- return characteristic.displayName;
134
- }
135
- if ('UUID' in characteristic) {
136
- return lookupCharacteristicNameByUUID(this.api.hap.Characteristic, characteristic.UUID);
137
- }
138
- return undefined;
149
+ return characteristic.name ??
150
+ characteristic.displayName ??
151
+ lookupCharacteristicNameByUUID(this.api.hap.Characteristic, characteristic.UUID);
152
+ }
153
+ getCategoryName(category) {
154
+ return this.categories ? this.categories[category] : 'Unknown';
139
155
  }
140
- /**
141
- * Registers a Homebridge PlatformAccessory.
142
- *
143
- * Calls {@link external:homebridge.API#registerPlatformAccessories}
144
- */
145
156
  registerPlatformAccessory(platformAccessory) {
146
- this.log.debug(`registerPlatformAccessory(${chalk.blue(`[${platformAccessory.displayName}]`)})`);
147
- this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
148
- platformAccessory,
149
- ]);
150
- }
151
- /**
152
- * Function invoked when homebridge tries to restore cached accessory
153
- */
157
+ this.log.debug(`registerPlatformAccessory([${platformAccessory.displayName}])`);
158
+ this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [platformAccessory]);
159
+ }
154
160
  configureAccessory(accessory) {
155
- this.log.info(`Configuring cached accessory: ${chalk.blue(`[${accessory.displayName}]`)} UUID: ${accessory.UUID} deviceId: %s `, accessory.context?.deviceId);
156
- this.log.debug('%O', accessory.context);
161
+ this.log.info(`Configuring cached accessory: [${accessory.displayName}] UUID: ${accessory.UUID} deviceId: ${accessory.context.deviceId}`);
157
162
  this.configuredAccessories.set(accessory.UUID, accessory);
158
163
  }
159
- /**
160
- * Adds a new device.
161
- */
162
164
  foundDevice(device) {
163
- const deviceId = device.sys_info.deviceId;
164
- const deviceAlias = device.alias;
165
- const deviceHost = device.host;
166
- const deviceType = device.sys_info.mic_type;
167
- if (deviceId === null || deviceId.length === 0) {
168
- this.log.error('Missing deviceId: %s', deviceHost);
165
+ const { sys_info: { deviceId }, alias: deviceAlias, host: deviceHost, sys_info: { mic_type: deviceType } } = device;
166
+ if (!deviceId) {
167
+ this.log.error('Missing deviceId:', deviceHost);
169
168
  return;
170
169
  }
171
- if (this.homekitDevicesById.get(deviceId) !== undefined) {
172
- this.log.info(`Device already added: ${chalk.blue(`[${deviceAlias}]`)} %s [%s]`, deviceType, deviceId);
170
+ if (this.homekitDevicesById.has(deviceId)) {
171
+ this.log.info(`Device already added: [${deviceAlias}] ${deviceType} [${deviceId}]`);
173
172
  return;
174
173
  }
175
- this.log.info(`Adding: ${chalk.blue(`[${deviceAlias}]`)} %s [%s]`, deviceType, deviceId);
176
- this.log.info('Generating UUID for device: %s', deviceId);
177
- const uuid = this.api.hap.uuid.generate(deviceId);
178
- const accessory = this.configuredAccessories.get(uuid);
179
- this.homekitDevicesById.set(deviceId, this.createHomekitDevice(accessory, device));
174
+ this.log.info(`Adding: [${deviceAlias}] ${deviceType} [${deviceId}]`);
175
+ this.homekitDevicesById.set(deviceId, this.createHomekitDevice(device));
180
176
  }
181
177
  }
182
178
  //# sourceMappingURL=platform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import asyncio, eventlet, eventlet.wsgi, json, sys
2
+ from flask import Flask, request, jsonify
3
+ from flask_socketio import SocketIO
4
+ from kasa import Discover, Device
5
+
6
+ app = Flask(__name__)
7
+ socketio = SocketIO(app, cors_allowed_origins="*")
8
+
9
+ device_cache = {}
10
+
11
+ def custom_device_serializer(device):
12
+ def is_serializable(value):
13
+ try:
14
+ json.dumps(value)
15
+ return True
16
+ except TypeError:
17
+ return False
18
+
19
+ return {attr: getattr(device, attr) for attr in dir(device)
20
+ if not attr.startswith("_") and not callable(getattr(device, attr))
21
+ and not asyncio.iscoroutine(getattr(device, attr))
22
+ and is_serializable(getattr(device, attr))}
23
+
24
+ async def discover_devices():
25
+ devices = await Discover.discover()
26
+ all_device_info = {}
27
+ tasks = []
28
+ for ip, dev in devices.items():
29
+ tasks.append(update_device_info(ip, dev))
30
+ results = await asyncio.gather(*tasks)
31
+ for ip, info in results:
32
+ all_device_info[ip] = info
33
+ return all_device_info
34
+
35
+ async def update_device_info(ip, dev: Device):
36
+ await dev.update()
37
+ device_info = custom_device_serializer(dev)
38
+ device_config = dev.config.to_dict()
39
+ device_cache[ip] = {
40
+ "device_info": device_info,
41
+ "device_config": device_config
42
+ }
43
+ return ip, device_cache[ip]
44
+
45
+ async def get_device_info(device_config):
46
+ dev = await Device.connect(config=Device.Config.from_dict(device_config))
47
+ try:
48
+ device_info = custom_device_serializer(dev)
49
+ return {"device_info": device_info}
50
+ finally:
51
+ await dev.disconnect()
52
+
53
+ async def control_device(device_config, action, child_num=None):
54
+ kasa_device = await Device.connect(config=Device.Config.from_dict(device_config))
55
+ try:
56
+ if child_num is not None:
57
+ child = kasa_device.children[child_num]
58
+ await getattr(child, action)()
59
+ else:
60
+ await getattr(kasa_device, action)()
61
+ return {"status": "success", f"is_{action.split('_')[1]}": True}
62
+ except Exception as e:
63
+ return {"status": "error", "message": str(e)}
64
+ finally:
65
+ await kasa_device.disconnect()
66
+
67
+ def run_async(func, *args):
68
+ loop = asyncio.get_event_loop()
69
+ return loop.run_until_complete(func(*args))
70
+
71
+ @app.route('/discover', methods=['GET'])
72
+ def discover():
73
+ try:
74
+ devices_info = run_async(discover_devices)
75
+ return jsonify(devices_info)
76
+ except Exception as e:
77
+ app.logger.error(f"Error in /discover: {str(e)}")
78
+ return jsonify({"status": "error", "message": str(e)}), 500
79
+
80
+ @app.route('/getSysInfo', methods=['POST'])
81
+ def get_sys_info_route():
82
+ try:
83
+ data = request.json
84
+ app.logger.debug(f"Request data: {data}")
85
+ device_config = data['device_config']
86
+ device_info = run_async(get_device_info, device_config)
87
+ return jsonify(device_info)
88
+ except Exception as e:
89
+ app.logger.error(f"Error in /getSysInfo: {str(e)}")
90
+ return jsonify({"status": "error", "message": str(e)}), 500
91
+
92
+ @app.route('/controlDevice', methods=['POST'])
93
+ def control_device_route():
94
+ try:
95
+ data = request.json
96
+ app.logger.debug(f"Request data: {data}")
97
+ device_config = data['device_config']
98
+ action = data['action']
99
+ child_num = data.get('child_num')
100
+ result = run_async(control_device, device_config, action, child_num)
101
+ return jsonify(result)
102
+ except Exception as e:
103
+ app.logger.error(f"Error in /controlDevice: {str(e)}")
104
+ return jsonify({"status": "error", "message": str(e)}), 500
105
+
106
+ if __name__ == '__main__':
107
+ port = int(sys.argv[1])
108
+ print(f"Starting server on port {port}")
109
+ eventlet.wsgi.server(eventlet.listen(('127.0.0.1', port)), app)
@@ -9,8 +9,8 @@ declare class PythonChecker {
9
9
  private readonly venvPythonExecutable;
10
10
  private readonly venvConfigPath;
11
11
  private readonly requirementsPath;
12
- constructor(platform: KasaPythonPlatform, storagePath: string, pythonExecutable?: string);
13
- allInOne(forceVenvRecreate?: boolean): Promise<void>;
12
+ constructor(platform: KasaPythonPlatform);
13
+ allInOne(): Promise<void>;
14
14
  private ensurePluginDir;
15
15
  private ensurePythonVersion;
16
16
  private ensureVenvCreated;