So, probably like many hackerspaces, Diyode spends a lot of time on our IRC channel. We also have a good few members who compulsively check the webcam whenever someone enters the shop. So when April first rolled around on a Monday this year, I figured it was time to put the CodeShield to work. I present: the IRC triggered, arduino controlled, floating head! This is the feed from the classroom webcam:
The face rising is triggered by a specific phrase on the Diyode IRC channel. We have a server in the shop that runs our access control system, including a bot that hangs out on the IRC channel so that it can post workshop events to the IRC, and collect to-do items and meeting topics from the chat room. The bot can also speak Text-to-Speech phrases with an IRC command.
The prank was to attract attention to the Diyode webcam on IRC (“Hey, someone just entered the shop without the doorbot noticing”), and then trigger a face to appear right in front of the cam while everyone was watching. For the face, I chose the disturbingly brilliant Jackson Blankenship. A specific phrase spoken on the IRC channel would trigger IRC python script on the linux box to send a message over USB to the arduino above the camera. Then the servo on the codeshield would make the face rise slowly in front of the webcam, then drop back down, freaking the crap out of anyone watching.
The Setup
The photo above shows the arduino/codeshield on a wooden block above the webcam. Three laser-cut arms control the face rising (I tweaked the design a bit after I took the photo).
Here’s the .ai file for laser cutting the arms. Particularly useful for the cut-out of the servo setting, if you’re doing something similar with sg90 servos.
The Code:
The Access Control box is running linux, with the responsibilities for the the IRC being handling by a python script. Some bits, obviously, have been changed for security reasons…
#!/usr/bin/python
import sys
import socket
import string
import os
import time
import conf
import datetime
import httplib
import urllib2
import MySQLdb
import calendar
import serial
from serial.tools import list_ports
if conf.platform == 'linux':
from festival import say
HOST='irc.freenode.net' #The server we want to connect to
PORT=6667 #The connection port which is usually 6667
NICK='DiyodeDoorBot' #The bot's nickname
IDENT='pybot'
REALNAME='Diyode HQ Door Bot'
OWNER='diyode' #The bot owner's nick
CHANNELINIT='#diyode' #The default channel for the bot
readbuffer='' #Here we store all the messages from server
s=socket.socket( ) #Create the socket
s.settimeout(5)
s.connect((HOST, PORT)) #Connect to server
s.send('NICK '+NICK+'n') #Send the nick to server
s.send('USER '+IDENT+' '+HOST+' bla :'+REALNAME+'n') #Identify to server
def doSpeak(msg):
if conf.platform == 'linux':
say(msg)
else:
os.system('say "'+msg.replace('"','')+'"')
def saveMessage(message, sender):
d = datetime.datetime.utcnow()
timestamp = calendar.timegm(d.utctimetuple())
conn = MySQLdb.connect(host= "localhost", user="-------", passwd="----------", db="-------")
x = conn.cursor()
sql = "INSERT INTO irc_events (message,timestamp,sender) VALUES ('%s','%s','%s')" % (message,timestamp,sender)
x.execute("INSERT INTO irc_events (message,timestamp,sender) VALUES (%s, %s, %s)", (message,timestamp,sender))
conn.commit()
conn.close()
def parsemsg(msg):
global CHANNELINIT
complete=msg[1:].split(':',1) #Parse the message into useful data
info=complete[0].split(' ')
msgpart=complete[1]
msgpartLower = msgpart.lower()
sender=info[0].split('!')
saveIt = 1
if msgpart[0]=='`' and sender[0]==OWNER: #Treat all messages starting with '`' as command
saveIt = 0;
cmd=msgpart[1:].split(' ')
if cmd[0]=='op':
s.send('MODE '+info[2]+' +o '+cmd[1]+'n')
if cmd[0]=='deop':
s.send('MODE '+info[2]+' -o '+cmd[1]+'n')
if cmd[0]=='voice':
s.send('MODE '+info[2]+' +v '+cmd[1]+'n')
if cmd[0]=='devoice':
s.send('MODE '+info[2]+' -v '+cmd[1]+'n')
if cmd[0]=='sys':
syscmd(msgpart[1:],info[2])
elif msgpartLower.find('!speak') == 0:
doSpeak(msgpart[6:])
s.send('PRIVMSG '+CHANNELINIT+' :Message spoken.n')
if msgpartLower.find('!speak: hello?') == 0:
doPrank()
elif msgpartLower.find('!newtopic") == 0:
doSaveTopic(msgpart[13:], sender[0])
elif msgpartLower.find('!todo') == 0:
doSaveTask(msgpart[5:], sender[0])
if msgpart[0]=='-' and sender[0]==OWNER : #Treat msgs with - as explicit command to send to server
saveIt = 0;
cmd=msgpart[1:]
s.send(cmd+'n')
if conf.debug:
print 'cmd='+cmd
if saveIt and msgpart.find('Welcome to the freenode Internet Relay Chat Network') != 0:
saveMessage(msgpart.strip(), sender[0])
def syscmd(commandline,channel):
cmd=commandline.replace('sys ','')
cmd=cmd.rstrip()
os.system(cmd+' >temp.txt')
a=open('temp.txt')
ot=a.read()
ot.replace('n','|')
a.close()
s.send('PRIVMSG '+channel+' :'+ot+'n')
return 0
def checkFile():
h = open(conf.ircFlagFile,'r')
contents = h.read()
h.close()
return contents
def clearFile():
h = open(conf.ircFlagFile,'w')
h.write('-')
h.close()
def doSaveTopic(topic, sender):
h = open(conf.topicFile,'a')
now = str(datetime.datetime.utcnow())
topic = "%s:::%s:::%sn" % (now,topic.strip(),sender.strip());
print topic
h.write(topic)
h.close()
s.send('PRIVMSG '+CHANNELINIT+' :' + 'Topic Saved: http://diyode.com/topics.phpn')
getURL('http://www.diyode.com/interface/UpdateTopics.php')
def doSaveTask(task, sender):
h = open(conf.taskFile,'a')
now = str(datetime.datetime.utcnow())
task = "%s:::%s:::%sn" % (now,task.strip(),sender.strip());
print task
h.write(task)
h.close()
s.send('PRIVMSG '+CHANNELINIT+' :' + 'To Do Item Saved: http://diyode.com/tasks.phpn')
getURL('http://www.diyode.com/interface/updateTasks.php')
def getURL(urlStr):
#print "getting URL: "+urlStr
try:
fileHandle = urllib2.urlopen(urlStr,timeout=3)
str1 = fileHandle.read()
fileHandle.close()
#print 'getUrl Result: '+str1
return str1
except IOError:
print 'Cannot open URL %s for reading' % urlStr
return False
def doPrank():
if arduino1:
arduino1.write("P");
port1 = ""
ports = list_ports.comports()
for port in ports:
if (port[0].find("usb") != -1):
if port1 == "":
port1 = port[0]
if (port1 == ""):
print "there are no arduinos attached"
else:
arduino1 = serial.Serial(port1, 115200)
print("arduino1 connected to "+port1)
clearFile()
pongCount = 0;
while pongCount < 600:
pongCount = pongCount + 1
if pongCount % 10:
if not conf.checkRun():
print "Stopping irc"
exit()
try:
line = s.recv(1000) #recieve server messages
time.sleep(0.25)
except:
line = ''
if len(line):
if conf.debug:
print line #server message is output
if line.find(' :+i')!=-1:
time.sleep(0.5)
print 'joining #diyode'
s.send('JOIN '+CHANNELINIT+'n') #Join a channel
pongCount = 0
if line.find('PRIVMSG')!=-1: #Call a parsing function
parsemsg(line)
line=line.rstrip() #remove trailing 'rn'
linebits=line.split()
if(linebits[0]=='PING'): #If server pings then pong
if conf.debug:
print "pongCount %d" % (pongCount)
s.send('PONG '+linebits[1]+'n')
pongCount = 0
sendMsg = checkFile()
if sendMsg != '-':
if conf.debug:
print sendMsg
s.send('PRIVMSG '+CHANNELINIT+' :'+sendMsg+'n')
clearFile()
conn.close()
Plugged into the linux box is an arduino with CodeShield attached, and the face hanging on a laser cut arm attached to the codeshield’s servo. This is the sketch running on the arduino
#include <Servo.h>
#define ENCODER_A 14
#define ENCODER_B 15
#define ENCODER_PORT PINC
#define SWITCH 13
#define BUTTON 12
#define RGB_RED 11
#define RGB_GREEN 10
#define RGB_BLUE 9
#define LED 6
#define SERVO 5
#define PIEZO 3
#define RELAY 2
#define POT 2
#define HALL 3
#define THERMISTOR 4
#define PHOTOCELL 5
Servo aServo;
char incomingByte;
char mode = '-';
char val[7];
int col = 1;
int a = 0;
void setup() {
Serial.begin (115200);
aServo.attach(SERVO);
}
void loop() {
if (Serial.available() > 0) {
incomingByte = Serial.read();
if (incomingByte == 'p' ||incomingByte == 'P') {
if (a == 0) {
a = 1;
}
}
}
if (a) {
int angle = 45 + 90 * sin(a * 0.00174532922);
aServo.write(angle);
if (a++ > 1800) {
a = 0;
}
}
delay(10);
}
Pingback: Pranking a hackerspace IRC for April Fool’s Day - RaspberryPiBoards
Pingback: Pranking a hackerspace IRC for April Fool’s Day | Daily IT News on IT BlogIT Blog
Pingback: Travesuras de un IRC hackerspace para el Día de los Inocentes - | Indagadores |Seguridad informatica |Seguridad en internet
Pingback: Pranking a hackerspace IRC for April Fool’s Day | Make, Electronics projects, electronic Circuits, DIY projects, Microcontroller Projects - makeelectronic.com