Open draggett opened 9 years ago
Hi @draggett,
I think we need to find a common interface for Thing and stick to it. Events, properties, actions, context, dependencies, etc, are good examples of what we can use to define this common interface.
I also think that we should use JSON-LD only for serialization. After having a common interface we are going to be able to transform the JSON-LD to some Go type representation.
We also should avoid using reflection in Go, whenever possible, because it is slow and subject to runtime errors which we want to avoid. Type assertion is a better tool for detecting different interfaces or types.
The javascript mindset is very different from the Go's one. So I need to understand better what the javascript version is doing to propose something solid in Go. So I have a few questions:
On 27 Jun 2015, at 19:17, Herbert Fischer notifications@github.com wrote:
Hi @draggett https://github.com/draggett,
I think we need to find a common interface for Thing and stick to it. Events, properties, actions, context, dependencies, etc, are good examples of what we can use to define this common interface.
I also think that we should use JSON-LD only for serialization. After having a common interface we are going to be able to transform the JSON-LD to some Go type representation.
We also should avoid using reflection in Go, whenever possible, because it is slow and subject to runtime errors which we want to avoid. Type assertion is a better tool for detecting different interfaces or types.
The javascript mindset is very different from the Go's one. So I need to understand better what the javascript version is doing to propose something solid in Go. So I have a few questions:
If the thing function could be expressed as an action, instead of a noun, what it would be? I’m not sure I understand that question. For things, actions are methods that may return results, but that may take an appreciable time, and as such it makes sense to handle results asynchronously. JSON-RPC shows how that can be done. Are the Things actions going to be defined only in server code? Or are they expected to be defined through a HTTP REST API There are two cases: the first is where a server defines a thing along with its implementation. The second is where a server hosts a proxy for a thing on another server. The two cases can be thought of as server and client that are connected through messaging at the transport layer. We want to support multiple protocols and not just HTTP. When a thing’s properties are updated, the updates need to be notified to all of the proxies for that thing. When a proxy invokes an action on a thing, the result for that action (if any) should only be sent to that proxy. registration process? I'm asking this because there is no way to evaluate dynamic Go code. We need a means to register things and proxies for things, and way to implement that in Go in the absence of a means to evaluate dynamic Go code. Go’s interfaces provide a means to build internal representations from arbitrary JSON-LD models. However, in practice the application code has to have some knowledge of the things it wants to manipulate. The developer should therefore be in a position to use static typing to express that knowledge, and the question is how to connect the two approaches. Without reflection or dynamic code compilation, I am not sure how to proceed. You can see some ideas that I am considering for a C-based server at:
https://github.com/w3c/wot-arduino/issues/1
Is there any reason why the model and implementation are two different arguments in the thing function? It was cleaner for the NodeJS code. The model is a JSON object, and the implementation is essentially an interface that supports start and stop methods, as well as methods for each of the thing’s actions.
Who will access the model properties and call the unlock() function? The start method is the first place where developers can initialise their thing. This could including setting timers that trigger calls to handlers e.g. at a fixed interval (JavaScript’s setInterval function). You can set handlers of events. You also need to define handlers for actions.
In my slides I describe a door, light switch and an agent that controls both of them. The agent is a thing with properties whose values are the door and the switch. The agent can set an event handler on the key event on the door and user that to turn on the light when the correct key is inserted. See slide 15 and 16 in http://www.w3.org/2015/05/wot-framework.pdf http://www.w3.org/2015/05/wot-framework.pdf . Note that after some discussion on the NodeJS server Github site, we’ve decided to drop @dependencies, so the up to date syntax is at:
https://github.com/w3c/web-of-things-framework/blob/master/demo.js <https://github.com/w3c/web-of-things-framework/blob/master/demo.js>
Note that for resource constrained servers using CoAP, the restricted packet size makes it appropriate to look at binary encodings of messages. There are several possible approaches. One of them s CBOR. Another is EXI which started life focusing on XML but has expanded in scope to cover JSON.
— Dave Raggett <dsr@w3.org mailto:dsr@w3.org>
The Web of Things framework needs to expose APIs for registering a new thing along with its model and implementation, and for registering a proxy for a thing identified by a URI for its model. Both APIs are asynchronous.
The code for the framework takes the model and uses it to generate an object with the corresponding events, properties and actions. For a new thing, the properties are bound to getter and setter methods. The getter can be used to couple the thing to a sensor. The setter can be used to couple the thing to an actuator, but must also couple to the transport layer to notify proxies of changes to this property. Actions are bound by name to implementation methods. The implementation must also provide start and stop methods for initialising and de-initialising the thing. For a proxy properties are bound to getter and setter methods that couple to the transport layer. Actions are likewise bound to the transport layer, and can deliver asynchronous results.
Go is a statically typed programming language. In principle, if you know a priori the models of the things you want to deal with, then you could declare these directly as Go types. If a proxied thing has a property that you don't know about, the code would essentially ignore it. For a new thing, the Web of Things framework would use reflection to map the thing's type to Linked Data for serialisation as JSON-LD. This assumes that we can fully express thing models as Go types, and necessitates conventions for expressing metadata and events.
Another approach is to dynamically generate objects from the model and to use reflection to inspect the resultant type. Go provides interfaces as containers for types and values. In particular, the empty interface can contain any type. The techniques needed are explained in the post on the laws of reflection and the post on JSON and Go. See also the Go implementation of JSON-LD by Stanislav Nazarenko. This dynamic approach has the benefit of providing full access to a thing and its model, but the downside of a more cumbersome syntax for accessing a things properties or methods. Some of this complexity can be ameliorated by casting the thing to a known type.
I am new to Go, and would very much appreciate some help with implementing both approaches and providing examples of their use.
Here is an example of registering a new thing with the NodeJS server:
The thing() method takes 3 arguments. The first is the name of the thing, which is used to generate the URI that the server will use to expose the thing's model. The second is the thing's model. The third is the thing's implementation with start and stop methods, and a unlock method corresponding to the unlock action.
In the example, the thing has two events named "bell" and "key". The "bell" event has no data, whilst the "key" event has a single boolean argument named "valid". There is a single property "is_open" which is a boolean. There is a single method "unlock" which has no arguments and returns no data. If it did, these would be defined via an object with fields for the arguments and the response. Objects can likewise be used for metadata for properties, e.g. to indicate minimum and maximum values for numeric properties.
Questions:
What would be the syntax for directly defining this thing's model as a Go type? If the dynamic approach is used, what would be the code for accessing the is_open property and calling the unlock() function?