venerdì 31 gennaio 2014

Phonegap-Cordoba 3.0 con Android/Ios/FirefoxOS

Visto che oramai ho terminali Android, Ios e FirefoxOs ho voluto riprovare ad usare Phonega e nel frattempo le procedure di installazione sono decisamente cambiate


Phonegap/Cordoba si installa mediante Node.js per cui si deve prima installare il pacchetto Node.Js
Su Windows e MacOs c'e' un semplice installare mentre su Linux Node.js si installa scaricando direttamente i sorgenti e con la classica procedura
./configure
make
make install
(la procedura non e' rapidissima)

successivamente si inizia ad installare Phonegap con il comando
npm install -g phonegap
(forse e' inutile ma ho installato anche Cordova)
npm install -g cordova


si crea quindi il progetto
phonegap create hello com.example.hello HelloWorld
cd hello

e qui iniziano le differenze che ho trovato con le istruzioni ufficiali del sito

per creare il progetto Phonegap Android si deve dare direttamente il comando
phonegap build android
(devono essere setttata la Path per trovare la directory tools e platform-tools dell'SDK di Android altrimenti il comando fallisce con il comando
)
oppure
phonegap build ios

per lanciare l'esecuzione sul telefono
phonegap run android

oppure
phonegap run ios
(se non viene trovato il telefono fisico viene lanciato in automatico l'emulatore.

Nel caso di IOS deve essere prima installato il pacchetto ios-sim con i comandi
sudo su
xcodebuild -license
npm install -g ios-sim
)
Lanciato il comando l'emulatore parte ma si arriva a questo errore

Di fatto la directory www del progetto creato su Ios risulta vuota (c'e' solo un file .xml). Per risolvere il problema l'unica soluzione che ho trovato e' stata quella di copiare la directory www da un progetto Phonegap creato su Linux. Fatto cio' tutto inizia a funzionare perfettamente

A questo per aggiungere funzionalita' legate all'hardware dei telefoni si devono installare i plugin per le varie funzionalita'. Per test e' stato scaricato ed attivato il 

cordova plugin add org.apache.cordova.device

Ed ecco lo stesso programma di esempio che funziona, senza modifiche, sulle due piattaforme Android ed Ios

Phonegap su Ios

Phonegap su emulatore Android in Ios

si puo' aggiungere al progetto anche FirefoxOs mediante
cordova platform add firefox

il problema e' che l'emulatore di Firefox Os non funziona sotto Mac Os X (almeno al momento in cui scrivo questa riga). Parte e si chiude dopo qualche secondo. Per ovviare al problema ho spostato tutta la cartella della piattaforma Firefox sull'emulatore di Windows e selezionato il file manifest.
Si osserva che il supporto di Phonegap a Firefox e' ancora poco maturo in quanto le API ancora non funzionano (almeno quelle dell'esempio)









Installazione Arch Linux

E' da un po' di tempo che sento un gran parlare di Arch Linux e volevo provare ma la procedura di installazione e' cosi' antiquata (mi sembra di essere tornato nel 1998) che mi ero sempre scoraggiato....ma sembra che i vantaggi siano ricompensati dalla fatica di installazione



Per la prova ho installato Arch Linux su Virtualbox partendo con boot da Cd (nessun network install per adesso)

Si arriva ad una shell bash con privilegi di root
Per prima cosa si imposta la tastiera italiana
loadkeys it

si edita quindi il file locale.gen
nano /etc/locale.gen

togliendo il cancelletto alla riga di interesse
it_IT.UTF-8 UTF-8

si lancia poi il comando
locale-gen 

e si esporta la variabile LANG
export LANG=it_IT.UTF-8

la rete e' stata configurata mediante DHCP senza troppi problemi.
A questo punto si inizia il partizionamento del disco fisso (semplice, una partizione piu' una swap)

fdisk /dev/sda
n - p - 1 
l'inizio della partizione e' confermata come default
la dimensione della partizione e' fissata in 7 Giga con il comando
+7G

per la swao
n - p - 2
conferma tutto
con t si cambia il tipo della seconda partizione da Linux (83) a Linux Swap (82)

p per verificare
w per scrivere ed uscire

si formatta la prima partizione come ext4
mkfs.ext4 /dev/sda1
si attiva la seconda partizione come swap
mkswap /dev/sda2

lsblk /dev/sda
mount /dev/sda1 /mnt

Adesso c'e' bisogno della rete. Se c'e' un proxy si devono effettuare i settaggi
export http_proxy=http://mioproxy:8080
export https_proxy=http://mioproxy:8080

si aggiornano i pacchetti e si installa il sistema base
pacstrap -i /mnt base
si conferma vengono scaricati circa 140 Mb

si effettua il chroot
arch-chroot /mnt /bin/bash

si ripetono i settaggi locali
nano /etc/locale.gen
it_IT.UTF-8 UTF-8
locale-gen
echo LANG=it_IT.UTF-8 > /etc/locale.conf # export LANG=it_IT.UTF-8
loadkeys it 
setfont Lat2-Terminus16

per renderlo definitivo
nano /etc/vconsole.conf
KEYMAP=it FONT=Lat2-Terminus16


per settare la timezone
ln -s /usr/share/zoneinfo/Europe/Rome /etc/localtime

per settare l'orologio
hwclock --systohc --utc

abilitazione del DHCP per la rete
systemctl enable dhcpcd.service

a questo punto si mette la password per root
passwd

e si installa Grub
pacman -S grub
grub-mkconfig -o /boot/grub/grub.cfg
grub-install --target=i386-pc --recheck /dev/sda

si termina quindi la prima fase dell'installazione
exit
umount -R /mnt
reboot

a questo punto e' meglio creare un utente non amministratore per l'uso normale
useradd -m luca
passwd luca

abilitazione del comparto sonoro
pacman -S alsa-utils

Installazione di XOrg ed LXDE
pacman -S xorg-server xorg-server-utils xorg-xinit mesa lxde dbus xf86-video-fbdev

prima di lanciare il comando startx si deve creare il file .xinitrc nella propria home
nano .xinitrce si  aggiunge la seguente riga
exec startlxde


adesso si puo' lanciare
startx

Installazione di Slim
pacman -S slims
ystemctl enable slim

Purtroppo per Arch non c'e' supporto semplice per Virtualbox per cui c'e' da fare un po' di lavoro a mano
pacman -S virtualbox-guest-utils

si crea e si edita il file virtualbox.conf
nano/etc/modules-load.d/virtualbox.confaggiungendo su ogni riga
vboxguest
vboxsf
vboxvideo

e da linea di comando si lancia
VBoxClient-all
systemctl enable vboxservice


alla fine il sistema e' decisamente performante (anche perche' ridotto all'osso) ma penso che si possa arrivare a conclusioni simili (e con minor fatica) facendo una installazione manuale di Debian da Netinstall

Midnight Commander su Os X

Dove c'e' una shell ci dovrebbe essere Midnight Commander ..ed Os X non fa eccezione
Il programma si puo' installare da questo link
Essendo un programma da shell alla fine dell'installazione non si trova niente nella cartella Applicazioni, ma basta aprire un terminale e digitare mc che si apre Midnight Commander
Ci sono un po' di problemi di ambientazioni da Linux/PC a OsX in quanto nelle tastiere Apple non e' presente il tasto Ins, per selezionare si preme la combinazione CTRL+T

Di default inoltre i tasti funzione delle tastiere Apple hanno altre funzioni. Per abilitare il comportamento classico da Impostazioni Tastiera si deve spuntare "Utilizza tutti i tasti F1,F12 come tasti funzione" e nel tab successivo (Abbreviazioni da tastiera) si deve togliere la scorciatoia di F9 ed F10 (in particolare F10 che serve ad uscire da mc)






Piena del Mugnone


Attraversamento depuratore Pian del Mugnone

Attraversamento a monte di Pian del Mugnone


mercoledì 29 gennaio 2014

Seti@home

Dopo oltre 10 anni sono ritornato a far lavorare il calcolatore per Seti@home (oltre ad un progetto per la struttura 3D delle proteine)



In attesa di dire WOW.....

Mandelbrot su IPhone/IOS

Per disegnare Mandelbrot su un Iphone per prima cosa si deve trovare una superficie su cui disegnare.
Scartata l'ipotesi di OpenGL (troppo complicata), la cosa piu' semplice e' utilizzare la libreria Quartz 2D facendo un subclass di UIView (per il dettaglio seguire questo link)




Questo puo' essere effettuato con i seguenti comandi (partendo da un progetto vuoto con View-Based Application)
File -> Add Files to 
si seleziona Objective-C Class e in basso si seleziona SubClass of UIView
Si seleziona un nome per la nuova classe e si conclude

In seguito dall'Interface Builder (il creatore di interfacce visuali) si seleziona tutta la finestra (UIView), si preme Command+4 e si modifica la classe da UIView con il nome precedentemente selezionato

Fatto cio' si trova che nel file miaclasse.m un scheletro vuoto di una funzione drawRect.Qui si puo' inserire il codice per la generazione dell'insieme di Mandelbrot

------------------------------------------------------------
//
//  Draw2D.m
//  Mand
//
//  Created by Luca Innocenti on 27/01/14.
//  Copyright (c) 2014 Luca Innocenti. All rights reserved.
//

#import "Draw2D.h"

@implementation Draw2D

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 2.0);
    CGContextSetStrokeColorWithColor(context, [UIColor blackColor].CGColor);

    
    int SCREEN_WIDTH = 480;
    int SCREEN_HEIGHT = 320;
    
    float re_min = -2.0;
    float im_min = -1.2;
    float re_max = 1.0;
    float im_max = 1.2;
    int iterazioni = 60;
    float a,b;
    float x,y,x_new,y_new;
    int test;
    int k,j,i;
    
    float re_factor = (re_max-re_min);
    float im_factor = (im_max-im_min);
    for (i=0;i<SCREEN_HEIGHT;i++)
    {
        for (j=0;j<SCREEN_WIDTH;j++)
        {
            a = re_min+(j*re_factor/SCREEN_WIDTH);
            b = im_min+(i*im_factor/SCREEN_HEIGHT);
            x = 0;
            y = 0;
            test = 0;
            for (k=0;k<iterazioni;k++)
            {
                x_new = (x*x)-(y*y)+a;
                y_new = (2*x*y)+b;
                if (((x_new*x_new)+(y_new*y_new))>4)
                {
                    test = k;
                    if (k%2)
                    {
                        CGContextMoveToPoint(context, i, j);
                        CGContextAddLineToPoint(context, i+1,j);
                        CGContextStrokePath(context);
                    }
                    break;
                }
                x = x_new;
                y = y_new;
            }
        }
    }
}

@end
--------------------------------------------------------------


martedì 28 gennaio 2014

ADS1115 ADC 16Bit su Arduino Uno

Per il progetto di acquisizione dati del Laboratorio Terre del Dipartimento di Scienze della Terra e' necessario utilizzare un convertitore analogico digitale migliore di quello presente su Arduino (10 bit =1024 livelli per Arduino Uno e 12 bit=4096 livelli per Arduino Due)

La soluzione piu' semplice e' stata utilizzare l'ADS1115, un integrato che dialoga su canale I2C con quattro ingressi analogici (in multiplex) con un ADC da 16 bit montato su una BreakOut della AdaFruit


http://learn.adafruit.com/assets/2675
Le connessioni sono semplici

Vdd = 5 V Arduino
GND = GND Arduino
SDA = A4 Arduino
SCL = A5 Arduino

non sono necessarie le resistenze di PullUp sui pin A4,A5
L'integrato ADS1115 contiene al suo interno sia l'oscillatore che la tensione di riferimento per cui non e' necessaria ulteriore elettronica di contorno. E' possibile anche settare il valore del guadagno

Per i vari valori di guadagno si hanno differenti valori di fondo scala e differente sensibilita'

Gain 2/3 : fondo scala 6.144V 1bit = 0.1875 mV
Gain 1 : fondo scala 4.096V 1bit = 0.125 mV
Gain 2 : fondo scala 2.048V 1bit = 0.0625 mV
Gain 4 : fondo scala 1.024V 1bit = 0.03125 mV
Gain 8 : fondo scala 0.512V 1bit = 0.015625 mV
Gain 16 : fondo scala 0.256V 1bit = 0.0078125 mV

(attenzione: se si setta un guadagno e si eccede il fondo scala si rischia di bruciare l'ADC)

Considerando le tensioni di lettura della strumentazione del laboratorio di geotecnica il Gain ottimale e' il 4

Per controllare questo componente si usa la libreria scaricabile a questo indirizzo 

Di seguito un semplice esempio ovvero la misura della tensione su un potenziometro variabile (montato su A0 dell'ADS1115)


ed ecco il semplice codice per la lettura
----------------------------------------------------------
#include <Wire.h>
#include <Adafruit_ADS1015.h>

Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */

void setup(void) 
{
  Serial.begin(9600);
  //                                                                ADS1015  ADS1115
  //                                                               -------  -------
  ads.setGain(GAIN_TWOTHIRDS);  // 2/3x gain +/- 6.144V  1 bit = 3mV      0.1875mV (default)
  // ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
  // ads.setGain(GAIN_TWO);        // 2x gain   +/- 2.048V  1 bit = 1mV      0.0625mV
  // ads.setGain(GAIN_FOUR);       // 4x gain   +/- 1.024V  1 bit = 0.5mV    0.03125mV
  // ads.setGain(GAIN_EIGHT);      // 8x gain   +/- 0.512V  1 bit = 0.25mV   0.015625mV
  // ads.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV
  
  ads.begin();
}

void loop(void) 
{
  int16_t adc0, adc1, adc2, adc3;

  adc0 = ads.readADC_SingleEnded(0);
  Serial.print("AIN0: "); Serial.println(adc0);
  delay(100);
}


Bussola non funzionante su Alcatel One Touch Fire 4012X

Aggiornamento
Dopo un mese e 20 giorni il telefono e' rientrato dall'assistenza Alcatel con il medesimo problema
Nonostante quanto riportato dai siti vedi per esempio qui, e qui  mi viene il forte sospetto che il telefono non abbia un sensore per la bussola
---------------------------------------------------------

Alla fine non ho resistito e mi sono comprato l'unico terminale attualmente disponibile in Italia che monta Firefox Os, ovvero l'Alcatel One Touch Fire.
Lo scopo dell'acquisto era quello di effettuare il porting di Geocompass anche per Firefox OS (e nel frattempo imparare un po' di HTML5)

Con mia grande sorpresa pero' la bussola non risulta funzionante. Mediante programma sono riuscito a leggere i valori di inclinazione ma non quelli dell'azimuth (la API e' la medesima quindi non e' un problema di programmazione). Ho provato quindi a scaricare dal Market delle applicazioni di bussola con il medesimo risultato. Nessun segnale dal sensore magnetico

Ho riportato quindi il telefono in assistenza con due scenari possibili:
1) il sensore e' rotto
2) non e' stato implementato il driver all'interno del sistema operativo

Nel negozio era disponibile un altro esemplare in vetrina e grazie al venditore e' stato possibile accenderlo ed installare applicazioni per bussola scaricate sempre dal Market. Medesimo risultato. La bussola non funziona
Attendo speranzoso che torni dall'assistenza ma il sospetto di aver comprato un oggetto per niente testato e' forte


Problemi su bussola di smartphone

Alcune persone del Dipartimento di Scienze Geologiche dell'Universita' di Firenze mi hanno segnalato che la mia applicazione Geocompass non funziona. Il primo istinto e' stato dire: non e' possibile, l'applicazione e' stata scaricata da oltre 2500 persone non ho mai avuto segnalazioni in merito
Sono andato quindi a verificare di persona ed in effetti durante le prove il valore di Dip rimaneva fisso mentre il valore di Strike oscillava sensibilmente. Nelle mie prove non avevo osservato il fenomeno e sono rimasto perplesso. Una volta tornato a casa ho riprovato l'applicazione ed il difetto non si mostrava


A questo punto ho condotto la prova mostratta nel video. Con la stessa applicazione (la mia Geocompass), sullo stesso telefono (il mio Nexus S) ho fatto una prova di misura presso l'ufficio e dopo mezz'ora presso il DST ad Arcetri. Come si vede ad Arcetri le misure oscillano in un range di +- 20° (le misure sono state effettuate il piu' distante possibile da eventuali fonti di interferenza)

Si vede anche chiaramente che il sensore affetto e' il solo sensore magnetico infatti la misura di Dip e' eseguita solo tramite l'accelerometro (e' un calcolo in base alla scomposizione del vettore della forza di gravita') ed e' stabile mentre varia il valore di Strike e' che funzione sia dell'accelerometro sia della bussola digitale

Il sospetto e' che il sensore magnetico sia ingannato da qualche interferenza localizzata

ps: il fenomeno non sembra ascrivibile a cattiva calibrazione del sensore

giovedì 16 gennaio 2014

Arduino nano ed interruttore al mercurio

Un amico mi ha richiesto un sistema basato su Arduino che fosse alimentato da una batteria, che fosse il piu' piccolo possibile e che fosse sempre spento a meno di un evento (il rovesciamento della scheda)

La soluzione piuttosto stupida e' stata quella di usare come fonte di alimentazione una pila V4034PX della Varta da 6 V ed una Arduino micro (hanno piu' o meno le stesse dimensioni)

Tra il polo positivo della pila ed il Vcc dell'Arduino e' stato messo un interruttore a Mercurio (che normalmente e' in posizione aperta). Quando la scheda viene rovesciata il circuito si chiude e si accende l'Arduino


sdf




martedì 14 gennaio 2014

Da Os X 10.6 a 10.7 via USB - Errore su installazione

Mi sono trovato a dover aggiornare un MacBook (Intel Core Due Duo con 2 Giga di Ram) per il passaggio da Mac Os X 10.6 a 10.7. (fra parentesi ho pochissima esperienza con i Mac ed in particolari con la nuova generazione Intel)
Non avendo un supporto fisico (leggasi DVD) ho preparato una chiavetta USB con il metodo che ho riassunto nel video sottostante. In sintesi si prende una chiavetta da almeno 8 Giga, si apre Utility Disco, si formatta la chiavetta e poi si ripristina sulla stessa chiavetta il .dmg del sistema operativo



A questo punto ho fatto partire la macchina tenendo premuto il tasto Option (Alt) e selezionando la chiavetta come disco di avvio. In tutte le prove effettuate, dopo un po' di pensatoio da parte dell'installer, viene sempre generato questo errore. Ho provato a rimuovere la partizione bootcamp, provato a formattare tutto il disco ... niente da fare



Frugando per forum ho trovato l'indicazione di formattare la PRAM prima di tentare l'installazione. A questo punto ho proceduto accendendo il calcolatore e premendo subito la combinazione Option+Command+P+R, il Mac fa Boing e poi fa il reboot. A questo punto ho fatto ripartire l'installazione da Usb Key e tutto e' terminato in modo corretto


Compressione SMS in Android (2)

Riprendendo dalla puntata precedente, in questo caso la compressione non e' orientata ai caratteri ma si basa sull'ottimizzare il numero di bit per comprimere il dato. Come gia' detto l'obbiettivo e' trasferire informazioni geografiche quindi coordinate lat/long che possono essere descritte come numeri in virgola mobile (non e' previsto avere segni di separazione perche' sara' solo la posizione a determinare la distinzione tra un dato ed il successivo)

Una coordinata in gradi decimali (se non ho sbagliato) necessita' di almeno 5 decimali per avere una precisione al secondo di arco in grado sessagesimali.
La logica e' piu' o meno questa:
1) si prende il numero in virgola mobile e lo si converte nella sua rappresentazione binaria (come stringa)
2) si divide la stringa in pezzi da 7 bit (per il formato SMS)
3) si prendono solo i primi 5 gruppi di 7 bit (il resto dell'informazione e' ridondante)
4) i 7 bit vengono convertiti in un intero (0-127) e quindi nel corrispondente caratttere della tabella SMS
5) il percorso inverso per la riconversione in float

il vantaggio non e' drammatico. Si descrive un numero che puo' essere scritto con 8 caratteri in 5 gruppi da 7 bit (quindi il messaggio occupa circa 0.62 dell'originale, ovvero 1.6 dipende da punto si vede)
Questi sono i passaggi

-------------------------------------------------------------------
Messaggio originale :43.26432
100000001000101101000011101010100111100110111011101011011100000
Messaggio compresso : ¡"h:S
100000001000101101000011101010100110000000000000000000000000000
Messaggio decompresso : 43.26431846618652
-------------------------------------------------------------------
ed ecco il codice

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

package sms_compr;

import java.math.BigInteger;

/**
 *
 * @author l.innocenti
 */
public class Sms_compr {
    private static int valore;
    private static String reverse = "";
    private static String passaggio = "";
    
    

     static private int converti_sms(char carattere)
    {
       int codice=0;
       switch (carattere)
            {
             case '@': codice=0;break;
             case '£': codice=1;break;
             case '$': codice=2;break;
             case '¥': codice=3;break;
             case 'è': codice=4;break;
             case 'é': codice=5;break;
             case 'ù': codice=6;break;
             case 'ì': codice=7;break;
             case 'ò': codice=8;break;
             case 'Ç': codice=9;break;
             case '\n': codice=10;break;
             case 'Ø': codice=11;break;
             case 'ø': codice=12;break;
             case '\r': codice=13;break;
             case 'Å': codice=14;break;
             case 'å': codice=15;break;
             case 'Δ': codice=16;break;
             case '_': codice=17;break;
             case 'Φ': codice=18;break;
             case 'Γ': codice=19;break;
             case 'Λ': codice=20;break;
             case 'Ω': codice=21;break;
             case 'Π': codice=22;break;
             case 'Ψ': codice=23;break;
             case 'Σ': codice=24;break;
             case 'Θ': codice=25;break;
             case 'Ξ': codice=26;break;
             //case '': codice=27;break;
             case 'Æ': codice=28;break;
             case 'æ': codice=29;break;
             case 'ß': codice=30;break;
             case 'É': codice=31;break;
             case ' ': codice=32;break;
             case '!': codice=33;break;
             case '"': codice=34;break;
             case '#': codice=35;break;
             case '¤': codice=36;break;
             case '%': codice=37;break;
             case '&': codice=38;break;
             case '\'': codice=39;break;
             case '(': codice=40;break;
             case ')': codice=41;break;
             case '*': codice=42;break;
             case '+': codice=43;break;
             case ',': codice=44;break;
             case '-': codice=45;break;
             case '.': codice=46;break;
             case '/': codice=47;break;
             case '0': codice=48;break;
             case '1': codice=49;break;
             case '2': codice=50;break;
             case '3': codice=51;break;
             case '4': codice=52;break;
             case '5': codice=53;break;
             case '6': codice=54;break;
             case '7': codice=55;break;
             case '8': codice=56;break;
             case '9': codice=57;break;
             case ':': codice=58;break;
             case ';': codice=59;break;
             case '<': codice=60;break;
             case '=': codice=61;break;
             case '>': codice=62;break;
             case '?': codice=63;break;
             case '¡': codice=64;break;
             case 'A': codice=65;break;
             case 'B': codice=66;break;
             case 'C': codice=67;break;
             case 'D': codice=68;break;
             case 'E': codice=69;break;
             case 'F': codice=70;break;
             case 'G': codice=71;break;
             case 'H': codice=72;break;
             case 'I': codice=73;break;
             case 'J': codice=74;break;
             case 'K': codice=75;break;
             case 'L': codice=76;break;
             case 'M': codice=77;break;
             case 'N': codice=78;break;
             case 'O': codice=79;break;
             case 'P': codice=80;break;
             case 'Q': codice=81;break;
             case 'R': codice=82;break;
             case 'S': codice=83;break;
             case 'T': codice=84;break;
             case 'U': codice=85;break;
             case 'V': codice=86;break;
             case 'W': codice=87;break;
             case 'X': codice=88;break;
             case 'Y': codice=89;break;
             case 'Z': codice=90;break;
             case 'Ä': codice=91;break;
             case 'Ö': codice=92;break;
             case 'Ñ': codice=93;break;
             case 'Ü': codice=94;break;
             case '§': codice=95;break;
             case '¿': codice=96;break;
             case 'a': codice=97;break;
             case 'b': codice=98;break;
             case 'c': codice=99;break;
             case 'd': codice=100;break;
             case 'e': codice=101;break;
             case 'f': codice=102;break;
             case 'g': codice=103;break;
             case 'h': codice=104;break;
             case 'i': codice=105;break;
             case 'j': codice=106;break;
             case 'k': codice=107;break;
             case 'l': codice=108;break;
             case 'm': codice=109;break;
             case 'n': codice=110;break;
             case 'o': codice=111;break;
             case 'p': codice=112;break;
             case 'q': codice=113;break;
             case 'r': codice=114;break;
             case 's': codice=115;break;
             case 't': codice=116;break;
             case 'u': codice=117;break;
             case 'v': codice=118;break;
             case 'w': codice=119;break;
             case 'x': codice=120;break;
             case 'y': codice=121;break;
             case 'z': codice=122;break;
             case 'ä': codice=123;break;
             case 'ö': codice=124;break;
             case 'ñ': codice=125;break;
             case 'ü': codice=126;break;
             case 'à': codice=127;break;
       }
       return codice;
    }

    public static void main(String[] args) {
         char[] sms = new char[128];
        

        sms[0] = '@';
        sms[1] = '£';
        sms[2] = '$';
        sms[3] = '¥';
        sms[4] = 'è';
        sms[5] = 'é';
        sms[6] = 'ù';
        sms[7] = 'ì';
        sms[8] = 'ò';
        sms[9] = 'Ç';
        sms[10] = '\n';
        sms[11] = 'Ø';
        sms[12] = 'ø';
        sms[13] = '\r';
        sms[14] = 'Å';
        sms[15] = 'å';
        sms[16] = 'Δ';
        sms[17] = '_';
        sms[18] = 'Φ';
        sms[19] = 'Γ';
        sms[20] = 'Λ';
        sms[21] = 'Ω';
        sms[22] = 'Π';
        sms[23] = 'Ψ';
        sms[24] = 'Σ';
        sms[25] = 'Θ';
        sms[26] = 'Ξ';
        //sms[27] = '';
        sms[28] = 'Æ';
        sms[29] = 'æ';
        sms[30] = 'ß';
        sms[31] = 'É';
        sms[32] = ' ';
        sms[33] = '!';
        sms[34] = '"';
        sms[35] = '#';
        sms[36] = '¤';
        sms[37] = '%';
        sms[38] = '&';
        sms[39] = '\'';
        sms[40] = '(';
        sms[41] = ')';
        sms[42] = '*';
        sms[43] = '+';
        sms[44] = ',';
        sms[45] = '-';
        sms[46] = '.';
        sms[47] = '/';
        sms[48] = '0';
        sms[49] = '1';
        sms[50] = '2';
        sms[51] = '3';
        sms[52] = '4';
        sms[53] = '5';
        sms[54] = '6';
        sms[55] = '7';
        sms[56] = '8';
        sms[57] = '9';
        sms[58] = ':';
        sms[59] = ';';
        sms[60] = '<';
        sms[61] = '=';
        sms[62] = '>';
        sms[63] = '?';
        sms[64] = '¡';
        sms[65] = 'A';
        sms[66] = 'B';
        sms[67] = 'C';
        sms[68] = 'D';
        sms[69] = 'E';
        sms[70] = 'F';
        sms[71] = 'G';
        sms[72] = 'H';
        sms[73] = 'I';
        sms[74] = 'J';
        sms[75] = 'K';
        sms[76] = 'L';
        sms[77] = 'M';
        sms[78] = 'N';
        sms[79] = 'O';
        sms[80] = 'P';
        sms[81] = 'Q';
        sms[82] = 'R';
        sms[83] = 'S';
        sms[84] = 'T';
        sms[85] = 'U';
        sms[86] = 'V';
        sms[87] = 'W';
        sms[88] = 'X';
        sms[89] = 'Y';
        sms[90] = 'Z';
        sms[91] = 'Ä';
        sms[92] = 'Ö';
        sms[93] = 'Ñ';
        sms[94] = 'Ü';
        sms[95] = '§';
        sms[96] = '¿';
        sms[97] = 'a';
        sms[98] = 'b';
        sms[99] = 'c';
        sms[100] = 'd';
        sms[101] = 'e';
        sms[102] = 'f';
        sms[103] = 'g';
        sms[104] = 'h';
        sms[105] = 'i';
        sms[106] = 'j';
        sms[107] = 'k';
        sms[108] = 'l';
        sms[109] = 'm';
        sms[110] = 'n';
        sms[111] = 'o';
        sms[112] = 'p';
        sms[113] = 'q';
        sms[114] = 'r';
        sms[115] = 's';
        sms[116] = 't';
        sms[117] = 'u';
        sms[118] = 'v';
        sms[119] = 'w';
        sms[120] = 'x';
        sms[121] = 'y';
        sms[122] = 'z';
        sms[123] = 'ä';
        sms[124] = 'ö';
        sms[125] = 'ñ';
        sms[126] = 'ü';
        sms[127] = 'à';
        double lat = 43.26432; //64 bit
        String stringa;
        String compressa = "";
        
        System.out.println("Messaggio originale :"+ lat);

        //convert il double in una stringa con la conversione binaria del dato
        stringa = Long.toBinaryString(Double.doubleToRawLongBits(lat));
        System.out.println(stringa);
        
        //divide il dato in pezzi da 7 bit
        //per mandare il dato via SMS con la tabella caratteri SMS
        String b1 = stringa.substring(0, 7);
        String b2 = stringa.substring(7, 14);
        String b3 = stringa.substring(14, 21);
        String b4 = stringa.substring(21, 28);
        String b5 = stringa.substring(28, 35);
        //String b6 = stringa.substring(35, 42);
        //String b7 = stringa.substring(42, 49);
        //String b8 = stringa.substring(49, 56);
      
        //convert il valore binario a base 7 in intero
        int d1 = Integer.parseInt(b1, 2);
        int d2 = Integer.parseInt(b2, 2);
        int d3 = Integer.parseInt(b3, 2);
        int d4 = Integer.parseInt(b4, 2);
        int d5 = Integer.parseInt(b5, 2);
        //int d6 = Integer.parseInt(b6, 2);
        //int d7 = Integer.parseInt(b7, 2);
        //int d8 = Integer.parseInt(b8, 2);
        
        //usando la tabella di compressione prende i primi 5 gruppi di 7 bit
        //e li codifica come SMS
        //compressa = compressa + sms[d1]+sms[d2]+sms[d3]+sms[d4]+sms[d5]+sms[d6]+sms[d7]+sms[d8];
        compressa = compressa + sms[d1]+sms[d2]+sms[d3]+sms[d4]+sms[d5];
        System.out.println("Messaggio compresso : "+compressa);
        
        for (int t=0; t<compressa.length();t++)
            {
            valore = converti_sms(compressa.charAt(t));
            String v = Integer.toBinaryString(valore);
           reverse = new StringBuffer(v).toString();
           //System.out.println(reverse);


        

            while ((reverse.length() %7) != 0)
                {
                reverse = "0"+reverse ;
                }
            passaggio = passaggio + reverse;
            //System.out.println("a "+reverse);

            }
        

        
        passaggio = passaggio + "0000000000000000000000000000";
        System.out.println(passaggio);

        
        double doubleVal = Double.longBitsToDouble(new BigInteger(passaggio, 2).longValue());
        System.out.println("Messaggio decompresso : "+doubleVal);
        
        
        
    }
    
}

Compressione SMS in Android

Per la solita applicazione su cui sto lavorando adesso, sarebbe utile effettuare la compressione dei dati di un SMS per trasportare la maggiore quantita' di informazioni. Ho fatto un paio di prove, la prima e' questa basata semplicemente sulla compressione dei caratteri

Fonte Wikipedia


I dati previsti sono numerici con alcuni segni di interpunzione per cui l'intero set di caratteri puo' essere descritto con un set di 16 caratteri (4 bit). I dati trasportati sono coordinate geografiche, informazioni sul tempo, dati di antenne e stato della batteria
Considerando che la tavola dei caratteri piu' semplice per gli SMS racchiude 7 bit c'e' un discreto guadagno (un fattore di 1.75)

Attualmente gli SMS permettono di inviare 1120 bit, ovvero 160 caratteri con la tabella a 7 bit e 140 con la tabella ad 8 bit.(le tabelle dei codici SMS non sono confrontabili con quelle ASCII)

Usando il codice riportato dopo il salto e' stata effettuata una prova codificando

---------------------------------------------
Messaggio : 12.3455;43.123123;22;-45;13:23:21 12/03/2013
Lungh. messaggio 44
Valore numerici convertiti a 7 bit 72 22 11 85 39 120 34 98 72 120 17 58 45 116 33 30 68 7 97 71 84 0 23 2 72 127 127 
Messaggio compresso a 7 Bit tabella GSM : HΠØU'x"bHx_:-t!ßDìaGT@Ψ$Hàà
Lungh.Mess.Compresso 27
Messaggio Decompresso :12.3455;43.123123;22;-45;13:23:21 12/03/2013   
---------------------------------------------

Come si osserva che il messaggio e' compresso con un fatto di circa 1.7 (il limite teorico di 1.75 non e' raggiunto per una serie di aggiustamenti nel passare da 4 a 7 bit)


Smartphone e privacy

Ieri ho trovato questo BlackBerry a terra per strada. E' il secondo cellulare che trovo, il primo lo trovai al cinema oltre 10 anni fa (considerando la diffusione dei cellulari direi che la mia media di ritrovamento e' piuttosto scarsa)


Il cellulare era acceso e sbloccato per cui nel giro di 5 minuti ho trovato nell'agenda un numero relativo ad un familiare del proprietario ed il telefono e' stato restituito
C'e' pero' da fare una considerazione: se fossi stato un male intenzionato mi sono trovato per le mani un oggetto con configurato un account Google (con sicuramente l'account di posta configurato viste le icone sulla home) ma anche un account Facebook (sempre viste le icone sulla home) e con un po' di fortuna avrei raccattato una quantita' di dati sensibili preoccupante (se l'utente usava anche GDrive ero a cavallo)
Dieci anni fa ritrovare un telefono voleva dire, se maleintenzionati, farsi qualche telefonata gratuita e magari tenersi il telefono, oggi il rischio della perdita di uno smartphone e' decisamente preoccupante.
Di fatto lo stesso motivo che mi ha permesso di riconsegnare in breve tempo il telefono (ovvero il fatto che non fosse protetto con un pin code o simili) potrebbe riverlarsi, nelle mani sbagliate, un grave rischio per il conto in banca del proprietario

lunedì 13 gennaio 2014

Batteria bruciata su JIAYU G3T

Il telefono in questione, uno JIAYU G3T (in breve le caratteristiche 4.5 pollici HD IPS Gorillla Quad Core 1.5Ghz MTK6589T Android 4.2 Dual SIM WIFI GPS 8MP) durante la carica ha segnalato, tramite sistema operativo, un surriscaldamento della batteria

Il possessore, un amico, ha spento il telefono (lasciandolo pero' in carica). Al mattino successivo la pessima sorpresa: batteria fusa, parte della scocca fusa ed ovviamente telefono che non parte
Piccola nota: acquistato da circa un mese




Mandelbrot su Arduino con TvOut

Un metodo veloce per visualizzare dati derivanti da una Arduino senza utilizzare display appositi ed impiegando solo due uscite digitali puo' essere quella di ricorrere alla libreria TvOut ed inviando il segnale all'uscita SVideo di un comune televisore


In questo modo, usando un semplice connettore S-Video ed un paio di resistenze, si puo' avere una visualizzazione senza troppi problemi
Lo schema delle resistenza e' il seguente


Alcuni riportano che' obbligatoria una resistenza da 75 Ohm anche sul GND. Per quanto mi riguarda il tutto ha funzionato anche senza (ho avuto difficolta' a trovare questo taglio di resistenza)
Importante: sul sito e' indicato che per la Arduino Uno i pin digitali da collegare sono D7 (Video), D9 (Sync) e GND ma nel mio caso hanno funzionato D8 (Video), D9 (Sync) e GND

La risoluzione di base e' sostanzialmente pessima, un misero 128x98, ma per un sistema cosi' semplice non e' male
Ovviamente non potevo esimermi dal provare a disegnare l'insieme di Mandelbrot




-----------------------------------------------------------------------------
#include <TVout.h>
TVout TV;


int SCREEN_WIDTH = 0;
int SCREEN_HEIGHT = 0;

float re_min = -2.0;
float im_min = -1.2;
float re_max = 1.0;
float im_max = 1.2;
int iterazioni = 60;
float a,b;
float x,y,x_new,y_new;
int test;
int k,j,i;


void setup(void) {
  TV.start_render(_PAL);
  TV.delay_frame(50);

  TV.clear_screen();
  SCREEN_WIDTH = TV.horz_res();
  SCREEN_HEIGHT = TV.vert_res();

  //---------------------------------
  float re_factor = (re_max-re_min);
  float im_factor = (im_max-im_min);
  for (i=0;i<SCREEN_HEIGHT;i++)
     {
     for (j=0;j<SCREEN_WIDTH;j++)
      {
      a = re_min+(j*re_factor/SCREEN_WIDTH); 
      b = im_min+(i*im_factor/SCREEN_HEIGHT);
      x = 0;
      y = 0;
      test = 0;
      for (k=0;k<iterazioni;k++)
       {
       x_new = (x*x)-(y*y)+a;
       y_new = (2*x*y)+b;
       if (((x_new*x_new)+(y_new*y_new))>4)
        {
        test = k;
        if (k%2)
          {
            TV.set_pixel(j,i,1); 
         }     
        break;
        }
       x = x_new;
       y = y_new;
       }
      }
     }
}

void loop(void) {
  while (1) {}
}