Meet Butler and Cue

Provocation 1: Counter Culture

IntermediateFull instructions provided1,305
Meet Butler and Cue

Things used in this project

Hardware components

Arduino Yun
Arduino Yun
microcontroller for Butler
×1
Momentary Button
buttons for Butler
×2

Story

Read more

Code

butler.txt

Plain text
The Arduino code for Butler.
#include <Bridge.h>
#include <Process.h>
#include <Temboo.h>
#include "TembooAccount.h"
#include "TwilioAccount.h"

const int LED = 13;
const int FOOD = 12;
const int DRINK = 7;
boolean TEXTED = false;

int RECEIVED = 0;
const int FRIENDS = 4;
String friends[] = {"Drake", "Eric", "Jon", "Chris"};
String oldIDs[] = {"", "", "", ""};
String numbers[] = {"+1 XXX-XXX-XXXX", "+1 XXX-XXX-XXXX", "+1 XXX-XXX-XXXX", "+1 XXX-XXX-XXXX"};

void setup() {
  Bridge.begin();
  Serial.begin(9600);

  //Configure pins
  pinMode(FOOD, INPUT_PULLUP);
  pinMode(DRINK, INPUT_PULLUP);
  
  //Initialize message IDs
  for (int i = 0; i < FRIENDS; i++) {
    String initID = "";
    TembooChoreo incomingSMS = createIncomingSMSChoreo(numbers[i]);
    incomingSMS.run();

    while (incomingSMS.available()) {
      String field = incomingSMS.readStringUntil('\x1F');
      field.trim();
      String data = incomingSMS.readStringUntil('\x1E');
      data.trim();

      if (field == "sid") { initID = data; }
    }
    delay(1000); incomingSMS.close();
    oldIDs[i] = initID;
  }
}

TembooChoreo createOutgoingSMSChoreo(String firstName, String number, String type) {
  TembooChoreo OutgoingSMSChoreo;
  OutgoingSMSChoreo.begin();

  //Choreo Setup
  OutgoingSMSChoreo.setAccountName(TEMBOO_ACCOUNT);
  OutgoingSMSChoreo.setAppKeyName(TEMBOO_APP_KEY_NAME);
  OutgoingSMSChoreo.setAppKey(TEMBOO_APP_KEY);
  OutgoingSMSChoreo.setChoreo("/Library/Twilio/SMSMessages/SendSMS");

  //API Inputs
  OutgoingSMSChoreo.addInput("AccountSID", TWILIO_ACCOUNT_SID);
  OutgoingSMSChoreo.addInput("AuthToken", TWILIO_AUTH_TOKEN);
  OutgoingSMSChoreo.addInput("From", TWILIO_NUMBER);
  OutgoingSMSChoreo.addInput("To", number);

  //Message Body
  String message = "Hey " + firstName + ", Sofia is making " + type + " at her apartment - want to join?";
  OutgoingSMSChoreo.addInput("Body", message);

  return OutgoingSMSChoreo;
}

TembooChoreo createIncomingSMSChoreo(String number) {
  TembooChoreo IncomingSMSChoreo;
  IncomingSMSChoreo.begin();

  //Choreo Setup
  IncomingSMSChoreo.setAccountName(TEMBOO_ACCOUNT);
  IncomingSMSChoreo.setAppKeyName(TEMBOO_APP_KEY_NAME);
  IncomingSMSChoreo.setAppKey(TEMBOO_APP_KEY);
  IncomingSMSChoreo.setChoreo("/Library/Twilio/SMSMessages/GetLastMessageFromNumber");

  //API Inputs
  IncomingSMSChoreo.addInput("AccountSID", TWILIO_ACCOUNT_SID);
  IncomingSMSChoreo.addInput("AuthToken", TWILIO_AUTH_TOKEN);
  IncomingSMSChoreo.addInput("From", number);
  IncomingSMSChoreo.addInput("ResponseMode", "verbose");

  //Output Filters
  IncomingSMSChoreo.addOutputFilter("sid", "/sid", "Response");
  IncomingSMSChoreo.addOutputFilter("body", "/body", "Response");

  return IncomingSMSChoreo;
}

void speak(String text) {
  Process p;
  p.begin("/mnt/sda1/tts.py");
  p.addParameter(text);
  p.run();
}

void loop() {
  String newID, body;
  int foodValue = digitalRead(FOOD);
  int drinkValue = digitalRead(DRINK);

  //Button Pressed
  if (foodValue == LOW || drinkValue == LOW) {
    String type = "stuff";
    if (foodValue == LOW) { type = "food"; } else if (drinkValue == LOW) { type = "tea"; }
    digitalWrite(LED, HIGH);
    speak("Sending text to your friends");
    int success = 0;

    for (int i = 0; i < FRIENDS; i++) {
      TembooChoreo outgoingSMS = createOutgoingSMSChoreo(friends[i], numbers[i], type);
      success = success + outgoingSMS.run();
      delay(1000); outgoingSMS.close();
    }

    if (success == 0) {
      speak("Texts sent!");
    } else {
      speak("Texts failed.");
    }
    
    RECEIVED = 0;
    TEXTED = (success == 0) ? true : false;
  } else if (TEXTED) {
    digitalWrite(LED, LOW);

    //Checking for new texts
    for (int i = 0; i < FRIENDS; i++) {
      TembooChoreo incomingSMS = createIncomingSMSChoreo(numbers[i]);
      incomingSMS.run();

      while (incomingSMS.available()) {
        String field = incomingSMS.readStringUntil('\x1F');
        field.trim();
        String data = incomingSMS.readStringUntil('\x1E');
        data.trim();

        if (field == "sid") {
          newID = data;
        } else if (field == "body") {
          body = data;
        }
        Serial.println(body);
      }
      delay(1000); incomingSMS.close();

      if (oldIDs[i] != newID) {
        oldIDs[i] = newID;
        RECEIVED++;
        String message = friends[i] + " says, '" + body + "'.";
        speak(message);
      }
    }
    
    if (RECEIVED == FRIENDS) { TEXTED = false; RECEIVED = 0; }
    delay(7000);
  }
}

tts.py

Python
Python script on Linux side for Butler.
#! /usr/bin/python

import urllib
import pycurl
import os
import sys
from subprocess import call
import string

url = 'http://tts-api.com/tts.mp3?q=' + urllib.quote(sys.argv[1])
filename = 'audio.mp3'

print('==> downloading audio from: ' + url)
f = open(filename, 'wb')
c = pycurl.Curl()
c.setopt(c.FOLLOWLOCATION, 1L)
c.setopt(c.URL, url)
c.setopt(c.WRITEFUNCTION, f.write)
c.perform()

c.close()
f.close()

call(['/usr/bin/madplay', filename])

cue.txt

Plain text
The Arduino code for Cue.
#include <Wtv020sd16p.h>
#include <SimpleTimer.h>
#include <Servo.h>

// motor variables
SimpleTimer timer;
Servo servo;
boolean locked = false;
int pos = 0;
int seconds = 3;
const int BUTTON = 10;
const int SERVO = 9;
const int LED = 13;

// audio variables
const int microphonePin = 0;
const int ledPin = 13;
int sample;
const int threshold = 500;
int resetPin = 2;  // The pin number of the reset pin.
int clockPin = 3;  // The pin number of the clock pin.
int dataPin = 4;  // The pin number of the data pin.
int busyPin = 5;  // The pin number of the busy pin.
Wtv020sd16p wtv020sd16p(resetPin,clockPin,dataPin,busyPin);
int count = 0;

void lock() {
  if (locked) {
    for (pos = 180; pos >= 1; pos--) {
      servo.write(pos); delay(15);
      locked = false;
    }
  } else {
    for (pos = 0; pos <= 180; pos++) {
      servo.write(pos); delay(15);
      locked = true;
    }
  }
}

void setup() {
  Serial.begin(9600);
  wtv020sd16p.reset();
  servo.attach(SERVO);
  pinMode(BUTTON, INPUT_PULLUP);
}

void loop() {
  int buttonValue = digitalRead(BUTTON);
  timer.run();
  
  // put your main code here, to run repeatedly:
  if (buttonValue == LOW) {
    digitalWrite(LED, LOW);
    lock();
    timer.setTimeout(seconds * 1000, lock); 
  }
  
  digitalWrite(LED, HIGH);
  
  sample = analogRead(microphonePin);
  Serial.println(sample);
  if (sample < threshold) { count++; } else { count = 0;}
  
  if (count >= 5) {
    wtv020sd16p.playVoice(3);
    delay(3000);
    count = 0;
  }
}

Credits

Sofia Dewar

Sofia Dewar

4 projects • 3 followers
Oscar Segovia

Oscar Segovia

6 projects • 5 followers
Mechanical Engineering with a focus on design
Andrea Deng

Andrea Deng

9 projects • 6 followers
designer. dancer. adventurer.
Drake Myers

Drake Myers

5 projects • 3 followers
Jon Lai

Jon Lai

5 projects • 2 followers

Comments