lunedì 1 aprile 2013

Zbar QRcode Scanner

Sulla base dell'esperienza di questo post sull'utilizzo della libreria zxing ha voluto provare la libreria ZBar piu' che altro per la necessita' di avere una maggiore velocita' di acquisizione

La principale differenza tra i due metodi e' che in Zxing si usa l'Intent ovvero si lancia una applicazione esterna e si attende il risultato mentre con ZBar si usa una libreria nativa inclusa nella propria applicazione


Il risultato e' una velocita' di elaborazione decisamente piu' veloce (ho dovuto creare una procedura apposita per impedire le acquisizione multiple su un stesso QrCode perche' il programma e' piu' veloce nel riconoscimento dello spostamento della mano)

Molto utile e' l'esempio compreso nella libreria che rende il tutto operativo in pochi minuti

Segue il codice di un programma che sto sviluppando per il riconoscimento dei pettorali delle corse podistiche
-----------------------------------------------------------------------

/*
 * Basic no frills app which integrates the ZBar barcode scanner with
 * the camera.
 * 
 * Created by lisah0 on 2012-02-24
 */
package net.sourceforge.zbar.android.CameraTest;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

import net.sourceforge.zbar.android.CameraTest.CameraPreview;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;

import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Button;
import android.widget.Toast;

import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.Size;

import android.widget.TextView;

/* Import ZBar Class files */
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;
import net.sourceforge.zbar.Config;

public class CameraTestActivity extends Activity
{
    private Camera mCamera;
    private CameraPreview mPreview;
    private Handler autoFocusHandler;

    TextView scanText;
    Button scanButton;

    ImageScanner scanner;

    private boolean previewing = true;
private long partenza;
private String old_pettorale;
private String pettorale;
private TextView pett;
private EditText man;
private int contatore;


    static {
        System.loadLibrary("iconv");
    } 

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        contatore = 0;
        pettorale = "";
        
        autoFocusHandler = new Handler();
        mCamera = getCameraInstance();

        /* Instance barcode scanner */
        scanner = new ImageScanner();
        scanner.setConfig(0, Config.X_DENSITY, 3);
        scanner.setConfig(0, Config.Y_DENSITY, 3);

        mPreview = new CameraPreview(this, mCamera, previewCb, autoFocusCB);
        FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
        preview.addView(mPreview);
        scanText = (TextView)findViewById(R.id.scanText);
        pett = (TextView)findViewById(R.id.pettorale);
        man = (EditText)findViewById(R.id.editText1);

        //gestisce l'introduzione manuale del pettorale
        man.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
                    //Log.d("test","Premuto il tasto Done");
                pettorale = man.getText().toString();
                    long attuale = System.currentTimeMillis();
                    long x = (attuale-partenza) / 1000;
          long seconds = x % 60;
          x /= 60;
          long minutes = x % 60;
          x /= 60;
          long hours = x % 24;
          x /= 24;
          long days = x;
          contatore = contatore + 1;
          String ora_passaggio = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
          String race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
          String str3 = Integer.toString(contatore)+";"+pettorale + ";" + race_time +"\n";
          pett.setText(str3);
         
     
          
          playAlarm();
          scrivi(ora_passaggio+";"+str3);
          send_udp(str3);
                    man.setText("");
                    old_pettorale=pettorale;
                    
                    }

// TODO Auto-generated method stub
return false;
}
});
        
    }

    public void onPause() {
        super.onPause();
        releaseCamera();
    }

    /** A safe way to get an instance of the Camera object. */
    public static Camera getCameraInstance(){
        Camera c = null;
        try {
            c = Camera.open();
        } catch (Exception e){
        }
        return c;
    }

    private void releaseCamera() {
        if (mCamera != null) {
            previewing = false;
            mCamera.setPreviewCallback(null);
            mCamera.release();
            mCamera = null;
        }
    }

    private Runnable doAutoFocus = new Runnable() {
            public void run() {
                if (previewing)
                    mCamera.autoFocus(autoFocusCB);
            }
        };

    PreviewCallback previewCb = new PreviewCallback() {
            private long attuale;
private String race_time;
private String ora_passaggio;
private String str3;
private String chk;

public void onPreviewFrame(byte[] data, Camera camera) {
                Camera.Parameters parameters = camera.getParameters();
                Size size = parameters.getPreviewSize();

                Image barcode = new Image(size.width, size.height, "Y800");
                barcode.setData(data);

                int result = scanner.scanImage(barcode);
                
                if ((result != 0) && (!start)) 
            {
            pett.setText("Partenza non effettuata");
            }
                
                if ((result != 0) && (start)) {
                    SymbolSet syms = scanner.getResults();
                    for (Symbol sym : syms) {
                        pettorale = sym.getData();        
                    }
                        attuale = System.currentTimeMillis();
                        if (!pettorale.equals(old_pettorale)) //evita le immissioni multiple di un pettorale
                       {
              long x = (attuale-partenza) / 1000;
          long seconds = x % 60;
          x /= 60;
          long minutes = x % 60;
          x /= 60;
          long hours = x % 24;
          x /= 24;
          long days = x;
          contatore = contatore + 1;
          chk ="Arrivo";
          race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
          ora_passaggio = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
          str3 =  Integer.toString(contatore)+";"+pettorale + ";" + race_time +"\n";
          pett.setText(str3);
          
          playAlarm();
          old_pettorale = pettorale;
          //pettorale = "";
          scrivi(ora_passaggio+";"+str3);
          send_udp(str3);
                   }
                        else
                        {// se il pettorale e' gia' stato battuto fai un suono differente
               //scanText.setText("Gia' acquisito");
                                               
                        }
                        
                        
        } //if result
            } // preview Frame
        }; //termina il callback
        
        
 private void playAlarm() {
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
 }     
        

 private void scrivi(String testo)
{
File sdcard = Environment.getExternalStorageDirectory();
    if (sdcard.canWrite()) 
     {
     File localFile2 = new File(sdcard, "passaggi.txt");
         FileWriter localFileWriter1 = null;
 try {
localFileWriter1 = new FileWriter(localFile2, true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 BufferedWriter localBufferedWriter = new BufferedWriter(localFileWriter1);
 try {
localBufferedWriter.write(testo);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 try {
localBufferedWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
 }// chiude la scrittura su file
 }


 private void send_udp(String testo)
 {
DatagramSocket socket = null;
//testo = "luca";
try {
socket = new DatagramSocket();
} catch (SocketException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
    InetAddress serverIP = null;
try {
serverIP = InetAddress.getByName("192.168.0.100");
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
     byte[] outData = testo.getBytes();
     DatagramPacket out = new DatagramPacket(outData,outData.length, serverIP,55000);
     try {
socket.send(out);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
     socket.close();
 }

    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();
}

    // Mimic continuous auto-focusing
    AutoFocusCallback autoFocusCB = new AutoFocusCallback() {
            public void onAutoFocus(boolean success, Camera camera) {
                autoFocusHandler.postDelayed(doAutoFocus, 1000);
            }
        };
private boolean start;
        
    @Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(1,1,0,"Partenza");
menu.add(1,2,1,"Annulla passaggio");
return true;
}
    
    public boolean onOptionsItemSelected(MenuItem item)
    {
    
switch(item.getItemId())
{
case 1:
if (!start) 
{
  start = true;
      partenza = System.currentTimeMillis();
      long x2 = (partenza) / 1000;
  long seconds2 = x2 % 60;
  x2 /= 60;
  long minutes2 = x2 % 60;
  x2 /= 60;
  long hours2 = x2 % 24;
  x2 /= 24;
  //long days = x;
      send_udp("Partenza   "+String.format("%02d:%02d:%02d", hours2,minutes2,seconds2));
          pett.setText("Partenza effettuata");
          scrivi("Partenza   "+String.format("%02d:%02d:%02d", hours2,minutes2,seconds2)+"\n");
          playAlarm();
}

else
{
Toast.makeText(this, "Partenza gia' effettuata",Toast.LENGTH_SHORT).show();
return false;
}


   Timer ti = new Timer();
   ti.scheduleAtFixedRate(new TimerTask() {
           public void run() {
            runOnUiThread(new Runnable() {
          private long attuale;
private String race_time;

@Override
          public void run() {
           //String tempo = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy").format(new Date(System.currentTimeMillis()));
           if (partenza > 0)
           {
            attuale = System.currentTimeMillis();
    long x = (attuale-partenza) / 1000;
    long seconds = x % 60;
    x /= 60;
    long minutes = x % 60;
    x /= 60;
    long hours = x % 24;
    x /= 24;
    //long days = x;
    race_time = String.format("%02d:%02d:%02d", hours,minutes,seconds);
    scanText.setText(race_time);
           }
    }});}}, 0, 1000);
 //fa partire il cronometro della corsa
 partenza = System.currentTimeMillis();
   return true;
   
case 2:
send_udp("Annullato pettorale " + pettorale);
      pett.setText("Annullato pettorale " + pettorale);
      scrivi("Annullato pettorale " + pettorale+"\n");
      contatore = contatore - 1;
return true;

}

return false;
}
   
}

Allineare i widgets in Qt

In condizioni normali se si ridimensiona una finestra Qt i widgets in essa contenuti non si dimensionano a loro volta con effetti grafici piuttosto sgradevoli

Per evitare questo effetto si puo' cliccare destro sul form e selezionare Layout/(...) per ottenere un ridimensionamento automatico


venerdì 29 marzo 2013

Sqlite Manager su Windows

Per gestire i file generati da Sqlite su Windows puo' essere utile usare il programma che si scarica gratuitamente da questo link


QTimer in Qt

Questo componente non visuale permette di gestire eventi a tempi predefiniti

La sintassi e' piuttosto semplice: si crea l'oggetto e si associa una funzione che viene richiamata ogni volta che l'oggetto genera un evento


Nell'esempio seguente gli eventi vengono generati ogni secondo
------------------------------------------

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTimer>

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();
    void TimerEvent();

private:
    Ui::MainWindow *ui;
    QTimer timer;
    unsigned contatore;
};

#endif // MAINWINDOW_H
------------------------------------------

------------------------------------------
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTimer>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    contatore = 0;
    connect(&timer, SIGNAL(timeout()), this, SLOT(TimerEvent()));
    this->timer.start(1000);
}


void MainWindow::TimerEvent()
{
    contatore++;
    QString str;
    str.append(QString("%1").arg(contatore));
    ui->pushButton->setText(str);
    qDebug()<< contatore;
}
------------------------------------------

Importare Progetti Qt in QtCreator da Windows a Linux

Per poter spostare un progetto in Qt/QtCreator sviluppato su Windows in una Linux Box non e' sufficiente copiare la directory dei sorgenti in quanto una volta aperto il file .pro in QtCreator si avranno errori in particolare sul file Make

e' quindi necessario, prima di aprire il file .pro
1) Cancellare la directory di debug/release
2) Cancellare Makefile, Makefile.debug, Makefile.Release
3) cancella object_script*.*
4) cancellare il file *.pro.user (attenzione non file .pro)

a questo punto si puo' aprire il file .pro e compilare.
I file mancanti verranno ricostruiti sulla base delle impostazione Linux

(informazione ripresa da qui)

Spedire pacchetti UDP con Netcat

Per fare delle prove di server UDP puo' essere utile il programma netcat (che non e' installato di default in Debian ma deve essere aggiunto con apt-get install netcat)

una volta avviato il server UDP si puo' inviare pacchetti UDP con la seguente sintassu
dove localhost e' l'indirizzo del server (in questo caso in locale) e 21567 e' la porta di ascolto del server

echo -n "hello" | nc -u -w1 localhost 21567

giovedì 28 marzo 2013

Deploy Application in Qt su Windows

Una volta creata una applicazione Qt funzionante in Window puo' venire il momento di distribuirla

Per prima cosa si deve creare il file eseguibile dentro a QtCreator  selezionando l'opzione Release nei metodi di compilazione. Nella cartella del progetto viene quindi creata una sottocartella Release con l'eseguibile

Per visualizzare le dipendenza si puo' usare il programma Depend (scaricabile a questo link)


Si copiano quindi nella directory release dell'eseguibile le DLL necessarie copiandole da C:\QtSDK\Desktop\Qt\4.7.3\mingw\bin
che nel caso in esame sono
QtCore4.dll
QtGui4.dll
QtSql4.dll

a queste vanno aggiunte
libgcc_s_dw2-1.dll
mingwm10.dll

si zippa il contenuto della directory e tramite il software NSIS si crea un installer scegliendo l'opzione "Installer based in Zip File"


Virtualbox KVM error

Cercando di usare Virtualbox mi e' uscito questo messaggio di errore   VT-x is being used by another hypervisor (VERR_VMX_IN_VMX_ROOT_MO...