-
Notifications
You must be signed in to change notification settings - Fork 63
NodeJS server for the Web of Things Framework
This will expand into a full description of the Web of Things Framework and the NodeJS implementation
The Internet of Things suffers from fragmentation with numerous non-interoperable platforms and data silos. The Web of Things seeks to address this by connecting IoT platforms via the Web, using an abstraction layer above the transport protocols, as no one protocol is a good fit to all situations. The starting point is the notion of "things" as virtual representations of physical or abstract entities, where the virtual representations are hosted on web servers.
Each "thing" has a URI for a declarative description in terms of the thing's events, properties, actions and metadata. The description is formally based on W3C's resource description framework (RDF). This description is used when registering a "thing" along with its implementation (server B below). It is also used when creating a proxy on one server (server A) for a thing on another server (server B).
The framework avoids the need for web developers to deal directly with the transport protocols. Instead, developers script the objects created by the framework in the script's execution environment. Things can have properties which are other things. The framework automatically deals with this by creating proxies for these other things. The process allows for cyclic dependencies between things, e.g where A depends on B which in turn depends upon A. When A starts and B has yet to start, any messages sent from A to B are automatically held until B has started.
The NodeJS implementation of the Web of Things Framework provides a method for registering a new thing along with its name, description and implementation. The name is used to construct the URI by which the thing's description will be published. The implementation is an object which must have start and stop methods, both of which are passed the object corresponding to the "thing". The start method provides an opportunity to initialise the thing, and to register observers for the thing's events.
Additional methods are provided for registering and unregistering a proxy. When registering a proxy, you provide the URI for its description and a function to be called when the proxy has been instantiated as a "thing" in the scripts execution space. This function is passed the object for the "thing" and can be used to register observers for the thing's events.
When a thing's properties are updated the servers exchange messages to update all of the thing's proxies. Note that unless otherwise declared in the thing's description, properties are read-only. Attempting to set such properties results in an exception. When a script call an action exposed by a proxy for a thing, the server that hosts the proxy will pass a message to the proxied thing to remotely invoke the action. Depending on the thing's description, this may result in an asynchronous result. This will be implemented as a JavaScript Promise.
Thing descriptions are serialised as JSON-LD. This is a representation of RDF in JSON that shields developers for the details of RDF through context definitions that bind names to the full URI required by RDF. For examples of thing descriptions see demo.js.
The NodeJS server currently supports the use of HTTP for accessing thing descriptions and WebSockets for messaging. A single web socket connection between pairs of servers is shared for the proxies between those servers. Further work is planned on adding support for additional protocols such as CoAP, MQTT, MQTT-SN and XMPP. Servers have metadata describing what protocols, data formats and encodings they support. This metadata allows a server hosting a proxy for a thing, to know how to communicate with the server for that thing. For servers that support HTTP, this metadata can be retrieved via a GET on the path /.well-known/protocols
An open question is whether to extend the framework to allow for proxying a single value as opposed to a "thing". In principle, you could register an observer for a property identified by a URI and use a function to set its value.