using javascript to put the "internet" in iot
TRANSCRIPT
-
Using JavaScript to Put the Internet in IoT
@kevinswiber
-
Open source platform for the Internet of Things
http://zettajs.org
-
Internet of Things
-
Ubiquitous Computing
-
Like control systems
Sensor Actuator
Controller
Environment
The Internet
but on the Internet
-
More than 50B connected devices by 2020
-
99 Problems
-
Technology
-
Coordination
-
Analysis
-
Experience
-
Decisions
-
Protocols HTTP/1.1 WebSockets SPDY Future: HTTP/2
-
Crossing Network Boundaries
Access Interaction Streaming
-
Why Node? Evented, async Open Source Cross-platform Because you know JavaScript!
-
Nuts & Bolts
-
Reaching the Edge
DevicesDevicesDevices
Zetta
Zetta
DevicesDevicesDevices
Zetta
ClientsClientsClients
ClientsClientsClients Private Network
Data Center
Internet
-
Desired Architectural Properties
Decoupling of implementations
Independent evolution
Scale
Load balancing
Centralize complexity, distribute simplicity
Reduce latency
Support event streams
-
Architectural Constraints Client-server, stateless, cacheable, layered
system, uniform interface, etc.
Wait, isnt that REST?
-
The hypest of all media!
http://sirenspec.org
-
What about event streams?
-
How streams are done over HTTP today
WebHooks
Chunked Transfer-Encoding
HTTP Pipelining
Long Polling
Server Sent Events
XXXXX
-
Just upgrade
-
Zetta Process
Zetta Components
Scouts Drivers
Apps
create
observe
-
Model drivers as finite state machines
LED.prototype.init = function(config) { config .type('led') .state('off') .when('off', { allow: ['turn-on'] }) .when('on', { allow: ['turn-off'] }) .map('turn-on', this.turnOn) .map('turn-off', this.turnOff); };
-
Transitions are represented as affordances in the API.
"actions": [ { "name": "turn-on", "method": "POST", "href": ..., "fields": [ { "name": "action", "type": "hidden", "value": "turn-on" } ] } ]
-
We need to consume an object stream.
links: [ { title: pulse, rel: [http://rels.zettajs.io/object-stream], href: ws://... } ]
-
We need to consume an object stream.
wscat -c ws://... connected (press CTRL+C to quit) < {"topic":"heartbeat/1/pulse","timestamp":1411757412119,"data":61} < {"topic":"heartbeat/1/pulse","timestamp":1411757412620,"data":65} < {"topic":"heartbeat/1/pulse","timestamp":1411757413121,"data":69} < {"topic":"heartbeat/1/pulse","timestamp":1411757413622,"data":71} < {"topic":"heartbeat/1/pulse","timestamp":1411757414124,"data":66} < {"topic":"heartbeat/1/pulse","timestamp":1411757414626,"data":64} < {"topic":"heartbeat/1/pulse","timestamp":1411757415128,"data":68} < {"topic":"heartbeat/1/pulse","timestamp":1411757415629,"data":63} < {"topic":"heartbeat/1/pulse","timestamp":1411757416130,"data":65} < {"topic":"heartbeat/1/pulse","timestamp":1411757416631,"data":63}
-
Monitor resource events before taking action.
links: [ { title: logs, rel: [ monitor, http://rels.zettajs.io/object-stream ], href: ws://... } ]
-
Monitor resource events before taking action.
wscat -c ws://... connected (press CTRL+C to quit) < {"topic":"led/2/logs","timestamp":1411809676901,"transition":"turn-on","input":[],"properties":{"id":"2","type":"led","name":null,"state":"on"}} < {"topic":"led/2/logs","timestamp":1411809677548,"transition":"turn-off","input":[],"properties":{"id":"2","type":"led","name":null,"state":"off"}} < {"topic":"led/2/logs","timestamp":1411809678483,"transition":"turn-on","input":[],"properties":{"id":"2","type":"led","name":null,"state":"on"}} < {"topic":"led/2/logs","timestamp":1411809679126,"transition":"turn-off","input":[],"properties":{"id":"2","type":"led","name":null,"state":"off"}}
-
We also need binary.
links: [ { rel: [http://rels.zettajs.io/binary-stream], href: ws://..., type: video/mpeg, } ]
-
We also need binary.
wscat -c ws://... connected (press CTRL+C to quit) Q`rCEDDIp=`"3ss79:Yk}{` 5e\`>9%J[K89\z^> 8X Gp;WqXF h1{%O;7
-
We also need binary.
wscat -c ws://... connected (press CTRL+C to quit)
-
Reactive Clientsvar siren = require('siren'); !siren() .load('http://zetta-cloud-2.herokuapp.com') .link('http://rels.zettajs.io/peer', 'Detroit') .entity(function(e) { return e.properties.type === 'sound'; }) .link('http://rels.zettajs.io/object-stream', 'level') .monitor() .subscribe(console.log);
-
Reactive Clientsvar zrx = require('zrx'); !zrx() .load('http://zetta-cloud-2.herokuapp.com') .server('Detroit') .device(function(d) { return d.type === 'sound'; }) .stream('level') .subscribe(console.log);
-
It works!
-
Going Forward
-
Solve the producer-consumer problem.
-
Reactive Stream Control Protocol
Consumer controlled streams
Runs over WebSockets
Multiplex streams
URI scheme definition
Will be supported on HTTP/2 + WebSockets.
-
What can you do with streams?
Monitoring values over time
Distributed data processing
Event sourcing
Batches
-
// TODO:
Extract reactive hypermedia framework from Zetta internals.
Produce a clean specification and documentation.
Experiment with multiple languages/platform implementations.
-
Hit me up! [email protected]
https://twitter.com/kevinswiber
https://linkedin.com/in/kevinswiber
https://github.com/kevinswiber