venerdì 30 agosto 2013

Creazione di post automatici su Facebook (3)


Arduino con shield Ethernet e sullo sfondo il post automatico su Facebook

E con questo siamo arrivati al termine del lavoro per poter postare su Facebook mediante Arduino.

Visti i precedenti post (1 e 2) adesso si deve configurare l'Arduino come Client Http per chiamare lo script Php che genera post automaticamente mediante l'access_token

La cosa e' piuttosto semplice e viene compiuta dallo sketch sottostante che crea una chiamata HTTP passando i parametri via GET. Il codice si commenta da solo

----------------------------------------
#include <Ethernet.h>
#include <SPI.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte server[] = { 150, 217, 73, XX }; 

EthernetClient client;

void setup()
{
  Ethernet.begin(mac);
  Serial.begin(9600);
  client.connect(server, 80);
  delay(1000);

  Serial.println("connecting...");

  if (client.connected()) {
    Serial.println("connected");
    client.println("GET /luca/xxxxxx/example3.php?msg=Arduino_automatico HTTP/1.0");
    client.println();
  } else {
    Serial.println("connection failed");
  }
}

void loop()
{
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    for(;;)
      ;
  }
}
------------------------------------------------------
sul lato server il log di apache mostra la connessione dell'Arduino con il web server

----------------------------
m.xxxxx.unifi.it:80 79.4.7.201 - - [29/Aug/2013:23:01:31 +0200] "GET /luca/xxxxx/example3.php?msg=Arduino_automatico HTTP/1.0" 200 418 "-" "-"

giovedì 29 agosto 2013

Problema di DNS su Ubuntu Server

E' accaduta una cosa curiosa sul server sul quale effettuo alcune prove tra cui quella di Facebook.
A seguito di una interruzione del corrente il server si e' spento brutalmente ed alla riaccensione erano scomparse le impostazioni del DNS (il file /etc/resolv.conf era vuoto con l'indicazione di non editare a mano)

E' stato necessario ripopolare il file /etc/resolv.conf con la sintassi

nameserver xxx.xxx.xxx.xxx

probabilmente le impostazioni del DSN vengono gestite in automatico da qualche programma (vedi questo link) ma su una macchina server mi sembra una scelta quantomeno discutibile

Creazione di post automatici su Facebook (2)

Proseguendo il discorso iniziato con il post precedente adesso si cerca di pubblicare un post senza l'interazione utente utilizzando l'access token

La stringa dell'access token e' quella lunga stringa alfanumerica che viene prodotta come risultato dallo script del post precedente
Per la politica di Facebook attualmente questo metodo funziona solo per 60 giorni perche' gli access token hanno una durata temporale; dopo tale scadenza l'utente deve riloggarsi  manualmente ed ottenere un nuovo access token

Questo script di fatto e' una versione semplificata del precedente in cui tutta la fase di autenticazione e' contenuta nell'access token

E' stato leggermente modificato il campo messaggio in modo da renderlo dinamico.
In questo modo se si aggiunge la variale msg alla URL si modifica il testo del messaggio
tipo

http://www.mioserver//script.php?msg=Luca

--------------------------------------------------------------------
<?
require_once '../src/facebook.php';

$appid = '6731359560xxxxxx';
$appsecret = 'dde6cfb07dbb769c7efe949cxxxxxxx';
$msg = $_GET["msg"];
$title = 'Messaggio Automatico Arduino';
$uri = 'http://debiaonoldcomputers.blogspot.com/';
$desc = 'Luca Innocenti.';
$pic = 'https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgluMOnPyTph3iUuLEcHHX8yoUSfMUnM5JlJH4xtJUoNTbZydICSkco_aB1Nc_gZ521xnI_JRptSkThfY7w1-dVLT7_9y5lzyWslzLYnhTQaExMPdr9Z8-Ed73ymkPwQwpnXmKuhfGdJPJ4/s400/Basic-+Facebook+Developers.jpg';
$action_name = 'Action Link in the Footer of the Post';
$action_link = 'http://debiaonoldcomputers.blogspot.com/';

$facebook = new Facebook(array(
 'appId' => $appid,
 'secret' => $appsecret,
 'cookie' => false,
 ));

 $user = $facebook->getUser();
 $accessToken = "CAAJkNq2LttoBAJywtmNSbVHqFPubOjYmQ2yyUG4kpibD75BHid9J7xsvif8osSOc4ewgK4aYerrLZBsZCQM5wykRTYVLDkCJXlXYl3gi8WFRQ8U4p4y4ZAXYsdamz6RVdRJZAe4vZA80mWBayuG0qc4IAj2TMDmQXKiv1OrKp8CwKjD6Rz2ZCAqpxxxxxxxx";

$attachment = array(
'access_token' => $accessToken,
'message' => $msg,
'name' => $title,
'link' => $uri,
'description' => $desc,
'picture'=>$pic,
'actions' => json_encode(array('name' => $action_name,'link' => $action_link))
);
$status = $facebook->api("/me/feed", "post", $attachment);
print "Ok";
?>


mercoledì 28 agosto 2013

Creazione di post automatici su Facebook

Questo post e' relativo ad un tentativo di connettere una Arduino ad un profilo Facebook per pubblicare i dati di un sensore

Esempi di pubblicazione automatica di post su Facebook se ne trovano a decine ma sono quasi tutti inutili perche' relativi ad API e sistemi di autenticazione non piu' in utilizzo presso Facebook

Per prima cosa, come visto in questo post, si deve creare una applicazione Facebook scegliendo stavolta App on Facebook. 
Si devono quindi compilare i dati delle informazioni di base, togliere la modalita' SandBox e poi indicare l'indirizzo della directory del server dove sono contenuti gli script Php che contengono l'applicazione (anche qui l'indizzo del server deve essere FQD e deve essere disponibili https)


a questo punto si inizia a lavorare sul lato server copiando l'SDK PHP di Facebook ed aggiungendo il seguente script (ripreso da questo link)  nella directory indicata nella schermata precedente
--------------------------------------------------------------
<?php

 require_once '../src/facebook.php';

// configuration
 $appid = '67313595xxxxxxxx';
 $appsecret = 'dde6cfb07dbb769c7efxxxxxxx';
 $msg = 'Messaggio';
 $title = 'Titolo';
 $uri = 'http://www.google.com';
 $desc = 'Descrizione';
 $pic = 'http://www.testcom/test.png';
 $action_name = 'Action Link in the Footer of the Post';
 $action_link = 'http://www.nathanbolin.com';

$facebook = new Facebook(array(
 'appId' => $appid,
 'secret' => $appsecret,
 'cookie' => false,
 ));


$user = $facebook->getUser();

// Contact Facebook and get token
 if ($user) {
// you're logged in, and we'll get user acces token for posting on the wall
try {
$accessToken = $facebook->getAccessToken();
if (!empty( $accessToken )) {
$attachment = array(
'access_token' => $accessToken,
'message' => $msg,
'name' => $title,
'link' => $uri,
'description' => $desc,
'picture'=>$pic,
'actions' => json_encode(array('name' => $action_name,'link' => $action_link))
 );

$status = $facebook->api("/me/feed", "post", $attachment);
} else {
$status = 'No access token recieved';
}
  } catch (FacebookApiException $e) {
  error_log($e);
  $user = null;
}
 } else {
// you're not logged in, the application will try to log in to get a access token
header("Location:{$facebook->getLoginUrl(array('scope' => 'photo_upload,user_status,publish_stream,user_photos,manage_pages'))}");
 }
print_r($status);
?>
------------------------------------

Se tutto e' andato a buon fine si avra' come risultato una pagina con scritto l'access token utilizzato (ovvero l'autorizzazione di Facebook) e nel proprio profilo Facebook si avra' il post pubblicato

Il passo successivo sara' utilizzare l'access token per evitare che vi debba essere l'interazione umana per effettuare il login in modo da permettere ad Arduino di pubblicare dati in automatico

martedì 27 agosto 2013

Sostituzione batteria tampone Mac Mini G4

Dopo un po' di tempo il mio vetusto (ma sempre bellissimo Mac Mini G4) ha deciso che la batteria tampone dell'orologio era finita.
La sostituzione e' un esercizio di forza bruta e coraggio
Per prima cosa, rovesciando il Mini, si inserisce una spatola (una spatola per il gesso e' perfetta)  nella fessura della base (da evitare il lato posteriore e quello anteriore) e si fa forza fino a far scattare le mollette.
Si procede quindi sul lato anteriore e sull'altro lato


Giunti qui si devono svitare tre viti (cacciavite da orologiaio magnetizzato consigliato) per rimuovere l'unita' ottica e l'hard disk (attenzione: per i modelli con bluetooth e wifi si devono staccare dei cavi), un po' di attenzione al filo del pulsante di accensione nella parte posteriore lato destro


la parte superiore ed inferiore sono collegate da un connettore a pettine sul retro. Sollevare con delicatezza

Si arriva quindi alla batteria CR 2032. Per toglierla il movimento deve essere prima verso il basso e poi verso l'esterno



Gestione dispositivi di Android

Visto che oramai e' chiaro che se si perde (o viene rubato il cellulare) ci si trova praticamente in mutande nei confronti di chi ritrova il telefono questa nuova funzione di Android di localizzare il telefono ed eventualmente rimuovere i dati e' fantastica

Di fatto e' necessario che il telefono abbia una scheda che permetta il traffico dati (se e' agganciato WiFi con le mie prove non funziona). Dopo di cio' ci si collega al link
https://www.google.com/android/devicemanager
e si puo' verificare (con ampio margine di errore) dove si trova il telefono, lo si puo' far squillare ed infine si possono cancellare da remoto i dati sensibili


Riconoscimento automatico oggetti in OpenCV

Una delle funzioni piu' carine di OpenCV e' quella che permette di individuare oggetti in automatico all'interno di una immagine. Il mio obbiettivo sarebbe quello di determinare la presenza di cartelli stradali.

Per una prova ho preso una normale immagine scattata con la fotocamera del cellulare


Ho cercato quindi di individuare in automatico la posizione del cartello di precedenza
Il programma deriva direttamente dagli esempi di OpenCV

-------------------------------------------------
#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"

using namespace cv;

void readme();

/** @function main */
int main( int argc, char** argv )
{
  if( argc != 3 )
  { readme(); return -1; }

  Mat img_object = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
  Mat img_scene = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );

  if( !img_object.data || !img_scene.data )
  { std::cout<< " --(!) Error reading images " << std::endl; return -1; }

  //-- Step 1: Detect the keypoints using SURF Detector
  int minHessian = 400;

  SurfFeatureDetector detector( minHessian );

  std::vector<KeyPoint> keypoints_object, keypoints_scene;

  detector.detect( img_object, keypoints_object );
  detector.detect( img_scene, keypoints_scene );

  //-- Step 2: Calculate descriptors (feature vectors)
  SurfDescriptorExtractor extractor;

  Mat descriptors_object, descriptors_scene;

  extractor.compute( img_object, keypoints_object, descriptors_object );
  extractor.compute( img_scene, keypoints_scene, descriptors_scene );

  //-- Step 3: Matching descriptor vectors using FLANN matcher
  FlannBasedMatcher matcher;
  std::vector< DMatch > matches;
  matcher.match( descriptors_object, descriptors_scene, matches );

  double max_dist = 0; double min_dist = 100;

  //-- Quick calculation of max and min distances between keypoints
  for( int i = 0; i < descriptors_object.rows; i++ )
  { double dist = matches[i].distance;
    if( dist < min_dist ) min_dist = dist;
    if( dist > max_dist ) max_dist = dist;
  }

  printf("-- Max dist : %f \n", max_dist );
  printf("-- Min dist : %f \n", min_dist );

  //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
  std::vector< DMatch > good_matches;

  for( int i = 0; i < descriptors_object.rows; i++ )
  { if( matches[i].distance < 3*min_dist )
     { good_matches.push_back( matches[i]); }
  }

  Mat img_matches;
  drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
               good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
               vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

  //-- Localize the object
  std::vector<Point2f> obj;
  std::vector<Point2f> scene;

  for( int i = 0; i < good_matches.size(); i++ )
  {
    //-- Get the keypoints from the good matches
    obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
    scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
  }

  Mat H = findHomography( obj, scene, CV_RANSAC );

  //-- Get the corners from the image_1 ( the object to be "detected" )
  std::vector<Point2f> obj_corners(4);
  obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
  obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows );
  std::vector<Point2f> scene_corners(4);

  perspectiveTransform( obj_corners, scene_corners, H);

  //-- Draw lines between the corners (the mapped object in the scene - image_2 )
  line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners[1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 );
  line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0), scene_corners[2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
  line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0), scene_corners[3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
  line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0), scene_corners[0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );

  //-- Show detected matches
  imshow( "Good Matches & Object detection", img_matches );

  waitKey(0);
  return 0;
  }

  /** @function readme */
  void readme()
  { std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
-------------------------------------------------

per prima cosa ho usato come immagine di training il cartello di precedenza estratto dalla medesima immagine.

Il risultato e' ottimale


a questo punto le cose si complicano. Ho scattato una seconda foto spostandomi di qualche metro per cambiare la prospettiva

Si ha ancora un qualche risultato ma chiaramente basta una piccola modifica per confondere l'algoritmo
Ancora piu' difficile. Invece di tagliare l'immagine ho preso una immagine generica di un cartello di precedenza (da Google Images)


il risultato e' decisamente pessimo

sostanzialmente un esperimento fallito e come al solito "conoscere la risposta aiuta nel risolvere un problema"

Feature Matching OpenCv

Il problema e' il seguente: trovare le differenze tra le due foto. Le due immagini sono state riprese a distanza di oltre un anno ed il ...