-
-
Save torarnv/7f1eb93de4d1abe3910839de628b1d05 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit e08a61503694907f7ece8f40b6b3ac02e5524256 | |
Author: Tor Arne Vestbø <torarnv@gmail.com> | |
Date: Tue Aug 29 22:44:45 2023 +0200 | |
Expose updateCapabilityValue endpoint from ManagerDevices | |
The setCapabilityValue endpoint will end up in the device's | |
_onSetCapabilityValue callback, triggering its capability | |
listeners, which in turn results in sending an external | |
state change to the connected device (via API, RF, etc). | |
In the cases where we are informing Homey about an external | |
state change that has already happened, we want to update | |
Homey's state, run Flows, etc, but not recurse back into | |
the device's _onSetCapabilityValue, as that would send | |
out a redundant external state change, potentially | |
triggering a mode in the external device such as the | |
typical "choose dim level" behavior. | |
This is where updateCapabilityValue is useful. | |
The endpoint has offers the same `value` and | |
`transactionId` arguments as setCapabilityValue | |
(although the latter isn't propagated for either | |
of them), but does not offer `opts`, as that was | |
not handled by any of the existing plumbing for | |
updateCapabilityValue. | |
As the application-side device keeps its own local | |
state for each capability, we need to emit an | |
onDeviceUpdateCapabilityValue message to the driver | |
as well, so that the app is in sync with what Homey | |
knows. | |
Note that during setCapabilityValue, which calls | |
updateCapabilityValue as part of the implementation, | |
the setCapabilityValue callback comes in first, so | |
there is no issue with emitting another callback | |
to the application's driver and devices. | |
The virtual device driver seems to use its own | |
dispatching of driver messages, so an additional | |
entry has been added there too to forward the | |
onDeviceUpdateCapabilityValue to the device, | |
via an onUpdateCapabilityValue callback, but | |
none of the virtual devices seem to keep state | |
that would necessitate overriding this callback. | |
Fixes: athombv/homey-web-api-issues#47 | |
diff --git v10.2.1/dist/lib/Device.js patched/dist/lib/Device.js | |
index 3f4d2c5..fdc9e96 100644 | |
--- v10.2.1/dist/lib/Device.js | |
+++ patched/dist/lib/Device.js | |
@@ -956,6 +956,15 @@ module.exports = class Device extends CRUDItem { | |
originName, | |
originUri, | |
}) { | |
+ // Let the App know | |
+ await this.sendMessageToDriver({ | |
+ event: 'onDeviceUpdateCapabilityValue', | |
+ data: { | |
+ capabilityId, | |
+ value, | |
+ }, | |
+ }); | |
+ | |
// Energy | |
// Calculate Energy Usage | |
if (ENERGY_CAPABILITIES.includes(capabilityId)) { | |
diff --git v10.2.1/dist/lib/Driver.js patched/dist/lib/Driver.js | |
index e68773b..048100d 100644 | |
--- v10.2.1/dist/lib/Driver.js | |
+++ patched/dist/lib/Driver.js | |
@@ -220,6 +220,7 @@ module.exports = class Driver extends CRUDItem { | |
'onDeviceRename', | |
'onDeviceSettings', | |
'onDeviceSetCapabilityValue', | |
+ 'onDeviceUpdateCapabilityValue', | |
'onPairSessionCreate', | |
'onPairSessionEvent', | |
'onPairSessionCallback', | |
diff --git v10.2.1/dist/lib/ManagerDevices.js patched/dist/lib/ManagerDevices.js | |
index 6166e09..2bb1ed7 100644 | |
--- v10.2.1/dist/lib/ManagerDevices.js | |
+++ patched/dist/lib/ManagerDevices.js | |
@@ -116,6 +116,29 @@ module.exports = class ManagerDevices extends Manager { | |
}); | |
}, | |
}, | |
+ updateCapabilityValue: { | |
+ path: '/device/:deviceId/capability/:capabilityId/update', | |
+ method: HTTP_METHODS.PUT, | |
+ scopes: [SCOPES.DEVICE_CONTROL], | |
+ parameters: { | |
+ value: { | |
+ in: 'body', | |
+ required: true, | |
+ type: [String, Number, Boolean], | |
+ }, | |
+ transactionId: { | |
+ in: 'body', | |
+ type: String, | |
+ }, | |
+ }, | |
+ async operation({ $session, ...props }) { | |
+ const origin = HomeyUtil.getOriginObject({ $session }); | |
+ return this.updateCapabilityValue({ | |
+ ...props, | |
+ ...origin, | |
+ }); | |
+ }, | |
+ }, | |
}; | |
static CAPABILITY_HELPERS = Object.keys(HomeyLib.getCapabilities()).reduce( | |
@@ -205,6 +228,30 @@ module.exports = class ManagerDevices extends Manager { | |
}); | |
} | |
+ async updateCapabilityValue({ | |
+ deviceId, | |
+ capabilityId, | |
+ value, | |
+ originUserId, | |
+ originUserName, | |
+ originClientId, | |
+ originClientName, | |
+ originName, | |
+ originUri, | |
+ }) { | |
+ const device = await this.getDevice({ id: deviceId }); | |
+ return device.updateCapabilityValue({ | |
+ capabilityId, | |
+ value, | |
+ originUserId, | |
+ originUserName, | |
+ originClientId, | |
+ originClientName, | |
+ originName, | |
+ originUri, | |
+ }); | |
+ } | |
+ | |
async getCapabilityHelper({ capabilityId }) { | |
return this.constructor.CAPABILITY_HELPERS[capabilityId] || {}; | |
} | |
diff --git v10.2.1/dist/lib/VirtualDevice.js patched/dist/lib/VirtualDevice.js | |
index f1859b6..ba4e8ad 100644 | |
--- v10.2.1/dist/lib/VirtualDevice.js | |
+++ patched/dist/lib/VirtualDevice.js | |
@@ -13,6 +13,10 @@ module.exports = class VirtualDevice extends CRUDItem { | |
// Overload me | |
} | |
+ async onUpdateCapabilityValue({ capabilityId, value }) { | |
+ // Overload me | |
+ } | |
+ | |
async onAdded() { | |
// Overload me | |
} | |
diff --git v10.2.1/dist/lib/VirtualDriver.js patched/dist/lib/VirtualDriver.js | |
index 44c4048..e7fe3f0 100644 | |
--- v10.2.1/dist/lib/VirtualDriver.js | |
+++ patched/dist/lib/VirtualDriver.js | |
@@ -178,6 +178,10 @@ module.exports = class VirtualDriver extends CRUDItem { | |
return virtualDevice.onSetCapabilityValue(data); | |
} | |
+ if (event === 'onDeviceUpdateCapabilityValue') { | |
+ return virtualDevice.onUpdateCapabilityValue(data); | |
+ } | |
+ | |
if (event === 'onFlowCardAutocomplete') { | |
const { onAutocomplete } = | |
this.constructor.MANIFEST.flow[data.type][data.id].args[data.name]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment