Skip navigation

Raspberry Pi

September 1, 2017 Previous day Next day

This guide provides step-by-step instructions for wiring a robot arm to your MATRIX Creator and then having that arm hit a gong whenever a Stripe sale or Slack command is received. It demonstrates how to use the GPIO pins of the MATRIX Creator to control a servo and how to receive a Slack or Stripe response to trigger the arm.

 

 

Required Hardware

Before you get started, let's review what you'll need.

  • Raspberry Pi 3 (Recommended) or Pi 2 Model B (Supported) - Buy on Element14 - Pi 3 or Pi 2.
  • MATRIX Creator - The Raspberry Pi does not have a built-in microphone, the MATRIX Creator has an 8 mic array perfect for Alexa - Buy MATRIX Creator on Element14.
  • Micro-USB power supply for Raspberry Pi - 2.5A 5V power supply recommended
  • Micro SD Card (Minimum 8 GB) - You need an operating system to get started. NOOBS (New Out of the Box Software) is an easy-to-use operating system install manager for Raspberry Pi. The simplest way to get NOOBS is to buy an SD card with NOOBS pre-installed - Raspberry Pi 16GB Preloaded (NOOBS) Micro SD Card. Alternatively, you can download and install it on your SD card.
  • A USB Keyboard & Mouse, and an external HDMI Monitor - we also recommend having a USB keyboard and mouse as well as an HDMI monitor handy if you're unable to remote(SSH)into your Pi.
  • Internet connection (Ethernet or WiFi)
  • (Optional) WiFi Wireless Adapter for Pi 2 (Buy on Element14). Note: Pi 3 has built-in WiFi.
  • Gong - You can use a bell or anything else that makes noise when hit - Buy on Amazon
  • Robot Arm - we recommend the meArm because it is a simple robot arm with many degrees of motion - Buy Here
  • Jumper Wires - used to connect the robot arm to the MATRIX Creator - Buy on Amazon

For extra credit, enable remote(SSH) into your device, eliminating the need for a monitor, keyboard and mouse - and learn how to tail logs for troubleshooting.

 

Let's get started

We will be using MATRIX CORE to program the Raspberry Pi and MATRIX Creator in Javascript by using its Protocol Buffers.

 

Step 1: Build your meArm

Follow this guide to build your meArm. (skip step 2 of the meArm guide)

 

Step 2: Setting up MATRIX CORE

Download MOS (MATRIX Open System) to get all the dependencies for MATRIX CORE on your computer using the following installation guide in the MATRIX Docs: Installation Guide

 

Step 3: Create the app folder and its files

In the directory that you choose create a folder called MATRIX-Gong-Master. Within that folder create three files names as follows: app.js, configure.json, and package.json.

 

Step 4: Configuration

The configure.json file is used to read your API Keys, server port, and slack channel to post in. Here is the code:

 

{
    "apiKeys":{
        "slack":"YOUR-BOT-USER-OAUTH-ACCESS-TOKEN",
        "stripe":"YOUR-KEY-HERE"
    },
    "slackChannel": "#gong_master",
    "serverPort": 6000
}

 

Follow Step 5 to retrieve your Slack access token and follow Step 6 to retrieve your Stripe key. Set the slackChannel to your desired channel to list all gong events and set the serverPort to the port you will be using to accept the requests.

 

Step 5: Slack Setup

To properly integrate Slack, a few minor edits need to be made before we insert the API Key.

1. Create a new Slack app and select which team you want to install it for.

2. Under features, click on slash commands to create a new command.

          Set the Command to what you would like to type to trigger the arm in Slack.

          Point the Request URL to http://YOUR-PUBLIC-IP:PORT/slack_events. You can find your Public IP here and you can learn how to port forward here.

          Example of this below:

Screen Shot 2017-08-30 at 12.03.44 PM.png

3. Once saved, go into Bot Users and set a username of your choice.

4. The next step for Slack is to go into OAuth & Permissions and allow the following under Scopes:

          Send a bot with the username [your bot's name]

          Post messages as [your bot's name]

          Example of this below:

Screen Shot 2017-08-30 at 12.11.22 PM.png

5. Slack is now configured to run your Gong Master! At the top of the page you'll find 2 API Keys. Copy the Bot User OAuth Access Token and paste it into your configure.json file. Example of the API keys below:

Screen Shot 2017-08-30 at 12.21.14 PM.png

Step 5: Stripe Setup

1. If you do not already have a Stripe account register here and activate your account.

2. Go to API on the left side of the Stripe Dashboard and click Webhooks at the top.

3. Click Add endpoint on the right and type your URL that you will be received requests at as follows: http://YOUR-PUBLIC-IP:PORT/events. You can find your Public IP here and you can learn how to port forward here.

4. From there select the Webhook version you would like to use and press "Select types to send" where you will be able to select what event types you want to accept. In our case we will be using "charge.succeeded" and "invoice.payment_succeeded". Example of this below:

Screen Shot 2017-08-31 at 9.32.53 AM.png

5. Stripe is now configured to send events to your URL. Go to the Webhook you just created click "Click to reveal" in the Signing Secret section to retrieve your API key to add to your configure.json file. Example of this below:

Screen Shot 2017-08-31 at 9.44.37 AM.png

Step 6: Robot Arm Wiring

1. Using the jumper wires we are going to wire the bottom servo of the robot arm to the MATRIX Creator. First connect the Yellow servo wire to pin the pin on the MATRIX Creator labeled GP00.

2. Connect the Red servo wire to one of the pins on the MATRIX Creator labeled 5V. (there are two pins labeled 5V, either one will work)

3. Finally connect the Brown Servo wire to one of the pins on the MATRIX Creator labeled GND. (there are two pins labeled GND, either one will work)

Examples of this below:

MATRIX-Servo-Overview.JPG

IMG_5600.JPG

 

Step 7: app.js Code Overview

Below all the code for the app.js file is reviewed. You can copy and paste it all or copy the file from the GitHub repo for the project here.

 

Global Variables

This is section defines and configures all the necessary libraries we need.

///////////////////////////
// Global Vars
///////////////////////////
var creator_ip = '127.0.0.1'//local ip
var creator_servo_base_port = 20013 + 32;//port to use servo driver.
var matrix_io = require('matrix-protos').matrix_io;//MATRIX protocol buffers
//Setup connection to use MATRIX Servos
var zmq = require('zmq');
var configSocket = zmq.socket('push')
configSocket.connect('tcp://' + creator_ip + ':' + creator_servo_base_port);
//Api keys
var fs = require("fs");
var userConfig = JSON.parse(fs.readFileSync(__dirname+'/configure.json'));
//Libraries
var stripe = require('stripe')(userConfig.apiKeys.stripe);
var request = require('request');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();

 

Set Servo Position

This function is meant to simplify moving a servo in MATRIX CORE. The pin for the servo used is set to 0, but it can be changed to any other pin freely with no errors.

///////////////////////////
// SET SERVO POSITION
//////////////////////////
function moveServo(angle){
    //configure which pin and what angle
    var servo_cfg_cmd = matrix_io.malos.v1.io.ServoParams.create({
        pin: 0,
        angle: angle
    });
    //build move command
    var servoCommandConfig = matrix_io.malos.v1.driver.DriverConfig.create({
        servo: servo_cfg_cmd
    });
    //send move command
    configSocket.send(matrix_io.malos.v1.driver.DriverConfig.encode(servoCommandConfig).finish());
}

 

Gong Swing Timing

Using our previously defined function, for moving servos, this function is creating the swing motion that will be called when we want our Gong Master to use the gong. The variables above our function, gongsInQueue and gongInUse, are meant to allow the gong to handle multiple requests and to properly wait for each swing before swinging again.

///////////////////////////
// GONG SWING TIMING
//////////////////////////
var gongsInQueue = 0;//gongs requested
var gongInUse = false;//control swing usage

function gongMaster(){
    setInterval(function() {
        //checks for gongs queued and for current swing to stop
        if(gongsInQueue > 0 && !gongInUse){ 
            gongInUse = true;
            gongsInQueue--;//lower queue amount by 1
            moveServo(180);//swing gong arm
            //delay for position transition 
            setTimeout(function(){
                moveServo(90);//gong arm rest position
                //delay for position transition 
                setTimeout(function(){
                    gongInUse = false;
                },400);
            },300);
        }
    },200)
}

 

Post Slack Message

Using your Slack API Key, a message can be posted to the slack channel set in configure.json.

///////////////////////////
// POST SLACK MESSAGE 
//////////////////////////
function logToSlack(message){
    request({
            // HTTP Archive Request Object 
            har: {
              url: 'https://slack.com/api/chat.postMessage',
              method: 'POST',
              headers: [
                {
                  name: 'content-type',
                  value: 'application/x-www-form-urlencoded'
                }
              ],
              postData: {
                mimeType: 'application/x-www-form-urlencoded',
                params: [
                  {
                    name: 'token',
                    value: userConfig.apiKeys.slack
                  },
                  {
                    name: 'channel',
                    value: userConfig.slackChannel
                  },
                  {
                    name: 'link_names',
                    value: true
                  },
                  {
                    name: 'text',
                    value: message
                  }
                ]
              }
            }
        });
}

 

Handle API Events

This function is where the events for the Slack and Stripe API are handled. Once either API is processed, gongsInQueue is increased to let the GongMaster() function know that it's time to gong!

///////////////////////////
// HANDLE API EVENTS
//////////////////////////
function processEvents(api, event){
    //stripe events
    if(api === 'stripe'){
        if(event.type === 'charge.succeeded'){
            if(event.data.object.status === 'paid'){
                console.log('There was a charge for '+event.data.object.amount);
                logToSlack("A Charge Has Occured");
                gongsInQueue++;//gong once
            }
        }
        else if(event.type === 'transfer.paid'){
            if(event.data.object.status === 'paid'){
                console.log('There was a transfer for '+event.data.object.amount);
                logToSlack("A Transfer Has Occured");
                gongsInQueue+=2;//gong twice
            }
        }
    }
    //slack event
    else if(api === 'slack'){
        //check that slack is sending a slash command event
        if(typeof event.command !== 'undefined' && event.command !== null)
            //check that the command is /gong
            if(event.command === '/gong'){
                gongsInQueue++;
                logToSlack('@'+event.user_name+' has summoned me!');
            }
    }
    //unhandled event
    else{
        console.log('I was not made to handle this event');
    }
}

 

Server

The final part of the code is creating the server that listens to messages from Stripe and Slack. Once the server receives a message (POST Request)  it will begin to make use of all the previously defined functions.

//////////////////////
// SERVER
/////////////////////
app.use(bodyParser.urlencoded({ extended: true })); //handle urlencoded extended bodies
app.use(bodyParser.json()); //handle json encoded bodies

//STRIPE POST Request Handling
app.post('/events', function(req, res) {
    processEvents('stripe', req.body);//begin gong process
    res.sendStatus(200);//evrything is okay
});

//SLACK POST Request Handling
app.post('/slack_events', function(req, res) {
    //check that request is from slack (not guaranteed)
    if( req.headers['user-agent'].indexOf('https://api.slack.com/robots') > 0){
        processEvents('slack', req.body);//begin gong process
        console.log("received request from slack");
        res.send(req.body.user_name + ', Your Wish Has Been Gonged!');//response to user for /gong
    }
    //request is not from slack
    else
        res.send('You Have Angered The Gong Master!');
});

//Create Server
app.listen(userConfig.serverPort, function() {
    console.log('Gong listening on port '+userConfig.serverPort+'!');
    gongMaster();//listening for gong requests
});

 

Step 8: Code for package.json

This is the reference for all the libraries and scripts used in this project.

{
  "name": "gong_master",
  "version": "1.0.0",
  "description": "robot gong that uses the slack and stripe api",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Carlos Chacin",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.17.2",
    "express": "^4.15.4",
    "matrix-protos": "0.0.13",
    "request": "^2.81.0",
    "stripe": "^4.24.1",
    "zmq": "^2.15.3"
  }
}

 

Step 9: Running the program

From the project directory run "node app.js" in the CLI to start the program.

To test in Slack, use the command you made and the Gong Master should respond to your request!

GongMasterDemo.gif

 

All code for the app can be found on GitHub here: https://github.com/matrix-io/MATRIX-Gong-Master

Filter Blog

By date: By tag: