Skip to content
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

API improvement: track TD (interactions) #96

Closed
zolkis opened this issue Feb 22, 2018 · 11 comments
Closed

API improvement: track TD (interactions) #96

zolkis opened this issue Feb 22, 2018 · 11 comments

Comments

@zolkis
Copy link
Contributor

zolkis commented Feb 22, 2018

This comment will be updated with the TD spec, which exposes the following structure for a Thing (translated to "raw" WebIDL):

interface Thing {
  readonly attribute DOMString name;
  readonly attribute USVString baseURL;
  readonly attribute sequence<DOMString> @context;
  readonly attribute sequence<DOMString> @type;
  readonly attribute sequence<Dictionary> security;  // not defined yet
  readonly attribute sequence<Interaction> interaction;
};

interface Interaction {
  readonly attribute DOMString name;
  readonly attribute sequence<Form> endpoint;  // interaction endpoint
  readonly attribute sequence<DOMString> @type;
};

interface Property: Interaction {
  readonly attribute DataSchema schema;
  readonly attribute boolean writable;
  readonly attribute boolean observable;
};

interface Action: Interaction {
  readonly attribute DataSchema inputSchema;
  readonly attribute DataSchema outputSchema;
};

interface Event: Interaction {
  readonly attribute DataSchema schema;
};

typedef JSON DataSchema;

dictionary Form {
  required USVString href;
  USVString mediaType;
  DOMString rel;
};

This issue serves as discussion for a scripting API that best represents this structure, including introspection.

@zolkis
Copy link
Contributor Author

zolkis commented Feb 22, 2018

Following recent discussions, looks like the best way to represent Thing interactions is using (interface) objects for Property, Action and Event. A Thing could be represented the following way in the Scripting API.

interface ConsumedThing {
  readonly attribute DOMString name;
  readonly attribute USVString baseURL;
  getter sequence<DOMString> ("@context");
  getter sequence<DOMString> ("@type");
  readonly attribute sequence<Dictionary> security;  // not defined yet
  readonly attribute maplike<DOMString, Property> properties;
  readonly attribute maplike<DOMString, Actions> actions;
  readonly attribute maplike<DOMString, Event> events;
};

[NoInterfaceObject]
interface Interaction {  // abstract class
  readonly attribute DOMString name;
  readonly attribute sequence<WebLink> links;  // interaction endpoint
  getter sequence<DOMString> ("@type");
};

interface ThingProperty: Interaction {
  readonly attribute DataSchema schema;
  readonly attribute boolean writable;
  readonly attribute boolean observable;
  Promise<any> get();
  Promise set(any value);
  Observable<any> observe();  // may allow options later
};

interface ThingAction: Interaction {
  readonly attribute DataSchema inputSchema;
  readonly attribute DataSchema outputSchema;
  Promise<any> run(any parameters);
};

interface ThingEvent: Interaction {
  readonly attribute DataSchema schema;
  readonly any data;
};

ThingEvent implements Observable;

typedef JSON DataSchema;

dictionary WebLink {
  required USVString href;
  USVString mediaType;
  DOMString relationType;
  DOMString anchor;
};

The interface for ExposedThing will be addressed later, but would not change much except for adapting to the changes above.

@zolkis
Copy link
Contributor Author

zolkis commented Feb 22, 2018

@danielpeintner @knimura @mkovatsc any opinions?
(This is for discussions on the next F2F).

Some explanation on maplike. These are name-object pairs in our case (e.g. a dictionary), so we could say

let t = await thing.properties["temperature"].get();

or

await thing.properties.temperature.set(25);

For Events, one could say

let subscription = thing.events["temperaturechange"]
                               .subscribe( t => { console.log("T = " + t); });

@zolkis zolkis changed the title API improvement: exposing interactions API improvement: track TD (interactions) Feb 23, 2018
@mkovatsc
Copy link
Contributor

The direction looks good to me! (I wrote similar goal examples in w3c/wot-thing-description#87 (comment) except that I played with read(), write(), invoke(), subscribe() instead of get(), set(), ...)

I have to look deeper into maplike and what you mean by it. For now I prefer the dot notation style (i.e., also have let subscription = thing.events.temperaturechange.subscribe( ... );. So it might be good to restrict the format of names to valid identifiers for this. It would also hide the semantic annotations in the "simple access mode" (as it feels as if that was desired by programmers...).

@zolkis
Copy link
Contributor Author

zolkis commented Feb 23, 2018

Actually I made a change to use read() and write(), but with the examples above get() and set() had more meaning (e.g. we set temperature, and not write it).

maplike just makes it possible to refer to an object with a name, like it was a dictionary member, for instance your example above:
let subscription = thing.events.temperaturechange.subscribe( ... );
which is the same as
let subscription = thing.events["temperaturechange"].subscribe( ... );

About hiding semantic annotations (mostly @type), and properly dealing with DataSchema, I am all ears :).

@mkovatsc
Copy link
Contributor

Yes, when looking at this now, get and set look fine.

If only we could quickly find why we changed from get/set to read/write back then... could avoid going in circles :)

maplike

Okay, so just what one would expect for JavaScript. The @ prefix would nicely omit semantic annotations in autocomplete when using the dot notation, but they are still accessible..

@danielpeintner
Copy link
Contributor

So from what I understood we can compare

thing.properties["temperature"].get();

with what we used to have so far

thing.readProperty("temperature");

This is a nice and easy mapping. I assume some more features such as thing.properties reporting a list of possible properties et cetera (for interspection later on). Does that work with maplike?

What I am not fully sure of is wether this API improvement is meant to be something additional (more or less syntactic sugar) or whether the old API is meant to fully disappear. I assume one API is better than many.

Moreover, I wonder how would the ExposedThing interface look like?
thing.properties.add({name: "newTemperate", ...})
Again, does that work with maplike?

Note: I also think we need to agree on in the group what languages we plan to support with the Scripting API. We currently focus on JavaScript with some eyes on TypeScript. We identified that nice JS code like thing.foo (in JS mapping to thing.getFoo()) does not exist in TypeScript. There might be other restrictions in other languages.

@mkovatsc
Copy link
Contributor

To my understanding, this is an new iteration to be discussed in Prague, which would fit directly to the simplified, JSON-like TD.

@zolkis
Copy link
Contributor Author

zolkis commented Feb 26, 2018

Yes, this issue/proposal is to be discussed in the next F2F.
Don't be blocked on maplike, think like it's a Dictionary where the properties are of the same kind of objects.

@mkovatsc
Copy link
Contributor

@zolkis I think we need to prepare this based on the Simplified TD proposal, as it would allow Thing software object instances to directly correspond to the TD structure allowing for very transparent introspection (colloquially speaking, a Thing without handler code would be basically equal to a JSON.parse(myTD)). How should we do this? TD session is planned for Tuesday, API session for Wednesday...

@zolkis
Copy link
Contributor Author

zolkis commented Mar 22, 2018

Thing without handler code would be basically equal to a JSON.parse(myTD)

Sounds good.

@zolkis
Copy link
Contributor Author

zolkis commented Jun 8, 2018

Handled by #113.

@zolkis zolkis closed this as completed Jun 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants