diff --git a/Behaviours.h b/Behaviours.h
index 94f5a3b2e47a536c88c3fbee386f7a1bb05a2ef7..2f9de936b32c4af4cb4bb4102d30af36a042f490 100644
--- a/Behaviours.h
+++ b/Behaviours.h
@@ -1,19 +1,15 @@
 #ifndef BEHAVIOUR_h
 #define BEHAVIOUR_h
 
-
-
-
-
 class Behaviour {
 protected:
   boolean _interruptable = true;
   boolean _temp = false;
   boolean _priority = false;
   boolean _running = false;
+  boolean _background = false;
   String _name = "name";
 
-
 public:
   Behaviour(String name) : _name(name) {};
   ~Behaviour() {};
@@ -23,17 +19,19 @@ public:
   //Can this behaviour be run quickly without stopping what's going on (e.g. comms, debug)
   virtual boolean is_temp() { return _temp; };
   //Should this behaviour override others
-  virtual boolean is_priority() {return _priority;};
+  virtual boolean is_priority() { return _priority; };
   //Is the behaviour running
-  virtual boolean is_running() {return _running;};
+  virtual boolean is_running() { return _running; };
+  //What's the name of this behaviour
+  virtual boolean is_background() { return _background; };
   //What's the name of this behaviour
-  virtual String name() {return _name; };
+  virtual String name() { return _name; };
   //What arguments does the behaviour take? Override this to document your behaviour
-  virtual char* args() {return "(no args)"; };
+  virtual char* args() { return "null"; };
   //Start the behaviour, with arguments (don't know why this can't be virtual?)
-  virtual String start(String args) {Serial.println("Base start called <"+args+">");};
+  virtual String start(String args) { Serial.println("Base start called <"+args+">"); };
   //Update the behaviour periodically
-  virtual void update() {};
+  virtual void update() { };
   //Start the behaviour, with arguments (don't know why this can't be virtual?)
   virtual void stop() { _running = false; };
 };
@@ -53,15 +51,13 @@ public:
 class BehaviourTable {
   Behaviour* behaviours[40];
 
-
 public:
   int num = 0;
-  BehaviourTable() {
 
-  }
+  BehaviourTable() {}
+
   void add(Behaviour *b) {
     behaviours[num] = b;
-
     num++;
   }
 
@@ -81,20 +77,4 @@ public:
   }
 };
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 #endif
diff --git a/Button.h b/Button.h
new file mode 100644
index 0000000000000000000000000000000000000000..66d4dd01ba5cf52323503912d9fb4d351ba5fccb
--- /dev/null
+++ b/Button.h
@@ -0,0 +1,149 @@
+#ifndef BUTTON_h
+#define BUTTON_h
+
+class Button {
+
+  private:
+    
+    int _pin;
+    int _id;
+
+    bool _state;
+
+    volatile bool _inputFlag = false;
+    bool _changeFlag = false;
+
+    bool _pressedFlag = false;
+    bool _holdFlag = false;
+
+    unsigned long _previousTimer;
+
+    int _clickInterval = 1000;
+    int _holdInterval = 1000;
+    int _repeatInterval = 1000;
+
+    void (*_cb)(Button*, uint8_t, bool); // Callback function
+
+    bool _read() {
+      return digitalRead(_pin);
+    }
+
+    void _setClickInterval(int x) {
+      _clickInterval = x;
+    }
+
+    void _setHoldInterval(int x) {
+      _holdInterval = x;
+    }
+
+    void _setRepeatInterval(int x) {
+      _repeatInterval = x;
+    }
+
+  public:
+
+    // Public members:
+
+    static const uint8_t kEventPressed = 0;        // Button was pressed
+    static const uint8_t kEventReleased = 1;       // Button was released
+    static const uint8_t kEventClicked = 2;        // Button was clicked (pressed and released within _clickInterval)
+    static const uint8_t kEventHeld = 3;    // Button was held down for longer than _holdInterval
+    static const uint8_t kEventTick = 4;  // Event released every _repeatInterval when button held
+
+    // Public functions:
+
+    Button(int pin, int id = 99) : _pin(pin), _id(id) {
+      pinMode(_pin, INPUT_PULLUP);
+      _state = _read();
+      _previousTimer = millis();
+    }
+
+    void initInterrupts(void(*function)()) {
+      attachInterrupt(_pin, function, CHANGE);
+    }
+
+    void setEventHandler(void(*function)(Button*, uint8_t, bool)) {
+      _cb = function;
+    }
+
+    bool getState() {
+      return _state;
+    }
+
+    int getId() {
+      return _id;
+    }
+
+    int getClickInterval() {
+      return _clickInterval;
+    }
+
+    int getHoldInterval() {
+      return _holdInterval;
+    }
+
+    int getRepeatInterval() {
+      return _repeatInterval;
+    }
+
+    void check() {
+      unsigned long timer = millis();
+      unsigned long deltaTime = timer - _previousTimer;
+      _state = _read();
+
+      if (_inputFlag == true) {
+        _inputFlag = false;
+
+        // Button pressed
+        if (_state == LOW
+            && _pressedFlag == false) {
+          _pressedFlag = true;
+          _previousTimer = timer;
+          _cb(this, kEventPressed, _state);
+          return;
+
+        // Button clicked
+        } else if (_state == HIGH
+                  && deltaTime < _clickInterval
+                  && _holdFlag == false) {
+          _pressedFlag = false;
+          _previousTimer = timer;
+          _cb(this, kEventClicked, _state);
+          return;
+
+        // Button released
+        } else if (_state == HIGH) {
+          _pressedFlag = false;
+          _holdFlag = false;
+          _previousTimer = timer;
+          _cb(this, kEventReleased, _state);
+          return;
+        }
+      }
+
+      // Button held
+      if (_state == LOW
+          && deltaTime > _holdInterval
+          && _holdFlag == false) {
+        _holdFlag = true;
+        _previousTimer = timer;
+        _cb(this, kEventHeld, _state);
+        return;
+
+      // Button tick
+      } else if (_state == LOW
+                && deltaTime > _repeatInterval
+                && _holdFlag == true) {
+        _previousTimer = timer;
+        _cb(this, kEventTick, _state);
+        return;
+      }
+    }
+
+    void ICACHE_RAM_ATTR tick() {
+      _inputFlag = true;
+    }
+
+};
+
+#endif
diff --git a/ButtonBehaviours.h b/ButtonBehaviours.h
new file mode 100644
index 0000000000000000000000000000000000000000..bbc7d675552c7427013ca318cd7bb3fccbb5067d
--- /dev/null
+++ b/ButtonBehaviours.h
@@ -0,0 +1,117 @@
+#ifndef BUTTON_BEHAVIOUR_h
+#define BUTTON_BEHAVIOUR_h
+#include "Arduino.h"
+#include "Behaviours.h"
+#include <VizBlocks.h>
+
+class ButtonPressed : public Behaviour {
+  /*
+   * Class that defines a behaviour that publishes a
+   * ButtonPressed message to the input topic of the
+   * MQQT broker
+   */
+   VizBlocks* _node;
+
+public:
+  ButtonPressed(VizBlocks* node, String name = "ButtonPressed") :
+    Behaviour(name), _node(node){ }
+
+  char* args() {return "<String buttonId>"; };
+
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Input\":{\"type\":\"" + String(name()) + "\",\"button\":\"" + args + "\"}}";
+    _node->announce(str);
+    return "ButtonPressed behaviour " + _name + " with (" + args + ")";
+  }
+};
+
+class ButtonReleased : public Behaviour {
+  /*
+   * Class that defines a behaviour that publishes a
+   * ButtonReleased message to the input topic of the
+   * MQQT broker
+   */
+   VizBlocks* _node;
+
+public:
+  ButtonReleased(VizBlocks* node, String name = "ButtonReleased") :
+    Behaviour(name), _node(node){ }
+
+  char* args() {return "<String buttonId>"; };
+
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Input\":{\"type\":\"" + String(name()) + "\",\"button\":\"" + args + "\"}}";
+    _node->announce(str);
+    return "ButtonReleased behaviour " + _name + " with (" + args + ")";
+  }
+};
+
+class ButtonClicked : public Behaviour {
+  /*
+   * Class that defines a behaviour that publishes a
+   * ButtonClicked message to the input topic of the
+   * MQQT broker
+   */
+   VizBlocks* _node;
+
+public:
+  ButtonClicked(VizBlocks* node, String name = "ButtonClicked") :
+    Behaviour(name), _node(node){ }
+
+  char* args() {return "<String buttonId>"; };
+
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Input\":{\"type\":\"" + String(name()) + "\",\"button\":\"" + args + "\"}}";
+    _node->announce(str);
+    return "ButtonClicked behaviour " + _name + " with (" + args + ")";
+  }
+};
+
+class ButtonHeld : public Behaviour {
+  /*
+   * Class that defines a behaviour that publishes a
+   * ButtonLongPressed message to the input topic of the
+   * MQQT broker
+   */
+   VizBlocks* _node;
+
+public:
+  ButtonHeld(VizBlocks* node, String name = "ButtonHeld") :
+    Behaviour(name), _node(node){ }
+
+  char* args() {return "<String buttonId>"; };
+
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Input\":{\"type\":\"" + String(name()) + "\",\"button\":\"" + args + "\"}}";
+    _node->announce(str);
+    return "ButtonHeld behaviour " + _name + " with (" + args + ")";
+  }
+};
+
+class ButtonTick : public Behaviour {
+  /*
+   * Class that defines a behaviour that publishes a
+   * ButtonRepeatPressed message to the input topic of the
+   * MQQT broker
+   */
+   VizBlocks* _node;
+
+public:
+  ButtonTick(VizBlocks* node, String name = "ButtonTick") :
+    Behaviour(name), _node(node){ }
+
+  char* args() {return "<String buttonId>"; };
+
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Input\":{\"type\":\"" + String(name()) + "\",\"button\":\"" + args + "\"}}";
+    _node->announce(str);
+    return "ButtonTick behaviour " + _name + " with (" + args + ")";
+  }
+};
+
+#endif
diff --git a/CommsBehaviours.h b/CommsBehaviours.h
new file mode 100644
index 0000000000000000000000000000000000000000..3def262017d5ab3ca6c1f50f9883cd8edf77e193
--- /dev/null
+++ b/CommsBehaviours.h
@@ -0,0 +1,109 @@
+#ifndef COMMS_BEHAVIOUR_h
+#define COMMS_BEHAVIOUR_h
+#include "Arduino.h"
+#include "Behaviours.h"
+#include <VizBlocks.h>
+
+/*
+ * --------------------------------------------------
+ * ---------------- SendCapabilities ----------------
+ * --------------------------------------------------
+ */
+
+class SendCapabilities : public Behaviour {
+   VizBlocks* _node;
+
+public:
+  SendCapabilities(VizBlocks* node, String name = "SendCapabilities") :
+    Behaviour(name), _node(node){ }
+
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    _node->announce_capabilities();
+    return "SendCapabilities behaviour " + _name;
+  }
+
+};
+
+/*
+ * --------------------------------------------------
+ * ---------------------- Link ----------------------
+ * --------------------------------------------------
+ */
+
+class Link : public Behaviour {
+  VizBlocks* _node;
+  String _peerId;
+  const int _timeoutInterval = 5000;
+  unsigned long _t = 0;
+
+public:
+  Link(VizBlocks* node, String name = "Link") : Behaviour(name), _node(node)  { _background = true; }
+
+  char* args() {return "<String peerId>"; };
+
+  String start(String args) {
+    _running = true;
+    if (args == name() || args.indexOf(" ")>0) {
+      return "Invalid args (" + args + ") in behaviour " + name();
+    }
+
+    _t = millis();
+
+    if (args == _peerId) {
+      return "Link ping from (" + _peerId + ")";
+    }
+
+    _peerId = args;
+
+    String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Link\":{\"peerId\":\"" + _peerId + "\"}}";
+    _node->announce(str);
+
+    return "New link with (" + _peerId + ")";
+  }
+
+  void update() {
+    if (millis() > (_t+_timeoutInterval)) {
+      String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Unlink\":{\"peerId\":\"" + _peerId + "\"}}";
+     _node->announce(str);
+      _peerId = "";
+      _running = false;
+    }
+  }
+
+};
+
+/*
+ * --------------------------------------------------
+ * ------------------- PingServer -------------------
+ * --------------------------------------------------
+ */
+
+class PingServer : public Behaviour {
+  VizBlocks* _node;
+  String str;
+  const int _interval = 4000;
+  unsigned long _t = 0;
+
+public:
+  PingServer(VizBlocks* node, String name = "PingServer") : Behaviour(name), _node(node) { _background = true; }
+
+  String start(String args) {
+    _background = true;
+    _running = true;
+    _t = millis();
+    str = "{\"id\":\"" + String(_node->getId()) + "\",\"PingServer\":{}}";
+    _node->announce(str);
+    return "Pinging server";
+  }
+
+  void update() {
+    if (millis() > (_t+_interval)) {
+      _t = millis();
+     _node->announce(str);
+    }
+  }
+
+};
+
+#endif
diff --git a/LEDBehaviours.h b/LEDBehaviours.h
index c20cc2a05515499fe498cf3ec43730178f7b22c3..533e57879a6f46ea2857e6431e7c17561a8517ad 100644
--- a/LEDBehaviours.h
+++ b/LEDBehaviours.h
@@ -10,7 +10,7 @@ class NumLEDs : public Behaviour {
   uint32_t _color;
 
 public:
-  NumLEDs(Adafruit_NeoPixel* strip, String name = "num_leds", uint32_t color=0xFFFFFFFF) :
+  NumLEDs(Adafruit_NeoPixel* strip, String name = "NumLEDs", uint32_t color=0xFFFFFFFF) :
       Behaviour(name), _strip(strip), _color(color){ }
   char* args() {return "<int num_leds>"; };
 
@@ -33,7 +33,7 @@ class BrightnessLEDs : public Behaviour {
   uint32_t _sat;
 
 public:
-  BrightnessLEDs(Adafruit_NeoPixel* strip, String name = "num_leds", uint32_t hue=0, uint32_t sat=0) :
+  BrightnessLEDs(Adafruit_NeoPixel* strip, String name = "BrightnessLEDs", uint32_t hue=0, uint32_t sat=0) :
       Behaviour(name), _strip(strip), _hue(hue), _sat(sat){ }
   char* args() {return "<int brightness>"; };
 
@@ -58,7 +58,7 @@ class BreathingLEDs : public Behaviour {
   int _direction = 1;
 
 public:
-  BreathingLEDs(Adafruit_NeoPixel* strip, String name = "breathe_leds", uint32_t hue=0, uint32_t sat=0) :
+  BreathingLEDs(Adafruit_NeoPixel* strip, String name = "BreathingLEDs", uint32_t hue=0, uint32_t sat=0) :
       Behaviour(name), _strip(strip), _hue(hue * 255), _sat(sat) { }
   char* args() {return "<int rate (1-255ish)>"; };
 
diff --git a/NameDictionary.h b/NameDictionary.h
new file mode 100644
index 0000000000000000000000000000000000000000..0feeda45ae25858f2f47977214c837bb409bfb6e
--- /dev/null
+++ b/NameDictionary.h
@@ -0,0 +1,80 @@
+#ifndef NAMEDICTIONARY_h
+#define NAMEDICTIONARY_h
+
+typedef struct {
+  String key;
+  String value;
+} keyValuePair;
+
+class NameDictionary {
+
+  keyValuePair data[50] = {
+    {"c2c373", "abe"},
+    {"c31d9d", "aja"},
+    {"c2b603", "ace"},
+    {"da58f5", "ali"},
+    {"da6195", "alf"},
+    {"da50d8", "amy"},
+    {"da5649", "ann"},
+    {"c2b2d6", "art"},
+    {"da516d", "aya"},
+    {"c2a597", "bea"},
+    {"da5331", "bev"},
+    {"8e07b",  "bob"},
+    {"c318a1", "bud"},
+    {"da5a56", "deb"},
+    {"da4a70", "cal"},
+    {"c2c5c2", "cam"},
+    {"c2a5e6", "che"},
+    {"c2a23f", "dot"},
+    {"c2c415", "dan"},
+    {"c2bf2a", "dax"},
+    {"30d6ed", "fin"},
+    {"30d00b", "jim"},
+    {"1a6b16", "joe"},
+    {"8810e9", "kat"},
+    {"31054b", "kev"},
+    {"30ce48", "sam"},
+    {"30db8b", "tim"},
+  };
+
+  int _arraySize;
+
+  public:
+    NameDictionary() {
+      _arraySize = sizeof(data) / sizeof(keyValuePair);
+    };
+
+    String get(String key) {
+      for (int i = 0; i < _arraySize; i++) {
+        if (key == data[i].key) {
+          return data[i].value;
+        }
+      }
+      return key;
+    };
+
+    void list() {
+      for (int i = 0; i < _arraySize; i++) {
+        Serial.println(data[i].key + " : " + data[i].value);
+      }
+    };
+
+    void values() {
+      for (int i = 0; i < _arraySize; i++) {
+        Serial.println(data[i].value);
+      }
+    };
+
+    void keys() {
+      for (int i = 0; i < _arraySize; i++) {
+        Serial.println(data[i].key);
+      }
+    };
+
+    int length() {
+      return _arraySize;
+    }
+};
+
+#endif
diff --git a/Potentiometer.h b/Potentiometer.h
new file mode 100644
index 0000000000000000000000000000000000000000..29949e6ea5ba3dd130f83c1c7170c618c12f83da
--- /dev/null
+++ b/Potentiometer.h
@@ -0,0 +1,88 @@
+#ifndef POTENTIOMETER_h
+#define POTENTIOMETER_h
+
+class Potentiometer {
+
+  int EMA_S = 0;          //initialization of EMA S
+  float EMA_a = 0.6;
+
+  int _pin;
+  int _id;
+
+  int _value;
+  int _previousReading;
+
+  bool _inputFlag = false;
+  bool _changeFlag = false;
+
+  unsigned long _previousTimer;
+  int _interval = 200;
+
+  void (*_cb)(Potentiometer*, uint8_t, uint8_t); // Callback function
+
+  int _read() {
+    int sensorValue = analogRead(_pin);                //read the sensor value using ADC
+    EMA_S = (EMA_a*sensorValue) + ((1-EMA_a)*EMA_S);   //run the EMA
+    int mappedValue = map(EMA_S, 5, 1023, 0, 100);
+
+    return mappedValue;
+  }
+
+  void _setValue(int x) {
+    _value = x;
+  }
+
+  public:
+
+    static const uint8_t kEventStableUpdate = 0;
+    static const uint8_t kEventUnstableUpdate = 1;
+
+    Potentiometer(int pin, int id = 99) : _pin(pin), _id(id) {
+      pinMode(pin, INPUT);
+      EMA_S = analogRead(_pin);  //set EMA S for t=1
+      _value = EMA_S;
+      _previousReading = EMA_S;
+
+      _previousTimer = millis();
+      _inputFlag = true;
+    };
+
+    void setEventHandler(void(*function)(Potentiometer*, uint8_t, uint8_t)) {
+      _cb = function;
+    }
+
+    int getValue() {
+      return _value;
+    }
+
+    int getId() {
+      return _id;
+    }
+
+    void check() {
+      unsigned long timer = millis();
+      unsigned long deltaTime = timer - _previousTimer;
+
+      int reading = _read();
+      int deltaValue = abs(reading - _value);
+
+      if (reading != _value) {
+        _inputFlag = true;
+      }
+
+      if (_inputFlag == true && deltaValue > 1) {
+        _inputFlag = false;
+        _changeFlag = true;
+        _previousTimer = timer;
+        _setValue(reading);
+        _cb(this, kEventUnstableUpdate, getValue());
+      }
+
+      if (_changeFlag == true &&  deltaTime > _interval) {
+        _changeFlag = false;
+        _cb(this, kEventStableUpdate, getValue());
+      }
+    }
+};
+
+#endif
diff --git a/PotentiometerBehaviours.h b/PotentiometerBehaviours.h
new file mode 100644
index 0000000000000000000000000000000000000000..6bfe27c131cad098a82d92ac4e033646f23aa4b0
--- /dev/null
+++ b/PotentiometerBehaviours.h
@@ -0,0 +1,39 @@
+#ifndef POTENTIOMETER_BEHAVIOUR_h
+#define POTENTIOMETER_BEHAVIOUR_h
+#include "Arduino.h"
+#include "Behaviours.h"
+#include <VizBlocks.h>
+
+class PotentiometerUpdated : public Behaviour {
+  /*
+   * Class that defines a behaviour that publishes a
+   * ButtonPressed message to the input topic of the
+   * MQQT broker
+   */
+   VizBlocks* _node;
+
+public:
+  PotentiometerUpdated(VizBlocks* node, String name = "PotentiometerUpdated") :
+    Behaviour(name), _node(node){ }
+
+  char* args() {return "<String potentiometerId> <int value>"; };
+
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    int index = args.indexOf(" ");
+    String pot = "";
+    String value = "";
+
+    if ( index > 0 ) {
+      pot = args.substring(0, index);
+      value = args.substring(index+1);
+    } else {
+      return "PotentiometerUpdated behaviour args error!";
+    }
+    String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Input\":{\"type\":\"" + String(name()) + "\",\"pot\":\"" + pot + "\",\"value\":\"" + value + "\"}}";
+    _node->announce(str);
+    return "PotentiometerUpdated behaviour " + _name + " with (" + args + ")";
+  }
+};
+
+#endif
diff --git a/README.md b/README.md
index db81da6926e09be5d68bdaf39beb8a0339dd76a7..41ef90fef54dd650e6b5294a491468294a073333 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Wallvis Framework
+# VizBlocks Framework
 
 This is an Arduino library that lets you easily create nodes to stick on the wall. Each node will listen on an MQTT channel, and respond to commands. So a node with a servo motor in might respond to:
 * `wiggle 30` - wiggle by 30 degrees a few times
@@ -7,9 +7,9 @@ These commands can be put in via NodeRED, or through the USB Serial connection f
 
 ## Installation
 
-One way to install this is put it in you personal Arduino libraries directory. On a mac, this is `~/Documents/Arduino/libraries`. It is best to check it out with a capitalised name, i.e. `WallvisFramework` not `wallvisframework`. To do this, you can use:
+One way to install this is put it in you personal Arduino libraries directory. On a mac, this is `~/Documents/Arduino/libraries`. It is best to check it out with a capitalised name, i.e. `VizBlocksFramework` not `VizBlocksframework`. To do this, you can use:
 
-`git clone https://git.ecdf.ed.ac.uk/design-informatics/wallvis/wallvisframework.git WallvisFramework`
+`git clone https://git.ecdf.ed.ac.uk/design-informatics/VizBlocks/VizBlocksframework.git VizBlocksFramework`
 
 The library will then appear in your list of Arduino libraries, along with examples.
 
@@ -26,18 +26,18 @@ Because this is not a single sketch, development needs a bit of thinking about.
 # Usage
 
 
-The library is designed to be used within normal Arduino sketches. It wraps up most of the business of connecting to MQTT etc. in a `WallVis` class, and you then give it a bunch of `Behaviours` that do interesting things.
+The library is designed to be used within normal Arduino sketches. It wraps up most of the business of connecting to MQTT etc. in a `VizBlocks` class, and you then give it a bunch of `Behaviours` that do interesting things.
 
 ## Setup
 The node is set up with all of the connection information for the WiFi network and for NodeRE, e.g.:
 
 ```arduino
-#include <WallVis.h>
+#include <VizBlocks.h>
 
-WallVis node(
+VizBlocks node(
   "new001",     // Our ID
-  "WallVisNet", //Wifi Access Point
-  "wallvisAP",  //WiFi Password
+  "VizBlocksNet", //Wifi Access Point
+  "VizBlocksAP",  //WiFi Password
   "192.168.4.1",//IP address of Node RED server
   1883          //Port for Node RED server
   );
@@ -118,3 +118,28 @@ _Please update this table as you generate new behaviours!_
 At first - make behaviours with your sketch, while you are testing them. See the examples for this!
 
 When you've got something stable, add it to the library. If it fits within an existing file, add it to that (e.g. if it's another thing tthat Servos do, add it to `ServoBehaviours.h`). If it's a new kind of thing, then create a new file and add it in there. (Make sure you do the #IFNDEF stuff - ask if you don't know what that is!).
+
+## Helpful link:
+
+Node Red commands for Evan's blocks:
+
+Servos:
+* `wiggle <int>` - int between 0 - 180
+* `slow_wiggle <int>` - int between 0 - 180
+* `fast_wiggle <int>` - int between 0 - 180
+* `goto <int>` - int between 0 - 180
+* `drop` - behaviour that rotates from 0 to 180 and back again
+
+LEDs:
+* `green_leds <int>` - turns LEDs green, int between 0 - 12
+* `red_leds <int>` - turns LEDs red,  int between 0 - 12
+* `leds <int>` - turns LEDs white,  int between 0 - 12
+* `green <int>` - turns all LEDs green with set brightness, int between 0 - 100 ?
+* `red <int>` - turns all LEDs red with set brightness, int between 0 - 100 ?
+* `breathe <int>` - LEDs increase / decrease brightness with set speed, int between ?
+* `breathe_blue <int>` - blue LEDs increase / decrease brightness with set speed, int between ?
+
+
+## Helpful link:
+
+https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html
diff --git a/RotaryEncoder.h b/RotaryEncoder.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b6901f6c696e84e9f3fa3e81ca644ff888a58d1
--- /dev/null
+++ b/RotaryEncoder.h
@@ -0,0 +1,192 @@
+#ifndef ROTARYENCODER_h
+#define ROTARYENCODER_h
+
+class RotaryEncoder {
+
+    // Private members:
+
+    int _pinA;
+    int _pinB;
+    int _id;
+
+    volatile int _state[2];
+    volatile int _position;
+
+    volatile bool _inputFlag = false;
+    bool _changeFlag = false;
+
+    unsigned long _previousTimer;
+    int _interval = 200;
+
+    void (*_cb)(RotaryEncoder*, uint8_t, int); // Callback function
+
+    // {newPin2, newPin1, oldPin2, oldPin1}
+    int movements[5][4][4] = {
+      { // No movement
+        {0, 0, 0, 0},
+        {0, 1, 0, 1},
+        {1, 0, 1, 0},
+        {1, 1, 1, 1}
+      },
+      { // +1
+        {0, 0, 0, 1},
+        {0, 1, 1, 1},
+        {1, 0, 0, 0},
+        {1, 1, 1, 0}
+      },
+      { // -1
+        {0, 0, 1, 0},
+        {0, 1, 0, 0},
+        {1, 0, 1, 1},
+        {1, 1, 0, 1}
+      },
+      { // +2
+        {0, 0, 1, 1},
+        {1, 1, 0, 0}
+      },
+      { // -2
+        {0, 1, 1, 0},
+        {1, 0, 0, 1}
+      },
+    };
+
+    // Private Functions:
+
+    void _setState(int a, int b) {
+      _state[0] = a;
+      _state[1] = b;
+    }
+
+    void _incrementPosition(int delta) {
+      _position = _position + delta;
+    }
+
+    int _findChange(int state1[2], volatile int state2[2]) {
+      int stateAppend[] = {state1[1], state1[0], state2[1], state2[0]};
+
+      for (int i = 0; i < 3; i++) {
+        for (int j = 0; j < 4; j++) {
+          if (_compareArrays(stateAppend, movements[i][j])) {
+            if (i == 0) {
+              return 0;
+            }
+            else if (i == 1) {
+              return 1;
+            }
+            else if (i == 2) {
+              return -1;
+            }
+            else if (i == 3) {
+              return 2;
+            }
+            else if (i == 4) {
+              return -2;
+            }
+          }
+        }
+      }
+
+      for (int i = 3; i < 5; i++) {
+        for (int j = 0; j < 2; j++) {
+          if (_compareArrays(stateAppend, movements[i][j])) {
+            if (i == 3) {
+              return 2;
+            }
+            else if (i == 4) {
+              return -2;
+            }
+          }
+        }
+      }
+      Serial.println("INVALID DATA");
+      return 0;
+    }
+
+    boolean _compareArrays(int a[4], int b[4]) {
+      if (a[0] != b[0]) {
+        return false;
+      }
+      if (a[1] != b[1]) {
+        return false;
+      }
+      if (a[2] != b[2]) {
+        return false;
+      }
+      if (a[3] != b[3]) {
+        return false;
+      }
+      return true;
+    }
+
+  public:
+
+    // Public members:
+
+    static const uint8_t kEventStableUpdate = 0;
+    static const uint8_t kEventUnstableUpdate = 1;
+
+    //Public Functions:
+
+    RotaryEncoder(int pinA, int pinB, int id = 99) : _pinA(pinA), _pinB(pinB), _id(id) {
+      pinMode(_pinA, INPUT_PULLUP);
+      pinMode(_pinB, INPUT_PULLUP);
+
+      _previousTimer = millis();
+      _setState(digitalRead(_pinA), digitalRead(_pinB));
+      setPosition(0);
+    }
+
+    void initInterrupts(void(*function)()) {
+      attachInterrupt(_pinA, function, CHANGE);
+      attachInterrupt(_pinB, function, CHANGE);
+    }
+
+    void setEventHandler(void(*function)(RotaryEncoder*, uint8_t, int)) {
+      _cb = function;
+    }
+
+    int getPostition() {
+      return _position;
+    }
+
+    int getId() {
+      return _id;
+    }
+
+    void setPosition(int value) {
+      _position = value;
+    }
+
+    void check() {
+      unsigned long timer = millis();
+      unsigned long deltaTime = timer - _previousTimer;
+
+      if (_inputFlag == true) {
+        _inputFlag = false;
+
+        _changeFlag = true;
+        _previousTimer = timer;
+
+        _cb(this, kEventUnstableUpdate, getPostition());
+      }
+
+      if (_changeFlag == true && deltaTime > _interval) {
+        _changeFlag = false;
+
+        _cb(this, kEventStableUpdate, getPostition());
+      }
+    }
+
+    void ICACHE_RAM_ATTR tick() {
+      int tempState[] = {digitalRead(_pinA), digitalRead(_pinB)};
+      int delta = _findChange(tempState, _state);
+      if (delta != 0) {
+        _incrementPosition(delta);
+        _inputFlag = true;
+      }
+      _setState(tempState[0], tempState[1]);
+    }
+
+};
+
+#endif
diff --git a/RotaryEncoderBehaviours.h b/RotaryEncoderBehaviours.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ffeb485e1dcc5091af2a95e3572cf13899b976d
--- /dev/null
+++ b/RotaryEncoderBehaviours.h
@@ -0,0 +1,40 @@
+#ifndef ROTARYENCODER_BEHAVIOUR_h
+#define ROTARYENCODER_BEHAVIOUR_h
+#include "Arduino.h"
+#include "Behaviours.h"
+#include <VizBlocks.h>
+
+class RotaryEncoderUpdated : public Behaviour {
+  /*
+   * Class that defines a behaviour that publishes a
+   * ButtonPressed message to the input topic of the
+   * MQQT broker
+   */
+   VizBlocks* _node;
+
+public:
+  RotaryEncoderUpdated(VizBlocks* node, String name = "RotaryEncoderUpdated") :
+    Behaviour(name), _node(node){ }
+
+  char* args() {return "<String rotaryEncoderId> <int position>"; };
+
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    int index = args.indexOf(" ");
+    String encoder = "";
+    String position = "";
+
+    if ( index > 0 ) {
+      encoder = args.substring(0, index);
+      position = args.substring(index+1);
+    } else {
+      return "RotaryEncoderUpdated behaviour args error!";
+    }
+
+    String str = "{\"id\":\"" + String(_node->getId()) + "\",\"Input\":{\"type\":\"" + String(name()) + "\",\"encoder\":\"" + encoder + "\",\"position\":\"" + position + "\"}}";
+    _node->announce(str);
+    return "RotaryEncoderUpdated behaviour " + _name + " with (" + args + ")";
+  }
+};
+
+#endif
diff --git a/ServoBehaviours.h b/ServoBehaviours.h
index 7fbeb200701f3317e50b6b12641ed8b49017ef6b..03d5fa0f83e59e2ed357ece91cefce8cab3fd177 100644
--- a/ServoBehaviours.h
+++ b/ServoBehaviours.h
@@ -9,7 +9,7 @@ class ServoGoto : public Behaviour {
   Servo _servo;
 
 public:
-  ServoGoto(Servo servo, String name = "goto") :  Behaviour(name), _servo(servo){ }
+  ServoGoto(Servo servo, String name = "ServoGoto") :  Behaviour(name), _servo(servo){ }
   //ServoMove(Servo servo, String name) : Behaviour(name), _servo(servo) {}
 
   char* args() {return "<int angle>"; };
@@ -33,7 +33,7 @@ class ServoWiggle : public Behaviour {
   int _wiggle_factor = 5;
 
 public:
-  ServoWiggle(Servo servo, String name, int slowness=3) : Behaviour(name), _servo(servo),_wiggle_factor(slowness) {}
+  ServoWiggle(Servo servo, String name = "ServoWiggle", int slowness=3) : Behaviour(name), _servo(servo),_wiggle_factor(slowness) {}
   char* args() {return "<int wiggle_angle>"; };
   String start(String args) {
     _wiggle_angle = args.toInt();
@@ -60,7 +60,7 @@ public:
 
 };
 
-class RotateReturn : public Behaviour {
+class ServoRotateReturn : public Behaviour {
   Servo _servo;
   int _start_angle = 0;
   int _end_angle = 180;
@@ -70,7 +70,7 @@ class RotateReturn : public Behaviour {
   int _pause = 500;
 
 public:
-  RotateReturn(Servo servo, String name="rotate", int delay=30, int pause=500, int start_angle = 2, int end_angle=178 ) :
+  ServoRotateReturn(Servo servo, String name="ServoRotateReturn", int delay=30, int pause=500, int start_angle = 2, int end_angle=178 ) :
         Behaviour(name), _servo(servo),_delay(delay), _pause(pause), _start_angle(start_angle), _end_angle(end_angle) {}
   char* args() {return "<int number_of_cycles>"; };
   String start(String args) {
diff --git a/WallVis.cpp b/VizBlocks.cpp
similarity index 100%
rename from WallVis.cpp
rename to VizBlocks.cpp
diff --git a/WallVis.h b/VizBlocks.h
similarity index 63%
rename from WallVis.h
rename to VizBlocks.h
index 78b4257baf66a0be3fd42c0d96dd26c11ce25382..d497a71da59fc35fedb5e1db1cc1a6526eb9449b 100644
--- a/WallVis.h
+++ b/VizBlocks.h
@@ -1,5 +1,5 @@
-#ifndef WALLVIS_H
-#define WALLVIS_H
+#ifndef VizBlocks_H
+#define VizBlocks_H
 #include "Arduino.h"
 #include "Behaviours.h"
 #include "ServoBehaviours.h"
@@ -10,11 +10,9 @@
 #include "Adafruit_MQTT_Client.h"
 
 #define MQTT_topic  "new001"
+#define NUM_BACKGROUND_BEHAVIOURS 5
 
-
-
-
-class WallVis {
+class VizBlocks {
   char* _ssid;
   char* _wifi_pass;
   char* _id;
@@ -22,34 +20,42 @@ class WallVis {
   int _port;
   BehaviourTable _behaviours;
   Behaviour* _active = nullptr;
+  Behaviour* _background[NUM_BACKGROUND_BEHAVIOURS];
   int _loop_time = 5;
   Adafruit_MQTT_Client* _mqtt;
   Adafruit_MQTT_Subscribe* _device_subscription;
+
   Adafruit_MQTT_Publish* _announce;
   Adafruit_MQTT_Publish* _my_announce;
-  WiFiClient* _client;
   String _my_announce_channel;
+
+  Adafruit_MQTT_Publish* _input;
+  Adafruit_MQTT_Publish* _my_input;
+  String _my_input_channel;
+
+  WiFiClient* _client;
   boolean _wifi;
 
+  String capabilitiesJSON[50];
+
 public:
-  WallVis(char* id, char* ssid="WallVisNet", char* wifi_pass="wallvisAP",
-    char* server="192.168.4.1",int port=1883) : _id(id), _server(server), _port(port), _ssid(ssid), _wifi_pass(wifi_pass) {} ;
+  VizBlocks(char* id, char* ssid="VizBlocksNet", char* wifi_pass="VizBlocksAP",
+    char* server="172.20.10.8",int port=1883) : _id(id), _server(server), _port(port), _ssid(ssid), _wifi_pass(wifi_pass) {} ;
 
   void command_callback(char *data, uint16_t len) {
     Serial.println("Got command: ");
     Serial.println(data);
   }
 
-  void set_wifi(boolean v ) { _wifi = v; }
-
+  void set_wifi(boolean v) { _wifi = v; }
 
   /*
-   * Set up the WallVis node - WiFi, MQTT
+   * Set up the VizBlocks node - WiFi, MQTT
    */
   void init() {
     Serial.setTimeout(100);
     Serial.println();
-    Serial.println(F("WallVis Node starting up"));
+    Serial.println(F("VizBlocks Node starting up"));
     Serial.println("Initialising " + String(_id));
 
     if( _wifi ) {
@@ -88,13 +94,12 @@ public:
       MQTT_connect();
     }
 
+    generateCapabilitiesJSON();
     announce_capabilities();
     Serial.println("Init finished");
 
   }
 
-
-
   /*
    * Add a behaviour to the list of possible behaviours
    */
@@ -107,15 +112,22 @@ public:
    * this function is the only thing you should need to call. It will manage
    * it's own delay, so you can call as often as possible.
    */
-  void vis_loop() {
+  void run() {
     int loop_start_time = millis();
     serial_command();
     if( _wifi ) { mqtt_command(); }
     if( _active ) {
-      //Serial.println("Updating "+_active->name());
       _active -> update();
-      if( ! _active->is_running() ) _active = nullptr;
+      if( ! _active->is_running() ) { _active = nullptr; }
+    }
+
+    for (int i = 0; i < NUM_BACKGROUND_BEHAVIOURS; i++) {
+      if( _background[i] ) {
+        _background[i] -> update();
+        if( !_background[i] -> is_running() ) { _background[i] = nullptr; }
+      }
     }
+
     int loop_time_taken = millis()-loop_start_time;
     if( loop_time_taken < _loop_time ) {
       delay( _loop_time - loop_time_taken );
@@ -128,6 +140,7 @@ public:
   void serial_command() {
     if( Serial.available() ) {
       String cmd = Serial.readStringUntil('\n');
+      cmd.replace("\r", "");
       Serial.println(process(cmd));
     }
   }
@@ -151,33 +164,61 @@ public:
   /*
    * Process a command. This means:
    * - split the command name from the arguments
-   * - call process_comman with the separated command and argument string
+   * - call process_command with the separated command and argument string
    */
   String process(String input) {
-    int index = input.indexOf(" ");
-    String command = "";
-    String args = "";
 
-    if( index) {
-      command = input.substring(0,index);
-      args = input.substring(index+1);
-    } else {
-      command = input;
+    if (!(input.indexOf("<") >= 0 || input.indexOf(">") >= 0 || input.indexOf("-") >= 0)) {
+      int index = input.indexOf(" ");
+      String command = "";
+      String args = "";
+
+      if( index ) {
+        command = input.substring(0,index);
+        args = input.substring(index+1);
+      } else {
+        command = input;
+      }
+      return process_command(command, args);
     }
-    return process_command(command, args);
+  }
+
+  String input_event(String input) {
+    return process(input);
   }
 
   /*
    * Process a command and its arguments. This means:
-   * - look for a Behaiour with the right name
+   * - look for a Behaviour with the right name
    * - if found, then call that behaviour with the arguments (which are still a single string)
    */
   String process_command(String command, String args) {
     Serial.println("Processing <"+command+"> <"+args+">");
     Behaviour* b = _behaviours.get(command);
     if(b) {
+      // Stop whatever behaviour is running in the active slot.
       if( _active ) { _active->stop(); }
       Serial.println( "Found behaviour: <"+command+">" );
+
+      if ( b->is_background() ) {
+        // If this behaviour is already running in the background, refresh it and move on.
+        for (int i = 0; i < NUM_BACKGROUND_BEHAVIOURS; i++) {
+          if ( _background[i] ) {
+            if ( b->name() == _background[i]->name() ) {
+              return( b->start(args) );
+            }
+          }
+        }
+        // Else, if there is space for another background behaviour, start it running.
+        for (int i = 0; i < NUM_BACKGROUND_BEHAVIOURS; i++) {
+          if ( !_background[i] ) {
+            _background[i] = b;
+            return( b->start(args) );
+          }
+        }
+        return "Couldn't run command: " + command + ". Background behaviours full.";
+      }
+
       _active = b;
       return( b->start(args) );
     } else {
@@ -214,35 +255,51 @@ public:
     Serial.println("MQTT Connected!");
   }
 
+  void generateCapabilitiesJSON() {
+    String head = "{\"id\":\"" + String(_id) + "\",\"Behaviour\":{";
+    for (int i = 0; i < _behaviours.get_num_behaviours(); i++) {
+      Behaviour* b = _behaviours.get_by_num(i);
+      String args = b->args();
+      String body = "\"name\":\"" + b->name() + "\",\"args\":\"" + args + "\"}}";
+      String str = head + body;
+      capabilitiesJSON[i] = str;
+    }
+  }
+
+  void announce(String doc) {
+    if( _wifi ) { _my_announce->publish(doc.c_str()); }
+    Serial.print("-->");
+    Serial.println(doc);
+  }
+
   void announce_capabilities() {
-    Serial.print("Node ");
-    Serial.println(_id);
+    String doc;
     if( _wifi ) {
       if( ! _announce->publish(_id) ) { Serial.println("Couldn't make announcement"); }
     }
     for( int i = 0; i < _behaviours.get_num_behaviours(); i++ ) {
-      Behaviour* b = _behaviours.get_by_num(i);
-      String doc = b->name() + ": " + b->args();
-      if( _wifi ) { _my_announce->publish(doc.c_str()); }
-      Serial.print("-->");
-      Serial.println(doc);
+      doc = capabilitiesJSON[i];
+      announce(doc);
     }
   }
 
-};
-
-
+  void setID(char* id) {
+    _id = id;
+  }
 
-/* Left here temporarily - can't use a member function as a callback
-   So this was the start of a way to create a static function that would work
-void* current_wallvis;
+  char* getId() {
+    return _id;
+  }
 
-void test_callback(char *data, uint16_t len) {
-  Serial.println("Callback: ");
-  Serial.println(data);
-  ((WallVis*)current_wallvis)->process(String(data));
-}
-*/
+};
 
+/*
+ * These behaviours depend on VizBlocks class so they must be included after
+ * it has been defined.
+ */
+#include "CommsBehaviours.h"
+#include "ButtonBehaviours.h"
+#include "PotentiometerBehaviours.h"
+#include "RotaryEncoderBehaviours.h"
 
 #endif
diff --git a/examples/.DS_Store b/examples/.DS_Store
deleted file mode 100644
index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000
Binary files a/examples/.DS_Store and /dev/null differ
diff --git a/examples/CustomBehaviour/CustomBehaviour.ino b/examples/CustomBehaviour/CustomBehaviour.ino
index 1b35d6caffa44b2d05adbb0349bae6844f09e989..80f71db0ea352cd46bdef073c3ae9f2e27591295 100644
--- a/examples/CustomBehaviour/CustomBehaviour.ino
+++ b/examples/CustomBehaviour/CustomBehaviour.ino
@@ -1,10 +1,10 @@
-#include <WallVis.h>
+#include <VizBlocks.h>
 #include <Behaviours.h>
 
-WallVis node(
+VizBlocks node(
   "new001",     // Our ID
-  "WallVisNet", //Wifi Access Point
-  "wallvisAP",  //WiFi Password
+  "VizBlocksNet", //Wifi Access Point
+  "VizBlocksAP",  //WiFi Password
   "192.168.4.1",//IP address of Node RED server
   1883          //Port for Node RED server
   );
diff --git a/examples/EventButton/EventButton.ino b/examples/EventButton/EventButton.ino
new file mode 100644
index 0000000000000000000000000000000000000000..993153756473915a59ff9f9f8a1d7193f7fc5905
--- /dev/null
+++ b/examples/EventButton/EventButton.ino
@@ -0,0 +1,57 @@
+#include "Button.h"
+
+const int pin = 2;
+const int ID = 0;
+
+Button b(pin, ID);
+
+void ICACHE_RAM_ATTR ISR() {
+  b.tick();
+}
+
+void setup() {
+  // put your setup code here, to run once:
+  Serial.begin(115200);
+  b.initInterrupts(ISR);
+  b.setEventHandler(cb);
+  delay(500);
+  
+  Serial.println("\n\nESP8266 Button Test:");
+}
+
+void loop() {
+  // put your main code here, to run repeatedly:
+  b.check();
+}
+
+void cb(Button* button, uint8_t eventType, bool state) {
+  /*
+   * Rotary Encoder event handler that triggers VizBlocks behaviours
+   */
+   
+  String idString = String(button->getId());
+
+  Serial.println("Button ID: " + idString + " Event Type: " + String(eventType) + " State: " + String(state));
+
+  switch(eventType) {
+    case Button::kEventPressed:
+    //Do something
+    break;
+    
+    case Button::kEventReleased:
+    //Do something else
+    break;
+
+    case Button::kEventClicked:
+    //Do something else
+    break;
+
+    case Button::kEventHeld:
+    //Do something else
+    break;
+
+    case Button::kEventTick:
+    //Do something else
+    break;
+  }
+}
diff --git a/examples/EventPotentiometer/EventPotentiometer.ino b/examples/EventPotentiometer/EventPotentiometer.ino
new file mode 100644
index 0000000000000000000000000000000000000000..a078a53ae14df5961abc0bea5e9e28eda374ba3a
--- /dev/null
+++ b/examples/EventPotentiometer/EventPotentiometer.ino
@@ -0,0 +1,40 @@
+#include "Potentiometer.h"
+
+const String device_id = String(ESP.getChipId(), HEX);
+
+const int sensorPin = A0;
+
+Potentiometer pot(sensorPin, 0);
+
+void setup() {
+  Serial.begin(115200);
+  pot.setEventHandler(cb);
+  delay(500);
+
+  Serial.println("\n\nESP8266 Potentiometer Test");
+  Serial.println("\nThis is board: " + device_id + "\n");
+}
+
+void loop() {
+  pot.check();
+}
+
+void cb(Potentiometer* potentiometer, uint8_t eventType, uint8_t sensorValue) {
+  /*
+   * Potentiometer Event Handler that triggers VizBlocks behaviours
+   */
+  
+  String idString = String(potentiometer->getId());
+
+  Serial.println("Slider ID: " + idString + " Event Type: " + String(eventType) + " Sensor Value: " + String(sensorValue));
+
+  switch(eventType) {
+    case Potentiometer::kEventStableUpdate:
+    //Do something
+    break;
+    
+    case Potentiometer::kEventUnstableUpdate:
+    //Do something else
+    break;
+  }
+}
diff --git a/examples/EventRotaryEncoder/EventRotaryEncoder.ino b/examples/EventRotaryEncoder/EventRotaryEncoder.ino
new file mode 100644
index 0000000000000000000000000000000000000000..ea731d762c96fd658d009f4ed61877e313bb2d01
--- /dev/null
+++ b/examples/EventRotaryEncoder/EventRotaryEncoder.ino
@@ -0,0 +1,45 @@
+#include "RotaryEncoder.h"
+
+const int pinA = 4;
+const int pinB = 5;
+const int ID = 0;
+
+RotaryEncoder re(pinA, pinB, ID);
+
+void ICACHE_RAM_ATTR ISR() {
+  re.tick();
+}
+
+void setup() {
+  // put your setup code here, to run once:
+  Serial.begin(115200);
+  re.initInterrupts(ISR);
+  re.setEventHandler(cb);
+  delay(500);
+  
+  Serial.println("\n\nESP8266 Rotary Encoder Test:");
+}
+
+void loop() {
+  re.check();
+}
+
+void cb(RotaryEncoder* rotaryEncoder, uint8_t eventType, int position) {
+  /*
+   * Rotary Encoder event handler that triggers VizBlocks behaviours
+   */
+   
+  String idString = String(rotaryEncoder->getId());
+
+  Serial.println("Encoder ID: " + idString + " Event Type: " + String(eventType) + " Position: " + String(position));
+
+  switch(eventType) {
+    case RotaryEncoder::kEventStableUpdate:
+    //Do something
+    break;
+    
+    case RotaryEncoder::kEventUnstableUpdate:
+    //Do something else
+    break;
+  }
+}
diff --git a/examples/ExampleNode/ExampleNode.ino b/examples/ExampleNode/ExampleNode.ino
index f3715bea31c5b155427a20b0a0ba925e28e4adbb..50ac91c41c94ad6b04be1a505b2c0d072221081d 100644
--- a/examples/ExampleNode/ExampleNode.ino
+++ b/examples/ExampleNode/ExampleNode.ino
@@ -1,11 +1,11 @@
 #include <Servo.h>
 
-#include <WallVis.h>
+#include <VizBlocks.h>
 
-WallVis node(
+VizBlocks node(
   "new001",     // Our ID
-  "WallVisNet", //Wifi Access Point
-  "wallvisAP",  //WiFi Password
+  "NodeRedServer", //Wifi Access Point
+  "NodeR3dAP",  //WiFi Password
   "192.168.4.1",//IP address of Node RED server
   1883          //Port for Node RED server
   );
@@ -43,7 +43,7 @@ void setup()
   node.add(new ServoWiggle(s1, "wiggle") );
   node.add(new ServoWiggle(s1, "slow_wiggle", 10) );
   node.add(new ServoWiggle(s1, "fast_wiggle", 1) );
-   
+
   //Add in a behaviour that just goes to a certain angle, with the default name 'goto'
   node.add(new ServoGoto(s1) );
 
@@ -58,7 +58,7 @@ void setup()
   node.add(new BrightnessLEDs(&strip, "green", 120, 255 ));
   node.add(new BreathingLEDs(&strip, "breathe", 120, 0 ));
   node.add(new BreathingLEDs(&strip, "breathe_blue", 170, 255 ));
- 
+
   //Initialise the whole infrastructure
   node.set_wifi(false);
   node.init();
diff --git a/examples/ExampleNodeAutoID/ExampleNodeAutoID.ino b/examples/ExampleNodeAutoID/ExampleNodeAutoID.ino
new file mode 100644
index 0000000000000000000000000000000000000000..0fddbb20485323bdd75f21869af95b7f203203c7
--- /dev/null
+++ b/examples/ExampleNodeAutoID/ExampleNodeAutoID.ino
@@ -0,0 +1,94 @@
+#include "NameDictionary.h"
+#include <Servo.h>
+#include <VizBlocks.h>
+
+//Get device name
+const String device_id = String(ESP.getChipId(), HEX);
+NameDictionary d;
+const String name = d.get(device_id);
+char _name[10];
+
+// Set up the servo we will use
+Servo s1 = Servo();
+
+// Set up LEDs as well
+#define LED_COUNT 12
+#define LED_PIN    D2
+Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
+
+VizBlocks node(
+  "null",     // Our ID
+  "NodeRedServer", //Wifi Access Point
+  "NodeR3dAP",  //WiFi Password
+  "192.168.4.1",//IP address of Node RED server
+  1883          //Port for Node RED server
+  );
+
+void setup()
+{
+  // Attach the servo to the right pin on the board
+  s1.attach(D3);
+
+  // Start the LED library
+  strip.begin();
+  strip.fill(strip.Color(30,255,80));
+  strip.show();
+
+  delay(100);
+  strip.fill(0);
+  strip.show();
+
+  //Get the serial port ready
+  Serial.begin(115200);
+  Serial.println("Serial started!");
+
+  delay(500);
+
+  //Print device name
+  if (name == device_id) {
+    Serial.println("!!! This device doesn't have a name yet. Let's call it: " + name);
+  } else {
+    Serial.println("Device name: " + name);
+  }
+
+  name.toCharArray(_name, 10);
+  node.setID(_name);
+
+  //Add in a test behaviour that responds to the command 'hello'
+  node.add(new TestBehaviour("hello") );
+
+  //Add in three different versions of the servo wiggling, with different speed parameters
+  node.add(new ServoWiggle(s1, "wiggle") );
+  node.add(new ServoWiggle(s1, "slow_wiggle", 10) );
+  node.add(new ServoWiggle(s1, "fast_wiggle", 1) );
+
+  //Add in a behaviour that just goes to a certain angle, with the default name 'goto'
+  node.add(new ServoGoto(s1) );
+
+  //Add in a behaviour that rotates from 0 to 180 and back again (e.g. dropping a ball trustball style)
+  node.add(new RotateReturn(s1,"drop",1,500, 3, 175) );
+
+  //A few useful LED behaviours
+  node.add(new NumLEDs(&strip, "green_leds", strip.Color(10, 255, 15) ) );
+  node.add(new NumLEDs(&strip, "red_leds", strip.Color(255, 30, 40) ));
+  node.add(new NumLEDs(&strip, "leds"));
+  node.add(new BrightnessLEDs(&strip, "red", 0, 255 ));
+  node.add(new BrightnessLEDs(&strip, "green", 120, 255 ));
+  node.add(new BreathingLEDs(&strip, "breathe", 120, 0 ));
+  node.add(new BreathingLEDs(&strip, "breathe_blue", 170, 255 ));
+
+  //Initialise the whole infrastructure
+  node.set_wifi(true);
+  node.init();
+
+  delay(500);
+
+  Serial.println("PactVis Outputs Test:");
+}
+
+
+void loop()
+{
+  //Should be all we have to do
+  node.vis_loop();
+}
diff --git a/examples/IdLookUpStruct/IdLookUpStruct.ino b/examples/IdLookUpStruct/IdLookUpStruct.ino
new file mode 100644
index 0000000000000000000000000000000000000000..2901af67405c25e170c922e7155d49800263940e
--- /dev/null
+++ b/examples/IdLookUpStruct/IdLookUpStruct.ino
@@ -0,0 +1,29 @@
+#include "NameDictionary.h"
+
+const String device_id = String(ESP.getChipId(), HEX);
+String name;
+
+NameDictionary d;
+
+void setup() {
+  // put your setup code here, to run once:
+  Serial.begin(115200);
+
+  Serial.println("\n\nESP8266 ID Look Up Test");
+  Serial.println("Device ID: " + device_id);
+
+  String name = d.get(device_id);
+
+  if (name == "null") {
+    name = device_id;
+    Serial.print("!!! This device doesn't have a name yet. Let's call it: " + name);
+  } else {
+    Serial.print("Device name: " + name);
+  }
+  
+}
+
+void loop() {
+  // put your main code here, to run repeatedly:
+
+}
diff --git a/examples/InputNode/InputNode.ino b/examples/InputNode/InputNode.ino
new file mode 100644
index 0000000000000000000000000000000000000000..6109769cc1b85779b058f60a8a68ed1d262a28c4
--- /dev/null
+++ b/examples/InputNode/InputNode.ino
@@ -0,0 +1,179 @@
+#include "NameDictionary.h"
+#include "Button.h"
+#include "Potentiometer.h"
+#include "RotaryEncoder.h"
+#include "VizBlocks.h"
+#include "Behaviours.h"
+
+//Get device name
+const String device_id = String(ESP.getChipId(), HEX);
+NameDictionary d;
+const String name = d.get(device_id);
+char _name[10];
+
+//Init button
+const int bPin = 2;
+const int bID = 0;
+Button b(bPin, bID);
+
+//Init potientiometer
+const int pPin = A0;
+const int pID = 1;
+Potentiometer p(pPin, pID);
+
+//Init rotary encoder
+const int rePinA = 4;
+const int rePinB = 5;
+const int reID = 2;
+RotaryEncoder re(rePinA, rePinB, reID);
+
+//Construct VizBlocks
+VizBlocks node(
+  "null",     // Our ID
+  "NodeRedServer", //Wifi Access Point
+  "NodeR3dAP",  //WiFi Password
+  "192.168.4.1",//IP address of Node RED server
+  1883          //Port for Node RED server
+  );
+
+//Interrupt Serivce Routine
+void ICACHE_RAM_ATTR bISR() {
+  b.tick();
+}
+
+void ICACHE_RAM_ATTR reISR() {
+  re.tick();
+}
+
+void setup() {
+  // put your setup code here, to run once:
+  Serial.begin(115200);
+  Serial.println("Serial started!");
+
+  //Pass event handlers into button
+  b.initInterrupts(bISR);
+  b.setEventHandler(bCB);
+
+  //Pass event handlers into potentiometer
+  p.setEventHandler(pCB);
+
+  //Pass event handlers into rotary encoder
+  re.initInterrupts(reISR);
+  re.setEventHandler(reCB);
+
+  delay(500);
+
+  //Print device name
+  if (name == device_id) {
+    Serial.println("!!! This device doesn't have a name yet. Let's call it: " + name);
+  } else {
+    Serial.println("Device name: " + name);
+  }
+
+  name.toCharArray(_name, 10);
+  node.setID(_name);
+
+  //Node behaviours:
+  node.add(new SendCapabilities(&node) );
+  node.add(new ButtonClicked(&node, "ButtonClicked") );
+  node.add(new ButtonHeld(&node, "ButtonHeld") );
+  node.add(new ButtonTick(&node, "ButtonTick") );
+  node.add(new ButtonReleased(&node, "ButtonReleased") );
+  node.add(new PotentiometerUpdated(&node, "PotentiometerUpdated") );
+  node.add(new RotaryEncoderUpdated(&node, "RotaryEncoderUpdated") );
+
+
+  //Initialise the whole infrastructure
+  node.set_wifi(true);
+  node.init();
+
+  delay(500);
+
+  Serial.println("PactVis Inputs Test:");
+}
+
+void loop() {
+  // put your main code here, to run repeatedly:
+  node.vis_loop();
+  b.check();
+  p.check();
+  re.check();
+}
+
+void bCB(Button* button, uint8_t eventType, bool state) {
+  /*
+   * Button event handler that triggers VizBlocks behaviours
+   */
+
+  String idString = String(button->getId());
+
+  Serial.println("Button ID: " + idString + " Event Type: " + String(eventType) + " State: " + String(state));
+
+  switch(eventType) {
+    case Button::kEventPressed:
+    //Do something
+    break;
+
+    case Button::kEventReleased:
+    //Do something else
+    node.input_event("ButtonReleased " + idString);
+    break;
+
+    case Button::kEventClicked:
+    //Do something else
+    node.input_event("ButtonClicked " + idString);
+    break;
+
+    case Button::kEventHeld:
+    //Do something else
+    node.input_event("ButtonHeld " + idString);
+    break;
+
+    case Button::kEventTick:
+    //Do something else
+    node.input_event("ButtonTick " + idString);
+    break;
+  }
+}
+
+void pCB(Potentiometer* potentiometer, uint8_t eventType, uint8_t sensorValue) {
+  /*
+   * Potentiometer Event Handler that triggers VizBlocks behaviours
+   */
+
+  String idString = String(potentiometer->getId());
+
+  Serial.println("Slider ID: " + idString + " Event Type: " + String(eventType) + " Sensor Value: " + String(sensorValue));
+
+  switch(eventType) {
+    case Potentiometer::kEventStableUpdate:
+    //Do something
+    node.input_event("PotentiometerUpdated " + idString + " " + String(sensorValue));
+    break;
+
+    case Potentiometer::kEventUnstableUpdate:
+    //Do something else
+    break;
+  }
+}
+
+void reCB(RotaryEncoder* rotaryEncoder, uint8_t eventType, int position) {
+  /*
+   * Rotary Encoder event handler that triggers VizBlocks behaviours
+   */
+
+  String idString = String(rotaryEncoder->getId());
+
+  Serial.println("Encoder ID: " + idString + " Event Type: " + String(eventType) + " Position: " + String(position));
+
+  switch(eventType) {
+    case RotaryEncoder::kEventStableUpdate:
+    //Do something
+    node.input_event("RotaryEncoderUpdated " + idString + " " + String(position));
+    break;
+
+    case RotaryEncoder::kEventUnstableUpdate:
+    //Do something else
+    break;
+  }
+}
diff --git a/examples/LoopingBehaviour/LoopingBehaviour.ino b/examples/LoopingBehaviour/LoopingBehaviour.ino
index 7938c8f4838ebc568cd7763dda72f50458db2170..8596b76fcce043a0d1c4c33bed28e269a107cd39 100644
--- a/examples/LoopingBehaviour/LoopingBehaviour.ino
+++ b/examples/LoopingBehaviour/LoopingBehaviour.ino
@@ -1,10 +1,10 @@
-#include <WallVis.h>
+#include <VizBlocks.h>
 #include <Behaviours.h>
 
-WallVis node(
+VizBlocks node(
   "new001",     // Our ID
-  "WallVisNet", //Wifi Access Point
-  "wallvisAP",  //WiFi Password
+  "VizBlocksNet", //Wifi Access Point
+  "VizBlocksAP",  //WiFi Password
   "192.168.4.1",//IP address of Node RED server
   1883          //Port for Node RED server
   );
diff --git a/examples/MultipleServos/MultipleServos.ino b/examples/MultipleServos/MultipleServos.ino
index 335e8a4aa805f819779d7c78a3192e75faae5780..e486733067f548d68fb231cab8ef1e58819c5252 100644
--- a/examples/MultipleServos/MultipleServos.ino
+++ b/examples/MultipleServos/MultipleServos.ino
@@ -1,11 +1,11 @@
 #include <Servo.h>
 
-#include <WallVis.h>
+#include <VizBlocks.h>
 
-WallVis node(
+VizBlocks node(
   "new001",     // Our ID
-  "WallVisNet", //Wifi Access Point
-  "wallvisAP",  //WiFi Password
+  "VizBlocksNet", //Wifi Access Point
+  "VizBlocksAP",  //WiFi Password
   "192.168.4.1",//IP address of Node RED server
   1883          //Port for Node RED server
   );
diff --git a/examples/MyExampleNode/MyExampleNode.ino b/examples/MyExampleNode/MyExampleNode.ino
new file mode 100644
index 0000000000000000000000000000000000000000..c89f827ae20ba090ee8ba9c9fe55a642bb2ec928
--- /dev/null
+++ b/examples/MyExampleNode/MyExampleNode.ino
@@ -0,0 +1,64 @@
+#include <AceButton.h>
+#include <AdjustableButtonConfig.h>
+#include <ButtonConfig.h>
+
+#include <VizBlocks.h>
+
+VizBlocks node(
+  "new001",     // Our ID
+  "JR", //Wifi Access Point
+  "hotsp0t2",  //WiFi Password
+  "172.20.10.8",//IP address of Node RED server
+  1883          //Port for Node RED server
+  );
+
+int counter = 0;
+
+/*
+ * Class that defines a custom behaviour
+ */
+class Input : public Behaviour {
+public:
+  Input(String name) : Behaviour(name)  {}
+
+  /*
+   * This is the bit that actually does something!
+   * args has all of the information that you are given in it, i.e. if
+   * your command is called 'custom', and the command was "custom 50",
+   * args would be "50"
+   */
+  String start(String args) {
+    //This is where you do your stuff for a simple behaviour
+    node.input_publish("input " + args);
+    return "Input behaviour " + _name + " with (" + args + ")";
+  }
+};
+
+void setup()
+{
+
+  //Get the serial port ready
+  Serial.begin(115200);
+
+  //Add in a test behaviour that responds to the command 'hello'
+  node.add(new TestBehaviour("hello") );
+  node.add(new Input("input") );
+  
+ 
+  //Initialise the whole infrastructure
+  node.set_wifi(true);
+  node.init();
+}
+
+
+void loop()
+{
+  //Should be all we have to do
+  node.vis_loop();
+
+  counter++;
+  if (counter >= 100) {
+    node.input_event("input buttonpress");
+    counter = 0;
+  }
+}
diff --git a/examples/StarterNodePactman/StarterNodePactman.ino b/examples/StarterNodePactman/StarterNodePactman.ino
new file mode 100644
index 0000000000000000000000000000000000000000..3294673c05143ef26b7bf35defae7a47690d56d1
--- /dev/null
+++ b/examples/StarterNodePactman/StarterNodePactman.ino
@@ -0,0 +1,191 @@
+#include "NameDictionary.h"
+#include "Button.h"
+#include "Potentiometer.h"
+#include "RotaryEncoder.h"
+#include <VizBlocks.h>
+#include <Behaviours.h>
+
+//Get device name
+const String device_id = String(ESP.getChipId(), HEX);
+NameDictionary d;
+const String name = d.get(device_id);
+char _name[10];
+
+//Init as a VizBlock node with "null" ID.
+VizBlocks node(
+  "null",     // Our ID
+  "NodeRedServer", //Wifi Access Point
+  "NodeR3dAP",  //WiFi Password
+  "192.168.4.1",//IP address of Node RED server
+  1883          //Port for Node RED server
+  );
+
+//Init button
+const int bPin = D2;
+const int bID = 0;
+Button b(bPin, bID);
+
+//Button Interrupt Service Routine
+void ICACHE_RAM_ATTR bISR() {
+  b.tick();
+}
+
+//Init potientiometer
+const int pPin = A0;
+const int pID = 0;
+Potentiometer p(pPin, pID);
+
+//Init rotary encoder
+const int rePinA = D4;
+const int rePinB = D5;
+const int reID = 0;
+RotaryEncoder re(rePinA, rePinB, reID);
+
+//Rotary Encoder Interrupt Serivce Routine
+void ICACHE_RAM_ATTR reISR() {
+  re.tick();
+}
+
+unsigned long t = 0;
+const int pingInterval = 4000;
+
+void setup()
+{
+  //Get the serial port ready
+  Serial.begin(115200);
+  Serial.println("Serial started!");
+  delay(500);
+
+  //Pass event handlers into button
+  b.initInterrupts(bISR);
+  b.setEventHandler(bCB);
+  //Pass event handlers into potentiometer
+  p.setEventHandler(pCB);
+  //Pass event handlers into rotary encoder
+  re.initInterrupts(reISR);
+  re.setEventHandler(reCB);
+
+  //Print device name
+  if (name == device_id) {
+    Serial.println("!!! This device doesn't have a name yet. Let's call it: " + name);
+  } else {
+    Serial.println("Device name: " + name);
+  }
+  name.toCharArray(_name, 10);
+  node.setID(_name);
+
+  //Add in the custom behaviour we defined earlier.
+  node.add(new SendCapabilities(&node) );
+  node.add(new PingServer(&node) );
+  node.add(new Link(&node) );
+
+  node.add(new ButtonPressed(&node) );
+  node.add(new ButtonReleased(&node) );
+  node.add(new ButtonClicked(&node) );
+  node.add(new ButtonHeld(&node) );
+  node.add(new ButtonTick(&node) );
+  node.add(new PotentiometerUpdated(&node) );
+  node.add(new RotaryEncoderUpdated(&node) );
+
+  //Initialise the whole infrastructure
+  node.set_wifi(true);
+  node.init();
+  delay(500);
+
+  node.process("PingServer");
+}
+
+void loop()
+{
+  node.run();
+  b.check();
+  p.check();
+  re.check();
+  pingComms(pingInterval);
+}
+
+void pingComms(int interval) {
+  unsigned long timeNow = millis();
+  if (timeNow > t + interval) {
+    t = timeNow;
+    Serial.println("Link " + name);
+  }
+}
+
+void bCB(Button* button, uint8_t eventType, bool state) {
+  /*
+   * Button event handler that triggers VizBlocks behaviours
+   */
+
+  String idString = String(button->getId());
+
+  Serial.println("Button ID: " + idString + " Event Type: " + String(eventType) + " State: " + String(state));
+
+  switch(eventType) {
+    case Button::kEventPressed:
+    //Do something
+    break;
+
+    case Button::kEventReleased:
+    //Do something else
+    node.input_event("ButtonReleased " + idString);
+    break;
+
+    case Button::kEventClicked:
+    //Do something else
+    node.input_event("ButtonClicked " + idString);
+    break;
+
+    case Button::kEventHeld:
+    //Do something else
+    node.input_event("ButtonHeld " + idString);
+    break;
+
+    case Button::kEventTick:
+    //Do something else
+    node.input_event("ButtonTick " + idString);
+    break;
+  }
+}
+
+void pCB(Potentiometer* potentiometer, uint8_t eventType, uint8_t sensorValue) {
+  /*
+   * Potentiometer Event Handler that triggers VizBlocks behaviours
+   */
+
+  String idString = String(potentiometer->getId());
+
+  Serial.println("Slider ID: " + idString + " Event Type: " + String(eventType) + " Sensor Value: " + String(sensorValue));
+
+  switch(eventType) {
+    case Potentiometer::kEventStableUpdate:
+    //Do something
+    node.input_event("PotentiometerUpdated " + idString + " " + String(sensorValue));
+    break;
+
+    case Potentiometer::kEventUnstableUpdate:
+    //Do something else
+    break;
+  }
+}
+
+void reCB(RotaryEncoder* rotaryEncoder, uint8_t eventType, int position) {
+  /*
+   * Rotary Encoder event handler that triggers VizBlocks behaviours
+   */
+
+  String idString = String(rotaryEncoder->getId());
+
+  Serial.println("Encoder ID: " + idString + " Event Type: " + String(eventType) + " Position: " + String(position));
+
+  switch(eventType) {
+    case RotaryEncoder::kEventStableUpdate:
+    //Do something
+    node.input_event("RotaryEncoderUpdated " + idString + " " + String(position));
+    break;
+
+    case RotaryEncoder::kEventUnstableUpdate:
+    //Do something else
+    break;
+  }
+}
diff --git a/examples/ThreeButtonNodePactman/ThreeButtonNodePactman.ino b/examples/ThreeButtonNodePactman/ThreeButtonNodePactman.ino
new file mode 100644
index 0000000000000000000000000000000000000000..2180d7710ec89fa5b749d358ad2159a58e8bb406
--- /dev/null
+++ b/examples/ThreeButtonNodePactman/ThreeButtonNodePactman.ino
@@ -0,0 +1,130 @@
+#include "NameDictionary.h"
+#include "Button.h"
+#include <VizBlocks.h>
+#include <Behaviours.h>
+
+//Get device name
+const String device_id = String(ESP.getChipId(), HEX);
+NameDictionary d;
+const String name = d.get(device_id);
+char _name[10];
+
+//Init as a VizBlock node with "null" ID.
+VizBlocks node(
+  "null",     // Our ID
+  "NodeRedServer", //Wifi Access Point
+  "NodeR3dAP",  //WiFi Password
+  "192.168.4.1",//IP address of Node RED server
+  1883          //Port for Node RED server
+  );
+
+//Init buttons on pins D2, D3, and D4
+Button b0(D2, 0);
+Button b1(D3, 1);
+Button b2(D4, 2);
+
+//Button Interrupt Service Routines
+void ICACHE_RAM_ATTR D2_interrupt() { b0.tick(); }
+void ICACHE_RAM_ATTR D3_interrupt() { b1.tick(); }
+void ICACHE_RAM_ATTR D4_interrupt() { b2.tick(); }
+// Pin interrupts can only use global or static functions as callbacks,
+// so we have to create these wrappers, even though they are ugly :(
+
+unsigned long t = 0;
+const int pingInterval = 4000;
+
+void setup()
+{
+  //Get the serial port ready
+  Serial.begin(115200);
+  Serial.println("Serial started!");
+  delay(500);
+
+  //Pass event handlers into buttons
+  b0.initInterrupts(D2_interrupt);
+  b0.setEventHandler(bCB);
+  b1.initInterrupts(D3_interrupt);
+  b1.setEventHandler(bCB);
+  b2.initInterrupts(D4_interrupt);
+  b2.setEventHandler(bCB);
+
+  //Print device name
+  if (name == device_id) {
+    Serial.println("!!! This device doesn't have a name yet. Let's call it: " + name);
+  } else {
+    Serial.println("Device name: " + name);
+  }
+  name.toCharArray(_name, 10);
+  node.setID(_name);
+
+  //Add in the custom behaviour we defined earlier.
+  node.add(new SendCapabilities(&node) );
+  node.add(new PingServer(&node) );
+  node.add(new Link(&node) );
+
+  node.add(new ButtonPressed(&node) );
+  node.add(new ButtonReleased(&node) );
+  node.add(new ButtonClicked(&node) );
+  node.add(new ButtonHeld(&node) );
+  node.add(new ButtonTick(&node) );
+
+  //Initialise the whole infrastructure
+  node.set_wifi(true);
+  node.init();
+  delay(500);
+
+  node.process("PingServer");
+}
+
+void loop()
+{
+  node.run();
+  b0.check();
+  b1.check();
+  b2.check();
+  pingComms(pingInterval);
+}
+
+void pingComms(int interval) {
+  unsigned long timeNow = millis();
+  if (timeNow > t + interval) {
+    t = timeNow;
+    Serial.println("Link " + name);
+  }
+}
+
+void bCB(Button* button, uint8_t eventType, bool state) {
+  /*
+   * Button event handler that triggers VizBlocks behaviours
+   */
+
+  String idString = String(button->getId());
+
+  Serial.println("Button ID: " + idString + " Event Type: " + String(eventType) + " State: " + String(state));
+
+  switch(eventType) {
+    case Button::kEventPressed:
+    //Do something
+    break;
+
+    case Button::kEventReleased:
+    //Do something else
+    node.input_event("ButtonReleased " + idString);
+    break;
+
+    case Button::kEventClicked:
+    //Do something else
+    node.input_event("ButtonClicked " + idString);
+    break;
+
+    case Button::kEventHeld:
+    //Do something else
+    node.input_event("ButtonHeld " + idString);
+    break;
+
+    case Button::kEventTick:
+    //Do something else
+    node.input_event("ButtonTick " + idString);
+    break;
+  }
+}