diff --git a/.homeycompose/capabilities/identify.json b/.homeycompose/capabilities/identify.json new file mode 100644 index 00000000..1274398e --- /dev/null +++ b/.homeycompose/capabilities/identify.json @@ -0,0 +1,12 @@ +{ + "type": "boolean", + "title": { + "en": "Identify", + "nl": "Identificeren" + }, + "getable": false, + "setable": true, + "uiComponent": "button", + "insights": false, + "icon": "assets/magnify.svg" +} diff --git a/app.json b/app.json index 4b19a1ce..1982c0fe 100755 --- a/app.json +++ b/app.json @@ -894,6 +894,7 @@ "local" ], "capabilities": [ + "identify", "measure_power", "meter_gas", "meter_water", @@ -1113,6 +1114,7 @@ "capabilities": [ "onoff", "dim", + "identify", "locked", "measure_power", "meter_power", @@ -1226,6 +1228,7 @@ "local" ], "capabilities": [ + "identify", "measure_power", "meter_gas", "meter_water", @@ -1820,6 +1823,7 @@ "local" ], "capabilities": [ + "identify", "meter_power.import", "meter_power.export", "measure_battery", @@ -2026,6 +2030,7 @@ "local" ], "capabilities": [ + "identify", "measure_water", "meter_water", "rssi" @@ -2270,6 +2275,18 @@ "nl": "cycli" } }, + "identify": { + "type": "boolean", + "title": { + "en": "Identify", + "nl": "Identificeren" + }, + "getable": false, + "setable": true, + "uiComponent": "button", + "insights": false, + "icon": "assets/magnify.svg" + }, "long_power_fail_count": { "type": "number", "title": { @@ -2587,4 +2604,4 @@ ] } } -} \ No newline at end of file +} diff --git a/assets/magnify.svg b/assets/magnify.svg new file mode 100644 index 00000000..e888746a --- /dev/null +++ b/assets/magnify.svg @@ -0,0 +1 @@ + diff --git a/drivers/energy/device.js b/drivers/energy/device.js index 89db28ae..eedaea6d 100644 --- a/drivers/energy/device.js +++ b/drivers/energy/device.js @@ -14,6 +14,9 @@ module.exports = class HomeWizardEnergyDevice extends Homey.Device { this._flowTriggerImport = this.homey.flow.getDeviceTriggerCard('import_changed'); this._flowTriggerExport = this.homey.flow.getDeviceTriggerCard('export_changed'); + this.registerCapabilityListener('identify', async (value) => { + await this.onIdentify(); + }); } flowTriggerTariff(device, tokens) { @@ -54,6 +57,19 @@ module.exports = class HomeWizardEnergyDevice extends Homey.Device { this.onPoll(); } + async onRequest(body) { + if (!this.url) return; + + const res = await fetch(`${this.url}/state`, { + method: 'PUT', + body: JSON.stringify(body), + headers: { 'Content-Type': 'application/json' }, + }).catch(this.error); + + if (!res.ok) + { throw new Error(res.statusText); } + } + onPoll() { if (!this.url) return; @@ -101,6 +117,10 @@ module.exports = class HomeWizardEnergyDevice extends Homey.Device { promises.push(this.addCapability('tariff').catch(this.error)); } + if (!this.hasCapability('identify')) { + await this.addCapability('identify').catch(this.error); + } + // Update values if (this.getCapabilityValue('measure_power') != data.active_power_w) { promises.push(this.setCapabilityValue('measure_power', data.active_power_w).catch(this.error)); } diff --git a/drivers/energy/driver.compose.json b/drivers/energy/driver.compose.json index 6815867c..27153c15 100644 --- a/drivers/energy/driver.compose.json +++ b/drivers/energy/driver.compose.json @@ -12,6 +12,7 @@ "local" ], "capabilities": [ + "identify", "measure_power", "meter_gas", "meter_water", @@ -213,4 +214,4 @@ "template": "add_devices" } ] -} \ No newline at end of file +} diff --git a/drivers/energy_socket/device.js b/drivers/energy_socket/device.js index f9536b99..b33d8058 100644 --- a/drivers/energy_socket/device.js +++ b/drivers/energy_socket/device.js @@ -23,6 +23,10 @@ module.exports = class HomeWizardEnergySocketDevice extends Homey.Device { await this.onRequest({ power_on: value }); }); + this.registerCapabilityListener('identify', async (value) => { + await this.onIdentify(); + }); + this.registerCapabilityListener('dim', async (value) => { await this.onRequest({ brightness: (255 * value) }); }); @@ -74,6 +78,18 @@ module.exports = class HomeWizardEnergySocketDevice extends Homey.Device { { throw new Error(res.statusText); } } + async onIdentify() { + if (!this.url) return; + + const res = await fetch(`${this.url}/identify`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + }).catch(this.error); + + if (!res.ok) + { throw new Error(res.statusText); } + } + onPoll() { if (!this.url) return; @@ -200,6 +216,10 @@ module.exports = class HomeWizardEnergySocketDevice extends Homey.Device { await this.addCapability('dim').catch(this.error); } + if (!this.hasCapability('identify')) { + await this.addCapability('identify').catch(this.error); + } + if (!this.hasCapability('locked')) { await this.addCapability('locked').catch(this.error); } diff --git a/drivers/energy_socket/driver.compose.json b/drivers/energy_socket/driver.compose.json index a70c231b..584c75e1 100644 --- a/drivers/energy_socket/driver.compose.json +++ b/drivers/energy_socket/driver.compose.json @@ -14,6 +14,7 @@ "capabilities": [ "onoff", "dim", + "identify", "locked", "measure_power", "meter_power", @@ -111,4 +112,4 @@ "template": "add_devices" } ] -} \ No newline at end of file +} diff --git a/drivers/energy_v2/device.js b/drivers/energy_v2/device.js index 33ed2a4b..fd8fe9da 100644 --- a/drivers/energy_v2/device.js +++ b/drivers/energy_v2/device.js @@ -15,6 +15,9 @@ module.exports = class HomeWizardEnergyDeviceV2 extends Homey.Device { this._flowTriggerImport = this.homey.flow.getDeviceTriggerCard('import_changed'); this._flowTriggerExport = this.homey.flow.getDeviceTriggerCard('export_changed'); + this.registerCapabilityListener('identify', async (value) => { + await this.onIdentify(); + }); } flowTriggerTariff(device, tokens) { @@ -55,6 +58,24 @@ module.exports = class HomeWizardEnergyDeviceV2 extends Homey.Device { this.onPoll(); } + async onIdentify() { + if (!this.url) return; + + const token = this.getStoreValue('token'); + + const res = await fetch(`${this.url}/api/system/identify`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + agent: new (require('https').Agent)({ rejectUnauthorized: false }), // Ignore SSL errors + }).catch(this.error); + + if (!res.ok) + { throw new Error(res.statusText); } + } + onPoll() { const httpsAgent = new https.Agent({ @@ -83,6 +104,11 @@ module.exports = class HomeWizardEnergyDeviceV2 extends Homey.Device { const promises = []; // Capture all await promises + // identify + if (!this.hasCapability('identify')) { + await this.addCapability('identify').catch(this.error); + } + // Save export data check if capabilities are present first if (!this.hasCapability('measure_power')) { promises.push(this.addCapability('measure_power').catch(this.error)); diff --git a/drivers/energy_v2/driver.compose.json b/drivers/energy_v2/driver.compose.json index 14704459..6561f9c0 100644 --- a/drivers/energy_v2/driver.compose.json +++ b/drivers/energy_v2/driver.compose.json @@ -12,6 +12,7 @@ "local" ], "capabilities": [ + "identify", "measure_power", "meter_gas", "meter_water", @@ -210,4 +211,4 @@ "template": "add_devices" } ] -} \ No newline at end of file +} diff --git a/drivers/plugin_battery/device.js b/drivers/plugin_battery/device.js index f6d653d6..3ccc8fdf 100644 --- a/drivers/plugin_battery/device.js +++ b/drivers/plugin_battery/device.js @@ -10,6 +10,10 @@ module.exports = class HomeWizardPluginBattery extends Homey.Device { async onInit() { this.onPollInterval = setInterval(this.onPoll.bind(this), POLL_INTERVAL); + + this.registerCapabilityListener('identify', async (value) => { + await this.onIdentify(); + }); } onDeleted() { @@ -38,6 +42,24 @@ module.exports = class HomeWizardPluginBattery extends Homey.Device { this.onPoll(); } + async onIdentify() { + if (!this.url) return; + + const token = this.getStoreValue('token'); + + const res = await fetch(`${this.url}/api/system/identify`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + agent: new (require('https').Agent)({ rejectUnauthorized: false }), // Ignore SSL errors + }).catch(this.error); + + if (!res.ok) + { throw new Error(res.statusText); } + } + onPoll() { const httpsAgent = new https.Agent({ @@ -81,6 +103,11 @@ module.exports = class HomeWizardPluginBattery extends Homey.Device { // Save export data check if capabilities are present first + // identify + if (!this.hasCapability('identify')) { + await this.addCapability('identify').catch(this.error); + } + // energy_import_kwh if (data.energy_import_kwh !== undefined) { if (!this.hasCapability('meter_power.import')) { diff --git a/drivers/plugin_battery/driver.compose.json b/drivers/plugin_battery/driver.compose.json index df1bb5df..424d9f18 100644 --- a/drivers/plugin_battery/driver.compose.json +++ b/drivers/plugin_battery/driver.compose.json @@ -12,6 +12,7 @@ "local" ], "capabilities": [ + "identify", "meter_power.import", "meter_power.export", "measure_battery", @@ -89,4 +90,4 @@ "template": "add_devices" } ] -} \ No newline at end of file +} diff --git a/drivers/watermeter/device.js b/drivers/watermeter/device.js index e2ab31eb..090e5671 100644 --- a/drivers/watermeter/device.js +++ b/drivers/watermeter/device.js @@ -9,6 +9,10 @@ module.exports = class HomeWizardEnergyWatermeterDevice extends Homey.Device { async onInit() { this.onPollInterval = setInterval(this.onPoll.bind(this), POLL_INTERVAL); + + this.registerCapabilityListener('identify', async (value) => { + await this.onIdentify(); + }); } onDeleted() { @@ -37,6 +41,18 @@ module.exports = class HomeWizardEnergyWatermeterDevice extends Homey.Device { this.onPoll(); } + async onIdentify() { + if (!this.url) return; + + const res = await fetch(`${this.url}/identify`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + }).catch(this.error); + + if (!res.ok) + { throw new Error(res.statusText); } + } + onPoll() { if (!this.url) return; @@ -72,6 +88,10 @@ module.exports = class HomeWizardEnergyWatermeterDevice extends Homey.Device { await this.addCapability('meter_water').catch(this.error); } + if (!this.hasCapability('identify')) { + await this.addCapability('identify').catch(this.error); + } + if (!this.hasCapability('rssi')) { await this.addCapability('rssi').catch(this.error); } diff --git a/drivers/watermeter/driver.compose.json b/drivers/watermeter/driver.compose.json index 7693259f..d0d42817 100644 --- a/drivers/watermeter/driver.compose.json +++ b/drivers/watermeter/driver.compose.json @@ -12,6 +12,7 @@ "local" ], "capabilities": [ + "identify", "measure_water", "meter_water", "rssi" @@ -85,4 +86,4 @@ "template": "add_devices" } ] -} \ No newline at end of file +}