martedì 31 gennaio 2012

HP-97

Tempo fa mi e' stato donato la calcolatrice programmabile nelle foto


Calcolatrice

Memoria esterna

Purtroppo chi mi ha dato l'oggetto mi ha detto che era funzionante ma non ha menzionato il fatto che funzionasse a 110 Volts..per cui quando ho cercato di dare corrente il calcolatore e' esploso (nel vero senso della parola....una volta aperto ho trovato un paio di componenti elettronici completamente distrutti) per cui adesso assolve alla funzione di soprammobile




lunedì 30 gennaio 2012

Sign an app

Per poter distribuire una applicazione Android e' necessario firmarla in modo digitale (vedere qui). Il certificato digitale non e' necessario che sia validato da una autorita' esterna.
Per poter firmare una applicazione da dentro Eclipse si puo' cliccare con il tasto destro sul progetto di cui si vuole rilasciare l'apk e scegliere Android Tool/Export Signed Application Package.
Si apre una finestra nel quale si sceglie il nome dell'applicazione e poi si puo' scegliere una firma digitale gia' creata oppure una gia' pronta

Prima schermata
Seconda Schermata

Definizione di una nuova chiave

Per quanta riguarda le versioni di debug queste sono firmate con una speciale chiave che puo' essere usata sull'emulatore o sul telefono di test ma non funziona su altri sistemi

DGPS Test

Mettendo insieme i vari pezzi di codice precedenti e' stata effettuata una prova usando sia  il sensore GPS Bluetooth che il sensore GPS Android.
I due sensori sono stati posti in acquisizione per tre minuti ad una distanza di pochi centimetri l'uno dall'altra e sincronizzati in modo empirico,

Calcolata la posizione media derivate dai due sensori sono stati calcolati e plottati i delta rispetto al valore medio
Grafico delle fluttuazioni GPS 

Si nota immediatamente come i due sensori lavorino in modo molto differente. Il sensore Bluetooth risente di fluttuazioni piu' ampie mentre il sensore Android si stabilizza rapidamente su una HDOP prossima ai 2 m. Riportando in pianta i dati si vede inoltre che la fluttuazione GPS ha un andamento completamente differente

Fluttuazioni in pianta del segnale GPS

Dettaglio della fluttuazione GPS per i due sensori
Al termine i punti medi dei due GPS risultano distanti 5 m mentre nella realta' si trovavano a pochi centimetri di distanza quindi il test e' stato un insuccesso... ma perche'????
Il sensore GPS del Bluetooth fornisce dati in formato DD MM.dd (gradi minuti.decimi minuto) il che vuole dire che la minima distanza apprezzata vale un centesimo di minuto
Prendiamo per esempio due punti entrambi a latitudine 45°N e longitudine 11°45,32' e 11°45,33' (ovvero distanti di 0.01 primi) che equivalgono a 11°45'19,19'' e 11°45'19,79''. La distanza tra queste
due posizioni risulta essere di circa 13 m. Quindi in linea di principio la colpa e' da attribuire nella scarsa sensibilita' del sensore GPS


Track GPS su Android Java

Ho fatto qualche tentativo di utilizzare Python per registrare i dati del GPS mediante il semplice script



--------------------------------------------------------------------------------------------------------------
import android,time
droid = android.Android()


droid.startLocating()
time.sleep(15)
while True:
loc = droid.readLocation().result
if loc == {}:
loc = getLastKnownLocation().result
if loc != {}:
try:
n = loc['gps']
except KeyError:
n = loc['network']
la = n['latitude']
lo = n['longitude']
print la,lo

--------------------------------------------------------------------------------------------------------------
ma dopo pochi secondi di utilizzo l'icona del GPS si spenge e viene visualizzato sempre lo stesso valore di latitudine e longitudine nonostante le normali fluttuazioni che affliggono tutti i sensori GPS.
Francamente non ho chiaro se il problema derivi dal mio hardware o dalle modifiche al firmware software del telefono (dato che il medesimo script ad altre persone funziona)
In ogni caso l'unica soluzione e' stata quella di convertire il progetto in Java

Manifest.xml (da notare le modifiche alle uses-permission ed all'icona personalizzata)

--------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.gpstest"
    android:versionCode="1"
    android:versionName="1.0" >


    <uses-sdk android:minSdkVersion="8" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>

    <application
        android:icon="@drawable/icon"
        android:label="@string/app_name" >
        <activity
            android:name=".GpsTestActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>


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


GpsTestActivity.java
In questo codice viene acquisita la posizione, l'accuratezza e l'ora, dati che poi vengono scritti sulla SD card su un file cvs dati_gps_android.txt
--------------------------------------------------------------------------------------------------------------

package com.test.gpstest;


import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;


import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.widget.Toast;


public class GpsTestActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        /* Use the LocationManager class to obtain GPS locations */
        LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        LocationListener mlocListener = new MyLocationListener();
        mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
    }
    public class MyLocationListener implements LocationListener
    {
    @Override
    public void onLocationChanged(Location loc)
    {
    loc.getLatitude();
    loc.getLongitude();
    loc.getAccuracy();
    String Text = "My current location is: " + "Latitud = " + loc.getLatitude() +"Longitud = " + loc.getLongitude()+" Accuracy = " + loc.getAccuracy();
    Toast.makeText( getApplicationContext(),Text,Toast.LENGTH_SHORT).show();
    // scrive i dati sul file
    try {
        File root = Environment.getExternalStorageDirectory();
        if (root.canWrite()){
            File gpxfile = new File(root, "dati_gps_android.txt");
            FileWriter gpxwriter = new FileWriter(gpxfile,true);
            BufferedWriter out = new BufferedWriter(gpxwriter);
            //String currentDateTimeString = DateFormat.getDateInstance().format(new Date());
            String currentTimeString = new SimpleDateFormat("HH:mm:ss").format(new Date());
            out.write(currentTimeString+";"+loc.getLatitude()+";"+loc.getLongitude()+";"+loc.getAccuracy()+"\n");
            out.close();
        }
    } catch (IOException e) {
   
    }


    }




    @Override
    public void onProviderDisabled(String provider)
    {
    Toast.makeText( getApplicationContext(),"Gps Disabled",Toast.LENGTH_SHORT ).show();
    }




    @Override
    public void onProviderEnabled(String provider)
    {
    Toast.makeText( getApplicationContext(),"Gps Enabled",Toast.LENGTH_SHORT).show();
    }




    @Override
    public void onStatusChanged(String provider, int status, Bundle extras)
    {


    }


    }/* End of Class MyLocationListener */
    
}

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

Rispetto al test precedente effettuato con un senbsore bluetooth esterno le condizioni di visibilita' del cielo erano decisamente migliori per cui l'errore di posizione e' risultato inferiore ai 5 m



Icone su applicazione Android

Per inserire una icona personalizzata in un progetto Android e' sufficiente inserire nelle directory una immagine .png come suggerito qui


res/drawable-hdpi
res/drawable-mdpi
res/drawable-ldpi


rispettivamente alle risoluzioni 72x72 (hdpi), 48x48 (mdpi) e 36x36 (ldpi) ed usando sempre lo stesso nome (per esempio miaicona.png)

Successivamente si dovra' modificare il file Manifest.xml

   <application
        android:icon="@drawable/miaicona"


inserendo il nome dell'icona dopo la scritta @drawable senza l'estensione png

Scrivere dati su SD Card


Modificando il codice ritrovato qui e' possibile scrivere i dati su un file presente nella SD Card
In questo esempio, mettendo a True, l'attributo di FileWrite si mette la scrittura in Append in modo da accodare i risultati in fondo al file
---------------------------------------------------------------------------------------------------------------------------

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

        double lat = 12.55;
        double lon = 43.14;
        try {
            File root = Environment.getExternalStorageDirectory();
            if (root.canWrite()){
                File gpxfile = new File(root, "gpxfile.gpx");  //nome del file
                FileWriter gpxwriter = new FileWriter(gpxfile,true);
                BufferedWriter out = new BufferedWriter(gpxwriter);
                String currentDateTimeString = DateFormat.getDateInstance().format(new Date());
                String currentTimeString = new SimpleDateFormat("HH:mm:ss").format(new Date());
                out.write(currentTimeString+";"+lon+";"+lat+"\n"); // stringa da scrivere
               // a differenza di Python si puo' scrivere su file anche dati float senza effettuare una esplicita conversione in string
                out.close();
            }
        } catch (IOException e) {
       
        }
---------------------------------------------------------------------------------------------------------------------------
Per rendere il codice operativo bisogna impostare nel file Manifest.xml la seguente riga prima del tag <application>

---------------------------------------------------------------------------------------------------------------------------
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
---------------------------------------------------------------------------------------------------------------------------

Suggerimenti di Eclipse



Usando Eclipse puo' tornare comodo usare i suggerimenti di completamento del codice
Se si digitano le seguenti righe pero'

--------------------------------------------------------------------------------------------
String currentDateTimeString = DateFormat.getDateInstance().format(new Date());
String currentTimeString = new SimpleDateFormat("HH:mm:ss").format(new Date());
--------------------------------------------------------------------------------------------

vengono proposti alcuni import mentre quelli corretti sono

--------------------------------------------------------------------------------------------
import java.text.DateFormat;
import java.text.SimpleDateFormat;
--------------------------------------------------------------------------------------------
In caso contrario il codice non compila

Il motivo dell'errore risiede nel fatto che i comandi sono contenuti, con lo stesso nome, in piu' librerie e quindi Eclipse, non sapendo quale scegliere, sbaglia





MOD su U8150

Per vari motivi ho provato a cambiare il sistema Android montato di fabbrica sul mio Huawei Ideos 8150 della Vodafone con risultati alterni. In particolare


  • Dronix 0.4 : francamente la migliore che ho provato. Veloce, parca di batteria, multitouch abilitato, permessi di root
  • Dronix 0.5.4 : un mezzo inferno. Venendo dalla positiva esperienza ho provato l'upgrade alla 0.5.4 piu' che altro per sperimentare l'USB Host per un futuro utilizzo con Arduino. Il telefono funziona abbastanza bene ma non vengono installati gli aggiornamenti del Market, non e' possibile installare gli apk compilati da Eclipse,  il kernel modificato per l'USB Host azzera la batteria nel giro di poche ore
  • CyanogenMod 7.2: una volta installata richiede il PIN per attivare il telefono ogni 10 secondi. Scartata immediatamente senza ulteriori prove
In tutto cio' ho provato a reinstallare anche il firmware originale della Vodafone ma devo ammettere di non essere riuscito a tornare indietro per cui adesso sto usando, con soddisfazione, la Dronix 0.4

sabato 28 gennaio 2012

Studio GPS per DGPS

Sto lavorando ad una idea su come poter utilizzare telefoni Android o GPS Bluetooth a basso costo per creare un sistema di GPS Differenziale (DGPS) per migliorare le prestazioni e ridurre l'errore di localizzazione.

Il primo passo che ho fatto e' stato quello di studiare un sensore GPS Bluetooth della BlueSoleil
Per stimare l'errore sono state fatte circa 700 misure mantenendo il sensore fermo e leggendo con uno script Python i codici NMEA che vengono generati sulla seriale

Lo script di acquisizione e' il seguente
Per la definizione dei codici NMEA e' stato utilizzato questo sito
Per il calcolo del checksum della stringa NMEA e' stato modificato il codice trovato qui
La parte principale del codice e' accreditata a http://www.robertprice.co.uk/robblog/archive/2007/1/Using_A_Bluetooth_GPS_From_Python.shtml
(il mio contributo e' modesto ma nessuno dei codici da solo era completo e corretto..diciamo che ho messo insieme i pezzi giusti)
-----------------------------------------------------------------------

import bluetooth
import re


def checksum(sentence):
    if re.search("\n$", sentence):
        sentence = sentence[:-1]


    nmeadata,cksum = re.split('\*', sentence)
    nmeadata = nmeadata[1:]
    calc_cksum = 0
    print "nmeadata "+nmeadata
    print "check :"+str(int(cksum,16))


    for s in nmeadata:
        calc_cksum ^= ord(s)
    print "check calc :"+str(calc_cksum)
    return nmeadata,int(cksum,16),calc_cksum






# bluetooth address of the GPS device.
addr = "00:0A:3A:1F:A4:2E"


# port to use.
port = 1


# create a socket and connect to it.
socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
socket.connect((addr, port))
data = ""
olddata = ""


f = open('dati_gps.txt','w')


while True:
data = socket.recv(1024)
#print data
  # make sure we actually have some data.
if len(data) > 0:
  
    # append the old data to the front of data.
data = olddata + data


    # split the data into a list of lines, but make
    # sure we preserve the end of line information.
    lines = data.splitlines(1)


    # iterate over each line
    for line in lines:
    
      # if the line has a carriage return and a
      # linefeed, we know we have a complete line so
      # we can remove those characters and print it.
      if line.find("\r\n") != -1 :
        line = line.strip()
       
gpsstring = line.split(',')
if gpsstring[0] == '$GPRMC':
#print line
data,cksum,calc_cksum = checksum(line)
#print cksum
#print calc_cksum
if cksum == calc_cksum:
#print "GPRMC-------------"

print "Tempo: " + gpsstring[1]
#print "Stato: " + gpsstring[2]
print gpsstring[3][:2]
print gpsstring[3][2:]
print gpsstring[5][:3]
print gpsstring[5][3:]

  lat_d = float(gpsstring[3][:2])+(float(gpsstring[3][2:])/60)
lon_d = float(gpsstring[5][:3])+(float(gpsstring[5][3:])/60)
  print "Lat:  " + gpsstring[3]+gpsstring[4]
  print "Long: " + gpsstring[5]+gpsstring[6]
print str(lat_d)
print str(lon_d)
  #print "Nodi: " + gpsstring[7]
print "Data : "+ gpsstring[9]
#print "Checksum : "+ gpsstring[12]
#print "------------------\n"
f.write(gpsstring[1]+";"+str(lat_d)+";"+str(lon_d)+"\n")




#if gpsstring[0] == '$GPGGA' :
#print "GPGGA-------------"
#print  line
  #print "Tempo :  " + gpsstring[1]

  #print "Lat:  " + gpsstring[2]+gpsstring[3]
  #print "Long: " + gpsstring[4]+gpsstring[5]
#print "Fix: " + gpsstring[6]
#print "Satelliti in vista: " + gpsstring[7]
#print "HDOP: " + gpsstring[7]
#print "Altezza: " + gpsstring[8]
#print "------------------\n"




#if gpsstring[0] == '$GPGSA' :
#print "GPGSA-------------"
#print  line
  #print "PDOP: " + gpsstring[14]
  #print "HDOP: " + gpsstring[15]
  #print "VDOP: " + gpsstring[16]
#print "------------------\n"




        # empty the olddata variable now we have
        # used the data.
        olddata = ""
      # else we need to keep the line to add to data
      else :
        olddata = line
-----------------------------------------------------------------------
Il sensore GPS acquisisce una volta al secondo (sembra impossibile modificare tale valore) in un formato gradi, minuti, decimi di minuto. I dati vengono salvati su file con ora,latitudine,longitudine

Per vedere la fluttuazione del segnale e' stata fatta una prova con una acquisizione di 10 minuti in condizioni non ottimali (il sensore era posto sul davanzale di una finestra e riusciva a vedere solo la meta' del cielo)

In figura sono riportati i punti delle varie misure ed in rosso il valore della misura media. La distribuzione lungo un solo asse e' da imputare alla visione del cielo da parte del sensore


giovedì 26 gennaio 2012

webView su Android per Python


Python per SL4A e' un linguaggio completo ma con scarso controllo sulla grafica dell'output
Per poter avere una interfaccia utente piu' completa (al di la' della schermata terminale) si puo' usare il controllo di webView che permette di impaginare la schermata come una pagina html

di seguito un esempio minimale

--------------------------------------------------------------------------------------------------------------------
import time
import android
from string import Template
pagina = '''<html><body>
<h1>Contatore</h1>
<ul>
<li><strong>Contatore: $contatore</li>
</ul>
</body></html>'''
if __name__ == '__main__':
    droid = android.Android()
    contatore = 1
    while contatore < 10:
        f = open('/sdcard/sl4a/scripts/contatore.html', 'w')
        s = Template(pagina)
        modifica = s.safe_substitute(contatore=str(contatore))
        f.write(modifica)
        f.close()
        droid.webViewShow('file:///sdcard/sl4a/scripts/contatore.html')
        time.sleep(1)
        contatore = contatore + 1

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


pagina e' una stringa che contiene il codice html piu' un tag speciale $contatore che sara' sostituito in modo dinamico durante l'esecuzione dello script.
In pratica la stringa Html diventa un template che viene modificato per sostituzione del tag speciale con il valore desiderato; il template poi viene riconvertito in stringa e poi salvato su file che sara' visualizzato da webView
E' possibile impaginare anche mediante css

Attenzione: se si perde il controllo dello script e' difficile interromperlo perche' sara' visualizzato a pieno schermo la finestra di webView

martedì 24 gennaio 2012

Calcola tempo passato in Python

il secondo pezzo che mi manca per calcolare la velocita' (nel post precedente era stata definita la distanza) e' quello di calcolare il tempo intercorso con l'approssimazione dei centesimi di secondo

scritto in Python il sistema e'
--------------------------------------------------------------------------------

import time


a = time.time()
time.sleep(1)
b = time.time()
print b - a

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

Calcolare la distanza geodetica tra due punti

Due le coordinate in gradi decimali la distanza geodetica tra due punti si puo' calcolare con il metodo descritto qui

la traduzione in Python e' la seguente
-------------------------------------------------------------------------------

import math


def distanza(lat1,lon1,lat2,lon2):
    la1 = math.radians(lat1)
    la2 = math.radians(lat2)
    lo1 = math.radians(lon1)
    lo2 = math.radians(lon2)
    dLat = la1-la2
    dLon = lo1-lo2
    a = math.sin(dLat/2)*math.sin(dLat/2)+math.sin(dLon/2)*math.sin(dLon/2)* math.cos(la1) * math.cos(la2)
    c = 2*math.atan2(math.sqrt(a),math.sqrt(1-a))
    dist = 6378137*c
    return dist


print distanza(45,11,46,10)

-------------------------------------------------------------------------------
lo script calcola la distanza tra i due punti a coordinate lat=45°,lon=11° e lat=46°,lon=10° con il risultato di una distanza di 135786.09 metri.

L'errore di calcolo derivante dall'impiego della formula e' stimato in circa allo 0.3% il che equivale a 3 m per chilometro

Il valore di 6378137 m e' il raggio terrestre secondo il sistema WGS-84.

Il calcolo sopra ripòrtato e' impostato considerando la terra sferica; per una maggiore precisione e' necessario usare la formula ellissoidica di Vincenty (qui)


Stavo andando a giro per l'hard disk con Midnight Commander quando ho dato Invio su un file .apk e mi sono accorto che di fatto e' solo un file zip con una diversa estensione....


lunedì 23 gennaio 2012

Nello stesso momento ........

Nello stesso momento in cui usciva Next sui computer dei mortali si vedevano queste immagini.




Un po' di tempo fa

ebbene si', anche io sto leggendo la biografia di Steve Jobs e sono arrivato al punto in cui vende Next ad Apple..mi sono incuriosito di vedere un sistema operativo su cui di fatto non ho mai messo le mani (non per eta' anagrafica ma per eccessiva rarita' delle macchine Next)

Avvio del SO




Desktop



Applicazioni Demo

Editor di testo


L'immancabile (negli anni 90) Mandelbrot

domenica 22 gennaio 2012

Dati su seriale tra Arduino e PC con Python

Questo esempio e' in preparazione di uno scambio di dati tra telefono Android ed Arduino.
Partendo dal caso piu' semplice (ovvero PC + Arduino) si puo' caricare sulla Arduino il seguente sketch
che in sostanza accende il led sul pin 13 quanto trasmette la stringa "hello"
--------------------------------------------------------------------

void setup() {                
  Serial.begin(9600);
  pinMode(13, OUTPUT);     
}


void loop() {
  digitalWrite(13, HIGH);   
  delay(1000);              
  int bytesSent = Serial.write("hello\n");
  digitalWrite(13, LOW);    
  delay(1000);              


}

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

il programma di lettura su PC (in Python) e' semplicemente, usando la libreria Pyserial
--------------------------------------------------------------------
import serial
arduino = serial.Serial('/dev/ttyUSB2', 9600)
i = 1
while (1):
print str(i) + ": " + arduino.readline()
i= i + 1
--------------------------------------------------------------------
il prossimo tentativo e' quello di far arrivare i dati direttamente ad Android mediante la modifica USB Host del Kernel ed un cavo USB OTG (On The Go)

Attenzione: il comando readline di Python richiede la lettura di una stringa terminata con un ritorno di new line, se la scheda trasmette sulla seriale ma non manda mai il newline il PC non intercetta mai la trasmissione

sabato 21 gennaio 2012

DRONIX su Huawei 8150 Ideos

Circa 15 giorni fa avevo installato la Dronix 0.4 con una procedura non lineare e non ero riuscito con lo stesso metodo ad inserire la 0.5.4 sul mio Ideos

Oggi ho trovato un metodo decisamente piu' lineare che merita di essere descritto

Prima di tutto ho installato l'app Rom Manager dall'Android Market ed ho scaricato il file zip del nuovo firmware sulla schedina microSD. Nella app ho selezionato di installare la Clockworkmod recovery e successivamente ho selezionato l'installazione da file zip indicando quella precedentemente salvata sulla SD (il programma permette di mettere la Cyanogenmod che presente il vantaggio di avere Android 2.3 ma lo svantaggio di non essere dichiarata stabile...peraltro io ho bisogno di testare l' USB Host Mode che e' sicuramente incluso nella Dronix e non e' certo sulla Cyanogenmod)

Qualche minuto di attesa e tutto e' andato a posto...direi anche troppo facile

venerdì 20 gennaio 2012

Log su Py4a

per loggare l'attivita' sullo script per il debug mandando delle stringhe su logcat si puo' usare il seguente comando
-------------------------------------------------------------
droid.log("test")
-------------------------------------------------------------

Eventi basati su chiamate in ingresso

per intercettare gli eventi di chiamate in ingresso al telefono si puo' usare la chiamata
----------------------------------------------------------------

import android
import time
droid = android.Android()
droid.startTrackingPhoneState()
while True:
time.sleep(5)
print droid.readPhoneState().result
droid.stopTrackingPhoneState()

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


readPhoneState.result riporta nella lista vari parametri; il quarto puo' essere "idle" quando il telefono e' in atteso oppure "ringing" quando il telefono squilla

Gestione SMS su Py4A

per gestire gli SMS su un telefono Android mediante Py4A si puo' impiegare lo script seguente (visto qui)

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

import android 
droid = android.Android() 


#conta gli SMS
print "Numero messaggi: " + str(droid.smsGetMessageCount(False,'inbox').result)


# estrae tutti i messaggi
messages = droid.smsGetMessages(False, "inbox", ["address", "body"])
for i in messages.result:
    print i["address"].encode("utf-8")
    print i["body"].encode("utf-8")


# estrae un messaggio dato il numero di ID
message = droid.smsGetMessageById(1, ["address", "body"]).result
print message["address"].encode("utf-8")
print message["body"].encode("utf-8")


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

martedì 17 gennaio 2012

Creare file .apk da Eclipse-ADT

il procedimento per creare i file di installazione e distribuzione .apk da Eclipse e' piuttosto banale
Una volta selezionato il progetto File/Export/Export Android Application

Selezionare il nome del progetto da esportare a cui segue la schermata  del keystore (il file deve avere l'estensione keystore)

Una nuova schermata con parametri da inserire (25 anni e' il valore minimo suggerito da Android)


ed infine si sceglie dove scrivere il file .apk. Tale file puo' essere distribuito, copiato sul telefono ed installato

Creare progetti Android con Eclipse/ADT

Per creare un nuovo progetto Android con Eclipe/ADT si clicchi su File/New/Other/Android Project

Compare quindi la schermata sottostante


in cui Project Name si puo' inserire il nome UDPClient (meglio non usare spazi..non si mai)
in Application Name si puo' inserire il nome in formato libero (spazi,virgole)
in Package Name si deve utilizzare le convenzioni Java per cui il nome puo' essere com.udp.client
in Activity Name si deve inserire il nome della classe che verra' generata in questo caso udpclient


Errori di Eclipse ADT nella creazione di un progetto

lasciando da parte Python sono tornato a rivedere un po' Eclipse e Java mi sono ritrovato con due errori nella fase di creazione di un nuovo progetto mi sono imbattuto in

Debug certificate expired in 03/01/2012.....

che si risolve cancellando il file /.android/debug.keystore (soluzione ripresa da qui) e probabilmente dovuta al fatto che non usavo piu' Eclipse da molto tempo

altro errore
Unable to open class file......R.java
la soluzione (qui) consiste nell'aprire e richiuedere Eclipse oppure cliccare sul progetto nel package explorer sulla sinistra con tasto destro/Source/Format

un altro problemino che0 ho riscontrato (forse a causa di una vecchia versione di ADT) e' che il plug-in cerca il file adb nella directory tools dell'SDK mentre nelle versioni piu' recenti e' stato spostato sotto platform-tools. Si puo' risolvere in modo un po' brutale copiando il file adb nella directory tools

lunedì 16 gennaio 2012

Pygame for Android - Trackpad

Un esempio per usare il telefono come trackpad.
Non ho trovato nell'installazione di Python una funzione si legasse agli eventi del touchscreen cosi' mi sono orientato alla versione di Pygame per Android



sul cellulare ho fatto girare questo script
--------------------------------------------------------------------------------------------------
import pygame
import android
import socket

hostname = "192.168.0.1"; 
port = 21567;
data = "";
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
s.connect((hostname,port));

FPS = 10
TIMEREVENT = pygame.USEREVENT

pygame.init()
screen = pygame.display.set_mode((240, 320))
android.init()
android.map_key(android.KEYCODE_BACK, pygame.K_ESCAPE)
pygame.time.set_timer(TIMEREVENT, 1000 / FPS)
while True:
ev = pygame.event.wait()
if android.check_pause():
android.wait_for_resume()
        if ev.type == pygame.MOUSEMOTION:
#print "pos (%d,%d)" % ev.pos
s.send(str(ev.pos[0])+";"+str(ev.pos[1]))
        elif ev.type == pygame.KEYDOWN and ev.key == pygame.K_ESCAPE:
            break

------------------------------------------------------------------------------------------
a differenza di Py4A, per Pygame si deve creare una directory pygame sulla SD e creare una directory per ognuno degli script che si devono testare. All'interno di questa directory si deve inserire un file icona, il file script che si deve necessariamente chiamare main.py ed un file denominato anrdroid.txt (per i dettagli consultare il sito)

A differenza di Py4A non e' possibile importare in modulo bluetooth per cui lo scambio dati e' avvenuta in UDP

Di seguito il programma server che replica a computer i movimenti del dito su telefono
-----------------------------------------------------------------------------------------
import string
from socket import *
import pygame

pygame.init()
size=[240,320]
screen=pygame.display.set_mode(size)
clock=pygame.time.Clock()


host = "192.168.0.1"
port = 21567
buf = 1024
addr = (host,port)

UDPSock = socket(AF_INET,SOCK_DGRAM)
UDPSock.bind(addr)

while 1:
data,addr = UDPSock.recvfrom(buf)
if not data:
print "Client has exited!"
break
else:
valori = string.split(data,";")
screen.set_at((int(valori[0]), int(valori[1])), (255,0,0))
pygame.display.flip()

UDPSock.close()








Conversione MOV to MPEG su Linux

per convertire i file filmato della fotocamera in un formato gestibile da Youtube si puo' fare

mencoder -of mpeg -ovc lavc -lavcopts vcodec=mpeg1video -nosound input.mov -o output.mpg

Log su Android

Per vedere il log delle attivita' del terminale Android si puo', collegando il cavo dati al PC, digitare il comando

adb logcat

per vedere solo i log generati da Python si puo' scrivere invece

adb logcat -s python:*

Datalogger su Bluetooth

Esempio di comunicazione via Bluetooth
Per funzionare si deve caricare sia sul telefono che sul computer la libreria PyBluez.
Per il telefono si deve seguire la procedura per importare i moduli di Py4a e quindi si deve scaricare il file .egg da posizionare poi nella directory download della scheda SD
Per la libreria sul computer ho riscontrato che scaricando i file tgz ed eseguendo python setup.py install si genera un errore di compilazione su gcc. Per questo motivo ho installato il pacchetto Debian gia' compilato python-bluez
----------------------------------------------------------------------------------------------------------------------------
# file: rfcomm-server.py
# auth: Albert Huang <albert@csail.mit.edu>
# desc: simple demonstration of a server application that uses RFCOMM sockets
#
# $Id: rfcomm-server.py 518 2007-08-10 07:20:07Z albert $


from bluetooth import *


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


port = server_sock.getsockname()[1]


uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"


advertise_service( server_sock, "SampleServer",
                   service_id = uuid,
                   service_classes = [ uuid, SERIAL_PORT_CLASS ],
                   profiles = [ SERIAL_PORT_PROFILE ], 
#                   protocols = [ OBEX_UUID ] 
                    )
                   
print "Waiting for connection on RFCOMM channel %d" % port


client_sock, client_info = server_sock.accept()
print "Accepted connection from ", client_info


try:
    while True:
        data = client_sock.recv(1024)
        if len(data) == 0: break
        print "%s" % data
except IOError:
    pass


print "disconnected"


client_sock.close()
server_sock.close()
----------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------

# file: rfcomm-client.py
# auth: Albert Huang <albert@csail.mit.edu>
# desc: simple demonstration of a client application that uses RFCOMM sockets
#       intended for use with rfcomm-server
#
# $Id: rfcomm-client.py 424 2006-08-24 03:35:54Z albert $


from bluetooth import *
import sys
import android
import time
import math


addr = None


droid = android.Android();
droid.startSensingTimed(1,1000)
time.sleep(3)


uuid = "94f39d29-7d6d-437d-973b-fba39e49d4ee"
service_matches = find_service( uuid = uuid, address = addr )


if len(service_matches) == 0:
    print "couldn't find the SampleServer service =("
    sys.exit(0)


first_match = service_matches[0]
port = first_match["port"]
name = first_match["name"]
host = first_match["host"]


sock=BluetoothSocket( RFCOMM )
sock.connect((host, port))


print "Connesso"
while True:
az = str(math.degrees(droid.sensorsReadOrientation().result[0]))
pitch = str(math.degrees(droid.sensorsReadOrientation().result[1]))
roll =  str(math.degrees(droid.sensorsReadOrientation().result[2]))
    data = az+";"+pitch+";"+roll
    if len(data) == 0: break
    sock.send(data)


sock.close()

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

Datalogger in UDP


L'ennesima versione del datalogger che usa il protocollo UDP per scambiare i dati
-----------------------------------------------------------------------------------------------------
import android
import socket
import time
import math




droid = android.Android();




hostname = "192.168.0.1"; 
port = 21567;
data = "";
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
s.connect((hostname,port));


droid.startSensingTimed(1,1000)
time.sleep(3)
while True:
az = str(math.degrees(droid.sensorsReadOrientation().result[0]))
pitch = str(math.degrees(droid.sensorsReadOrientation().result[1]))
roll =  str(math.degrees(droid.sensorsReadOrientation().result[2]))
s.sendto(az+";"+pitch+";"+roll,(hostname,port));
-----------------------------------------------------------------------------------------------------
# Server program

import string
from socket import *

host = "192.168.0.1"
port = 21567
buf = 1024
addr = (host,port)

UDPSock = socket(AF_INET,SOCK_DGRAM)
UDPSock.bind(addr)

while 1:
data,addr = UDPSock.recvfrom(buf)
if not data:
print "Client has exited!"
break
else:
valori = string.split(data,";")
print valori[0]
print valori[1]
print valori[2]

# Close socket
UDPSock.close()

Arduino + Python

Esempio di come pilotare una Arduino mediante Python

Ho fatto molte prove ma al momento l'unico sistema funzionate e' quello di impiegare le librerie che si trovano qui.

Prima di deve caricare lo sketch sulla scheda (il file pde) mediante il programmatore della Arduino ed in seguito si puo' lanciare lo script da computer


Esiste un problema: deve essere ricaricato lo sketch per ogni volta che si deve lanciare lo script Python
Di seguito lo script leggermente modificato rispetto a quello dell'esempio
-----------------------------------------------------------------------------------------
from arduino import Arduino
import time
my_board = Arduino('/dev/ttyUSB0')
my_board.output([11,12,13])
i=0
while(i<3):
    my_board.setHigh(13)
    time.sleep(1)
    my_board.setHigh(12)
    time.sleep(1)
    my_board.setLow(13)
    time.sleep(1)
    my_board.setLow(12)
    time.sleep(1)
    i+=1

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

Oggi mi gira il cubo

Un merge tra il codice ripreso qui del wireframe_cube.py ed il mio codice di datalogger_udp_client/server



Lato server
-------------------------------------------------------------------------------------------
"""
 Wireframe 3D cube simulation.
 Developed by Leonel Machava <leonelmachava@gmail.com>


 http://codeNtronix.com
modificato da Luca Innocenti
"""
import sys, math, pygame
from pygame.locals import *
import string
from socket import *


host = "192.168.0.1"
port = 21567
buf = 1024
addr = (host,port)




class Point3D:
    def __init__(self, x = 0, y = 0, z = 0):
        self.x, self.y, self.z = float(x), float(y), float(z)

    def rotateX(self, angle):
        """ Rotates the point around the X axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        y = self.y * cosa - self.z * sina
        z = self.y * sina + self.z * cosa
        return Point3D(self.x, y, z)

    def rotateY(self, angle):
        """ Rotates the point around the Y axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        z = self.z * cosa - self.x * sina
        x = self.z * sina + self.x * cosa
        return Point3D(x, self.y, z)

    def rotateZ(self, angle):
        """ Rotates the point around the Z axis by the given angle in degrees. """
        rad = angle * math.pi / 180
        cosa = math.cos(rad)
        sina = math.sin(rad)
        x = self.x * cosa - self.y * sina
        y = self.x * sina + self.y * cosa
        return Point3D(x, y, self.z)

    def project(self, win_width, win_height, fov, viewer_distance):
        """ Transforms this 3D point to 2D using a perspective projection. """
        factor = fov / (viewer_distance + self.z)
        x = self.x * factor + win_width / 2
        y = -self.y * factor + win_height / 2
        return Point3D(x, y, 1)


class Simulation:
    def __init__(self, win_width = 640, win_height = 480):
        pygame.init()


        self.screen = pygame.display.set_mode((win_width, win_height))
        pygame.display.set_caption("3D Wireframe Cube Simulation (http://codeNtronix.com)")
        
        self.clock = pygame.time.Clock()


        self.vertices = [
            Point3D(-1,1,-1),
            Point3D(1,1,-1),
            Point3D(1,-1,-1),
            Point3D(-1,-1,-1),
            Point3D(-1,1,1),
            Point3D(1,1,1),
            Point3D(1,-1,1),
            Point3D(-1,-1,1)
        ]


        # Define the vertices that compose each of the 6 faces. These numbers are
        # indices to the vertices list defined above.
        self.faces = [(0,1,2,3),(1,5,6,2),(5,4,7,6),(4,0,3,7),(0,4,5,1),(3,2,6,7)]


        self.angleX, self.angleY, self.angleZ = 0, 0, 0
        
    def run(self):
        """ Main Loop """
host = "192.168.0.1"
port = 21567
buf = 1024
addr = (host,port)

UDPSock = socket(AF_INET,SOCK_DGRAM)
UDPSock.bind(addr)


        while 1:
data,addr = UDPSock.recvfrom(buf)
valori = string.split(data,";")


#            for event in pygame.event.get():
#                if event.type == pygame.QUIT:
#                    sys.exit()
# if (event.type == KEYUP) or (event.type == KEYDOWN):
# if (event.key == K_a):
# self.angleX = self.angleX + 1
# if (event.key == K_z):
# self.angleX = self.angleX - 1


            self.clock.tick(50)
            self.screen.fill((0,0,0))


            # Will hold transformed vertices.
            t = []
            
for v in self.vertices:
       # Rotate the point around X axis, then around Y axis, and finally around Z axis.
       r = v.rotateX(self.angleX).rotateY(self.angleY).rotateZ(self.angleZ)
       # Transform the point from 3D to 2D
       p = r.project(self.screen.get_width(), self.screen.get_height(), 256, 4)
       # Put the point in the list of transformed vertices
       t.append(p)


for f in self.faces:
       pygame.draw.line(self.screen, (255,255,255), (t[f[0]].x, t[f[0]].y), (t[f[1]].x, t[f[1]].y))
       pygame.draw.line(self.screen, (255,255,255), (t[f[1]].x, t[f[1]].y), (t[f[2]].x, t[f[2]].y))
       pygame.draw.line(self.screen, (255,255,255), (t[f[2]].x, t[f[2]].y), (t[f[3]].x, t[f[3]].y))
       pygame.draw.line(self.screen, (255,255,255), (t[f[3]].x, t[f[3]].y), (t[f[0]].x, t[f[0]].y))
       
self.angleX = round(float(valori[0]),0)
self.angleY = round(float(valori[1]),0)
self.angleZ = round(float(valori[2]),0)
   
pygame.display.flip()


if __name__ == "__main__":
    Simulation().run()

-------------------------------------------------------------------------------------------
Lato client
-------------------------------------------------------------------------------------------

import android
import socket
import time
import math




droid = android.Android();




hostname = "192.168.0.1"; 
port = 21567;
data = "";
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);
s.connect((hostname,port));


droid.startSensingTimed(1,1000)
time.sleep(3)
while True:
az = str(math.degrees(droid.sensorsReadOrientation().result[0]))
pitch = str(math.degrees(droid.sensorsReadOrientation().result[1]))
roll =  str(math.degrees(droid.sensorsReadOrientation().result[2]))
s.sendto(az+";"+pitch+";"+roll,(hostname,port));

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