var net = require('net') //TCP Server
var sockets = [] //empty array for ppl who connect to server
var server = net.createServer(function(socket){
sockets.push(socket); //add person to socket
socket.on('data', function(data){
for(var i = 0; i<sockets.length; i++){
if(sockets[i] == socket) continue; //dont broadcast your own echo
sockets[i].write(data); //when data is received write
}
});
//remove socket from arary
socket.on('end', function(){
var i = sockets.indexOf(socket);
sockets.splice(i,1); //remove person from array
//could also do-- delete socket.[0]
});
});
server.listen(8000);This week I started reading Wired for Speech by Clifford Nass and Scott Brave. They discuss the human-computer relationship in regards to speech and have conducted many interesting tests to prove theories. Based on their studies humans have affiliations with computers that can speak which directly affects how they judge them and feel about them. For instance, a computer with a feminine voice who is teaching a lesson is more likely to be thought of as emotional and less strict than a computer with a male voice (who teaches the exact same lesson). Personalities are also generated based on how feminine or masculine a computers voice is even when synthetic.
Regarding the reciprocation of love to a computer – in December 2009 – a human for the first time attempted to marry a fictitious character from a video game. The character married was from a Nintendo DS game called “Love Plus.” Sal, the human, stated “I love this character, not a machine”…”I understand 100 percent that this is a game.” But does this love come from an addiction and are these feelings as ‘authentic’ as the love one feels for a human? Hiroshi Ashizaki, an author on internet and game addiction thinks that Sal’s relation is healthy and that the youth is feeling more and more comfortable expressing their true selves through virtual worlds rather than the real world.
Overall, there are a lot of mixed perceptions on this topic. With an experiment of my own I’m looking to help shed some more light on the topic (experiment to be announced when results are collected).
The Arduino code is as follows:
#define FORWARD 10 #define REVERSE 20 #define STOPPED 30 #define forwardPin 6 #define reversePin 7 #define leftPin 8 #define rightPin 9 #define pulseDuration 500 #include <SPI.h> #include <Ethernet.h> //setup 10 A5 DA 00 85 70 byte mac[] = { 0x10, 0xA5, 0xDA, 0x00, 0x85, 0x70 }; IPAddress server (XXX,XXX,XXX,XX); // my server int port = 12002; EthernetClient client; unsigned long startPulseTime = 0; int drivingState = STOPPED; int inByte = 0; // incoming serial byte // The setup() method runs once, when the sketch starts void setup() { // initialize the digital pin as an output: pinMode(forwardPin, OUTPUT); pinMode(reversePin, OUTPUT); pinMode(leftPin, OUTPUT); pinMode(rightPin, OUTPUT); Ethernet.begin(mac); Serial.begin(9600); delay(1000); if (Ethernet.begin(mac) == 0) { Serial.println("Failed to configure Ethernet using DHCP"); // no point in carrying on, so do nothing forevermore: for(;;) ; } Serial.println("Ethernet reday"); serverConnect(); } void serverConnect(){ Serial.println("connecting to remote server..."); if (client.connect(server, port)) { Serial.println("connected to remote server"); client.println('A'); } else { Serial.println("remote connection failed"); } } // the loop() method runs over and over again, // as long as the Arduino has power void loop() { // if we get a valid byte, read analog ins: if (client.available()) { // get incoming byte: inByte = client.read(); //Serial.print(inByte); switch(inByte){ case '2': Serial.println("forward"); forward(); break; case '8': Serial.println("reverse"); reverse(); break; case '4': Serial.println("left"); turnLeft(); break; case '6': Serial.println("right"); turnRight(); break; } } else { if (drivingState != STOPPED){ if ((millis() - startPulseTime) > pulseDuration){ Serial.println("pulse ended"); powerStop(); } } } } void forward(){ drivingState = FORWARD; startPulseTime = millis(); digitalWrite(reversePin, LOW); digitalWrite(forwardPin,HIGH); } void reverse(){ drivingState = REVERSE; startPulseTime = millis(); digitalWrite(forwardPin, LOW); digitalWrite(reversePin, HIGH); } void turnLeft(){ digitalWrite(rightPin,LOW); digitalWrite(leftPin, HIGH); } void turnRight(){ digitalWrite(leftPin, LOW); digitalWrite(rightPin,HIGH); }
The node code is as follows:
var agi_net = require('net'); var remote_net = require('net'); var REMOTE_PORT=12002; var AGI_HOST = '127.0.0.1'; var AGI_PORT = 12001; /** * AGI will only send key presses, and that's it. * There's no identifying characteristics, just raw press events. */ /** Remote clients send no info to this server. * all they do is receive byte representations of digits. * (0-9, #, *) on the phone's keypad as ascii bytes*/ //remote screens or physical objects var remoteClients = []; remote_net.createServer(function(sock){ console.log('CONNECTED REMOTE CLIENT: ' + sock.remoteAddress +':'+ sock.remotePort); remoteClients.push(sock); //add client // Add a 'close' event handler to this instance of socket sock.on('close', function() { for(var i = 0; i < remoteClients.length; i++) { if(remoteClients[i] == sock) { //remove client remoteClients.splice(i,1); break; } } console.log('DISCONNECTED REMOTE CLIENT: ' + sock.remoteAddress +':'+ sock.remotePort); }); // Add a 'data' event handler to this instance of socket sock.on('data', function(data) { for ( var i = 0; i < data.length; i++){ handleByte(data[i]); } function handleByte(buf){ console.log(buf); } }); }).listen(REMOTE_PORT); console.log('Server listening for remote connections on ' + REMOTE_PORT); agi_net.createServer(function(sock){ console.log('CONNECTED AGI CLIENT: ' + sock.remoteAddress +':'+ sock.remotePort); // Add a 'close' event handler to this instance of socket sock.on('close', function(data) { console.log('CLOSED AGI CLIENT: ' + sock.remoteAddress +':'+ sock.remotePort); }); // Add a 'data' event handler to this instance of socket sock.on('data', function(data) { console.log(data); //broadcast data to all remote clients for (var i = 0; i < remoteClients.length; i++){ var client = remoteClients[i]; client.write(data); } }); }).listen(AGI_PORT, AGI_HOST); console.log('Server listening for AGI connections on ' + AGI_HOST +':'+ AGI_PORT);
The AGI script is as follows:
#!/usr/bin/ruby #very simple implementation of asterisk -> server -> client stack #only sends the digit and the caller id. #designed for very simple control, like arduino or web page require 'rubygems' require 'ruby-agi' require 'socket' agi = AGI.new host = 'localhost' port = 12001 looping = true s = TCPSocket.open(host, port) agi.stream_file("vm-extension") while looping result = agi.wait_for_digit(-1) # wait forever if result.digit s.write "#{result.digit}" else #hangup broke the pending AGI request looping = false end end
The asterisk dialplan is as follows:
[rtt233_socketIO_arduino] exten => 1,1,Answer(); exten => 1,n,AGI(/home/rtilton1/asterisk_agi/socketIO_arduino.rb); exten => 1,n,Hangup();
All code examples and knowledge are curtesy to our awesome professor Chris Kairalla! I’m excited to continue on node and download the free book/pdf found here: http://visionmedia.github.com/masteringnode/
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"); } }


