lunedì 12 maggio 2014

Da SMB Share name a IP

Per trovare l'indirizzo IP di una connessione SMB  sotto Windows e'  sufficiente richiamare il comando NBTSTAT seguito dal nome del computer

Per esempio

nbtstat -a hw2229



giovedì 8 maggio 2014

Illegal Operation su OpenNi e IBM X40

Ho compilato da sorgenti le librerie OpenNI e PyOpenNI sul mio IBM X40 per poter usare il programmino per gestire il Kinect gia' visto in questi post



Con sopresa pero' lo script genera un errore di "Illegal Operation"
Dopo un po' di ricerche ho scoperto che OpenNi e' ottimizzato per utilizzare le estensioni delle istruzioni del processore SSE3 mentre il Centrino montato sull'X40 ammette solo le estensioni SSE2

In conclusione non si puo' usare Kinect accoppiato all'IBM X40

mercoledì 7 maggio 2014

Kinect per Belle Arti

Continuando gli esperimenti con Kinect ho provato ad acquisire la mappa di profondita' di un basso rilievo. Nello specifico si tratta dei fregi che si trovano sulla base dei leoni delle leonesse nel Piazzale delle Cascine a Firenze
Come si puo' osservare i risultati sono buoni (anche se un po' rumorosi) e le scansioni permettono si osservare dettagli anche molto fini

Fregio 1
Immagine di profondita'


Immagine RGB (da fotocamera)



Fregio 2 
Immagine di profondita'
Immagine RGB da Kinect



Bluetooth ed Android

Questa piccola applicazione interfaccia i sensori di Android  con un PC mediante Bluetooth.
In pratica viene avviata una connessione BT tra PC ed telefono e vengono passati i valori di azimuth, pitch e roll del telefono; dopo aver inviato la prima terna di valore il socket viene interrotto

Importanti: i due dispositivi devono essere gia' stati accoppiati in precedenza ed il BT deve essere gia' abilitato sul telefono


Lato Android
-------------------------------------------------
package com.luca.innocenti.btsensors;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import android.support.v7.app.ActionBarActivity;
import android.support.v4.app.Fragment;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.SensorEvent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.TextView;

@SuppressLint("NewApi")
public class MainActivity extends ActionBarActivity {

private static final String TAG = "BT";

//Bluetooth
public BluetoothAdapter mBluetoothAdapter;
public  BluetoothDevice mmDevice;
public BluetoothSocket mmSocket;
public OutputStream mmOutputStream;

//Sensori
public SensorManager mSensorManager;
    public Sensor mSensor;
    public double azimuth;
    public double pitch;
    public double roll;
    



@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);


setContentView(R.layout.activity_main);

if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment()).commit();
}

//Ricerca BT
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
   if(mBluetoothAdapter == null) {
     Log.d(TAG,"No bluetooth adapter available");
   }

   if(!mBluetoothAdapter.isEnabled()) {
     startActivityForResult( new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 0);
   }

   Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
   if(pairedDevices.size() > 0) {
     for(BluetoothDevice device : pairedDevices) {
       if(device.getName().equals("debian-x40-0")) { //qui si deve mettere il nome BT del PC
        Log.d(TAG,device.getName()+" "+device.getAddress() );
       
         mmDevice = device;
         break;
       }
     }
   }
//apre connessione
   UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard //SerialPortService ID
   try {
mmSocket = mmDevice.createInsecureRfcommSocketToServiceRecord(uuid);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}    
   try {
mmSocket.connect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
   try {
mmOutputStream = mmSocket.getOutputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
   
   //sensori
    mSensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
    mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);  
   
    
}


private void send_string(final String dati)
{
for (int t=0;t<dati.length();t++)
{
try {
mmOutputStream.write(dati.charAt(t));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

private final SensorEventListener mListener = new SensorEventListener() {
//manda una terna di valori pitch,roll ed azimuth e poi termina l'applicazione
public void onSensorChanged(SensorEvent event) {
   azimuth = event.values[0];
           pitch = event.values[1];
           roll = event.values[2];
              
           send_string(Double.toString(azimuth));
           send_string("A");
           send_string(Double.toString(pitch));
           send_string("A");
           send_string(Double.toString(roll));
           send_string("A");
           
           try {
mmSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
           //termina l'applicazione dopo la prima lettura
           finish();
           moveTaskToBack(true);
           android.os.Process.killProcess(android.os.Process.myPid());

           
           }

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub

}
};
 
    @Override
   protected void onResume()
   {
       super.onResume();
       mSensorManager.registerListener(mListener, mSensor,SensorManager.SENSOR_DELAY_GAME);
   }

   @Override
   protected void onStop()
   {
       mSensorManager.unregisterListener(mListener);
       super.onStop();
   }

   @Override
   protected void onDestroy()
   {
       mSensorManager.unregisterListener(mListener);
       super.onDestroy();
   }

   @Override
public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}

/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {


public PlaceholderFragment() {
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
return rootView;
}
}


}
----------------------------------------------------

Lato PC (Python)
-----------------------------------------------------
from bluetooth import *

server_sock=BluetoothSocket( RFCOMM )
server_sock.bind(("",PORT_ANY))
server_sock.listen(1)

port = server_sock.getsockname()[1]

uuid = "00001101-0000-1000-8000-00805F9B34FB"

advertise_service( server_sock, "SampleServer",
    service_id = uuid,
    service_classes = [ uuid, SERIAL_PORT_CLASS ],
    profiles = [ SERIAL_PORT_PROFILE ]
)


client_sock, client_info = server_sock.accept()
misura = ""

try:
    while True:
        data = client_sock.recv(1024)
        if len(data) == 0: break
        if data == 'A':
print misura
misura = ""
else:
misura = misura + data

except IOError:
    pass

client_sock.close()
server_sock.close()


Riduzione di dimensione di file mp3 con lame

Per una piccola applicazione devo mettere negli asset del progetto Android dei file mp3.


Trattandosi di un testo letto senza musica si puo' anche abbassare al massimo il rate del file.
Per questo si puo' usare lame con la stringa

lame --mp3input -b 8 input.mp3 output.mp3

Per esempio questo file (MPEG ADTS, layer III, v1,  32 kbps, 44.1 kHz, Monaural) della dimensione di 64470 byte e' stato convertito in questo file (8.mp3: MPEG ADTS, layer III,  v2.5,   8 kbps, 8 kHz, Monaural) della dimensione di 16272 byte con una compressione di circa 4 volte

Lame ha una serie di ottimizzazioni implicite per cui e' sostanzialmente inutile effettuare tentativi manuali

(Per ottenere le informazioni sui file mp3 si puo' usare il comando file)

martedì 6 maggio 2014

Adb unauthorized device

Con la versione Android 4.4 ci si puo' trovare di fronte al messaggio "device unauthorized" da adb

la soluzione e' molto semplice. Ci si e' dimenticati di andare sul telefono e si deve cliccare Ok sulla richiesta di autorizzazione

JPlayer

JPlayer e' un plugin di JQuery che permette di mostrare video ed eseguire file audio via browser in modo indipentente dal browser stesso e quindi con una migliore riuscita ed uniformita' tra i diversi client/browser (il tag <audio> per esempio non funziona in modo uguale sui differenti browser desktop e mobile)


Il codice sottostante mostra una implementazione completa del controllo
Si osserva che nelle prime righe sono caricate le librerie jquery e jplayer, in seguito viene definito il tipo di file ed il nome del file da riprodurre (in questo caso taxus.mp3)

In seguito si ha l'impostazione del vero e proprio player
Per la vestizione tutto e' gestito a livello di css per esempio
div.jp-audio width e' la dimesione totale del player
--------------------------------------------------------
<html>
<head>
  <link type="text/css" href="./skin/blue.monday/jplayer.blue.monday.css" rel="stylesheet" />
  <script type="text/javascript" src="./js/jquery-1.11.0.min.js"></script>
  <script type="text/javascript" src="./js/jquery.jplayer.min.js"></script>
  <script type="text/javascript">
    $(document).ready(function(){
      $("#jquery_jplayer_1").jPlayer({
        ready: function () {
          $(this).jPlayer("setMedia", {
            title: "Taxus",
            mp3: "./audio/taxus.mp3",
            });
        },
        swfPath: "/js",
        supplied: "mp3"
      });
    });
  </script>
</head>
<body>
  <div id="jquery_jplayer_1" class="jp-jplayer"></div>
  <div id="jp_container_1" class="jp-audio">
    <div class="jp-type-single">
      <div class="jp-gui jp-interface">
        <ul class="jp-controls">
          <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
          <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
          <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
          <li><a href="javascript:;" class="jp-mute" tabindex="1" title="mute">mute</a></li>
          <li><a href="javascript:;" class="jp-unmute" tabindex="1" title="unmute">unmute</a></li>
          <li><a href="javascript:;" class="jp-volume-max" tabindex="1" title="max volume">max volume</a></li>
        </ul>
        <div class="jp-progress">
          <div class="jp-seek-bar">
            <div class="jp-play-bar"></div>
          </div>
        </div>
        <div class="jp-volume-bar">
          <div class="jp-volume-bar-value"></div>
        </div>
        <div class="jp-time-holder">
          <div class="jp-current-time"></div>
          <div class="jp-duration"></div>
          <ul class="jp-toggles">
            <li><a href="javascript:;" class="jp-repeat" tabindex="1" title="repeat">repeat</a></li>
            <li><a href="javascript:;" class="jp-repeat-off" tabindex="1" title="repeat off">repeat off</a></li>
          </ul>
        </div>
      </div>
     <div class="jp-no-solution">
        <span>Update Required</span>
        To play the media you will need to either update your browser to a recent version or update your <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash plugin</a>.
      </div>
    </div>
  </div>
</body>
</html>
--------------------------------------------------------

E' possibile ottenere anche un player ridotto semplicemente cancellando i riferimenti ai pulsanti delle funzioni.
Un esempio minimale (solo Play e Stop)


ed il relativo codice
--------------------------------------------------------
<html>
<head>
  <link type="text/css" href="./skin/blue.monday/jplayer.blue.monday.css" rel="stylesheet" />
  <script type="text/javascript" src="./js/jquery-1.11.0.min.js"></script>
  <script type="text/javascript" src="./js/jquery.jplayer.min.js"></script>
  <script type="text/javascript">
    $(document).ready(function(){
      $("#jquery_jplayer_1").jPlayer({
        ready: function () {
          $(this).jPlayer("setMedia", {
            title: "Taxus",
            mp3: "./audio/taxus.mp3",
            });
        },
        swfPath: "/js",
        supplied: "mp3"
      });
    });
  </script>
</head>
<body>
  <div id="jquery_jplayer_1" class="jp-jplayer"></div>
  <div id="jp_container_1" class="jp-audio">
    <div class="jp-type-single">
      <div class="jp-gui jp-interface">
        <ul class="jp-controls">
          <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
          <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
          <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
        </ul>
      </div>
     <div class="jp-no-solution">
        <span>Update Required</span>
        To play the media you will need to either update your browser to a recent version or update your <a href="http://get.adobe.com/flashplayer/" target="_blank">Flash plugin</a>.
      </div>
    </div>
  </div>
</body>
</html>












































Rotazione 3D in Python

Una funzione per calcolare la rotazione 3d di un punto attorno al centro degli assi mediante Python usando gli angoli di Eulero
da Wikipedia


--------------------------------------------------------------
import math
import numpy

# yaw = alfa
# pitch = beta
# roll = gamma

def ruota3D(alfa,beta,gamma,x,y,z):
    alfa = math.radians(alfa)
    beta = math.radians(beta)
    gamma = math.radians(gamma)
    
    ca = math.cos(alfa)
    sa = math.sin(alfa)
    cb = math.cos(beta)
    sb = math.sin(beta)
    cg = math.cos(gamma)
    sg = math.sin(gamma)
    ma = numpy.empty((3,3))
    ma [0][0] = ca*cb
    ma [0][1] = ((ca*sb*sg)-(sa*cg))
    ma [0][2] = ((ca*sb*cg)+(sa*sg))
    ma [1][0] = sa*cb
    ma [1][1] = ((sa*sb*sg)+ (ca*cg))
    ma [1][2] = ((sa*sb*cg)-(ca*sg))
    ma [2][0] = -sb
    ma [2][1] =  cb*sg
    ma [2][2] = cb*cg
    nx1 = ma[0][0] * x
    nx2 = ma[0][1] * y
    nx3 = ma[0][2] * z
    nx = nx1+nx2+nx3
    
    ny1 = ma[1][0] * x
    ny2 = ma[1][1] * y
    ny3 = ma[1][2] * z
    ny = ny1+ny2+ny3
    
    nz1 = ma[2][0] * x
    nz2 = ma[2][1] * y
    nz3 = ma[2][2] * z
    nz = nz1+nz2+nz3
    return [nx,ny,nz]

xx = ruota3D(0,0,90,1,1,1)
print xx

lunedì 5 maggio 2014

JDK 8 e WIndows XP

Installando JDK8 su Windows XP, l'installer ha generato questo errore ovvero non e' stata trovata la chiave di registor RegDeleteKeyExA in ADVAPI32.DLL


Dopo un po' di ricerche ho trovato sul sito Oracle che JDK8 non supporta Windows XP e che quindi si deve rimanere sulla versione precedente

Editare file su server remoti

Accade spesso di dover editare file testo su server remoti. Al posto di spostare il file in locale, editarlo e poi ripassarlo sul server via SSH puo' essere comodo montare il filesystem remoto mediante SSHFS

su Debian di deve installare
apt-get install sshfs

si crea poi una directory
mkdir /mnt/remota

e si monta con
sshfs luca@150.217.xxx.xxx:/home/luca /mnt/remota

a questo punto in /mnt/remota troveremo i file remoti posti nella directory /home/luca e si editano direttamente i file remoti

per smontare la risorsa
fusermount -u /mnt/remota

di default questa operazione puo' essere effettuata solo da root. Per permettere ad un utente normale di usare sshfs si deve aggiungere al gruppo fuse (se si cerca di montare la risorsa remota via sshfs senza i permessi si ha il messaggio Transport Endpoint is not connected)

chgrp fuse /usr/bin/fusermount 
chmod u+s /usr/bin/fusermount 
adduser nomeutente fuse

mercoledì 30 aprile 2014

Errore Lint su esportazione di una applicazione Android

Al momento di esportare una applicazione da Eclipse mediante Android Tools, Lint ha deciso che per fare il suo lavoro dovevo effettuare la traduzione delle stringhe in tutte le lingue del mondo


Per ovviare al problema si puo' andare Window/Preference/Lint Error Checking e modificare l'errore Missing Translation da una Severity Fatal ad una Serverity Warning

Hotspot e Bluetooth su Android

Ed ecco che ho sperimentato un bel bug di Android. Usando contemporaneamente l'HotSpot WiFi e Bluetooth sul Motorola Moto G con Android KitKat 4.4.2 il sistema operativo interrompe la funzione HotSpot



Questo bug e' descritto in https://code.google.com/p/android/issues/detail?id=41631 e sembra che non sia presente un Android 4.3



Fluttuazione del segnale IBeacon


Iniziando a lavorare con le libreria IBeacon di Radius si nota chiaramente che i valori di distanza sono molto variabili ed ho fatto una piccolo test con una applicazione misurando (a geometria fissa quindi con la distanza tra IBeacon e telefono fissa) i valori getAccuracy


I risultati (48 misure per circa un minuto di test) sono riportati nel grafico soprastante. Il valore medio e' stato di 0.3 (i valori delle ordinate del grafico sono moltiplicate per 100) ma con una oscillazione massima di 1.01 e minima di 0.09. In definitiva la deviazione standard e' della stessa dimensione del valore medio

Cio' crea ovviamente problemi nella gestione della prossimita' al beacon

Il codice dell'applicazione puo' essere scaricato a questo indirizzo

lunedì 28 aprile 2014

April Beacon

Il dispositivo che mi sono trovato a testare e' un AprilBeacon 201 ai aprbrother.com basato sul modulo CC2540 BLE


L'alimentazione e' data da una pila CR2450 (da comprare a parte). Il modello e' completamente configurabile ed oltre a poter cambiare l'UUID (di default e' quello di test di Apple) e' possibile anche variare il Major e Minor Number la potenza di trasmissione

Usando la app AprilBeacon su Google Play si possono visualizzare i parametri di esercizio (per effettuare tale operazione si deve inserire il pin che e' 19566)

dalla applicazione si puo' vedere il livello della batteria, la potenza del segnale e le informazioni sul firmware



Al contrario dell'applicazione IOS (che si scarica da qui) non e' possibile modificare l'UUID. Il customer care della ditta dice che tale funzionalita' sara' disponibile tra circa un mese






LLama3 Anita

A seguito di questo post ho provato a vedere ho provato a vedere cosa accadeva ad utilizzare un modello specifico per la lingua italiana in...