Combinare semplicità, potenza e longevità in uno stesso progetto…
Da un pò mi frullava l’idea di realizzare qualcosa di simpatico che combinasse in se più “branche” dell’informatica.. qualcosa di semplice ma allo stesso tempo longevo che richiamasse un pò le mie conoscenze.
Il risultato? beh.. è ciò che voglio mostrarvi proprio adesso, a voi il giudizio!

Partiamo con ordine…
Circa 1 mese fa, con un pò di tempo libero e qualche idea gettata su carta ho iniziato la realizzazione di un progetto!
Dopo l’illuminazione, guardando e curiosando un pò sulla rete non vidi niente di simile a ciò che avevo in mente, quindi adesso, posso affermare quasi con certezza che si tratta del primo Facebook Notifier attualmente realizzato.

Facebook Notifier


Prototipazione del Facebook Notifier

Cos’è il Facebook Notifier?
Il Facebook Notifier è un device usb che segnala la presenza di notifiche sul vostro account di Facebook… ricorda chiaramente una piccola cassetta delle lettere in pieno stile americano..
quando sono presenti notifiche ancora da visionare la bandierina gialla, tramite un micro-servo, si alza.
Quando non vi sono più notifiche, la biandierina gialla si abbassa.

Il dispositivo è stato realizzato totalmente da 0, partendo da un’idea, giungendo alla sua progettazione e terminando con l’implementazione del codice e la sua costruzione finale.

Le conoscenze richieste per la realizzazione di un apparecchio come il fb notifier sono fondamentalmente 3:
– Un linguaggio di programmazione lato client/master per la realizzazione di un software di controllo che invii tramite seriale specifici output alla board che è connessa (tramite USB si intende).
– Un linguaggio di programmazione per l’implementazione del sistema di ricezione dei dati via seriale gestiti da un microcontrollore (nel mio caso un ATMEGA328 28pin ad 8 bit).
– Conoscenze elettroniche di base (utile la padronanza di una board di prototipazione elettronica, Arduino nel mio caso).

Facciamo adesso parlare le immagini!

Nella foto seguente il ritaglio della cassettina di cartone:

Ritaglio della cassettina

Poi il ritaglio della scritta “Facebook” da un semplice foglio di carta:

Ritaglio della scritta

In quest’altra foto la cassettina incollata con al suo interno l’elettronica per gestire la comunicazione seriale con il pc e pilotare il servo al verificarsi di specifici eventi:

Sguardo d'insieme sul Facebook Notifier

Qui invece si attende che la colla faccia presa fra l’erba sintetica, la tavola di legno e il palo di sostegno su cui poi verrà fissata la cassettina:

Palo di sostegno del fb notifier

Ed in fine, il progetto completato!

fb notifier terminato by Rocco Musolino

Per non dilungarmi troppo con le foto vi invito a visionare la gallery completa all’album su Flickr: http://www.flickr.com/photos/63209576@N05/show/
(Mi scuso in anticipo per la pessima qualità di alcune foto in particolare, verranno presto sostituite)

I componenti utilizzati sono di uso comune e facilmente reperibili in commercio:


– Per la prototipazione del dispositivo è stata utilizzata una board Arduino.
– Il design esterno è in cartone (vari pezzi incollati fra loro), sono bastati 3 cartoncini: blu, marrone, giallo.
– La base di appoggio è una semplice tavola di legno con sopra dell’erba sintetica.
– Il servo impiegato è un MG995 Tower Pro.

Per quanto concerne il lato software invece, è qui il vero cuore pulsante del progetto. Abbiamo 2 Sorgenti di codice. Il primo è un programma in Python che tramite la libreria Mechanize e Serial permettono al software di interfacciarsi con facebook, controllare eventuali notifiche e se presenti comunicarlo tramite seriale al dispositivo usb connesso (che altro non è che una board Arduino “ridotta all’osso”, sempre in ascolto sulla seriale, il cui micro-controllore è programmato in un certo modo, ovvero basta guardare il codice in linguaggio C che vedete ancora più sotto per intuirne il funzionamento).

CODICE DEL PROGRAMMA CLIENT IN PYTHON:

import mechanize
import cookielib
import serial
import sys
import time
import warnings
 
''' VERSIONE 2.3
A differenza della versione 2.0, in questa implementazione:
Invece che contare partendo dai 2 tag HTML presenti di default <div class="c">, e' possibile clikkare il link:
clikka su Clear Notifications (restera' solo un <div class="c">)
e iniziare a contare per i > 1
 
In questo modo evita di contare inviti ad eventi o avvisi di compleanno come fossero notifiche.
'''
 
warnings.filterwarnings("ignore") #nasconde eventuali warning
 
SERIALPORT = raw_input("Inserire la porta seriale a cui e' connesso il dispositivo: ")
# Set up serial port
try:
	ser = serial.Serial(SERIALPORT, 9600)
	ser.timeout = None #Non imposta alcun tempo di timeout
except serial.SerialException:
	print "No device connected - exiting..."
	time.sleep(4)
	sys.exit()
 
 
#In alternativa si puo' andare su facebook.com/notifications.php e appoggiarsi al feed rss (utilizzando poi la libreria python: feedparser).
# Browser
br = mechanize.Browser()
 
# Cookie Jar
cj = cookielib.LWPCookieJar()
br.set_cookiejar(cj)
 
# Browser options
br.set_handle_equiv(True)
br.set_handle_gzip(True)
br.set_handle_redirect(True)
br.set_handle_referer(True)
br.set_handle_robots(False)
 
# Follows refresh 0 but not hangs on refresh > 0
#br.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)
 
 
 
# User-Agent (this is cheating, ok?)
br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]
 
 
# Open some site, let's pick a random one, the first that pops in mind:
r = br.open('http://m.facebook.com')
#html = r.read()
 
# Show the source
#print html
# or
#print br.response().read()
 
# Show the html title
print "- Connesso a: " + br.title()
 
# Select the first (index zero) form
br.select_form(nr=0)
 
try:
  attesa = input("\nOgni quanti secondi vuoi controllare la presenza di nuove notifiche? ")
  while(attesa < 5):
      attesa = input("\n- E' consigliato un valore non sotto i 5 secondi.\nInserisci nuovamente un valore: ")
except:
  print "E' necessario inserire un valore numerico, non una stringa.\nChiusura programma..."
  time.sleep(5)
  sys.exit()
 
print "\n- Inserisci i tuoi dati di accesso per Facebook:\n"
# Let's search
br.form['email']='%s' % raw_input("Inserisci Email: ")
br.form['pass']='%s' % raw_input("Inserisci Password: ")
 
br.submit()
x = br.response().read()
z = x.count("Combinazione e-mail/password errata.")
 
while z:
  print "Impossibile effettuare l'accesso, password o username errati. Riprovare:\n"
  go = False
  br.select_form(nr=0)
  br.form['email']='%s' % raw_input("Inserisci Email: ")
  br.form['pass']='%s' % raw_input("Inserisci Password: ")
  br.submit()
  x = br.response().read()
  z = x.count("Combinazione e-mail/password errata.")
else:
  #siamo perfettamente loggati. (z = 0)
  go = True
  stato = False #stato della bandierina, False = abbassata
  try:
    br.follow_link(text='Elimina notifiche', nr=0) #Pulisce le notifiche precedenti
  except:
    print "\n Nessuna Notifica! \n"
  print "\n- Contrassegnate come lette, tutte le precedenti notifiche...\n"
  ser.write("n") #riportiamo il servo alla posizione iniziale.
 
while True and go:
  try:
    #br.reload()
    #print br.response().read()
    x = br.open('http://m.facebook.com/home.php?refid=0').read()
    i = x.count('<div class="c">') #Questo campo HTML viene ripetuto piu' di 1 volta se c'e' una notifica nuova (prima pero' vengono lette tutte le notifiche quali eventi etc.).
  except:
      print "Ritardo nel ricaricare la pagina, 3 secondi di attesa applicati..\n"
      time.sleep(3)
  if i >= 1:
      notifica = True #Notifiche da leggere
  else:
      i = 0
      notifica = False #Nessuna notifica da leggere
#controllo:
  if notifica == True:
      if stato == False: #Se la bandierina e' abbassata
       ser.write("m")
       print "Nuova notifica su Facebook, sollevamento bandierina..."
       stato = True
      else:
       print "Sono presenti notifiche ancora da visionare..."
 
  elif stato == False:
       print "Zzz..." #Bandierina gia' abbassata, nessuna notifica da visionare
 
  else:
       ser.write("n")
       print "Nessuna nuova notifica, bandierina in discesa..."
       stato = False     
 
  time.sleep(attesa) #Attesa prima di controllare la presenza di nuove notifiche
 
 
#END

CODICE PER MICRO-CONTROLLORE ATMEGA328 con Bootloader Arduino:

#include <MsTimer2.h>
#include <Servo.h>
Servo myservo;
int val;
int pos;
void flash() {
static boolean output = HIGH;
digitalWrite(9, output);
output = !output;
}
void setup()
{
pinMode(9, OUTPUT);
Serial.begin(9600);
Serial.flush();
myservo.attach(10); //pin segnale servo connesso al pin digitale 10
}
void loop()
{
if (Serial.available())
{
val = Serial.read();
Serial.println(val, BYTE);
if (val == 110) // n = 110 in dec
{
pinMode(9,0);
pos = 0;
}
else if (val == 109) //109 = m in dec
{
pinMode(9, OUTPUT);
 
MsTimer2::set(150, flash); // 150ms periodo
MsTimer2::start();
pos =110; //110 gradi di rotazione perchè non essendo nel mio caso preciso il servo non arrivava a 90 gradi esatti ma si fermava poco prima
}    
}
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(23);
}

La versione del software in python è arrivata alla 2.3, qualora decidessi di implementare nuove funzionalità o semplicemente aggiornarlo, il codice verrà sostituito direttamente in questa pagina. Lo stesso discorso vale per il codice del micro-controller.
E’ un progetto praticamente completo. E’ stato un piacevole passa tempo, un progettino molto divertente da realizzare, questo infatti non esclude che ve ne saranno degli altri in futuro (che prontamente condividerò con tutti voi). Detto questo, qualsiasi dubbio, critica o suggerimento è sempre ben accetta.

Qui di seguito il video in alta qualità: