Things Bus

From Pumping Station One
Jump to navigation Jump to search

We want to make a super-easy-to-integrate-with way to handle sensors and actuators around the space.


What is Things Bus?

Things bus is a an agreement on how devices in the space communicate to facilitate hacking and extension.

Node Types

There are 3 basic node types in things bus:

  • Sensors. Sensors produce data
  • Actuators. Data Sinks consume data, and probably do something interesting with it.
  • Neurons. Neurons take in sensory data, manipulate it in some way, and send the data to actuators.

Sensors

A simple of an example of a sensor would be a temperature sense in the space. A temperature sensor would be a Raspberry Pi hooked into a temperature sense, and would send out the current temperature every 5 minutes.

Sensors make data available by using a zmq bind PUB socket.

Actuators

An Actuator is something that, when triggered, does something. It doesn't have to be physical. An actuator could be as simple as an led wired into a Raspberry Pi that can be triggered by a Neuron.

Actuators consume data by using a zmq bind PULL socket

Neuron

Neurons communicate between sensors and actuators, and decide what effect, if any, sensory input should have on actuators.

There can be more complex arrangements, Neurons are free to communicate with other Neurons, and can trigger actuators without sensory input, and can read sensor data without actually forwarding it to an actuator.

  • Neurons consume information from sensors by using zmq connect SUB sockets to sensors
  • Nuerons send information to actuators by using zmq connect PUSH sockets to actuators.

Mixed Mode and Multi Mode Nodes

A given node on the things bus is likely to be of more than one type, and may exist just to proxy information around, or analyze data and have it be re-emmited as a new type of sensor.

Examples:

  • A Dust Collection Node would likely be both a sensor (Is it on?) and an actuator (Turn it on)

A Simple Example

The following is an example of a Neuron. It connects to sensory input, the hackerpspace's front and back doors, and sense data to an actuator, zirc, an actuator that writes data to #pumpingstationone on irc.freenode.net

Before running the example, you must have a recent python, recent libzmq installed, and must have pyzmq installed.

#!/usr/bin/env python
import zmq

context = zmq.Context.instance()

# Create a zmq socket that will SUBscribe to door nodes.
door_socket = context.socket(zmq.SUB)
door_socket.connect("tcp://frontdoor.pumpingstationone.org:5556")
door_socket.connect("tcp://backdoor.pumpingstationone.org:5556")

# The doors send a lot of types of messages. We only care about "door.state.unlock" messages
door_socket.setsockopt(zmq.SUBSCRIBE, b"door.state.unlock")

# create a zmq socket that will PUSH data to our IRC actuator node.
zirc_socket = context.socket(zmq.PUSH)
zirc_socket.connect('tcp://sally.ad.pumpingstationone.org:5558')

# Loop forever
while True:
    
    # Read messages from the doors
    topic, message = door_socket.recv_multipart()

    # Send the message to the irc channel
    zirc_socket.send(message)

Hardware

We are targetting Beagle Bone Blacks for node hardware. While in theory, the hardware can be anything, having a consistent dev platform is useful.

The BBB has 2 blocks of GPIO lines, and the capability of supporting up to 4 Serial devices. A lot of the types of data we want to collect are available over gpio and serial.

Things Bus Broker

For certain types of nodes, a broker that maintains state is useful. For details of this system, see https://github.com/eastein/thingsbus

Inter-Node Communication

The software for a node can be written in any language that supports zmq and json.

Nodes send messages using json data. Sensors use zmq PUB/SUB. Actuators use zmq PUSH/PULL. Neurons use whatever they have to do get the job done, which means they SUB to sensors, and PUSH to actuators.

Code Snippits

Sensors send data like this:

   import zmq
   context = zmq.Context.instance()
   socket = context.socket(zmq.PUB)
   socket.bind('tcp://*:5556')
   socket.send_multipart(('dot.delimited.filter', '{"json":"message"}'))

Neurons receive data like this:

   import zmq
   context = zmq.Context.instance()
   sensor = context.socket(zmq.SUB)
   sensor.connect("tcp://sensor.tld:5556")
   sensor.setsockopt(zmq.SUBSCRIBE, b"dot.delimited.filter")
   topic, message = sensor.recv_multipart()
   data = json.loads(message)

Neurons send data like this:

   import zmq
   context = zmq.Context.instance()
   actuator = context.socket(zmq.PUSH)
   actuator.connect('tcp://actuator.tld:5558')
   actuator.send_json(data)

Actuators receive data like this:

   import zmq
   context = zmq.Context.instance()
   socket = context.socket(zmq.PULL)
   socket.bind('tcp://*:5558')
   data = socket.recv_json()

Existing Nodes

See things bus data sources for things we already integrated with Things Bus.

Things We Want To Integrate

Status notices should be published so that consumers can subscribe to sections of the space that they are interested in for example:

  • Workshop
    • AC
    • Extraction
    • ColdMetals
      • Bandsaw
      • Bridgeport
      • BridgeportCNC
      • Lathe
    • HotMetals
      • Forge
      • Lincoln100
      • Lincoln125
      • ArgonTank
    • WoodShop
      • Dustcollector
      • Dustmeter
      • sawstop
      • bandsaw
    • CNC
      • Taz
      • AO-100
      • ShopBot
  • Electronics
    • Projector
  • Lounge
    • AC
    • Projector
    • Bar
  • Kitchen
    • BrewFridge
    • Fridge
    • Stove
  • General Area
    • Doors
      • Front
        • Front Doorbell
      • Rear
      • Lounge - Front and back
      • Starewell - Top and bottom
      • Bathrooms
    • Lights
    • A/C & Heat
  • Workshop
    • Forge
    • Dust Collector
    • LN2 Scale
  • Systems
    • Chillmon
    • Schedmon
    • DHCP
    • Netlogon
    • Access control
    • Server rack temp/power


See future things bus data sources for things to be integrated with Things Bus.

Future Features

Issuing commands

Commands for items should be sent to a queue, the controller/interface for the time should be subscribed to the queue and process the commands, queues should be laid out in a similar way to topics. Messages should also be json and well formed and documented.


Examples

Dust collector status messages

Transmitted to: /topic/PS1/Workshop/WoodShop/DustCollector

On event:

{ "source": "DustCollection", "location": "workshop", "messageType": "status", "status": "Dust collector turned on", "transition": true }

Periodic status:

{ "source": "DustCollection", "location": "workshop", "messageType": "status", "status": "Dust collector active", "transition": false }

Off event:

{ "source": "DustCollection", "location": "workshop", "messageType": "status", "status": "Dust collector turned off", "transition": fase }

Dust collector commands

Transmitted to: /queue/PS1/Workshop/WoodShop/DustCollector

Turn system on:

{ "target": "DustCollection", "location": "workshop", "messageType": "command", "command": "on"}

Turn system off:

{ "target": "DustCollection", "location": "workshop", "messageType": "command", "command": "off"}


References

The thread that started this off: https://groups.google.com/forum/#!topic/pumping-station-one/ogqSHK08DAI

Other Links

https://wiki.muc.ccc.de/uberbus:start?redirect=1

https://wiki.muc.ccc.de/uberbus:ubd

https://github.com/muccc/ubd

https://wiki.muc.ccc.de/uberbus:protocols

http://stackoverflow.com/questions/1534655/creating-a-program-to-be-broadcasted-by-avahi

http://www.avahi.org/wiki/Examples/PythonPublishAlias