text: TinkerhubTinkerhub
  Tinkerhub is a library for building, connecting, interacting and tinkering with things on your local network. It can be used for home automation, such as turning appliances on and off, monitoring sensor data and other IoT workloads.
  The base of Tinkerhub is a network in which a library can choose to expose things and appliances, such as lights, sensors and services. Any NodeJS instance connected to the network can then see and interact with these things.
  To setup a network the easiest way is to install tinkerhub-daemon to host plugins and to use tinkerhub-cli to interact with them.
  Getting started and joining the local networkGetting started and joining the local network
  Tinkerhub requires at least Node 8.
  To get started install the
  tinkerhub library:
  npm install tinkerhub
  Tinkerhub will automatically connect to other instances on the same local
  network and make their devices available to the local instance. This is done
  automatically on
  require('tinkerhub').
  // Asynchronously connect to instances on the local networkconst th = ;
  Discovering thingsDiscovering things
  Things can join or leave the network at any time. It's possible to listen
  to
  thing:available and
  thing:unavailable to be notified when this happens.
  th;
  The library provides access to everything it can reach via collections. A collection is a filtered view of things on the current network.
  // Get everythingconst allDevices = thall;// Filter things based on types, capabilities and tagsconst lights = th;
  Collections also support the
  thing:available and
  thing:unavailable events.
  const switchableLights = th;switchableLights;switchableLights; // Destroy the collection and remove all listeners
  The event
  thing:updated can be used to listen for updates, such as changes
  in name, tags, type or capabilities:
  switchableLights;
  Interacting with thingsInteracting with things
  All things have metadata associated with them, which contains information about their unique identifier, name (if any), types and capabilities.
  console; // "idOfDevice"console; // "Human-readable name if any"console; // Set [ 'light', 'otherType' ]console; // Set [ 'dimmable', 'colors' ]console; // Set [ 'livingroom', 'type:light', 'cap:dimmable' ]
  Types and capabilities are used to indicate what a thing is and what it is capable of doing. Most things you will encounter use a standarized API that is defined in the project called abstract-things.
  Performing actionsPerforming actions
  All things support actions, which can be invoked as normal JavaScript functions. Actions in Tinkerhub always return a promise that will resolve to the result of the invocation.
  // Turn on the thing on asynchronouslything;// Collections work the same but return a multi resultth;
  Listening for eventsListening for events
  Most things also emit events whenever things change. These can be listened
  to via
  on:
  // Start listeningconst handle = thing;// To stop listeninghandle;
  The same is true for collections, where an event will be trigged if any thing in the collection emits an event:
  const collection = th;
  Note: Collections do not return a event handles, the easiest way to stop
  listening for events on a collection is to call
  destroy() on it.
  Waiting for thingsWaiting for things
  Tinkerhub connects asynchronously and things can be found at any time so
  scripting can be difficult if you just want to perform an action or two.
  Something like this will fail if run via
  node script.js:
  const th = ;th; // Don't do this, the collection will be empty
  A special function named
  awaitThings is available for collections that will
  wait until things are mostly available:
  const th = ;th;// To exit Node
  This will wait in chunks of 500 ms for things to be found. After a few seconds it will resolve even if no things have been found.
  Building a thingBuilding a thing
  Things in Tinkerhub are based on the library abstract-things, it contains both generic and specific types and capabilities for things such as sensors, lights, humidifiers, switches and so on.
  A very basic thing may look something like this:
  const th = ;const Thing = ;const duration = ;/*** Timer that calls itself `timer:global` and that allows timers to be set* and listened for in the network.*/static {return 'timer';}{super;thisid = 'timer:global';}{if! name throw 'Timer needs a name';if! delay throw 'Timer needs a delay';delay = ;}// Register the timerth;
  Organizing ThingsOrganizing Things
  Things support user defined tags via their metadata. These tags are persisted on the same machine as a thing is registered. In the API tags are merged with system generated tags such as type tags and capability tags.
  This can be used to create groups of things, such as all things found in a certain room. This allows for things such as this:
  // Fetch lights in the living room and turn them onth;
  The thing metadata object contains an API that can be used to the user defined
  tags of a device. Currently the prefixes
  type: and
  cap: are reserved.
  console; // Get all of the tagsthingmetadata; // Add tags to the thingthingmetadata; // Remove tags from the thing
  The easiest way to tag upp things is to use tinkerhub-cli
  and simply do
  deviceIdOrTag metadata tag nameOfTag.
  Advanced matchingAdvanced matching
  Advanced matching is supported via
  th.match for example to match all lights
  that are not tagged with
  living-room:
  // Get lights not tagged with living-roomth
  th.match.or and
  th.match.and can be used to get things using more advanced
  queries:
  // Get things that are either lights or air purifiersth;// Get things that are either lights or air purifiers that can switch their powerth;// Either lights that can switch their power or things with switchable modeth;
  Extending things in the networkExtending things in the network
  Tinkerhub automatically merges things with the same identifier which allows one instance to be extended with new capabilities by other libaries.
  This is primarily used together with plugins that bridge in things, such as Bluetooth peripherals or Z-wave devices. This allows the bridge to provide a generic API and other libraries to extend these things and make them in to specific types.
  /** Get all Bluetooth Low Energy devices that are connected and extend them* if they support a certain type.*/th;});
  Handling errorsHandling errors
  Most things in Tinkerhub return promises and
  catch should be used to handle
  errors from all promises. There are three main ways errors should be handled:
  - Catch the error - but only if you can recover. Catching errors is usually done for non-important errors that can be recovered from by doing things such as retrying requests.
  {
  - Ignore the error - but only if you return a promise (or similar). This allows for example another consumer to handle the error in a better way.
  {return}
  - Log the error - when the error isn't that important or you can't recover from it. A utility is available that will do this:
  th.errorHandler.
  {return;}// Or when registering a thing:th;
  Development helperDevelopment helper
  When developing a plugin or custom behavior Tinkerhub contains a utility that will log and output errors from things such as unhandled promise rejections. To activate it, put something like this in the main file of the project:
  if! moduleparent// Only activate development mode if this file was run directly via `node nameOfFile.js`therrorHandler;
  This will turn on logging to the console for the namespace
  th:error. Any
  uncaught promise rejection or call to
  th.errorHandler will be displayed in
  full.
  Debug loggingDebug logging
  Tinkerhub uses debug for debug logging.
  Internal Tinkerhub-things live in the namespace
  th and things belong to the
  namespace
  things. Logging for both can be activated with
  th*:
  $ DEBUG=th\* node fileToRun.js
  Other interesting namespaces include the
  ataraxia which outputs information
  about the network and
  dwaal that outputs information about the key-value
  storage used by things (via abstract-things).
  State handlingState handling
  State is important in Tinkerhub, most things will have the capability
  state.
  State can be read and inspected by calling the
  state() action:
  collection;
  Things can also advertise that they are capabable of capturing and restoring
  state via the capability
  restorable-state. Things that are restorable will
  have these three actions available:
  restorableState(): Array[string]- Get all of the state keys that can be restored.
  captureState(): Object- Capture the current state as an object.
  setState(Object)- Set the state of the thing.
  To capture and restore the state the extra functions
  captureState(collection)
  and
  restoreState(collection, state) are available in
  tinkerhub/state:
  const captureState restoreState = ;
  An example of using capturing and restoring could be doing something like this to capture the state of lights, turn them off and a few seconds after restore their original state:
  const th = ;const captureState restoreState = ;let capturedState;let lights = thlights// When lights are available, capture their state// Handle the state and request lights to be turned off// Set a timeout for restoring the state five seconds after turning off// Log any errors;
  NetworkNetwork
  Tinkerhub creates a mesh network between instances. It is possible to use the library in several NodeJS instances on a single machine. Tinkerhub will manage the connections to other machines so that only a single network connection between machines exist.
  A network may come to look a bit like this, where each machine connect to each other machine, but instances within a machine mainly connect to themselves.
  +------------------+ |Machine #1 | | | | +--+ +--+ | | | +-----+ +--------+ +------------------+ | +--+ +-++ | | |Machine #2 | | | | | | | +------------------+ | | +--+ | +---------------------+ | | | | ++-+ | | | | | | +------------------+ | | +---------------------+ | |Machine #3 | | | | | | | | +--+ ++-+ | | | | +--------+ +----------+ | +--+ ++-+ | | | | | +--+ | | | | +----+ | | +--+ | +---------------------+