/ IoT and RESTful Hardware What We’ve Learned from Three Years Treating Motion as REST Alden Hart - Synthetos O’Reilly Solid Conference May 21, 2014
TinyG Motion Controller what’s TinyG? multi-axis motion control system designed for desktop CNC, 3D printing, pick & place… accepts Gcode from USB port and executes it locally on the board behaves like a RESTful server
The Controller Problem & Design Goals the problem the motion control functions are all good – but people got stuck at controller implementation specialized parsers and stateful clients got in the way design goals control interface that’s easy and intuitive simple compact / lightweight human readable / typeable / hackable relatively ubiquitous / low learning curve easily persisted and instantiated object oriented don’t have to be an industrial automation engineer to use (1 : 1000) does not require gateways or other additional hardware not design goals highly optimized transfer / storage support bandwidth starved and flakey communications channels support for hard, a-priori contracts XML-isms like Xpath/Xquery, annotation, schemas
RESTful Hardware what is RESTful? state exists on the server and is transferred to the client representation is flexible, independent well-defined resource model RESTful hardware server is an embedded chip / may not have an OS RESTful conventions make talking to the device very easy JSON JSON is the natural representation meets most of our design goals simple compact / lightweight human readable / typeable / hackable relatively ubiquitous / low learning curve easily persisted and instantiated object oriented
Putting JSON / REST on the Hardware put it On.The.Hardware code runs on the chip - not a gateway / translator / some-other-intermediary “Run JSON right over the traces” simple JSON parser, serializer, dispatcher and serial IO in < 8K C/C++ code bind names to dispatch tables to perform actions for the verbs marshalling in and out of floating point strtof() < 70 uSec on a 16 MHz AVR atmega328P (Arduino Uno) strtof() < 7uSec on a 84 MHz ARM Cortex M3 core all memory statically allocated – no mallocs transport doesn’t matter USB, SPI, Serial, MQTT, CoAP, HTTP… subset of JSON spec 7 bit ASCII only (UTF-8 sub-set) objects on a single line (no embedded line feeds) objects limited to 512 characters (less on smaller CPUs) decimal only, no hexadecimal limited support for arrays
Implementation Considerations well defined resource model static model – e.g. X axis, motor 1, machine setup parameters… dynamic model – e.g. position, velocity, coordinate system in use, tool in use… favor flat namespaces – right level of object granularity keeping it compact short, mnemonic tokens for names – e.g. xvm instead of XaxisVelocityMaximum don’t need to be globally unique – objects define scope many values are enumerated – e.g. 3 instead of GcodeProgramStop simple verbs (get, post) cheats & shortcuts no request headers. Use null to mean get no request ID – request / response is synchronous can consume Gcode natively without a JSON wrapper so people don’t have to pre-process their Gcode files
Implementation Examples from TinyG (1 of 2) get {“xvm”:null} {“ct”:null} {xvm:n} {ct:n} post (set) {xvm:16000} {ct:0.01} objects {x:{vm:16000}} {r:{x:{am:1,vm:16000,fr:10000,tn:0,tm:100,jm:200,jh:10000,jd:0.0100,sn:0,sx:0,sv:3000,lv:100,lb: ,zb:3.000}},f:[1,0,6,5473]} {r:{sys:{fb:428.01,fv:0.970,hp:1,hv:8,id:"2X2660-EVD”… {gc:”N75 G3 X Y Z I J0.0594”} footer revision status code flow control checksum footers f:[1,0,6,5473]
Implementation Examples from TinyG (2 of 2) status reports event reporting for the dynamic model timed and filtered timed reports during movement – e.g. every 250 milliseconds and at end-of-move filtered so only changed values are reported setup status report {sr:{posx:true, posy:true, posz:true, vel:true, momo:true, stat:true}} status reports for an X move from 0 to 100 {sr:{posx:0.000,vel:1.54,momo:0,stat:5}} {sr:{posx:2.494,vel: }} {sr:{posx:18.137,vel: }} {sr:{posx:43.528,vel: }} {sr:{posx:69.885,vel: }} {sr:{posx:91.760,vel: }} {sr:{posx:99.670,vel:479.38}} {sr:{posx: ,vel:0.00,stat:3}} exception reports {er:{fb:428.01,st:29,msg:"Generic exception report"}}
Useful Conventions We need some conventions for non-application specific functions don’t innovate. copy. $ root to discover objects (cribbed from JSONpath) {$:null} return top-level objects prefix for addressing, binding and routing assign a short name (handle) {ex1:null} address device “ex1” and route object to that device # topic prefix {#time:” T15:52:49.680Z”} devices that want time will process this message ! priority. Jump the queue {!fh:true}stop movement now! (feedhold)
Questions