martedì 12 marzo 2013

Esempio di utilizzo di Itext in Java

Presento adesso un esempio reale dell'utilizzo della libreria IText per la creazione di pettorali per una corsa podistica.
La caratteristica dei pettorali era quella di dover contenere, oltre al numero, anche il relativo QrCode. Il pettorale e' quindi determinato dalla sovrapposizione di una immagine di base con i logo, il QrCode ed il numero. Il tutto e' gia' formattato per andare direttamente in tipografia (il foglio in formato Super A3 comprende 4 numeri che saranno successivamente tagliati)

Immagine di fondo

QrCode


Il risultato finale

Il codice per la generazione dei Pdf e' il seguente. Si deve precisare che le immagini dei QrCode erano gia' state create con il programma presentato in un precedente post e viene usato un font speciale (CITYB.ttf)
----------------------------------------------------------------------

package pettorale;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;

/**
 *
 * @author l.innocenti
 */
public class Pettorale {
    private static PdfWriter writer;
    

    public static void main(String[] args) throws BadElementException, MalformedURLException, IOException {
        
    //String numero = args[0];
    String  numero = "175";
    int inizio = Integer.parseInt(numero);
    
    BufferedOutputStream out = null;
    try {
        out = new BufferedOutputStream (new FileOutputStream (new File ("Pettorale_"+numero+"_"+Integer.toString(inizio+3) +".pdf")));
        } catch (FileNotFoundException e) {
          e.printStackTrace();
        }
    
        //Definisce le dimensioni del foglio come SuperA3 (45x32 cm)
        //Itext usa una unita'  di misura in punti tipografici 
        //1 cm = 28.35 unita' per cui le dimesioni del foglio sono
        //45 cm = 1285 u
        //32 cm = 907 u
        Rectangle pagina = new Rectangle(1275, 907);
        Document doc = new Document (pagina,0,0,0,0);

        try
        {
            writer = PdfWriter.getInstance (doc, out);
            doc.open ();
            PdfContentByte canvas = writer.getDirectContent();
            
            //inserisce lo sfondo 
            Image pettorale = Image.getInstance("pettorale/vuoto.png");
            pettorale.setAbsolutePosition(0f, 0f);
            pettorale.scalePercent(24.5f);
            doc.add(pettorale);

            //inserisce il QrCode del numero del pettorale
            Image qrcode = Image.getInstance("qrcode/"+Integer.toString(inizio) +".png");
            qrcode.setAbsolutePosition(475f, 620f);
            qrcode.scalePercent(120f);
            doc.add(qrcode);
            
            //2° numero
            qrcode = Image.getInstance("qrcode/"+Integer.toString(inizio+1) +".png");
            qrcode.setAbsolutePosition(1125f, 620f);
            qrcode.scalePercent(120f);
            doc.add(qrcode);
            
            //3° numero
            qrcode = Image.getInstance("qrcode/"+Integer.toString(inizio+2) +".png");
            qrcode.setAbsolutePosition(475f, 170f);
            qrcode.scalePercent(120f);
            doc.add(qrcode);

            //4° numero
            qrcode = Image.getInstance("qrcode/"+Integer.toString(inizio+3) +".png");
            qrcode.setAbsolutePosition(1125f, 170f);
            qrcode.scalePercent(120f);
            doc.add(qrcode);

            
            //scrive il numero del pettorale alla giusta posizione
           //1° numero 
           if (inizio <10) {
                absText(Integer.toString(inizio),270,625);
            }
            if ((inizio >=10) && (inizio <= 99)) {
                absText(Integer.toString(inizio),235,625);
            }
            if ((inizio >=100) && (inizio <= 999)) {
               absText(Integer.toString(inizio),150,625);
            }
            
            //2°numero
            if (inizio+1 <10) {
               absText(Integer.toString(inizio+1),920,625);
            }
            if ((inizio+1 >=10) && (inizio+1 <= 99)) {
                absText(Integer.toString(inizio+1),885,625);
            }
            if ((inizio+1 >=100) && (inizio+1 <= 999)) {
               absText(Integer.toString(inizio+1),790,625);
            }

            //3°numero
            if (inizio+2 <10) {
               absText(Integer.toString(inizio+2),270,165);
            }
            if ((inizio+2 >=10) && (inizio+2 <= 99)) {
               absText(Integer.toString(inizio+2),235,165);
            }
            if ((inizio+2 >=100) && (inizio+2 <= 999)) {
               absText(Integer.toString(inizio+2),150,165);
            }
            
            //4°numero
            if (inizio+3 <10) {
               absText(Integer.toString(inizio+3),920,165);
            }
            if ((inizio+3 >=10) && (inizio+3 <= 99)) {
               absText(Integer.toString(inizio+3),885,165);
            }
            if ((inizio+3 >=100) && (inizio+3 <= 999)) {
               absText(Integer.toString(inizio+3),790,165);
            }

     
        }
        catch (DocumentException e)
        {
            System.out.println ("Fatal PDF error: " + e);
        }

        doc.close ();

    }
    
    private static void absText(String text, int x, int y) {
    try {
      PdfContentByte cb = writer.getDirectContent();
      BaseFont slam = BaseFont.createFont("CITYB.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
      cb.saveState();
      cb.beginText();
      cb.moveText(x, y);
      cb.setFontAndSize(slam, 200);
      cb.showText(text);
      cb.endText();
      cb.restoreState();
    } catch (DocumentException | IOException e) {
    }
  }
}
----------------------------------------------------------------------


Aggiornamento software Lumix DMC-LS5

Non pensavo che mi sarei mai ritrovato ad aggiornare il firmware ad una macchina fotografica (sarebbe curioso farlo con una Voigtlander  a rullino) ma e' accaduto con la Lumix DMC-LS5

In sostanza si deve scaricare il file di aggiornamento PDCE570a.elf ed inserirlo nella radice della scheda SD. Si accende quindi la macchina premendo contemporaneamente il tasto di scatto ed il tasto di accensione.

Dopo qualche secondo la macchina si spenge in automatico ed al nuovo riavvio si vede l'avvenuto aggiornamento




La prossima volta voglio i tasti CTRL+ALT+DEL insieme al pulsante di scatto

Falsi (Fake) Casio F-91W e G-9200-Riseman

Recentemente mi si e' rotto il cinturino del mio Casio F-91W (cosa abbastanza per questo orologio che e' sostanzialmente indistruttibile) e cercando mi sono accorto che i cinturini vanno dai 5 ai 10 euro mentre l'orologio nuovo completo viene venduto dai 17 ai 25 euro....insomma non conviene sostituito il pezzo

Andando a giro su Alibaba ho trovato un modello di Casio F-91W a 3 dollari (spedizione compresa)...un affare. Una volta arrivato l'oggetto mi sono reso conto che non si tratta di un vero Casio ma di una replica, seppur ben fatta. Esternamente le differenze sono solo sul fondello (la copia indica Made in China mentre l'originale Made in Thailandia) e sulla luce dell'illuminazione (sulla replica e' blu)

Originale a sinistra

Originale a sinistra

Le funzioni dell'orologio sono le medesime nella copia e nell'originale

Con lo stesso ordine ho preso anche un Casio G9200 a meno di 9 euro per una eventuale sostituzione del mio Casio W-753 (anche questo con problemi di cinturino). Francamente non sapevo che questo e' il modello di punta della serie G-Shock con prezzi di oltre 150 euro e la cosa mi doveva insospettire...io cercavo solo un orologio con un altimetro integrato.
Inutile dire che anche questo e' una copia dell'oroginale ma le funzioni sono purtroppo differenti: non e' presente l'altimetro/barometro/termometro, non ha la calibrazione via radio e non possiede la cella solare


Il metodo piu' semplice per distinguere la copia dall'originale e' la presenza di una G nel cerchio rosso (che e' presente solo nella copia)
Insomma. ho speso 10 euro per due copie ma volendo in fondo avere due cinturini direi che la spesa e' stata congrua. In piu' ho imparato una lezione per il futuro

Selezionare scheda di rete per Internet su LInux

In questo post verra' descritto come gestire una scheda di rete wireless USB in Linux.

Nel caso, come il mio, il portatile non possegga un pulsante fisico per disattivare la scheda di rete integrata non e' proprio banale utilizzare la scheda di rete supplementare in quanto il sistema operativo riconosce per prima la scheda integrata e la usera' come default


Una soluzione semplice potrebbe essere quella di disattivare una interfaccia di rete con

ifconfig wlan0 down

in questo modo si spenge la scheda integrata (wlan0) ma ci si accorge subito che non e' la soluzione finale in quanto non si riesce  a navigare su internet. In pratica si riesce ad utilizzare tutta la rete interna e si riesce a pingare il router ma nessun pacchetto viene instradato all'esterno

E' chiaro che deve essere configurata la tabella di routing
Se si digita route con le due schede attive si ottiene
---------------------------------------------------

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.0.1     0.0.0.0         UG    0      0        0 wlan0
link-local      *               255.255.0.0     U     1000   0        0 wlan0
192.168.0.0     *               255.255.255.0   U     0      0        0 wlan0
---------------------------------------------------

disattivando la scheda integrata wlan0
---------------------------------------------------
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
link-local      *               255.255.0.0     U     1000   0        0 wlan1
192.168.0.0     *               255.255.255.0   U     0      0        0 wlan1
---------------------------------------------------
si vede chiaramente la perdita dell'interfaccia di default

Supponendo che l'indirizzo del router di 192.168.168.0.1 si puo' scrivere

route add default gw 192.168.0.1 wlan1

a questo punto la  tabella di routing viene cosi' modificata
---------------------------------------------------
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.0.1     0.0.0.0         UG    0      0        0 wlan1
link-local      *               255.255.0.0     U     1000   0        0 wlan1
192.168.0.0     192.168.0.1     255.255.255.0   UG    0      0        0 wlan1
192.168.0.0     *               255.255.255.0   U     0      0        0 wlan1
---------------------------------------------------
e si riesce a navigare in Internet

In conclusione la sequenza di comandi per utilizzare a pieno la scheda Usb e'
ifconfig wlan0 down

route add default gw 192.168.0.1 wlan1

Errore Resource out of sync in Eclipse

Nel momento di esportare come file zip (Export to archive file) un progetto Android da Eclipse mi e' stato notificato l'errore di "Resource out of sync" su un file di cache del progetto.



La soluzione al problema risiede semplicemente nell'effettuare un Refresh del progetto

venerdì 8 marzo 2013

Tastiera per MK808

Mi sono comprato per l'Mk808 una tastiera vera al posto del mouse Logitech che usavo fino ad ieri piu' che altro per la navigazione internet perche' digitare gli indirizzi con il topo e' piuttosto noioso

La scelta e' caduta su una Logitech K700 che, acquistata su un sito cinese, e' costata meno dei Fly Mouse (che adesso vanno cosi' di moda) ed ha un touchpad integrato sulla tastiera classica



La K700 funziona al volo sull'MK808 e sono riconosciuti quasi tutti i tasti (compresi i tasti volume, tasti cursore, tasto home e back)

giovedì 7 marzo 2013

Creare file Jar con Eclipse

Per creare un file jar in Eclipse si deve prima cliccare sulla radice del progetto sulla finestra di sinistra e selezionare Export


Successivamente deve essere selezionato Runnable Jar File



Nell'ultima finestra, dal primo menu a tendina, deve essere selezionata la classe di lancio




Creare file Jar con Netbeans

Per ottenere dei file jar da distribuire di una propria applicazione da NetBeans e' sufficiente effettuare una Build del progetto (F11)

In questo modo viene creata una sottodirectory build nella quale sono contenuti tutti i file (librerie comprese) necessari per la redistribuzione dell'eseguibile


Creazione automatica QrCode in Java/Netbeans

Per generare QrCode in modo automatico in modo semplice si puo' utilizzare il metodo presentato a questo indirizzo

 Si deve scaricare la libreria XZing e si devono aggiungere al progetto le librerie core e javase contenute nelle sottodirectory del file zip


il codice e' stato modificato in modo da accettare in input sulla riga di comando (nella variabile args) il contenuto del QrCode. Questa motiva permette mediante una procedura batch di creare in automatico quanti QrCode si desiderino

-----------------------------------------
package qrcode;


import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Hashtable;

import com.google.zxing.client.j2se.MatrixToImageWriter;


/**
 *
 * @author l.innocenti
 */
public class QrCode {

    public static void main(String[] args) {
        Charset charset = Charset.forName("UTF-8");
        CharsetEncoder encoder = charset.newEncoder();
        byte[] b = null;
            try {
                // Convert a string to UTF-8 bytes in a ByteBuffer
                ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(args[0]));
                b = bbuf.array();
            } catch (CharacterCodingException e) {
                System.out.println(e.getMessage());
            }

            String data;
            try {
                data = new String(b, "UTF-8");
                // get a byte matrix for the data
                BitMatrix matrix = null;
                int h = 100;
                int w = 100;
                com.google.zxing.Writer writer = new MultiFormatWriter();
                try {
                    Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>(2);
                    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
                    matrix = writer.encode(data,
                    com.google.zxing.BarcodeFormat.QR_CODE, w, h, hints);
                } catch (com.google.zxing.WriterException e) {
                    System.out.println(e.getMessage());
                }

                // change this path to match yours (this is my mac home folder, you can use: c:\\qr_png.png if you are on windows)
                        String filePath = args[0]+".png";
                File file = new File(filePath);
                try {
                    MatrixToImageWriter.writeToFile(matrix, "PNG", file);
                    System.out.println("printing to " + file.getAbsolutePath());
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                }
            } catch (UnsupportedEncodingException e) {
                System.out.println(e.getMessage());
            }
            }
}
-----------------------------------------
Il risultato e' una immagine Png con nome uguale al contenuto del QrCode 
Per creare in automatico 1000 numeri QrCode di numeri progressivi si puo' creare un file batch su Windows con la seguente linea
-------------------------------------------------------------

FOR /L %%A IN (1,1,1000) DO java -jar Qrcode.jar %%A
-------------------------------------------------------------

mentre in Linux
-------------------------------------------------------------

#!/bin/bash
for i in {1..1000}
do
   java -jar Qrcode.jar $i
done
--------------------------------------------------------------


mercoledì 6 marzo 2013

Prima applicazione in GDX

So bene che e' un giochino di una stupidita' allarmante ma considerando il fatto che e' stato fatto partendo da zero in meno di 3 ore e che puo' essere visualizzato su Android, Ios, Java (ovvero un indefinito universo di computer desktop e portatili) ed HTML5 la cosa diventa qualcosa di piu' di un giochino

Versione Desktop (Java)



Versione Android
la libreria riscala le dimensioni previste per la finestra alle reali dimensioni dello schermo del telefono, per questo motivo l'immagine risulta distorta (in origine la visualizzazione e' in landscape)
----------------------------------------------------

package com.me.mygdxgame;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector3;

public class MyGdxGame implements ApplicationListener {
private OrthographicCamera camera;
private SpriteBatch batch;
private Rectangle droid_s;
private Texture droidImage;
private Texture palloneImage;
private Rectangle pallone_s;
private int speed_x;
private int speed_y;
private Sound ballSound;
private int Screen_width;
private int Screen_height;
private int rimbalzi;
private SpriteBatch spriteBatch;
private BitmapFont font;

@Override
public void create() {
//carica il file degli sprite che sono nella directory assets
//gli sprite devono avere come dimensioni potenze di 2 (in questo caso sono 32x32 pixel)
        droidImage = new Texture(Gdx.files.internal("data/droid.png"));
        palloneImage = new Texture(Gdx.files.internal("data/pallone.png"));
        
        //carica il font contenuto sempre dentro assets
        font = new BitmapFont(Gdx.files.internal("data/arial.fnt"), Gdx.files.internal("data/arial.png"), false);
        spriteBatch = new SpriteBatch(); //per la scritta
        batch = new SpriteBatch(); // per gli sprite 
        
        //carica il suono
        ballSound = Gdx.audio.newSound(Gdx.files.internal("data/palla.wav"));

        //inizializza le variabili
        Screen_width = 800;
        Screen_height = 480;
        rimbalzi = 0;
speed_x = 4 ; //velocita' della palla in pixel
speed_y = -4;

        camera = new OrthographicCamera();
        camera.setToOrtho(false, Screen_width, Screen_height);
        
        //rettangolo del robottino
droid_s = new Rectangle();
droid_s.x = Screen_width/2 - 32 / 2;
droid_s.y = 10;
droid_s.width = 32;
droid_s.height = 32;

//rettangolo della palla
pallone_s = new Rectangle();
pallone_s.x = Screen_width/2 - 32 / 2;
pallone_s.y = Screen_height/2 - 32 / 2;;
pallone_s.width = 32;
pallone_s.height = 32;
}

@Override
//cancella tutto in uscita dal programma
public void dispose() {
droidImage.dispose();
palloneImage.dispose();
batch.dispose();
spriteBatch.dispose();
font.dispose();
ballSound.dispose();
}

@Override
public void render() {
   Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        camera.update();
batch.setProjectionMatrix(camera.combined);
//controlla i rimbalzi
if (pallone_s.x < 0) speed_x = -speed_x;
if (pallone_s.x > 768) speed_x = -speed_x;
if (pallone_s.y == 64)   
{
if ((pallone_s.x >= droid_s.x-32) && (pallone_s.x < droid_s.x+32)) 
{
//se rimbalza sul robottino inverte marcia e fa il suono
speed_y = -speed_y;
ballSound.play();
// aggiorna il numero di rimbalzi
rimbalzi++;


}
}
if (pallone_s.y < 0) //se il pallone esce dal basso reinizia da capo
{
pallone_s.x = Screen_width/2 - 32 / 2;
pallone_s.y = Screen_height/2 - 32 / 2;
speed_x = 4 ;
speed_y = -4;
rimbalzi = 0;
}
if (pallone_s.y > 448) speed_y = -speed_y;
 
//muove la palla
pallone_s.x = pallone_s.x-speed_x;
pallone_s.y = pallone_s.y-speed_y;

//aggiorna lo schermo
batch.begin();
batch.draw(droidImage,droid_s.x,droid_s.y);
batch.draw(palloneImage,pallone_s.x,pallone_s.y);
batch.end();

spriteBatch.begin();
        font.draw(spriteBatch, Integer.toString(rimbalzi), 10, 320);
        spriteBatch.end();

        //gestisce l'input dell'utente e sposta il robottino
        //se non si l'interfaccia touch il robottino si sposta tenendo premendo il tasto
        //e muovendo il mouse
if(Gdx.input.isTouched()) {
        Vector3 touchPos = new Vector3();
        touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
        camera.unproject(touchPos);
        droid_s.x = touchPos.x;
     }
}

@Override
public void resize(int width, int height) {
}

@Override
public void pause() {
}

@Override
public void resume() {
}
}

----------------------------------------------------

Impostare i font per GDX con Hiero

La libreria grafica GDX necessita' che il formato grafico dei font sia di tipo particolare (con estensione fnt) e non il classico truetype od altri

per effettuare la conversione dai font gia' installati sulla macchina al formato GDX si puo' utilizzare il programma Hiero che si lancia

java -jar hiero.jar

Si apre la schermata sopra riportata dove si puo' scegliere il font e l'esportazione in fnt
Verranno creati due file che devono essere inseriti nella sottodirectory assets
Per utilizzare il font e creare una scritta su una finestra GDX il codice da inserire e'

----------------------------------

font = new BitmapFont(Gdx.files.internal("data/arial.fnt"), Gdx.files.internal("data/arial.png"), false);
spriteBatch = new SpriteBatch();
        

spriteBatch.begin();
font.draw(spriteBatch, "Luca", 10, 320);
spriteBatch.end();


martedì 5 marzo 2013

Primi passi con GDX

La libreria GDX e' indirizzata allo sviluppo di giochi che permette di scrivere il codice una sola volta ed avere la propria applicazione funzionante in Java, Android, HTML5 e IOS (ovviamente per poter effettuare la compilazione e' necessario aver installato e funzionante l'SDK di ciascun ambiente che per HTML5 risulta essere Google WebToolkit)

Per iniziare ad usa la libreria si deve scaricare la libreria ed il file gdx-setup-gui.jar e poi digitare

java -jar gdx-setup-gui.jar
tale programma crea lo scheletro dell'applicazioni nei vari linguaggi di programmazione

Una volta lanciato il programma si apre la schermata sottostante nel quale si possono impostare i vari settaggi (nel caso si puo' scaricare la libreria GDX o si puo' indicare dove e' posto il file .zip)




Terminato si effettua il Launch


La directory selezionata sara' popolata dai nuovi file. A questo punto si puo' aprire Eclipse e si seleziona Importa progetto esistente (attenzione da non confondere con Importa progetto Android esistente!!)


Si seleziona la directory in cui e' stato creato lo scheletro del programma e ci si trova di fronte ad una schermata di questo tipo

Ancora avanti ed al termine si avra' il Package Explorer di Eclipse popolato come segue 


Puo' accadere che vi sia un errore nel progetto HTML5 e puo' essere risolto come indicato nella seconda schermata del comando java -jar gdx-setup-gui.jar

Di fatto si lavorera' solo nel primo ramo del progetto (non in android.desktop,html) in quanto gli altri rami saranno solo dei wrapper


Soft Lockup su Debian Testing

Oramai e' cosi' tanto tempo che uso Linux che pensavo di averle e passate un po' tutte ma e' arrivata pronta la smentita

Qualche giorno fa avevo spento un vecchio portatile in modo normale senza nessun sintomo di errore (o meglio lo avevo spento un po' frettosolosamente perche' la spina a cui lo avevo attaccato a ricaricare aveva un po' di dispersione di corrente...lo shutdown era stato comunque corretto)

oggi al momento di riaccenderlo mi sono trovato davanti la seguente schermata


In pratica la CPU0 (l'unica!!) e' rimasta disattiva per 23 secondi ed il kernel ha mollato il colpo

Facendo partire il sistema con la visualizzazione dei comandi di boot l'ultimo comando ad essere tentato e'

rtc_cmos rtc can wake from s4

al momento non ho soluzioni

HP33s

Comprata su un mercatino a 15 euro questa e' la sorella minore (e piu' giovane) della HP48GX
Non ha capacita' grafiche ed e' solo blandamente programmabile..in compenso ha la notazione polacca inversa e la sua custodia originale

In sintesi una buona e solida calcolatrice scientifica




Scheda wireless long range Realtek 8187

UPDATE:
In Debian Squeeze il supporto a questa scheda di rete non e' compreso nel kernel ma si deve scaricare
apt-get install firmware-realtek
---------------------------------

Mi sono comprato per un po' di buon sano wardriving una scheda wireless con antenna ad alto guadagno che riporta sul retro una sigla di modello AWUS036H. La scheda si connette via USB

All'interno e' presente un chipset della Realtek 8187 che viene riconosciuto senza nessun problema dalla mia Debian Testing





Francamente al momento dell'acquisto ero un po' scettico ma come si puo' vedere dallo screenshot l'antenna esterna ad alto guadagno riesce a vedere in fase di prova tre access point in piu' della scheda integrata nel portatile; per quello che vedono entrambe le schede la qualita' del segnale della scheda esterna e' decisamente piu' alto


Bluetooth in LXDE su Debian

La gestione del Bluetooth in LXDE sotto Debian non e' banalissima come in Gnome dato che non e' presente nessuna applet nella traybar ne' si puo' aggiungere direttamente

Volendo evitare l'utilizzo dei comandi da shell si puo' premere la combinazione ALT+F2 digitando in seguito

bluetooth-applet

si vedra' cosi' comparire nella tray il simbolo di BT cosi' come in Gnome



lunedì 4 marzo 2013

Sensore di prossimita' Bluetooth



Uno degli utilizzi del bluetooth e' quello di utilizzare una apparecchiatura come una chiave per permettere l'accesso ad un servizio, nel momento in cui l'apparecchio ed il suo proprietario si allontana si puo'  effettuare la disconnessione o lo spengimento

Questa modalita' e' definita come "sensore di prossimita'" e vi sono due modalita'

1) Modalita' con accoppiamento
In generale e' possibile ottenere la qualita' del segnale (RSSI) di un apparecchio BT (e quindi la sola lontananza/vicinanza) solamente quando e' stato effettuato l'accoppiamento (o connessione)

In modo manuale si puo' seguire la presente procedura il seguente script in cui deve essere inserito il MAC address Bluetooth del dispositivo da monitorare

--------------------------------------------------------

#!/bin/bash
#set -o verbose sh -v
# Copied from Steven on http://gentoo-wiki.com/Talk:TIP_Bluetooth_Proximity_Monitor

# These are the sections you'll need to edit

 # You'll need to use the MAC address of your phone here
DEVICE="1C:66:AA:76:72:18" 

# How often to check the distance between phone and computer in seconds
CHECK_INTERVAL=2

# The RSSI threshold at which a phone is considered far or near
THRESHOLD=-13

# The command to run when your phone gets too far away
FAR_CMD='echo lontano'

# The command to run when your phone is close again
NEAR_CMD='echo lontano'

HCITOOL="/usr/bin/hcitool"
STARTX_PID=0
DEBUG="/tmp/btproximity.log"

connected=0

function msg {
    echo "$1" #>> "$DEBUG"
}

function check_connection {
    connected=0;
    found=0
    for s in `$HCITOOL con`; do
        if [[ "$s" == "$DEVICE" ]]; then
            found=1;
        fi
    done
    if [[ $found == 1 ]]; then
        connected=1;
    else
       msg 'Attempting connection...'
        if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
            msg 'Connected.'
            connected=1;
        else
                if [ -z "`l2ping -c 2 $DEVICE 2>&1`" ]; then
                        if [ -z "`$HCITOOL cc $DEVICE 2>&1`" ]; then
                            msg 'Connected.'
                            connected=1;
                        else
                        msg "ERROR: Could not connect to device $DEVICE."
                        connected=0;
                        fi
                fi
        fi
    fi
}

check_connection

while [[ $connected -eq 0 ]]; do
    check_connection
    sleep 3
done

name=`$HCITOOL name $DEVICE`
msg "Monitoring proximity of \"$name\" [$DEVICE]";

state="near"
while /bin/true; do

    check_connection

    if [[ $connected -eq 1 ]]; then
        rssi=$($HCITOOL rssi $DEVICE | sed -e 's/RSSI return value: //g')

        if [[ $rssi -le $THRESHOLD ]]; then
            if [[ "$state" == "near" ]]; then
                msg "*** Device \"$name\" [$DEVICE] has left proximity"
                state="far"
                $FAR_CMD > /dev/null 2>&1
            fi
        else
            if [[ "$state" == "far" && $rssi -ge $[$THRESHOLD+2] ]]; then
                msg "*** Device \"$name\" [$DEVICE] is within proximity"
                state="near"
                $NEAR_CMD > /dev/null 2>&1
                STARTX_PID=$(pgrep startx)
            fi
        fi
        msg "state = $state, RSSI = $rssi"
    fi

    sleep $CHECK_INTERVAL
done

--------------------------------------------------------

l'output e' di questo tipo
--------------------------------------------------------

Read RSSI failed: Input/output error
state = near, RSSI =
Attempting connection...
Connected.
state = near, RSSI = 0
state = near, RSSI = 0
Attempting connection...
Connected.
state = near, RSSI = 0
state = near, RSSI = -8
Attempting connection...
Connected.
state = near, RSSI = -11
*** Device "" [1C:66:AA:76:72:18] has left proximity
state = far, RSSI = -21
Attempting connection...
Connected.
state = far, RSSI = -23
state = far, RSSI = -24
Attempting connection...
state = far, RSSI = -20
state = far, RSSI = -22

-------------------------------------------------------

2) Modalita' senza accoppiamento
Negli esempi di PyBluez e' presente un esempio in examples/advanced denominato inquiry-with-rssi.py in cui e' possibile ottenere il valore di RSSI senza effettuare l'accoppiamento (ovviamente il dispositivo BT deve essere visibile)

L'output e' di questo tipo
--------------------------------------------------------

current inquiry mode is 1
[1C:66:AA:76:72:18] RSSI: [-46]
[00:1B:EE:58:93:22] RSSI: [-44]
current inquiry mode is 1
[00:1B:EE:58:93:22] RSSI: [-47]
[1C:66:AA:76:72:18] RSSI: [-46]
[30:17:C8:C7:9A:A4] RSSI: [-82]
current inquiry mode is 1
[00:1B:EE:58:93:22] RSSI: [-76]
[1C:66:AA:76:72:18] RSSI: [-79]
current inquiry mode is 1
[1C:66:AA:76:72:18] RSSI: [-72]
[30:17:C8:C7:9A:A4] RSSI: [-81]
[00:1B:EE:58:93:22] RSSI: [-79]
current inquiry mode is 1
[30:17:C8:C7:9A:A4] RSSI: [-83]
[1C:66:AA:76:72:18] RSSI: [-73]
[00:1B:EE:58:93:22] RSSI: [-79]
current inquiry mode is 1
[30:17:C8:C7:9A:A4] RSSI: [-81]
[00:1B:EE:58:93:22] RSSI: [-78]
current inquiry mode is 1
[30:17:C8:C7:9A:A4] RSSI: [-79]
[1C:66:AA:76:72:18] RSSI: [-73]
-------------------------------------------------


Il problema generale e' che il valore di RSSI non e' solo funzione della distanza ma anche della presenza di interferenze come i muri e della potenza delle antenne di ogni singolo dispositivo. Inoltre il valore, tenendo fermo il dispositivo, e'ì piuttosto oscillante per cui deve essere preso un valore medio. Per terminare la scansione dei dispositivi BT e' piuttosto lenta


Screenshot in LXDE

Per ottenere uno screenshot in LXDE si deve prima installare

apt-get install scrot

dopo di cio' si deve editare il file ~/.config/openbox/lxde-rc.xml  inserendo le seguenti linee
--------------------------
<keybind key="Print"> 
<action name="Execute"> 
<command>scrot</command>
 </action> 
</keybind>--------------------------

i file saranno salvati in formato .png con nome l'ora e la data nella propria directory home

Conferma uscita in Android

Per chiedere conferma dell'uscita da una applicazione si puo' usare il codice seguente che gestisce l'evento onBackPressed

--------------------------------

@Override
public void onBackPressed() {
   new AlertDialog.Builder(this)
          .setMessage("Vuoi uscire?")
          .setCancelable(false)
          .setPositiveButton("Si", new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int id) {
                   finish();
              }
          })
          .setNegativeButton("No", null)
          .show();
}

--------------------------------

giovedì 28 febbraio 2013

Semplice cronometro in Android

Una leggera modifica al post precedente per utilizzare il timer come cronometro



Alla partenza dell'Activity viene registrata l'ora in millisecondi, poi all'interno del thread viene effettuata la differenza in millisecondi tra la data attuale e quella della partenza ed il tutto viene formattato come ore:minuti:secondi
---------------------------------------------------------------------------

package com.example.timer;

import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.widget.TextView;

@SuppressLint("SimpleDateFormat")
public class MainActivity extends Activity {

private TextView txttimer;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txttimer = (TextView)findViewById(R.id.timer);

final long partenza = System.currentTimeMillis();


Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
   public void run() {
    runOnUiThread(new Runnable() {
@Override
public void run() {
long attuale = System.currentTimeMillis();
String tempo = new SimpleDateFormat("HH:mm:ss").format(attuale-partenza);
txttimer.setText(tempo);
}

});
}
       
        }, 0, 1000);
    }
    
}

Timer in Android

Creare una semplice applicazione di orologio puo' sembrare una cosa banale ma non in Android.
Per gestire il timer infatti e' necessario a ricorrere ad un thread separato che aggiorni l'interfaccia



Nell'esempio viene aggiornata una textview con l'ora corrente ogni 1000 millisecondi (1 sec)
-----------------------------------------------------------

package com.example.timer;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.widget.TextView;

@SuppressLint("SimpleDateFormat")
public class MainActivity extends Activity {

private TextView txttimer;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txttimer = (TextView)findViewById(R.id.timer);

Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
   public void run() {
    runOnUiThread(new Runnable() {
@Override
public void run() {
String tempo = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
txttimer.setText(tempo);
}

});
}
       
        }, 0, 1000);
    }
    
}

mercoledì 27 febbraio 2013

Ricevitore infrarosso PVCA-IR5U

Un altro regalo che mi e' arrivato e' il ricevitore ad infrarosso PVCA-IR5U che in origine era legato all'acquisto di un desktop Sony Vaio con il suo telecomando RM-GP5U

Le informazioni su Internet sono piuttosto scarse ma connesso a Windows XP la periferica si installa senza necessita' di driver


---------------------------------------------------
Feb 27 14:28:41 debian kernel: [  166.296207] usb 5-1: new low-speed USB device number 2 using uhci_hcd
Feb 27 14:28:41 debian kernel: [  166.488299] usb 5-1: New USB device found, idVendor=054c, idProduct=00d4
Feb 27 14:28:41 debian kernel: [  166.488314] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
Feb 27 14:28:41 debian kernel: [  166.488325] usb 5-1: Product: Sony IR Receiver
Feb 27 14:28:41 debian kernel: [  166.488333] usb 5-1: Manufacturer: Sony
Feb 27 14:28:41 debian mtp-probe: checking bus 5, device 2: "/sys/devices/pci0000:00/0000:00:1d.3/usb5/5-1"
Feb 27 14:28:41 debian mtp-probe: bus: 5, device: 2 was not an MTP device
Feb 27 14:28:42 debian kernel: [  166.713726] input: Sony Sony IR Receiver as /devices/pci0000:00/0000:00:1d.3/usb5/5-1/5-1:1.0/input/input12
Feb 27 14:28:42 debian kernel: [  166.715806] generic-usb 0003:054C:00D4.0001: input,hiddev0,hidraw0: USB HID v1.10 Keyboard [Sony Sony IR Receiver] on usb-0000:00:1d.3-1/input0
Feb 27 14:28:42 debian kernel: [  166.718373] usbcore: registered new interface driver usbhid
Feb 27 14:28:42 debian kernel: [  166.718387] usbhid: USB HID core driver
---------------------------------------------------

stranamente nel log sembra che la periferica sia vista come una Human Interface e nel dettaglio come una tastiera. Non e' comunque compatibile con Windows Media Center

quesea la descrizione in cat /proc/bus/input/devices
---------------------------------------------------
I: Bus=0003 Vendor=054c Product=00d4 Version=0110
N: Name="Sony Sony IR Receiver"
P: Phys=usb-0000:00:1d.0-1/input0
S: Sysfs=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/input/input12
U: Uniq=
H: Handlers=sysrq kbd event12 
B: PROP=0
B: EV=120013
B: KEY=10000 7 ff9f207a c140d7ff febeffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=ffff
---------------------------------------------------

Non puo' essere quindi usato per Lirc

Hamlet FE1500

Mi e' stata regalata la scheda PCMCIA Hamlet FE1500 e sono ritornato indietro nel tempo



Questa e' la stata la mia prima scheda di rete su un portatile e la ho barattata a suo tempo con una IBM EtherJet....credo che fosse il periodo di Red Hat 6

Il chipset montato e' un Realtek ed il modulo da caricare e'
modprobe 8139too

Purtroppo e' mancante il cavetto (mentre e' presente la scatolina in plastica trasparente originale) dove era alloggia il connettore RJ45 quindi il modello e' sostanzialmente inutile nelle condizioni attuali (vedi foto tratta da Google Images)





Mappa frane da news on line

Correva l'anno 2008 ed il mio direttore di Dipartimento mi aveva chiesto di lavorare sui Big Data per estrarre dati di geolocalizzazione...