-
Notifications
You must be signed in to change notification settings - Fork 65
Add a proposal for manageable affordances and data mapping #2162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://github.com/w3c/wot-thing-description/blob/main/planning/work-items/analysis/analysis-manageable-affordances.md does not contain any requirements and are not extended here. Also, the analysis content should be copied here (see https://github.com/w3c/wot-thing-description/tree/main/proposals/common-definitions).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be an analysis for data mapping first. The solved solution is not formally defined yet.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The proposal should explain how it addresses the concrete use cases in the analysis document. Currently, the examples in this document are still theoritical. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,243 @@ | ||
| # Proposal: Mapping data and managing complex interactions in WoT Thing Descriptions | ||
|
|
||
| The Web of Things (WoT) Thing Description (TD) provides an abstract model for describing a Thing's functionalities through its three traditional interaction affordances: Properties, Actions, and Events. This model excels at describing simple, atomic, and one-off interactions. However, complex systems — particularly those found in industrial automation, enterprise integration, and service orchestration — rely on interaction patterns that go beyond a simple request/response. These scenarios present two critical, unresolved challenges for the TD: | ||
|
|
||
| - Protocol Binding Complexity: The logical information (like state data or action input/output) must be mapped to the specific channels of various protocols (e.g., HTTP Headers, URI path variables, or specific binary payload formats like Modbus). Current TD mechanisms lack the necessary vocabulary to explicitly describe how abstract DataSchema elements are mapped to these diverse, channel-specific message components. | ||
| - Interaction Management Complexity: Traditional affordances struggle when interactions require ongoing oversight. These scenarios often transition from simple request/response into a more complex state machine or "application protocol." | ||
|
|
||
| While the WoT TD 1.1 introduced the concept of Manageable Actions via the `invokeaction`, `queryaction`, and `cancelaction` operations, the current model lacks the structure to support the full complexity of these long-running processes. Specifically, this gap includes the following: | ||
|
|
||
| - Runtime Data Handling: No support for managing dynamically generated identification (e.g., transaction or job IDs) across multiple protocol transactions. | ||
| - Queuing and Concurrency: Inability to describe and expose queues of actions. | ||
| - Multi-Affordance Dependencies: Missing mechanisms to describe complex alarms or state dependencies that involve the correlation of multiple affordances (a crucial feature in protocols like BACnet). | ||
|
|
||
| This proposed solution decided deliberately to connect two otherwise separate work items ([(Manageable Affordances](https://github.com/w3c/wot-thing-description/blob/main/planning/work-items/analysis/analysis-manageable-affordances.md) and ([Data Mapping](https://github.com/w3c/wot-thing-description/blob/main/planning/work-items/analysis/analysis-data-mapping.md))) to fill a logical common gap: mapping client side runtime state. In practice, the solution introduces two new concepts to the TD information model: | ||
|
|
||
| Variables (Runtime Data Holders): A mechanism to define reusable, structured **client-side** runtime data. | ||
|
|
||
| Capabilities / Clusters / Or? (Context and Management): A new top-level container that defines a stateful runtime context. It groups related affordances and, with a client state, establishes an explicit relationships between interactions (or group). | ||
|
|
||
| By establishing these two mechanisms, the TD can effectively model a very simple state machine and explicitly link different part of low level messages to the application layer. | ||
|
|
||
| --- | ||
|
|
||
| ## 2. Scope & Goals | ||
|
|
||
| - Fix the identified limitations in the WoT TD for complex interaction patterns. | ||
| - Define a simple yet powerful mechanism to cover most of the analyzed user stories and **implementations**. | ||
|
|
||
| --- | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3 is missing |
||
| ## 4. Proposed Core Mechanisms | ||
|
|
||
| This section defines the two new, orthogonal concepts. | ||
|
|
||
| ### 4.1 Concept A: Variables (Client side Runtime Data Modeling) | ||
|
|
||
| In the current TD model, we focused on describing interaction patterns between a client and a Thing. However, complex interactions often require the client to manipulate and manage the data exchanged with the remote Thing. To address this, we introduce the concept of **Variables**. | ||
|
|
||
| - **Definition:** **Variables** are internal, logical data structures defined within the TD scope to hold **runtime data** essential for complex interactions. They are _not_ automatically network-exposed Properties. | ||
| - **Role:** Serve as a clean way to describe the **mapping of runtime data** in an otherwise static document. | ||
| - **Declaration Mechanism:** A variable can be declared in any JSON schema that is used in the TD (e.g., as part of an Action input or output schema). Variables are identified by a unique name. | ||
| - **Usage:** A variable can be referenced in children elements of Affordances (e.g., in `forms` or `href` templates) using a defined syntax (e.g., `${variableName}`). When referenced, the client MUST create a two-way binding between the variable and the corresponding message component. | ||
|
|
||
| Example supporting [Data Mapping in HTTP](https://github.com/w3c/wot-thing-description/blob/main/planning/work-items/analysis/analysis-data-mapping.md#user-stories): | ||
|
|
||
| ```json | ||
| { | ||
| "actions": { | ||
| "startJob": { | ||
| "input": { | ||
| "type": "object", | ||
| "properties": { | ||
| "jobType": { "type": "string", "variable": "jobType" }, | ||
| "priority": { "type": "integer" } | ||
| } | ||
| }, | ||
| "forms": [ | ||
| { | ||
| "href": "http://example.com/jobs", | ||
| "htv:methodName": "POST", | ||
| "http:headers": { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is wrong usage of the http vocabulary. See https://w3c.github.io/wot-binding-templates/bindings/protocols/http/#binding-http-usage-1 I like this one more, but currently it is not how it should be modeled. |
||
| "X-Job-Type": "${jobType}" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the syntax should be defined here. Is this JSONata? |
||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| In the example above, the `jobType` property in the Action input schema is marked as a Variable. When the client invokes the `startJob` action, it will bind the value of `jobType` to the `X-Job-Type` HTTP header in the request and the real payload sent to the server will not contain the `jobType` field. | ||
|
|
||
| ```json | ||
| { | ||
| "priority": 5 | ||
| } | ||
| ``` | ||
|
Comment on lines
+73
to
+77
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't get this |
||
|
|
||
| If we want to support mapping low-level message parts, we can first map the low-level payload to our TD data model with a new keyword (e.g., `messageSchema`), and then use Variables to bind the runtime data to the low-level message parts. | ||
|
|
||
| Example: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would use the examples from ECHONET or WebThing here. |
||
|
|
||
| ```json | ||
| { | ||
| "property": { | ||
| "propX": { | ||
| "type": "number", | ||
| "variable": "propXValue", | ||
| "forms": [ | ||
| { | ||
| "href": "http://example.com/propX", | ||
| "messageSchema": { | ||
| "type": "object", | ||
| "properties": { | ||
| // User may choose to fully specify the payload schema or just the part they want to map | ||
| "value": { "type": "number", "variable": "propXValue" } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. using the variable here again feels weird. One is definition, one is usage so I think they should have different words. |
||
| } | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| The above example shows how to map a Property value to a low-level message payload using Variables. The `propXValue` variable is used to bind the Property value to the `value` field in the message payload (this works for both read and write operations). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the variable should be better argumented as in this example, there is no need for the variable keyword. Is the idea going towards something like having an object at the data schema where two keys are two variables and they are assigned to different parts of the message, i.e. one going to header and one to the body? Maybe this specific example can be used for a default variable name? I.e., if you don't specify the variable name, the data schema is used at form location (see comment on variable in the form). Can this be used to handle #1936 ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, it would be nice to show how this would work for showing different payloads for write and read. Read returns an object with value but writing only requires the affordance data schema. |
||
|
|
||
| #### Limitations & Future Work | ||
|
|
||
| - Dealing with mixed content-types (e.g., `PUT` body image + headers + query parameters) -> We actually still lack a way to model inputs/outputs that are files or other non-JSON data. Indeed, affordances that requires un-mapped content-types are encouraged to leave the "schema" part empty or use undefined. Future work may introduce a more formal way to model such cases. | ||
| - Complex data transformations -> Current proposal only supports direct 1:1 mapping between Variables and message components. Future work may introduce transformation functions or mapping expressions to support more complex scenarios. | ||
| - Protocol bindings may in the future introduce more advanced mapping mechanisms and decide a serialization format of structured variables (e.g., HTTP may declare that if a variable is type object and used in a query string, it can be serialized by restructuring the properties in X=Y query parameters). | ||
|
|
||
| #### Worth mention | ||
|
|
||
| We could also reconsider the use of JSON pointers for variable assignment instead of defining variables in the schema. This would not change the overall benefit. However, it would imply a dependency on other specification(s). The mechanism proposed here is self-contained and does not require external references (even if it is more simple). The implications of the feature proposed here are mostly on the client side implementation (i.e., the client must be able to manage runtime variables and bind them to message components) and profile-aware clients may just ignore the variable mechanism as it would probably be described by constraints in the protocol binding itself. | ||
|
|
||
| ### 4.2 Concept B: Capabilities / Clusters (Context and Management) | ||
|
|
||
| Building on the Variables mechanism, we introduce a new top-level structural element called **Capability** (or Cluster or some better name) to encapsulate related Affordances and Variables. This construct provides a runtime context for managing complex interactions that require stateful management. | ||
|
|
||
| - **Definition:** A **Capability** is a new top-level structural element that serves as a **runtime context** for a complex function. It groups a set of related Affordances and Variables. | ||
| - **Role:** Establish **scoping**, and define **relationships** between interactions. | ||
|
|
||
| --- | ||
|
|
||
| The idea is that a Capability can define the following: | ||
|
|
||
| - **State (set of Variables):** Define runtime client data structure shared by all affordances listed in it (e.g., `activeJobQueue`). | ||
| - **Subaffordances:** Group related Actions, Properties, and Events that operate within the same context. | ||
| - **Model**: Without needing to define all the affordances from scratch every time, we can define a set of common Thing Models (e.g., AsyncActionThingModel). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While it is good to use what we already have (TMs), we are starting to load too much into what a TM can be. It is already used in two rather different ways:
Now we would add another concept into the same word and people would be more lost about what to do with a TM they get.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I'm right in saying that currently a Consumer is never expected to fetch a Thing Model when it is referenced in a Thing Description, when a Thing Model is linked from a Thing Description it just indicates that the Thing Description is an instance of that model - the Thing Description still has to contain the full content of the Thing Model plus any instance-specific metadata. I think that's a good thing since it simplifies Consumer implementation. This would therefore be quite a big change because a Consumer now has to follow links in a Thing Description and fetch other resources in order to construct a complete Thing Description. |
||
|
|
||
| Example: | ||
|
|
||
| ```json | ||
| { | ||
| "capabilities": { | ||
| "PrintJobManager": { | ||
| "state": { | ||
| "type": "string", | ||
| "variable": "jobId" | ||
| }, | ||
| "properties": { | ||
| "activeJobQueue": { | ||
| "type": "array", | ||
| "items": { "type": "string" }, | ||
| "forms": [ | ||
| { | ||
| "href": "http://example.com/printjobs/queue", | ||
| "htv:methodName": "GET" | ||
| } | ||
| ] | ||
| } | ||
| }, | ||
| "actions": { | ||
| "submitPrintJob": { | ||
| "input": { | ||
| "type": "object", | ||
| "properties": { | ||
| "document": { "type": "string", "format": "uri" }, | ||
| "copies": { "type": "integer", "default": 1 } | ||
| } | ||
| }, | ||
| "output": { | ||
| "type": "string", | ||
| "variable": "jobId" | ||
| }, | ||
| "forms": [ | ||
| { | ||
| "href": "http://example.com/printjobs", | ||
| "htv:methodName": "POST" | ||
| } | ||
| ] | ||
| }, | ||
| "cancelPrintJob": { | ||
| "input": { | ||
| "type": "string", | ||
| "variable": "jobId" | ||
| }, | ||
| "forms": [ | ||
| { | ||
| "href": "http://example.com/printjobs/${jobId}", | ||
| "htv:methodName": "DELETE" | ||
| } | ||
| ] | ||
| } | ||
| }, | ||
| "events": { | ||
| "jobCompleted": { | ||
| "data": { | ||
| "type": "string", | ||
| "variable": "jobId" | ||
| }, | ||
| "forms": [ | ||
| { | ||
| "href": "http://example.com/printjobs/events" | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| We can simplify by defining a common Thing Model for such Capabilities (e.g., `PrintJobManagerThingModel`) that pre-defines the common affordances and state variables. The TD can then just reference this model and only define any customizations needed. | ||
| Example: | ||
|
|
||
| ```json | ||
| { | ||
| "capabilities": { | ||
| "PrintJobManager": { | ||
| "model": "http://example.com/PrintJobManagerThingModel" | ||
| // Customizations or overrides can be defined here if needed | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| #### Limitations & Future Work | ||
|
|
||
| - Naming and Terminology: The term "Capability" may conflict with existing IoT frameworks. Future work may explore alternative names like "Cluster" or "Module" or "Group" "RuntimeContext". | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It already conflicts with our terminology where we use capability together with affordance. Searching for "capabilit" in https://www.w3.org/TR/wot-architecture11 results in this. Not very happy with the current state but probably it is in people's minds already. |
||
| - Advanced Relationships: While this proposal introduces basic grouping and state management, future work may explore more advanced relationships between Capabilities (e.g., dependencies, hierarchies). | ||
| - Global operations still need to be defined outside capabilities (e.g., Thing level actions, see next sections). | ||
| - It is just one level of grouping. Future work may explore nested Capabilities or hierarchical structures although this may add complexity. | ||
|
|
||
| --- | ||
|
|
||
| #### A word about global operations (`queryall`, `readall`, `cancelall`, `readmultiple`, etc.) | ||
|
|
||
| Some of the user stories and implementations analyzed require global operations that span multiple affordances (e.g., `readall` properties, `cancelall` actions). These operations are orthogonal to the Capability concept and can be defined at the Thing level. In the past, we have pinpointed the criticalities of defining such global operations as new `op` values as they lack a proper way to describe their content type and schema. If we introduce this new concept, I don't see any issue in defining such global operations at the Thing level using the existing Action/Property/Event affordance structure. We can then still reuse regular mechanisms (e.g., input/output schemas, forms, etc.) to describe these global operations and their "multiple" counterparts is now straightforward to define. The only problem is that we may need to define new standard Thing Models for such global operations (e.g., `ReadAllPropertiesThingModel`, `CancelAllActionsThingModel`, etc.) to ensure consistency across different TDs. | ||
|
|
||
| ## 5. New Vocabulary & Schema (Summary) | ||
|
|
||
| This section provides a summary of the newly introduced terms for the proposed concepts. | ||
|
|
||
| | New Field | Location | Data Type | Description | | ||
| | :-------------- | :------------------ | :------------------ | :------------------------------------------------------------------------ | | ||
| | `variable` | Inside DataSchema | String | Marks a property as a Variable with the given name. | | ||
| | `capabilities` | Top-level map in TD | Map of Capabilities | Contains all defined Capabilities/Clusters. | | ||
| | `state` | Inside a Capability | DataSchema | Defines the client-side runtime data structures (e.g., `activeJobQueue`). | | ||
| | `model` | Inside a Capability | String (URI) | References a predefined Thing Model for the Capability. | | ||
| | `messageSchema` | Inside `form` | DataSchema | Defines the low-level message structure for mapping. | | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the file name has a typo manegiable should be manageable