an introduction to workflow-based programming with node-red

8
Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED - 1 - http://nodered.org An introduction to flowbased programming using NodeRED ! NodeRED is a visual tool for wiring the Internet of Things (IoT). NodeRED is platformindependent, but has been developed with small computers such as the Raspberry Pi in mind. ! Traditional IoT development can be very technical: Access to the GPIO and other hardware requires skills in C or assembler, output of data to web services or sending tweets and emails requires the use of complex APIs. NodeRED takes care of the technicalities and lets you concentrate on the logic of your workflow ! While most programming in NodeRED is done visually using predefined functions (“nodes”), any additional functionality can be added in JavaScript. ! NodeRED is a multipurpose jackknife – use it for any prototyping! WORKSHOP CONTENT: In this workshop, we’re going to use NodeRED to build a basic web server. We are going to build a web site that provides the functionality of an online chat application, i.e. you are going to learn about communication between a web browser and the underlying service.

Upload: boris-adryan

Post on 16-Jul-2015

1.787 views

Category:

Education


2 download

TRANSCRIPT

Page 1: An introduction to workflow-based programming with Node-RED

Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED

  - 1 -

 

 

 http://nodered.org

 An  introduction  to  flow-­based  programming  using  Node-­RED  

 

! Node-­RED   is   a   visual   tool   for   wiring   the   Internet   of   Things   (IoT).   Node-­‐RED   is  platform-­‐independent,   but   has   been   developed   with   small   computers   such   as   the  Raspberry  Pi  in  mind.  

 ! Traditional   IoT   development   can   be   very   technical:   Access   to   the   GPIO   and   other  hardware   requires   skills   in  C  or   assembler,   output  of  data   to  web   services  or   sending  tweets   and   emails   requires   the   use   of   complex   APIs.   Node-­RED   takes   care   of   the  technicalities  and  lets  you  concentrate  on  the  logic  of  your  workflow  

 ! While   most   programming   in   Node-­‐RED   is   done   visually   using   pre-­‐defined   functions  (“nodes”),  any  additional  functionality  can  be  added  in  JavaScript.  

 ! Node-­RED  is  a  multi-­purpose  jackknife  –  use  it  for  any  prototyping!  

 

 

WORKSHOP  CONTENT:  In  this  workshop,  we’re  going  to  use  Node-­‐RED  to  build  a  basic  web  server.   We   are   going   to   build   a   web   site   that   provides   the   functionality   of   an   online   chat  application,  i.e.  you  are  going  to  learn  about  communication  between  a  web  browser  and  the  underlying  service.  

Page 2: An introduction to workflow-based programming with Node-RED

Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED

  - 2 -

Technical  background:  For  this  workshop,  you  will  find  a  Raspberry  Pi  with  Node-­‐RED  already  installed.  While  the  installation  of  Node-­‐RED  software   is   relatively   easy,   it  would   be   difficult   to   include   this   step  within   the   time   constraints   of   the   exercise.   For   completeness,   this   is  what’s  happened  to  a  fresh  and  up-­‐to-­‐date  Raspian  installation  on  your  SD  card:  

1. Install  node.js  and  npm  as  per:  http://nodered.org/docs/hardware/raspberrypi.html  

2. Clone  Node-­‐RED  from  Github  and  install  as  described  here:  http://nodered.org/docs/getting-­started/installation.html  

Note:   To   leverage   the   power   of   Node-­‐RED,   consider   installing   nodes   for   email   or   raw   GPIO   access   as  well.   The   latter   is   described   here:  http://nodered.org/docs/hardware/raspberrypi.html  

 

1)  Exercise:  Starting  Node-­RED  as  Raspberry  Pi  user  

Node-­‐RED  can  be   installed  as  a   service  on   the  Raspberry  Pi,   i.e.   as  a  program   that’s   always  executed  when  your  Pi  is  running.  However,  this  is  only  useful  if  you  want  to  commit  your  Pi  for   this   particular   use   as   it   can   consume   considerable   resources.   For   everyone   else,   it’s  recommended  to  start  Node-­‐RED  only  when  needed:  

1. Open  the  LXTerminal    to  see  a  console  that  allows  you  to  enter  Linux  commands.  

2. Change  into  the  Node-­‐RED  directory  by  issuing  “cd  node-­‐red”.  

3. Start  Node-­‐RED  by  typing  “node  red.js”.  

 

You  should  now  see  Node-­‐RED  starting  up  –  that  may  take  a  few  seconds:  

 

Congratulations.  You’re  now  ready  for  the  exercises.  

Node-­‐RED  represents  a  server  on  the  basis  of  node.js  and   interacts  with   the  user   through  a  graphical   user   interface.   It   can   be   reached   on   port   1880.  To   use   Node-­RED,   open   a   web  browser  and  direct  it  to  http://localhost:1880  

It’s  useful  to  remember  that  Node-­‐RED  acts  as  a  server  in  your  entire  network.  That  is,  if  your  Raspberry  Pi’s  internal  IP  address  is  something  like  192.x.x.x,  every  computer  in  your  network  can  open  the  Node-­‐RED  GUI  through  http://192.x.x.x:1880.  You  can  make  your  system  more  restricted/secure  by  following  the  configuration  advice  on  http://nodered.org/docs/configuration.html.  

 

Page 3: An introduction to workflow-based programming with Node-RED

Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED

  - 3 -

2)  Exercise:  Your  first  flow  –  this  is  a  recap  for  those  who  attended  the  last  course  

The  best  way  to  explain  “a  flow”  is  by  creating  one.  In  this  mini  flow,  we’re  going  to  inject  a  value  into  our  debug  window  (refer  to  page  1  for  what  the  GUI  elements  are  called).  

1. Open  the  Epiphany  Web  Browser.  (It  supports  JavaScript  better  than  Midori).  

2. In  the  address  line,  enter  localhost:1880.  You  will  then  see  the  Node-­‐RED  GUI.  

3. Drag   and   drop   an   “inject”   node   from   the   nodes   library   into   the   flow   editor   (once  you’ve   chosen   the   inject   node,   you   should   see   some   general   explanation   about   its  functionality  in  the  info  pane  –  no  need  to  read  that  now).  

4. Drag  and  drop  a  “debug”  node  from  the  nodes  library  into  the  flow  editor.  

5. Create  a  pipe  between  the  inject  and  debug  nodes  by  drawing  a  connection  between  their  small  grey  rounded  rectangles.  

6. Change  from  the  info  pane  to  the  debug  pane  (upper  right).  

7. Deploy  (=start)  your  flow.  

8. Once  deployed,  press   the   left  blue  rectangle   that’s  attached   to   the   inject  node.  Check  what’s  happening  in  the  debug  pane.  

 

3)  Exercise:  Setting  up  a  static  website  

It  is  very  easy  to  set  up  a  very  basic  web  server  in  Node-­‐RED.  

1. From  the  input  panel,  chose  a  “http”  node.  

2. Change  the  properties  of  your  http  node  so  that  it  will   respond   to   GET   requests   to   /mypage   from   a  browser.  

3. Add  a  “template”  node  (from  the   function  panel),  and  a  “http  response”  node  from  the  output  panel.    

4. Wire  your  flow  together  as  shown  below:  

 

5. Deploy  your  flow.  

6. Once  deployed,  open  a  separate  browser  window  and  enter  localhost:1880/mypage.  

A  note  on  addresses  and  ports:  Web  servers  have  their  own  numerical  addresses,  e.g.  a  special  table  (called  DNS)  resolves  the  BBC  website  to  212.58.246.103.   Each   address   can   have   thousands   of   communication   channels   (called   ports).   A   standard   webpage   call   uses   port   80   by  default.  Your  own  machine   is  always  called  “localhost”  and  resolves  to  127.0.0.1.  A  default  Node-­‐RED  server  can  be  opened  on  port  1880.  Does  the  address  http://localhost:1880/mypage  make  more  sense  to  you  now?  

Page 4: An introduction to workflow-based programming with Node-RED

Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED

  - 4 -

4)  Exercise:    The  anatomy  and  function  of  a  template  node  

Our  previous  Node-­‐RED  workflow  hides  the  complexity  of  the  client  "  server  communication  via   the   hypertext   transfer   protocol   (“http”)   (which   sits   on   top   of   another   protocol,   TCP/IP,  which  sits  on  top  of…  …you  get  the  gist).  We  don’t  need  to  care  how  the  browser  talks  to  the  server.  

One   technicality   that   we   can’t   fully   get   around   in   this   workshop   is   HTML,   the   hypertext  markup  language.  It’s  the  code  that  describes  how  a  website  is  supposed  to  look.  It’s  beyond  the   scope   of   this   course   to   teach   you   all   goodness   of  HTML,   a   good   entry   point   for   further  explorations  is  here:  http://www.w3schools.com/html.  What  you  need  to  remember,  however,  is  that  the  template  node  encapsulates  a  minimal  HTML  page.  So  

 

 indeed  returns  

<!DOCTYPE html>

<html>

<head> </head>

<body> This is the payload: {{payload}} </body>

</html>

which  instructs  the  browser  to  show  the  text  you’ve  seen  in  Exercise  3.  

In   the  next  exercise,  we  will  use  additional  HTML  code   to  add  some  styling   to  our  website,  and  we  will  learn  to  use  the  moustache  {{  }}  format  to  add  dynamic  content  to  it.  

1. Drag  and  drop  a  “function”  node   into   the   flow  editor.  Call   it   “where   things  happen”.  Stick  it  in  between  the  http-­‐in  and  the  template  node.  

 

2. Edit  the  function:  Add  msg.payload = "Hello, Pi";  in  the  line  before  return msg;  

3. Change  the  template  into  This is the <b>message</b>: {{payload}}  

4. Deploy  your  flow  and  check  out  localhost:1880/mypage.    

Note:  If  you  know  HTML,  have  a  play  with  other  style  tags.  You  can  even  embed  CSS!  

 

Page 5: An introduction to workflow-based programming with Node-RED

Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED

  - 5 -

5)  Exercise:  Retain  state  

So   far   our   Node-­‐RED   flow   is   strictly   linear:   Once   the   /mypage   is   requested,   the   function  populates   the  variable  payload  with  “Hello,  Pi”,   the   template  node  embeds   this  payload   into  the  HTML  that’s  returned  to  the  server.  

How  can  we  put  other  things  into  the  payload?  

1. Wire  your  inject  node  from  Exercise  1  to  the  function  node.  Modify  the  inject  node  to  send  the  string  “Have  a  nice  day”  as  payload,  with  “new  message”  as  topic.  

 

2. Edit  the  function  node  to  contain  the  following  JavaScript:  

 

3. Deploy  the  flow.    

4. Look  at  localhost:1880/mypage  in  your  web  browser.  Note  what  you  see.  

5. Click  on  the  rounded  rectangle  on  the  left  of  your  inject  node.  

6. Reload   localhost:1880/mypage.   Note   what   you   see.   Can   you   make   sense   of   your  observation  in  the  light  of  your  JavaScript  code  from  step  2?  

A  bit  of  background:  

By  default,  most  wires  between  nodes  are  topic/payload  pairs,  a  bit  like  emails  have  subject  and  body.  However,   the  default  msg  variable  can  always  be  extended,  and  in  the  case  of   the  http  nodes  contain  an  entire  http  response  object.  

The  context  variable  is  available  in  the  function  node  to  retain  information  between  different  executions  of   the  node.   In  our  example,   if   the   input  message  msg   arrives   from  the   injection  node  (having  the  topic  “new  message”),  we  populate  context.value  with  the  payload  “Have  a  nice  day”  and   leave   the  node.   If   the   input  arrives   from   the  /mypage   http  node,  we  evaluate  whether  something  is  present  in  the  context  variable.  If  not,  we  deliver  the  payload  “never  got  anything”  for  rendering  in  the  template  node,  otherwise  we  take  it  from  the  context.  

The  special  case  context.global  is  a  variable  that  persist  between  executions  of  a  node  and  are  globally  available  to  all  other  function  nodes.  More  about  messages  and  context  variables  can  be  found  here:  http://nodered.org/docs/writing-­functions.html  

Page 6: An introduction to workflow-based programming with Node-RED

Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED

  - 6 -

6)  Exercise:  Returning  the  result  of  a  web  form  to  Node-­RED  

So  far  our  interaction  between  the  server  and  the  client  was  rather  unidirectional.  Following  the  http  request,  us  injecting  or  not  injecting  a  message  determined  the  actual  outcome.  Now,  we  extend  the  example  so  that  the  return  value  is  dependant  on  the  user’s  input.  

1. Drag  and  drop  a  “http”  input  node,  a  “template”  node  and  a  “http“  output  node  into  your   flow.   Set   the   input   node   to   respond   to   GET   request   on   /login.  Wire   the   nodes  together  as  shown  below:  

 

2. Add  the  following  HTML  to  your  template  node:  

<form action="http://localhost:1880/chat" method="post">

<b>User</b><br> <input type="text" name="user"/><br>

<button type="submit">Submit</button>

</form>

3. Add  another  set  of  four  nodes  to  your  flow.  Configure  the  http  input  node  to  respond  to   POST   requests   at   /chat.   This   is   how   your   server   is   going   to   react   to   form  submissions:  

 

4. Edit  the  function  node  to  extract  the  content  of  the  incoming  input  field  “user”  (if  not  empty)  and  assign  it  to  our  standard  payload:  

if (msg.req.body["user"] != "") {

msg.payload = msg.req.body["user"]

}

return msg;

5. The  template  node  can  simply  say:  The user’s name is: {{payload}}  

6. Deploy  and  test  your  flow  at  localhost:1880/login.  

Does  it  do  what  you  expect?  If  so:  Congratulations,  you’re  now  seeing  the  key  ingredients  to  a  basic  chat  server.  

 

 

Exercise  7:  Putting  it  all  together  

In  the  next  step  we’re  going  to  put  all  of  our  new  skills  together.  To  build  a  basic  chat  server,  all  we  need  is  a  little  more  trickery  with  the  context.global  to  retain  our  conversation  (we’re  going   to   use   context.global.dialog),   some   HTML   concept   called   iframe   to   separate   an   input  field  from  the  conversation,  and  a  bit  of  client-­‐sided  JavaScript  to  auto-­‐update  the  iframe.  

Page 7: An introduction to workflow-based programming with Node-RED

Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED

  - 7 -

1. Rewrite  the  function  node  following  the  /chat  http  input  like  this:  

if (msg.req.body["user"] != "") {

msg.payload = msg.req.body["user"]

}

if (msg.req.body["message"] != undefined) {

context.global.dialog +=

msg.req.body["user"]+':'+msg.req.body["message"]+"<BR>";

}

context.global.dialog = context.global.dialog || "";

return msg;

2. The  template  node  hides  most  of  the  trickery:  

<iframe src="http://localhost:1880/dialog" name="iframe_a" width="90%" height="70%"></iframe>

<form name="frm" action="http://localhost:1880/chat" method="post">

<b>Message from {{payload}}</b><br>

<input type="text" name="message" size="90%"/>

<input type="hidden" name="user" value="{{payload}}"><br>

<button type="submit">Submit</button>

</form>

<SCRIPT language="JavaScript">

window.setInterval("reloadIFrame();", 1000);

function reloadIFrame() { window.frames["iframe_a"].location.reload(); }

</SCRIPT>

3. We  need  another  set  of  http  input,  function,  template  and  http  out  nodes.  These  will  represent  the  /dialog  page  that’s  shown  in  the  iframe.  The  code  is  fairly  simple.  

 

4. Add   to   function   node   node   following   the   /dialog   http   input   msg.payload = context.global.dialog;  before  return msg;  

5. The  template  node  just  says:  {{payload}}  

6. Deploy  your  web  server.    

 

Open  localhost:1880/login  from  two  different  browser  windows  and  login  with  different  identities.   Both   windows   will   update   their   iframe   once   a   second,   showing   /dialog   as   it  continues   to   grow  on   the   server  with   lines   that   are   sent   via   the   form   field   “message”   from  either  client.  

Page 8: An introduction to workflow-based programming with Node-RED

Raspberry Pi Birthday Weekend & CamJam! Workshop: Node-RED

  - 8 -

 

Further  explanations  and  suggestions  for  experiments:  

So   far   all   code   refers   to   localhost:1880.   It   is   possible   to   change   the   default   port,   allowing  addresses   without   the   addition   of   :1880   (see   http://nodered.org/docs/configuration.html).  Furthermore,  localhost  is  only  visible  on  your  own  machine.  You  can  change  localhost  to  your  Raspberry   Pi’s   local   IP   address   (often   something   like   192.168.x.x   or   172.x.x.x)   and   request  your  chat  server   from  any  other  computer  within  your   local  network.  These  changes  would  impact  the  address  that’s  specified  in  the  HTML  form  definitions.  

 

Node-­‐RED  is  an  incredibly  powerful  framework  that  allows  you  to  do  things  in  very  little  time.  The  official   directory   of   flows   donated   to   the   community   is   here  http://flows.nodered.org  and  they  can  easily  be  imported  by  copying  &  pasting  the  JSON-­‐formatted  code.  

 

A  few  suggestions  and  examples  that  I  have  described  over  the  past  months  are  here:  

! Triggering   Node-­RED   with   drawings:   The   Aestheticodes  project   uses   a   QR   code   like   method   to   encode   information   in  beautiful  drawings.  Draw  a  picture,  take  a  photograph  with  your  mobile   and   trigger   the   debug   node   doing   that:  http://logic.sysbiol.cam.ac.uk/?p=1514  

 

! Control  Minecraft  with  Node-­RED:  The  Minecraft  Pi  Edition  can  be  controlled  through  Python,  but   that  may  not  be  easily  accessible   for  everyone.  With  a  MQTT-­‐to-­‐Minecraft  bridge,   the   Node-­‐RED   inject   nodes   can   be   used   to   control   Steve:  http://logic.sysbiol.cam.ac.uk/?p=1499  

 

! Got   an   AirPi   shield?   Monitor   your   room   climate   with   AirPi   and   Node-­RED:  http://logic.sysbiol.cam.ac.uk/?p=1423  

 

! The  first  CamJam  Node-­RED  tutorial  that  teaches  radio  communication  through  Ciseco  radio   modules   is   available   here:   http://www.slideshare.net/BorisAdryan/node-­red-­coursecamjamjuly2014