From a0131060640e5e695044bdd6026f1827ee959577 Mon Sep 17 00:00:00 2001 From: Lukas Obermeier Date: Sun, 1 Dec 2024 09:02:25 +0000 Subject: [PATCH] feat: make supported device types configurable Closes #430 --- README.md | 21 ++++++++++++++++ config.schema.json | 27 ++++++++++++++++++++ src/smartThingsPlatform.ts | 50 +++++++++++++++++++++++++------------- 3 files changed, 81 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 81b1d08..449cfde 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,13 @@ The following snippets shows all available properties you can use for the plugin "ipAddress": "xx:xx:xx:xx:xx:xx" } ], + "tvDeviceTypes": [ + "oic.d.tv", + "x.com.st.d.monitor" + ], + "soundbarDeviceTypes": [ + "oic.d.networkaudio" + ], "platform": "smartthings-tv" } ] @@ -219,6 +226,14 @@ The application's possible ids. Since some applications have different ids for d The icon to be used as a hint to iOS clients about what type of Accessory this represents. Can be used to override default values. +## tvDeviceTypes + +List of SmartThings device types that should be registered as TVs (leave empty to use default values). + +## soundbarDeviceTypes + +List of SmartThings device types that should be registered as Soundbar (leave empty to use default values). + ## Common issues ### TV does not show in HomeKit @@ -293,6 +308,12 @@ For some TVs display port sources do not show up. When having the same problem y The configured name can not be cached because TV is published as external accessory. To permanently change the name use [nameOverride](#nameoverride). +### Device does not get registered + +TVs do have different device types returned from SmartThings API. If your TV does not get registered, activate debug logging and look for a log entry like `Ignoring SmartThings device ... because device type ... is not in list of implemented/configured types [...]`. Use the device type stated here and add it to the matching configuration property [tvDeviceTypes](#tvdevicetypes) or [soundbarDeviceType](#soundbardevicetypes). + +Currently only the default values have been tested. So please create a ticket if you're running into any problems with your device type. If everything is working well please create a ticket as well so the device type can be added to the default configuration. + *** Since this is my first plugin it may contain some problems. Feel free to create an issue or pull request and I will try to help and fix the problems. diff --git a/config.schema.json b/config.schema.json index 379eb11..f05ebd3 100644 --- a/config.schema.json +++ b/config.schema.json @@ -225,6 +225,33 @@ } } } + }, + "tvDeviceTypes": { + "title": "TV device types", + "description": "List of SmartThings device types that should be registered as TVs (leave empty to use default values)", + "type": "array", + "items": { + "title": "Device type", + "type": "string", + "description": "The SmartThings device type as appearing in the Debug log" + }, + "default": [ + "oic.d.tv", + "x.com.st.d.monitor" + ] + }, + "soundbarDeviceTypes": { + "title": "Soundbar device types", + "description": "List of SmartThings device types that should be registered as Soundbar (leave empty to use default values)", + "type": "array", + "items": { + "title": "Device type", + "type": "string", + "description": "The SmartThings device type as appearing in the Debug log" + }, + "default": [ + "oic.d.networkaudio" + ] } } } diff --git a/src/smartThingsPlatform.ts b/src/smartThingsPlatform.ts index 4f63f34..51f1fb3 100644 --- a/src/smartThingsPlatform.ts +++ b/src/smartThingsPlatform.ts @@ -67,7 +67,9 @@ export class SmartThingsPlatform implements DynamicPlatformPlugin { void this.discoverDevices(config.token as string, deviceBlocklist ?? [], - config.deviceMappings as [DeviceMapping] ?? []); + config.deviceMappings as [DeviceMapping] ?? [], + config.tvDeviceTypes as [string] ?? ['oic.d.tv', 'x.com.st.d.monitor'], + config.soundbarDeviceTypes as [string] ?? ['oic.d.networkaudio']); }); } @@ -88,8 +90,11 @@ export class SmartThingsPlatform implements DynamicPlatformPlugin { * @param token the SmartThings API token * @param deviceBlocklist the device ids to be ignored * @param deviceMappings the array of configured DeviceMapping + * @param tvDeviceTypes the array of configured TV device types + * @param soundbarDeviceTypes the array of configured SoundBar device types */ - async discoverDevices(token: string, deviceBlocklist: [string], deviceMappings: [DeviceMapping]) { + async discoverDevices(token: string, deviceBlocklist: [string], deviceMappings: [DeviceMapping], + tvDeviceTypes: [string], soundbarDeviceTypes: [string]) { const client = new SmartThingsClient(new BearerTokenAuthenticator(token)); let externalAccessories: PlatformAccessory[] = []; @@ -103,7 +108,8 @@ export class SmartThingsPlatform implements DynamicPlatformPlugin { this.log.debug('Ignoring SmartThings device %s because it is on the blocklist', device.name ? device.name + ' (' + device.deviceId + ')' : device.deviceId); } else { - externalAccessories = externalAccessories.concat(await this.registerDevice(client, device, deviceMappings)); + externalAccessories = externalAccessories.concat( + await this.registerDevice(client, device, deviceMappings, tvDeviceTypes, soundbarDeviceTypes)); } } } catch (error) { @@ -124,24 +130,34 @@ export class SmartThingsPlatform implements DynamicPlatformPlugin { * @param client the SmartThingsClient used to send API calls * @param device the SmartThings Device * @param deviceMappings the array of configured DeviceMapping + * @param tvDeviceTypes the array of configured TV device types + * @param soundbarDeviceTypes the array of configured SoundBar device types * @returns the PlatformAccessory that must be published as external accessory or undefined * if accessory must not be published as external accessory */ - async registerDevice(client: SmartThingsClient, device: Device, deviceMappings: [DeviceMapping]): Promise { - switch (device.ocf?.ocfDeviceType) { - case 'oic.d.tv': - case 'x.com.st.d.monitor': - return await this.registerTvDevice(client, device, deviceMappings.find(mapping => mapping.deviceId === device.deviceId)); - - case 'oic.d.networkaudio': - return await this.registerSoundbarDevice(client, device, deviceMappings.find(mapping => mapping.deviceId === device.deviceId)); - - default: - this.log.debug('Ignoring SmartThings device %s because device type %s is not implemented: %s', - device.name ? device.name + ' (' + device.deviceId + ')' : device.deviceId, - device.ocf?.ocfDeviceType, JSON.stringify(device, null, 2)); - return []; + async registerDevice(client: SmartThingsClient, device: Device, deviceMappings: [DeviceMapping], + tvDeviceTypes: [string], soundbarDeviceTypes: [string]): Promise { + const deviceType = device.ocf?.ocfDeviceType; + + if (!deviceType) { + this.log.error('Ignoring SmartThings device %s because it has no device type', + device.name ? device.name + ' (' + device.deviceId + ')' : device.deviceId); + return []; + } + + const deviceMapping = deviceMappings.find(mapping => mapping.deviceId === device.deviceId); + + if (tvDeviceTypes.includes(deviceType)) { + return await this.registerTvDevice(client, device, deviceMapping); + } else if (soundbarDeviceTypes.includes(deviceType)) { + return await this.registerSoundbarDevice(client, device, deviceMapping); } + + this.log.debug('Ignoring SmartThings device %s because device type %s is not in list of implemented/configured types (%s): %s', + device.name ? device.name + ' (' + device.deviceId + ')' : device.deviceId, + device.ocf?.ocfDeviceType, tvDeviceTypes.concat(soundbarDeviceTypes).join(', '), + JSON.stringify(device, null, 2)); + return []; } /**