From d35d61035410b45f4cec256fc6667360c440892d Mon Sep 17 00:00:00 2001 From: Iain Anderson Date: Mon, 29 Nov 2021 14:50:19 +0000 Subject: [PATCH 1/6] feat: Add ADR for device functions Signed-off-by: Iain Anderson --- docs_src/design/TOC.md | 1 + .../device-service/0020-invoking-functions.md | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 docs_src/design/adr/device-service/0020-invoking-functions.md diff --git a/docs_src/design/TOC.md b/docs_src/design/TOC.md index c9716e68d9..140366bd31 100644 --- a/docs_src/design/TOC.md +++ b/docs_src/design/TOC.md @@ -20,3 +20,4 @@ | [0018 Service Registry](./adr/0018-Service-Registry.md) | Service registry usage for EdgeX services | | [0019 EdgeX-CLI V2](./adr/core/0019-EdgeX-CLI-V2.md) | EdgeX-CLI V2 Implementation | | [0020 Delay start services (SPIFFE/SPIRE)](./adr/security/0020-spiffe.md) | Secret store tokens for delayed start services | +| [0021 Invoking Device Functions](./adr/device-service/0021-invoking-functions.md) | RPC-like actions for devices | diff --git a/docs_src/design/adr/device-service/0020-invoking-functions.md b/docs_src/design/adr/device-service/0020-invoking-functions.md new file mode 100644 index 0000000000..dcc5f4cecf --- /dev/null +++ b/docs_src/design/adr/device-service/0020-invoking-functions.md @@ -0,0 +1,74 @@ +# Invoking Device Functions + + +## Status + +**Draft** + +## Context +This ADR presents a mechanism for invoking functions on a device. + +## Existing Behavior + +Device access in EdgeX is focussed on 'Readings' and 'Settings'. A device may +present values which are readable, representing some measurement or status, +such as a temperature or vibration reading. Also a setting such as a the +required speed of a fan motor may be written to and read back. + +What is not supported directly is 'Functions', where a device may be commanded +to do something. Examples could include perform a self-test, go into standby +mode for an hour, invalidate an access key. + +While such operations may modelled using virtual resources in a device profile, +this is unintuitive. + +## Decision + +1. Add a new section to device profiles describing functions + +{ + "deviceFunctions": + [ + { + "name": "Name by which the function is accessed", + "description": "Readable description of the function", + "attributes": { device-specific parameters which select this function }, + "parameters": + { + "in": + [ + { + "name": "Parameter name", + "description": "description of what the parameter controls", + "type": "Any of the usual EdgeX data types" + } + ], + "out": + [ + { + "name": "Parameter name", + "description": "description of what the parameter controls", + "type": "Any of the usual EdgeX data types" + } + ] + } + } + ] +} + +2. Add a REST endpoint to the device service for performing functions + +api/v2/device-funtion// + +This shold accept POST requests with parameters sent in a JSON (or CBOR) payload + +A successful invocation should return HTTP 200 with the out parameters in JSON +or CBOR format. + +Returnable errors should be +BAD REQUEST: parameters were missing or wrong type +INTERNAL SERVER ERROR: the DS implementation was unable to fulfill the request +NOT FOUND: no such device, or no such function +LOCKED: device or service is locked or down (adminstate, operating state) + +3. Add a REST endpoint to core-command for performing functions From 2fc4be16e33383afc7848d2fcfe9c8f16fece7ed Mon Sep 17 00:00:00 2001 From: Iain Anderson Date: Mon, 6 Dec 2021 14:59:45 +0000 Subject: [PATCH 2/6] feat: Device functions ADR Formatting fixes and language clarification Add parameter range limits and defaults Signed-off-by: Iain Anderson --- .../device-service/0020-invoking-functions.md | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/docs_src/design/adr/device-service/0020-invoking-functions.md b/docs_src/design/adr/device-service/0020-invoking-functions.md index dcc5f4cecf..8a46d19212 100644 --- a/docs_src/design/adr/device-service/0020-invoking-functions.md +++ b/docs_src/design/adr/device-service/0020-invoking-functions.md @@ -24,30 +24,34 @@ this is unintuitive. ## Decision -1. Add a new section to device profiles describing functions +**Add a new section to device profiles describing functions** +``` { "deviceFunctions": [ { "name": "Name by which the function is accessed", "description": "Readable description of the function", - "attributes": { device-specific parameters which select this function }, + "attributes": { device-service-specific attributes which select this function }, "parameters": { "in": [ { "name": "Parameter name", - "description": "description of what the parameter controls", - "type": "Any of the usual EdgeX data types" + "description": "(optional) description of what the parameter controls", + "type": "Any of the usual EdgeX data types", + "defaultValue": "(optional) value to use if param is not supplied", + "maximum": "(optional) for numerics, maximum allowed value", + "minimum": "(optional) for numerics, minimum allowed value" } ], "out": [ { - "name": "Parameter name", - "description": "description of what the parameter controls", + "name": "Name of returned value", + "description": "(optional) description of what the value indicates", "type": "Any of the usual EdgeX data types" } ] @@ -55,20 +59,24 @@ this is unintuitive. } ] } +``` -2. Add a REST endpoint to the device service for performing functions +Note: the `attributes` structure is analagous to `attributes` in a `deviceResource`. Each device service should document and implement a scheme of required attributes that will allow for selection of the relevant funtion. The function's `name` is intended for UI and logging purposes and should not be used for actual function selection on the device. -api/v2/device-funtion// +**Add a REST endpoint to the device service for performing functions** + +`api/v2/device-funtion//` This shold accept POST requests with parameters sent in a JSON (or CBOR) payload -A successful invocation should return HTTP 200 with the out parameters in JSON +A successful invocation should return HTTP 200 with the out values in JSON or CBOR format. Returnable errors should be -BAD REQUEST: parameters were missing or wrong type -INTERNAL SERVER ERROR: the DS implementation was unable to fulfill the request -NOT FOUND: no such device, or no such function -LOCKED: device or service is locked or down (adminstate, operating state) -3. Add a REST endpoint to core-command for performing functions +* BAD REQUEST: parameters were missing, wrong type, or out-of-range +* INTERNAL SERVER ERROR: the DS implementation was unable to fulfill the request +* NOT FOUND: no such device, or no such function +* LOCKED: device or service is locked or down (adminstate, operating state) + +**Add a REST endpoint to core-command for performing functions** From 639fb931e1ee552583c9897a64f2fe594b495c7a Mon Sep 17 00:00:00 2001 From: Iain Anderson Date: Tue, 7 Dec 2021 14:41:40 +0000 Subject: [PATCH 3/6] feat: Device functions ADR Specify asynchronous operation via MessageBus rather than synchronous REST Signed-off-by: Iain Anderson --- .../device-service/0020-invoking-functions.md | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/docs_src/design/adr/device-service/0020-invoking-functions.md b/docs_src/design/adr/device-service/0020-invoking-functions.md index 8a46d19212..79594e1e41 100644 --- a/docs_src/design/adr/device-service/0020-invoking-functions.md +++ b/docs_src/design/adr/device-service/0020-invoking-functions.md @@ -63,20 +63,43 @@ this is unintuitive. Note: the `attributes` structure is analagous to `attributes` in a `deviceResource`. Each device service should document and implement a scheme of required attributes that will allow for selection of the relevant funtion. The function's `name` is intended for UI and logging purposes and should not be used for actual function selection on the device. -**Add a REST endpoint to the device service for performing functions** +**Define MessageBus topics on which function call requests and replies are to be made** -`api/v2/device-funtion//` +`edgex/function-calls/device/[profile-name]/[device-name]/[function-name]` -This shold accept POST requests with parameters sent in a JSON (or CBOR) payload +The payload for messages on these topics should be of the form +``` +{ + requestId: "184b894f-a7b7-4d6c-b400-99961d462419", + parameters: { (a map of parameter values keyed by parameter name) } +} +``` + +The `requestId` may be any string but UUIDs are recommended. -A successful invocation should return HTTP 200 with the out values in JSON -or CBOR format. +`edgex/function-responses/device/[profile-name]/[device-name]/[function-name]` + +The device service will provide responses to function calls on this topic. The payload will be + +``` +{ + requestId: "184b894f-a7b7-4d6c-b400-99961d462419", + status: 0, + returnValues: { (a map of return values keyed by value name) } +} +``` + +or if a call fails + +``` +{ + requestId: "184b894f-a7b7-4d6c-b400-99961d462419", + status: (nonzero), + errorMessage "Message indicating the nature of the failure" +} +``` -Returnable errors should be +TODO: define status codes for common errors eg not found, locked etc -* BAD REQUEST: parameters were missing, wrong type, or out-of-range -* INTERNAL SERVER ERROR: the DS implementation was unable to fulfill the request -* NOT FOUND: no such device, or no such function -* LOCKED: device or service is locked or down (adminstate, operating state) +** The device SDKs will provide an API for the service implementations to implement these operations ** -**Add a REST endpoint to core-command for performing functions** From c5266fd752888ed3411ca5bc96804bb97228eb81 Mon Sep 17 00:00:00 2001 From: Iain Anderson Date: Wed, 15 Dec 2021 15:12:38 +0000 Subject: [PATCH 4/6] feat: Device functions ADR Clarify parameter specification, add error table, move ADR to no. 0021 Signed-off-by: Iain Anderson --- ...unctions.md => 0021-invoking-functions.md} | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) rename docs_src/design/adr/device-service/{0020-invoking-functions.md => 0021-invoking-functions.md} (71%) diff --git a/docs_src/design/adr/device-service/0020-invoking-functions.md b/docs_src/design/adr/device-service/0021-invoking-functions.md similarity index 71% rename from docs_src/design/adr/device-service/0020-invoking-functions.md rename to docs_src/design/adr/device-service/0021-invoking-functions.md index 79594e1e41..7e68879f4d 100644 --- a/docs_src/design/adr/device-service/0020-invoking-functions.md +++ b/docs_src/design/adr/device-service/0021-invoking-functions.md @@ -35,27 +35,24 @@ this is unintuitive. "description": "Readable description of the function", "attributes": { device-service-specific attributes which select this function }, "parameters": - { - "in": - [ - { - "name": "Parameter name", - "description": "(optional) description of what the parameter controls", - "type": "Any of the usual EdgeX data types", - "defaultValue": "(optional) value to use if param is not supplied", - "maximum": "(optional) for numerics, maximum allowed value", - "minimum": "(optional) for numerics, minimum allowed value" - } - ], - "out": - [ - { - "name": "Name of returned value", - "description": "(optional) description of what the value indicates", - "type": "Any of the usual EdgeX data types" - } - ] - } + [ + { + "name": "Parameter name", + "description": "(optional) description of what the parameter controls", + "type": "Any of the usual EdgeX data types", + "defaultValue": "(optional) value to use if param is not supplied", + "maximum": "(optional) for numerics, maximum allowed value", + "minimum": "(optional) for numerics, minimum allowed value" + } + ], + "returnValues": + [ + { + "name": "Name of returned value", + "description": "(optional) description of what the value indicates", + "type": "Any of the usual EdgeX data types" + } + ] } ] } @@ -99,7 +96,15 @@ or if a call fails } ``` -TODO: define status codes for common errors eg not found, locked etc +*Returned status codes* + +| Status | Meaning +|--------|-------- +| 0 | The operation was successful +| 1 | Parameters were missing, out of range or non-parsable +| 2 | The Device is DOWN or DISABLED +| 3 | No such device or function +| 100+ | Implementation-specific errors, defined for each Device Service ** The device SDKs will provide an API for the service implementations to implement these operations ** From 0d6d03bf8fd4c8ba72b5f0e0437ecc097d91b465 Mon Sep 17 00:00:00 2001 From: Iain Anderson Date: Mon, 20 Dec 2021 14:55:47 +0000 Subject: [PATCH 5/6] feat: Device functions ADR Remove contradictory text on function names, add SDK responsibilities Signed-off-by: Iain Anderson --- .../design/adr/device-service/0021-invoking-functions.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs_src/design/adr/device-service/0021-invoking-functions.md b/docs_src/design/adr/device-service/0021-invoking-functions.md index 7e68879f4d..9b1b2b0287 100644 --- a/docs_src/design/adr/device-service/0021-invoking-functions.md +++ b/docs_src/design/adr/device-service/0021-invoking-functions.md @@ -58,7 +58,7 @@ this is unintuitive. } ``` -Note: the `attributes` structure is analagous to `attributes` in a `deviceResource`. Each device service should document and implement a scheme of required attributes that will allow for selection of the relevant funtion. The function's `name` is intended for UI and logging purposes and should not be used for actual function selection on the device. +Note: the `attributes` structure is analagous to `attributes` in a `deviceResource`. Each device service should document and implement a scheme of required attributes that will allow for selection of the relevant funtion. **Define MessageBus topics on which function call requests and replies are to be made** @@ -102,9 +102,11 @@ or if a call fails |--------|-------- | 0 | The operation was successful | 1 | Parameters were missing, out of range or non-parsable -| 2 | The Device is DOWN or DISABLED +| 2 | The Device is DOWN or DISABLED (OperatingState / AdminState) | 3 | No such device or function | 100+ | Implementation-specific errors, defined for each Device Service -** The device SDKs will provide an API for the service implementations to implement these operations ** +** Device SDK enhancement ** + +The device SDKs will handle the messagebus communcations and parameter marshalling. The generic errors defined above may be detected in this SDK code. The SDKs will define APIs for the individual device services to implement the function invocations. From 8f0ee4b5667a257daee0d4675279a1e2309ebe17 Mon Sep 17 00:00:00 2001 From: Iain Anderson Date: Mon, 17 Jan 2022 12:10:15 +0000 Subject: [PATCH 6/6] feat: Device functions ADR Align with north-south messaging ADR (#23) Signed-off-by: Iain Anderson --- .../device-service/0021-invoking-functions.md | 66 +++++++++++++------ 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/docs_src/design/adr/device-service/0021-invoking-functions.md b/docs_src/design/adr/device-service/0021-invoking-functions.md index 9b1b2b0287..8b8700b8c6 100644 --- a/docs_src/design/adr/device-service/0021-invoking-functions.md +++ b/docs_src/design/adr/device-service/0021-invoking-functions.md @@ -39,7 +39,7 @@ this is unintuitive. { "name": "Parameter name", "description": "(optional) description of what the parameter controls", - "type": "Any of the usual EdgeX data types", + "type": "Any of the existing EdgeX data types", "defaultValue": "(optional) value to use if param is not supplied", "maximum": "(optional) for numerics, maximum allowed value", "minimum": "(optional) for numerics, minimum allowed value" @@ -50,7 +50,7 @@ this is unintuitive. { "name": "Name of returned value", "description": "(optional) description of what the value indicates", - "type": "Any of the usual EdgeX data types" + "type": "Any of the existing EdgeX data types" } ] } @@ -58,31 +58,43 @@ this is unintuitive. } ``` -Note: the `attributes` structure is analagous to `attributes` in a `deviceResource`. Each device service should document and implement a scheme of required attributes that will allow for selection of the relevant funtion. +Note: the `attributes` structure is analagous to `attributes` in a `deviceResource`. Each device service should document and implement a scheme of required attributes that will allow for selection of the relevant function. **Define MessageBus topics on which function call requests and replies are to be made** -`edgex/function-calls/device/[profile-name]/[device-name]/[function-name]` +These follow the style of messagebus usage set out in the North-South messaging ADR. + +`edgex/request/function/[device-service-name]/[device-name]` The payload for messages on these topics should be of the form ``` { - requestId: "184b894f-a7b7-4d6c-b400-99961d462419", - parameters: { (a map of parameter values keyed by parameter name) } + "correlation-id": "1dbbd344-c9f6-4714-8c89-91c1d5b11a90", + "deviceName": "device1", + "function": "functionname", + "request": + { + "requestId": "184b894f-a7b7-4d6c-b400-99961d462419", + "parameter1": "37", + "parameter2": "0" + } } -``` -The `requestId` may be any string but UUIDs are recommended. +``` -`edgex/function-responses/device/[profile-name]/[device-name]/[function-name]` +`edgex/response/function/[device-service-name]/[device-name]` The device service will provide responses to function calls on this topic. The payload will be ``` { - requestId: "184b894f-a7b7-4d6c-b400-99961d462419", - status: 0, - returnValues: { (a map of return values keyed by value name) } + "correlation-id": "1dbbd344-c9f6-4714-8c89-91c1d5b11a90", + "response": + { + "requestId": "184b894f-a7b7-4d6c-b400-99961d462419", + "statusCode": 0, + "returnVal1": "true" + } } ``` @@ -90,9 +102,13 @@ or if a call fails ``` { - requestId: "184b894f-a7b7-4d6c-b400-99961d462419", - status: (nonzero), - errorMessage "Message indicating the nature of the failure" + "correlation-id": "1dbbd344-c9f6-4714-8c89-91c1d5b11a90", + "response": + { + "requestId": "184b894f-a7b7-4d6c-b400-99961d462419", + "statusCode": (nonzero), + "message": "Message indicating the nature of the failure" + } } ``` @@ -101,12 +117,24 @@ or if a call fails | Status | Meaning |--------|-------- | 0 | The operation was successful -| 1 | Parameters were missing, out of range or non-parsable -| 2 | The Device is DOWN or DISABLED (OperatingState / AdminState) -| 3 | No such device or function +| 1 | Request message format error +| 2 | Parameters were missing, out of range or non-parsable +| 3 | The Device is DOWN or DISABLED (OperatingState / AdminState) +| 4 | No such device or function | 100+ | Implementation-specific errors, defined for each Device Service -** Device SDK enhancement ** +*Configuration* + +The topic prefixes `edgex/request/function` and `edgex/response/function` will be configurable in the device services. + +**Device SDK enhancement** The device SDKs will handle the messagebus communcations and parameter marshalling. The generic errors defined above may be detected in this SDK code. The SDKs will define APIs for the individual device services to implement the function invocations. +**Command service enhancement** + +The core-command service to be extended to provide access to device functions as it does for device readings and settings. + +## References + +* [ADR 0023-North-South-Messaging](https://github.com/edgexfoundry/edgex-docs/blob/master/docs_src/design/adr/0023-North-South-Messaging.md)