Skip to content

Simplified API for JavaScript and other programming languages #64

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

Closed
draggett opened this issue Oct 2, 2017 · 14 comments
Closed

Simplified API for JavaScript and other programming languages #64

draggett opened this issue Oct 2, 2017 · 14 comments
Labels
for next iteration Planned or postponed topics for the future

Comments

@draggett
Copy link
Member

draggett commented Oct 2, 2017

Properties

JavaScript supports getters and setters for object properties. This provides a means for accessing and assigning property values in a very direct way, e.g.

var p = room23.temperature;   // read the room's temperature property

room23.targetTemperature = 22;  // write to the targetTemperature property

The getters and setters would be automatically defined by the implementation of the functions exposed to applications for creating or consuming things as objects.

Some statically typed languages (e.g, Kotlin and Scala) provide syntactic support for getters and setters.

For other languages e.g. Java and Go lang, there are naming conventions for getter and setter methods, e.g.

double p = room23.temperature();   // read the room's temperature property

room23.setTargetTemperature(22);  // write to the targetTemperature property

You can easily find tutorials on the web e.g.

Note that for go lang at least, the convention is to avoid using "get" as a prefix for getters, see:

JavaScript and Python have native support for getters and setters

Actions

A similar simplification can be used for thing actions, i.e. to define an action as a method on the object for a thing

Actions are invoked just like regular object methods, and return promises for the action response.

    thing42.someAction(args).then(response => console.log(response));

where "someAction" is the name of an action for thing42.

Note that JavaScript object properties and methods can't have the same names. The same should hold true for the properties and actions of things.

Name spaces and observables

With the use of thing properties and actions as object properties and methods, we need a means to avoid name clashes with system properties and methods. One approach is to define a Web of things system object and to define methods for that object where a thing is passed as an argument. Another approach is to standardise a meta property for things that exposes an interface for such purposes as reading and updating thing metadata, and for registering observables for events.

The former approach is used below as a basis for applications to register handlers for events associated with an ECMAScript observable.

var subscription =  wot.observe(thing, observable, {
	next (value) { … },
	error (value) { … },
	complete () { … }
});

Where observable is the name of an event, property or action. Note that if we allow event names that are the same as property or action names, we could provide a specialised method for observeEvent as an alternative to observe.

Later when we are done we can call the unsubscribe method on the value returned by observe to unobserve the observable:

subscription.unsubscribe();

The application can raise an event as follows:

wot.notify(thing, eventName, value);

Here is an example of the second approach involving a reserved name for a meta property:

thing42.$meta.observeEvent("alarm", {
	next (value) { … },
	error (value) { … },
	complete () { … }
});

where the meta property has the reserved name "$meta". My personal preference is for the first approach which avoids the need for reserved names.

Produce vs Expose

In English, produce/consume are commonly used as paired terms whilst expose/consume are not. People fresh to the web of things would most likely be more comfortable with the former. One view is that applications expose things rather than creating them. I don't agree. The thing is an abstraction that the application creates on top of the physical device and the underlying IoT communication technologies used to access it. The application gets to define the thing's interaction model, and a given IoT device could be abstracted in multiple ways to suit different needs. This is likely when there is a mix of old and new applications consuming things, where the newer versions of things adds new capabilities that old applications don't know about.

I therefore like the following:

wot.produce(model); // returns promise with resolved thing

wot.consume(url);  // returns promise with resolved proxy for a thing

wot.supply(thing, market);  // returns promise with record of agreement

wot.model(thing);  // returns the thing's model

The last method provides a means for applications to introspect the interaction model for a thing. This allows smart applications to adapt to variations across things for devices from different vendors. This raises the question of the programming interface for thing models. In my case, I use simple JSON, but a second argument, or a separate method, could be used to access the model as an RDF graph for applications that want to operate on the semantic models of things. I have a simple JavaScript library module for easy operations on RDF.

The supply method is passed a thing together with a URI for a marketplace. This is used when an application hosted on a gateway hidden behind a firewall wants to supply a thing to an open Internet server for access by applications running externally to the firewall. It can also be used between clouds. One possible implementation of the supply method involves consuming a thing exposed by a cloud server, where that thing supports a management interface.

Application Platforms and Open Markets of Services

The Web of things is an object oriented abstraction of things that decouples applications from the underlying protocols and standards. Some devices may directly connect to cloud-based servers that then act as producers of things on behalf of those devices. For devices that are resource constrained, or which have only short range communications, e.g. Bluetooth, a gateway is needed. A gateway device acts as an application platform, enabling users to install applications as needed. This includes applications that act as producers of things and applications that act as consumers of things. Applications may choose to supply things to external marketplaces, e.g. on Internet cloud servers.

The protocols used between application platforms (including web browsers) are distinct from the protocols used by the IoT devices themselves. In practice, the vast majority of use cases could be addressed using HTTP and WebSockets between application platforms. An application platform playing the role of a gateway at the network edge could make it easy to create services across a wide range of de jure and de facto IoT standards.

  • The scripting API needs to enable applications to inspect and negotiate requirements for communication patterns, and adapt the application behaviour as appropriate.
  • The security framework needs to support encryption, authentication, access control etc.
  • For consumer applications there is a further requirement to address privacy, including compliance with applicable regulations, e.g. the EU's GDPR, which allows for heavy fines for non-compliance.

One approach is to use HTTP for authentication and access control, and web sockets for messaging. More details will be described in an issue for the security task force.

See scripting task force issue 34

@zolkis
Copy link
Contributor

zolkis commented Oct 9, 2017

wot.produce(model); // returns promise with resolved thing
wot.model(thing); // returns the thing's model

These would justify model be a property of thing. What type would model have?

@zolkis
Copy link
Contributor

zolkis commented Oct 9, 2017

The protocols used between application platforms (including web browsers) are distinct from the protocols used by the IoT devices themselves. In practice, the vast majority of use cases could be addressed using HTTP and WebSockets between application platforms.

Is WoT meant to be a protocol above other protocols then?

@zolkis
Copy link
Contributor

zolkis commented Oct 9, 2017

The scripting API needs to enable applications to inspect and negotiate requirements for communication patterns.

That sounds like the API should negotiate what the API should be. I thought the communication patterns are defined by the server Things. Did you mean initial "SDP-like" negotiation for comms parameters?

Then, it seems this applies to client API, right?

@zolkis
Copy link
Contributor

zolkis commented Oct 9, 2017

thing42.someAction(args).then(response => console.log(response));

I wonder is there a systematic rule based on which we choose between exposing factory methods or object methods? This could be also written as

wot.invokeAction(thing42, someAction, args).then(response => console.log(response));

which would be more in line with the style used elsewhere in the proposal. Also, this would allow more intuitive observation of an action, and a more uniform observe interface.

@draggett
Copy link
Member Author

draggett commented Oct 9, 2017

In object oriented programming it is common for objects to expose both properties and methods, so having both properties and actions (asynchronous methods) on the object standing for a thing would seem like a natural approach to take, along with promises as the basis for handling the asynchronous nature of responses for actions.

@zolkis
Copy link
Contributor

zolkis commented Oct 9, 2017

I got that part. What I see with this new proposal is the following:

  • exposing properties, actions and observables is very much fine
  • but this introduces another problem of namespacing
  • you use factory methods elsewhere, so the proposal is not really consistent
  • observation is more complex with this proposal
  • it is harder for implementations to have hooks for checking/enforcing policies than with all-factory methods.
  • some of the details are inconsistent too, e.g. why factory method on getting a model of a thing instead of exposing it as property, especially when that model was needed to construct the thing?

@draggett
Copy link
Member Author

draggett commented Oct 9, 2017

Matthias commented on the October 9 scripting telecon that simple assignment/access operations on properties doesn't address the asynchronicity of distributed environments. I therefore thought it worthwhile to provide some further background.

One scenario is where a battery operated device sleeps a lot to ensure a long battery life. The device is scheduled to wake up at regular intervals, e.g. once a minute. As a result there may be a substantial delay in updating a device property or invoking an action on the device.

Another scenario involves a spacecraft where the speed of light introduces long round trip times, e.g. between 30 and 60 minutes for a Mars orbiter, and longer for a lander which relies on line of sight access to an orbiter.

Actions for the web of things are explicitly asynchronous, and using promises provides a convenient programming API for handling responses. What about updating the value of properties? An underlying principle is to decouple applications from the communication patterns and protocols. A device may gather sensor readings at regular intervals and buffer them until the next transmission window occurs. A similar case can arise for actuators, where a sequence of updates is buffered for subsequent transmission to the device. The updates could be applied at regular intervals, or at a time designated with the update.

When an application script running on a remote application platform updates the value of a property, the update can be handled via an object setter function for that property. This function is provided by the application platform not the application. The application platform exploits the communication metadata for a thing to determine whether to buffer the update, and when to send updates. When the target device receives and applies the update, and sends a notification acknowledging this. The remote application platform can then signal the notification to the application as an event.

An example is a home thermostat where adjusting the target temperature manually locally shows the provisional update with one colour (orange) and changes this to another colour (green) once the acknowledgement from the target controller has been received.

Designers of things that abstract devices, have a choice between using properties or actions as they feel appropriate. Given the choice of an action, applications can update the user interface when the promise has been resolved. Alternatively, given the choice of a property, applications can set an observer for events that signal the acknowledgements from the device, and use the observer to update the user interface.

For streaming use cases, applications may find it convenient to register observers for a block containing a sequence of sensor readings, rather than handling each reading on its own. Similarly, applications may, in some situations, find it convenient to pass a block containing a sequence of updates for actuation rather than simply writing the updates to the corresponding properties.

This explanation shows the need for including communications metadata as part of the programming language neutral description of the interaction model for things. We should look at a range of use cases to find common patterns and shared vocabulary applicable to them.

@draggett
Copy link
Member Author

draggett commented Oct 9, 2017

Re: @zolkis - I agree that there are pros and cons in respect to the choice between having special methods on the object for a thing versus on a wot framework, where the thing is passed as an argument. Regardless of which choice is used for accessing a model for a thing, I see benefits from enabling applications to access and update the model, leaving it the platform to synchronise such changes with other applications involving that thing.

The suggested framework method to get a model for a thing is useful for applications that act as consumers or as producers for a thing. Consumers may want inspect the communications metadata to adapt their behaviour. They may want to set a preference. A producer may decide to update the model as the physical capabilities of a device change, e.g. upon detecting faults, or when a device is upgraded, e.g. a software update, or a physical update with a new hardware module.

  • exposing properties, actions and observables is very much fine
  • but this introduces another problem of namespacing

As I pointed out we could reserve part of the namespace, and in my former NodeJS implementation, I reserved all JavaScript object properties starting with the '@' character. However, an alternative is to have a framework method that returns a model for a thing, where the model exposes interfaces for all of the functions we wish to define.

  • you use factory methods elsewhere, so the proposal is not really consistent

I propose choices for discussion.

  • observation is more complex with this proposal

It requires an additional argument to pass the thing, and a different function name if we want to keep event names in a separate namespace from properties and and actions.

  • it is harder for implementations to have hooks for checking/enforcing policies than with all-factory methods.

Not really, apart from either passing the thing as an argument, or first getting the model as an object prior to setting hooks on it.

  • some of the details are inconsistent too, e.g. why factory method on getting a model of a thing instead of exposing it as property, especially when that model was needed to construct the thing?

Not really. A consumer needs a way to get a model for the thing it requested given the URI for its description. A producer passes a model for the thing it is creating. However, this could be a text based thing description, or a simple parsed JSON object. The application that produces a thing may want to access or update the model (see above), and for this it seems reasonable to offer the same programming interface as for applications that consume things.

@mkovatsc
Copy link
Contributor

Just some input on Dave's

Produce vs Expose
In English, produce/consume are commonly used as paired terms whilst expose/consume are not. People fresh to the web of things would most likely be more comfortable with the former.

I just read this on https://www.w3.org/TR/social-web-protocols/

how to expose/consume social content (reading)

So, we are not the only ones talking about expose/consume

@draggett
Copy link
Member Author

In respect to markets, "produce" and "consume" are commonly paired terms, and the aim of the web of things is to enable open markets of services that bring together producers and consumers of services.

@zolkis
Copy link
Contributor

zolkis commented Oct 11, 2017

The argument for produce-consume pair is valid in many contexts and has been noted.
Perhaps we can make an editor's note about this discussion.
For now and for WoT context I also vote for continuing using expose and consume, because:

  • the group has earlier agreed in this terminology
  • we use it in the FPWD
  • it is used elsewhere too
  • preferred by at least one chair
  • preferred by at least one Scripting editor.

WoT Scripting is an optional WoT module, therefore not all scripting implementations have to use this API. Also, produce seems to do slightly different thing than expose, so I don't see much of a conflict to be resolved on this.

@zolkis
Copy link
Contributor

zolkis commented Oct 27, 2017

I suggest we set up an experimental branch in scripting for exploring this, adding e.g. a separate markup file for alternative designs. I like the simplicity of the proposal, but would consider some changes.

zolkis added a commit to zolkis/wot-scripting-api that referenced this issue Jan 30, 2018
zolkis added a commit to zolkis/wot-scripting-api that referenced this issue Jan 30, 2018
@zolkis zolkis added the for next iteration Planned or postponed topics for the future label Sep 10, 2019
@zolkis
Copy link
Contributor

zolkis commented Oct 16, 2019

Since the current Scripting API is a group Note and not on the standards track, I suggest to create a new Note for the eventual simplified Scripting API.

Also, because of the divergence from this API and the different level of abstraction, it would make sense to have its own github repository with WG/IG members cooperating on that.

As such, closing this issue now.

@zolkis zolkis closed this as completed Oct 16, 2019
@draggett
Copy link
Member Author

That's fine with me. I am hoping to get time to work on ideas for a simpler API now that I am involved with an EU project on applying WoT to healthcare.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for next iteration Planned or postponed topics for the future
Projects
None yet
Development

No branches or pull requests

3 participants