Traditional conference rooms often come with frustrating user experiences where many callers can’t seem to get in, missed the invitation, or can’t seem to find the e-mail where the call details were provided. With Rehuddle, users are given several super simple ways to share: 1) click to automatically copy the call details to your clipboard 2) click to auto generate an e-mail with the call details 3) text message someone to join the room 4) share the room via facebook and 5) generate a call that places a caller directly in the room (no extension needed).
The site is built with Ruby, Asterisk, Javascript, Node.js, and MySQL. Each user that joins a “huddle” is provided an avatar based on the last four digits of their phone-number. This allows each user to be uniquely identified and understand who is on the call. The avatars are currently being generated using Node.js and Underscore.js. Node is being used to ping our mySQL server every second and pipe the results into a socket that the client can read by parsing JSON. Underscore.js is being used to compare the current list of callers with a previous list of callers. This allows the client to know which callers to add for each browser and which callers to remove. Each conference room also gets a unique URL. If a user creates a room called “Sony Meeting” – Rehuddle will auto generate a URL Rehuddle.com/sony-meeting where the call can live. This url generation is being done with Ruby utilizing Sinatra and Datamapper/MySQL. Within the room our copy to clipboard share feature is using a JQuery library called zClip. The SMS messages are being routed through a Twilio’s Ruby API, the Facebook share call-to-action is using the standard Facebook Developers share button, and the call generator is happening in Asterisk, but is routed through Flowroute through a SIP registry.
In future iterations Phil and I are looking to add document sharing features, editable name tags for each avatar, and potentially unique phone numbers for each room. We both feel that there’s a huge gap in the market for conference systems that are simple, easy to use, easy to share, and provide an informative and enjoyable web interface. We both look forward to more user testing to see where this product takes us. A big thank you goes to Chris Kairalla for teaching us Asterisk and helping us debug throughout the build!
My Ruby/Sinatra code is as noted below:
require 'sinatra' #generates a call file that will connect to the arduino context def gencallfile(numbertocall) time = (Time.now.to_f * 1000).to_i #current timestamp temp_dir = "/tmp/" callfile = "call_" + time.to_s + ".call" startcallfile = temp_dir + callfile end_dir = "/var/spool/asterisk/outgoing/" endcallfile = end_dir + callfile #write file to disk file = File.open(startcallfile,"w") file.puts("Channel: SIP/#{numbertocall}@flowroute\n") file.puts("MaxRetries: 1\n") file.puts("RetryTime: 60\n") file.puts("WaitTime: 30\n") file.puts("CallerID: Arduino <2122738466>\n") file.puts("Context: rtt233_arduinocall\n") file.puts("Extension: s\n") file.close #change file permission File.chmod(0777, startcallfile) FileUtils.chown(ENV['USER'],'asterisk',startcallfile) #move file to /var/spool/outgoing FileUtils.mv(startcallfile,endcallfile) end # Main route - this is the form where we take the input get '/' do call_number=params[:callnumber] if call_number gencallfile(call_number) # params[:callnumber] will be used to generate a call file # which will play back a message from the "Arduino". "Called #{call_number}" else "missing \"callnumber\" param" end end
My Arduino code is noted below:
//state constants #define HTTP_ACTIVE 10 #define HTTP_IDLE 20 #include <SPI.h> #include <Ethernet.h>fa //setup 70 A5 DA 00 85 70 byte mac[] = { 0x70, 0xA5, 0xDA, 0x00, 0x85, 0x70 }; IPAddress server (XXX,XXX,XXX,XX); // my server //client stuff char httpCommand[] = "GET /~rtilton1/sinatra/arduinocall/?callnumber=19174365310 HTTP/1.0"; EthernetClient client; byte httpState = HTTP_IDLE; int httpDelay = 5000; //wait at least this long in millis before sending another request unsigned long connectTime = 0; //button stuff const int buttonPin = 2; int buttonState = 0; void setup() { Serial.begin(9600); if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // no point in carrying on, so do nothing forevermore: for(;;) ; } // give the Ethernet shield a second to initialize: delay(1000); Serial.println("ready."); } void loop() { //read input from server, if any. if (client.available()) { char c = client.read(); Serial.print(c); } //check button, only read if there are no active http connections and we're past minimum delay if (httpState == HTTP_IDLE && pastHttpDelay()) { buttonState = digitalRead(buttonPin); if (buttonState == HIGH) { serverConnect(); } } //close client if disconnected if (!client.connected() && httpState == HTTP_ACTIVE) { client.stop(); httpState = HTTP_IDLE; Serial.println(); Serial.println("disconnected."); } } boolean pastHttpDelay(){ if ((millis() - connectTime) > httpDelay) { return true; } else { return false; } } void serverConnect(){ Serial.println("connecting to stu.itp.nyu.edu"); if (client.connect(server, 80)) { httpState = HTTP_ACTIVE; connectTime = millis(); //when did we connect? Serial.println("connected"); client.println(httpCommand); client.println(); } else { httpState = HTTP_IDLE; Serial.println("connection failed"); } }
For my redial midterm I created a website where this project can live. It uses asterisk to generate a call and bring a user through a dial plan where a MySQL database is communicated with through AGI, AJAX, and Ruby. Overall I’m happy with the way the project turned out and am excited to receive data to begin averaging the voices. Hopefully the results will prove to be interesting. Currently the site is hosted on the ITP server, but when it launches I plan to move it to voiceoftomorrow.com.
Today, Greg Borenstein gave us an introduction to Git and Github – both amazing and necessary tools within the development world. My GitHub account can be found here. The Git workflow is as follows:
- Do work
- Save changes (commit)
- Share changes (push)
- Get changes (pull)
- Experiment (branch)
- See changes (diff)
- Combine changes (merge)
- Undo changes (revert)
General commands that are important to know are:
pwd #where you are
cd #move to file directory
open . #opens in finder
mkdir #create a folder
ls #list content within the folder you’re looking at
man [command] #view manual of a specified commans (ex. man ls)
:q #quit if you’re in edit mode
ls -la #show hidden files
which git #shows where git is installed on your machine
open .git/config #opens git config file in that folder
Now onto the interesting stuff. How do you create a git repository, add, commit, and save locally:
git init #make git repository in current location
git status #show status of modifications
git add . #add everything in this folder to be commited
git commit -m “[message]” #commit to repository – this will create a number called a sha
If you have changed the file since your last commit you can use the following to view the difference, commit or revert
git log #views repository logs for this folder
git diff [sha1]..[sha2] #shows what has changed within the file
git revert [sha] #reverts to specific repository date
git reset — hard #undos the last git commit
git checkout -b [name] #creates a name associated with updates
git checkout [name] #brings you to how the file last looked like with that associated name. This is good in order to toggle between two peoples updates
Lastly, we learned how to push and pull our Git to a GitHub repository:
First – got to your Github.com account and create new repository. This will give you the information needed to go to your terminal and do the following:
git remote add [git@github.com:[username]/[repositoryName].git] #links the folder you’re in to the github folder
git add .
git commit -m “note”
git push #pushes files to the repository
If you’re pulling someone elses repository down into a local file you would do the following:
git remote add [name] https://github.com/[name]/[repositoryName].git #add the remote directory
git pull [name] master #pulls the files from external account
git pull #this is to pull from your own account




