Showing posts with label cool. Show all posts
Showing posts with label cool. Show all posts

Thursday, April 22, 2010

Quick and dirty Instant Messaging with Redis

(Aside: Yes this is a post after a zillion years, but I have a few more lined up, and waiting for some important stuff in about a week)

Redis is a wicked cool NoSQL database, in that storing stuff is not the only thing that it does. Mathias Meyer already has a collection of Redis use cases, but this great idea is mine. Like all good ideas it emerged in the shower :) ( I was not aware of Pieter Noordhuis' MUC when I did this, in either case mine deals with one-to-one IM )

Using the new publish-subscribe commands and a bit of node.js code, here is a tiny instant messaging server. An explanation follows, refer to the code while reading it, Blogger sucks for publishing code.

Here is how it works. For every client, the server maintains two connections to redis. This is because a subscriber is not allowed to invoke other commands. So we have a subscriber connection and publisher connection. Consider two clients are now connected, Alice and Bob.

When Alice connects ( NICK Alice ), we insert her nickname into 'mclarens:inside', a Redis set. This allows us to have a WHO command to list online members. Bob to does the same. To start chatting with Alice, Bob initiates a conversation ( TALKTO Alice ). The node server does none of its own client management. Instead each client just maintains subscriptions to two channels/classes. Each client is always subscribe to '[nick]:info', where it is notified of talk initiations and exits etc. When Bob wants to talk to Alice, he sends a 'start Bob' to Alice's info channel, 'Alice:info'. Then both Alice and Bob subscribe to the class 'Alice:Bob', using alphabetical order to decide the name. When either of them wants to talk to the other, they do MSG [nick] [message]. The connection uses the publish redis connection to send a message to the channel, resulting in both sides being notified of the incoming message.

To terminate the chat, one side just has to send a 'STOP [nick]'. That unsubscribes the user from the class so that he no longer receives messages. It also sends a 'stop [nick]' to the other side, so that he/she can also unsubscribe.

On QUIT, we simply remove ourselves from the mclarens:inside set, unsubscription is handled automatically by Redis!

That's it, simple Instant Messaging! Now this lacks any kind of security and ignore lists and status but proves the point. In fact I'm thinking of using this as the backend for the IM part of the XMPP server I'm hacking on. At this point it is in no shape to have this feature just yet, but it should some day.

(Thanks to roidrage and tnm on #redis for pointing out that I had to use two Redis connections for PubSub.)

Sunday, February 22, 2009

GMail Notifier on an Arduino

The exams are over and I've been hacking a bit on the Arduino today. So I came up with a simple hack which blinks an LED on the Arduino if you've got unread mails in your Gmail inbox. I assume that you're familiar with the basics of Arduino.

Equipment

  • A computer with an internet connection

  • Python

  • pySerial

  • Arduino ( I'm using Duemilanove )

  • Red LED

  • Pushbutton (optional)

  • Wires

On the computer

A python script will run continuously on the computer, and fetch the Gmail RSS feed every few minutes. pySerial will be used to notify the Arduino of new mails.

Here are our imports and constants

# ~ Gmail Notifier for Arduino
# ~ This file is released under the public domain

import httplib
import getpass
import base64
import re
import time
import serial

INTERVAL = 5 # check every INTERVAL minutes

serv = 'mail.google.com'
path = '/mail/feed/atom'
# ask user name and password and encode them for authentication

auth = base64.encodestring(
'%s:%s'%(raw_input('Username: '),
getpass.getpass()))


So first, fetching the feed. We'll use httplib. Here is the code:

def getfeed():
print 'Checking...'
conn = httplib.HTTPSConnection(serv)
conn.putrequest('GET', path)
conn.putheader('Authorization', 'Basic %s'%auth)
conn.endheaders()
return conn.getresponse().read()


Next lets get the count. Gmail replies in the following format. In the case of new mails there is more information, but we don't care about that. We're mainly interested in fullcount.

<?xml version="1.0" encoding="UTF-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<title>Gmail - Inbox for nsm.nikhil@gmail.com</title>
<tagline>New messages in your Gmail Inbox</tagline>
<fullcount>0</fullcount>
<link rel="alternate" href="http://mail.google.com/mail" type="text/html" />
<modified>2009-02-22T11:00:33Z</modified>
</feed>


So we'll use regular expressions to get the count.

def count(data):
matches = re.findall('<fullcount>([0-9]+)</fullcount>', data)
if len(matches) == 0:
print 'Error in parsing feed, check user name and password are correct'
return 0
return int(matches[0])


We'll need to write this to the serial port.

def writeSer(data):
try:
# the best way to find this out is to launch the Arduino environment
# and see what it says under Tools -> Serial Port
ser = serial.Serial('/dev/ttyUSB0')
ser.write(data)
except serial.serialutil.SerialException:
print 'Error writing to serial device'
raise


Now that we're done with the functions, it's time to make them work together


# subtract so that we check first time
last_check = time.time() - INTERVAL*60

while True:
if time.time() - last_check < INTERVAL*60:
continue
last_check = time.time()
msgs = count(getfeed())
print msgs,'mails'
writeSer(str(msgs))



Thats the computer part.

On the Arduino


The circuit :



The LED is on pin 13 and goes to ground. The button takes 5V through the power pins on the analog side, via a 220 ohm resistor. The other leg is grounded. Pin 4 can be used to read the state of the button. The wire from pin 4 connects to the 5V leg of the button.

The code is dead simple and so is presented together.


int ledPin = 13; // connect led to digital pin 13, or use default small one
int bPin = 4; // connect button to digital pin 4
boolean blink = false; // holds our current state

int INTERVAL = 200; // led blink rate in milliseconds

void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
}

void loop() {
if(Serial.available() > 0)
blink = Serial.read() > 48;// 48 is 0 is ASCII

if(digitalRead(bPin) == LOW) // button pressed
blink = false;

// blink is true if we got serial input
// or we had got serial input and button hasn't been pressed yet.
if(blink) {
digitalWrite(ledPin, HIGH);
delay(INTERVAL);
digitalWrite(ledPin, LOW);
delay(INTERVAL);
}
else
digitalWrite(ledPin, LOW);
}


The button is used to switch off the blinking once you've noticed that you've got mail and don't want it to keep blinking till the next check.

Running

Verify and Upload the code to the Arduino. You can try entering numbers in the Serial Monitor to check that the circuit works. Remember to switch off the Serial Monitor.

Now start your script, python mailarduino.py. Enter authentication details. Now sit back and relax... oh wait, you've got mail.

Full python script ( mailarduino.py )

import httplib
import getpass
import base64
import re
import time
import serial

INTERVAL = 5 # check every INTERVAL minutes

serv = 'mail.google.com'
path = '/mail/feed/atom'

auth = base64.encodestring(
'%s:%s'%(raw_input('Username: '),
getpass.getpass()))

def count(data):
matches = re.findall('<fullcount>([0-9]+)</fullcount>', data)
if len(matches) == 0:
print 'Error in parsing feed, check user name and password are correct'
return 0
return int(matches[0])

def getfeed():
print 'Checking...'
conn = httplib.HTTPSConnection(serv)
conn.putrequest('GET', path)
conn.putheader('Authorization', 'Basic %s'%auth)
conn.endheaders()
return conn.getresponse().read()

def writeSer(data):
try:
ser = serial.Serial('/dev/ttyUSB0')
ser.write(data)
except serial.serialutil.SerialException:
print 'Error writing to serial device'
raise

last_check = time.time() - INTERVAL*60 # subtract so that we check first time

while True:
if time.time() - last_check < INTERVAL*60:
continue
last_check = time.time()
msgs = count(getfeed())
print msgs,'mails'
writeSer(str(msgs))

Sunday, June 29, 2008

Public thin clients

Another cool new idea, and this time it is seriously cool ( unlike this ), though it may not be feasible with today's technology and economics. So here it goes:

Everybody has a cellphone these days, most of them support Internet access and they are pretty powerful in terms of processing power for most of the things anyone does on the web.
But I for one hate browsing on that disgusting little screen and typing URLs on the keypad. Even the iPhone can't match the joy of being able to view the entire page at once and still read every word. Maybe these are just my aesthetic idiosyncries but I like to be pampered.

So we have a collection of TFT touchscreens ( called PDA - Public Display for All ) all around us in public. They could look just like whiteboards. All you've to do is go near one and (assuming there is no queue) hook your cellphone up to the PDA using Bluetooth or some protocol not yet invented. Which means your data is available on the move, but you still get great visualisation and interaction. Once your work is done, you just leave and the phone disconnects itself.

Suppose your friend has this really cool video that you'd like, both of you latch onto the PDAs and drag-and-drop the photo.

The PDAs have absolutely no memory or trace of 'who' connected with them, they just display output and take input and pass it on to the anonymous user.

Additional features can of course be added:
  • Restrictions on how much time one person can use it, we don't want hoggers/freeloaders.
  • Privacy features like PDAs in phone booth like structures for all your secure transaction needs.
These could be charged for, free on advertisement based models or just paid for by the government as a public service ;)

I hope anyone who implements this before I grow up or the technology isn't available yet will please thank me and give me a share of the profits.

Friday, June 13, 2008

How cool is contextfree!

This is all it took:

startshape sun

rule sun {
sq { }
36* { r 10 } sq { }
}

rule sq {
SQUARE { hue 46 saturation 250 }
sq { x 1 y 1 s 0.8 brightness 0.4 }
}




to make this:

Sunday, February 17, 2008

Why factor is cool

Before beginning, I must admit I haven't messed with Factor for a couple of weeks now, nor do I contribute to it, I'm a Factor n00b. Please contradict peacefully.

Of course there are the usual reasons that it is open source, most of the standard libraries are in Factor itself, and that it has a really cool development environment. But almost every popular language these days has all that stuff.

The real reason I think factor is cool is because it still isn't near complete!

It's small and so the sense of community is much stronger, you can be the first to do things in Factor, when they've already been done elsewhere, and anyone with a decent education and experience could easily grok the theory too.

Small syntax


I would say Factor's basic constructs are even smaller than Python's. Just knowing a few shuffle words and USING:, defining words and quotations, gives you almost everything you need to know.

Everything else is just built on top of this.

Small population


At present Factor users are probably just in 2 digits. And there are no products (that I know of). Which means you could probably restructure the whole language without affecting anyone. This allows Factor to improve by rewrite, rather than by add-on.

Educational


Writing libraries for a new language means doing stuff that most have probably never done. So you have to learn about Unicode, or just traverse strings recursively (?!?) like I had to do in brainfacktor. ( Could it be better? )

Basically by keeping the core small, keeping a single stack and enforcing recursion by not having loops, Factor really forces iterative programmers to go stack based/functional. And that itself is a lot of fun, even though it is hard.

Reading about all the developers coding the standard libraries is also very informative, as is looking through the Factor sources.

And it would be fun to look at the interpreter, though I've never done it.



So that was my attempt at some evangelism :D

Saturday, July 14, 2007

Harry Potter and the Order of the Phoenix from the heart

Just back from seeing the fifth movie, and I'm in such a state of euphoria, I am just gonna let my subconscious type this. Man its so awesomely, splendidly, really really great. The effects, the acting, the everything is so totally spectacular. Its short ofcourse, but they have managed to put in enough to satisfy those who have read the book. It's this really cool thing about all these epic stories, HP, LOTR, Star Wars, they so totally immerse you in their world, trapping you for a few hours in a place with no worries, make you forget about your routine life. And if you are passionate about these things like I am, then you remember everything about them. I can probably list all the spells in HP and the whole history of Middle Earth, but I can't remember half the things I learnt yesterday in math. I just can't express in words how I feel after reading/watching stuff as good as this. So I will just leave those who do feel these things like I do to enjoy them...

Thursday, January 25, 2007

How cool is Alt + F2

I am always discovering new uses for the Run Command dialog of KDE. And now I learnt it can even do basic calculations, right there. Now if only it could handle scientific functions...