J U S T I NDustin LarimerKeen IO
Published © MIT

Trip Laser Party

Put trip wire lasers around your next event, to capture data, and visualize where people are moving around.

IntermediateFull instructions provided1,223
Trip Laser Party

Things used in this project

Hardware components

Photon
Particle Photon
×1
laser
×1
Adjustable Laser Mount
×1
Photo cell (CdS photoresistor)
×1

Story

Read more

Code

Laser Code

JavaScript
This is to make the trip laser work with the Particle Board.
int laser = 0;
unsigned int lastPublish = 0;
bool lastState = false;

void setup() {
    pinMode(A0, INPUT_PULLDOWN);
    pinMode(D7, OUTPUT);
}

void loop() {
    int val = analogRead(A0);
    unsigned int now = millis();
    unsigned int elapsed = now - lastPublish;


    bool broken = val < 4000;
    if (broken == lastState) {
        return;
    }

    digitalWrite(D7, (broken) ? HIGH : LOW);

    if (elapsed >= 1000) {
        String topic = ((broken) ? "laser/alarm" :  "laser/reset");
        String message = String(val);
        Particle.publish(topic, message);
        lastState = broken;
        lastPublish = millis();
    }
}

App code

JavaScript
Used Firebase, Particle Webhooks, and Keen IO to get the laser represented on the screen and blinking when it was tripped. The bar got bigger when it was tripped more rapidly to represent activity.
var React = require('react'),
    Keen = require('keen-js');

React.initializeTouchEvents(true);

var config = require('../config');

// Configure Firebase
var firebaseRef = new Firebase(config['firebase']);

// Configure Keen
// https://keen.io/project/KEEN_PROJECT_ID/workbench
var client = new Keen(config['keen']);
var gates = new Keen.Query('count', {
  eventCollection: 'lasers',
  groupBy: 'coreid',
  timeframe: 'this_1_minute'
});
var totals = new Keen.Query('count', {
  eventCollection: 'lasers',
  groupBy: 'coreid'
});


var Gate = React.createClass({

  getInitialState: function(){
    var rando = Math.round(Math.random()*300) + 50;
    return {
      a: {
        active: false,
        radius: 15,
        x: rando,
        y: rando - 50
      },
      b: {
        active: false,
        radius: 15,
        x: rando,
        y: rando + 50
      },
      stroke: '#808080',
      strokeWidth: 5
    }
  },

  handleMove: function(i, e){
    var state = this.state[i];
    if (!state.active) return;
    state.x = this.props.trace[0];
    state.y = this.props.trace[1];
    this.setState(state);
    firebaseRef.child('/gates/' + this.props.id).update(this.state);
  },
  handleDown: function(i,e){
    var state = this.state[i];
    state.active = true;
    state.radius = 25;
    this.setState(state);
    firebaseRef.child('/gates/' + this.props.id).update(this.state);
  },
  handleUp: function(i,e){
    var state = this.state[i];
    state.active = false;
    state.radius = 15;
    this.setState(state);
    firebaseRef.child('/gates/' + this.props.id).update(this.state);
  },

  tick: function(){
    var self = this;
    var diff = self.props.weight - self.state.weight;
    console.log(diff > 0, self.props.total);
    var interval = setInterval(function(){
      if (diff > 0) {
        self.setState({
          weight: self.state.weight ? 0 : self.props.weight,
          total: self.props.total
        });
        diff--;
      }
      else {
        clearInterval(interval);
        if (!self.state.weight) {
          self.setState({
            weight: self.props.weight
          });
        }
      }
    }, 500);
  },

  componentDidMount: function(){
    this.setState(this.props);
    setInterval(this.tick, 1000);
  },

  render: function(){
    return 



      {'ID: ' + this.props.id}
      {'Total: ' + this.state.total}

  }
});


var Stage = React.createClass({

  getDefaultProps: function(){
    return {
      gates: []
    }
  },

  getInitialState: function() {
    return {
      ix: 100,
      iy: 100,
      height: window.innerHeight,
      width: window.innerWidth,
      position: {
        x: window.innerWidth / 2,
        y: window.innerHeight / 2
      }
    };
  },

  getKeenResults: function(){
    client.run([gates, totals], function(err, res){
      res[0].result.forEach(function(record, i){
        var id = record.coreid;
        if (id) {
          firebaseRef.child('/gates/' + id).update({
            id: id,
            weight: record.result,
            total: res[1].result[i].result
          });
        }
      });
    });
  },

  componentDidMount: function() {
    var self = this;

    this.getKeenResults();
    setInterval(this.getKeenResults, 1000 * 5);

    firebaseRef.child('/gates').on('child_added', function(data){
      self.props.gates.push(data.val());
      self.forceUpdate();
    });

    firebaseRef.child('/gates').on('child_changed', function(data){
      self.props.gates.forEach(function(gate, i){
        if (gate.id === data.key()) {
          self.props.gates[i] = data.val();
        }
      });
    });

    firebaseRef.child('/gates').on('child_removed', function(data){
      self.props.gates.forEach(function(gate, i){
        if (gate.id === data.key()) {
          self.props.gates.splice(i, 1);
        }
      });
    });

    window.addEventListener('resize', this.handleResize);
    document.addEventListener('touchmove', this.preventBehavior, false);
  },

  handleResize: function(){
    this.setState({
      'height': window.innerHeight,
      'width': window.innerWidth
    });
  },

  preventBehavior: function(e){
    e.preventDefault();
  },

  handleMove: function(e){
    var touch = (e.touches) ? e.touches[0] : false;
    this.setState({
      ix: touch ? touch.pageX : e.clientX,
      iy: touch ? touch.pageY : e.clientY
    });
  },

  render: function(){
    var gates = this.props.gates.map(function(gate, index){
      // console.log(gate);
      return 
    }, this);

    return 






        {gates}

  }

});

React.render( , document.getElementById('stage') );

module.exports = Stage;

Webpage

HTML
Just a stage :)
    <!DOCTYPE html>
    <html>
    <head>
      <title>sparkeen</title>
      <style>
        body { margin: 0; }
        svg circle { cursor: move; }
      </style>
    </head>
    <body>
      <div id="stage"></div>
      <script src="https://cdn.firebase.com/js/client/2.0.1/firebase.js"></script>
      <script src="./app/index.js"></script>
    </body>
    </html>

Webhook Code

JSON
{
   "eventName": "laser",
   "url": "http://api.keen.io/3.0/projects/YOUR_PROJECT_ID/events lasers",
   "requestType": "POST",
   "headers": {
    "Authorization": "YOUR_AUTH_KEY"
   },
    "json": {
      "lasers": {
         "test": "1"
      }
    }
 }

Credits

J U S T I N

J U S T I N

1 project • 1 follower
Community & code, I like to help build stuff. A student of life & team member @Keen_IO
Dustin Larimer

Dustin Larimer

1 project • 1 follower
Keen IO

Keen IO

1 project • 3 followers
Platform & API for all your Analytics. Explore data your way. @techstars & @sequoia backed. platform status: @keenstatus

Comments

Add projectSign up / Login