Ho provato a dare un'occhiata ai Container per un eventuale utilizzo parallelo a sostitutivo di alcune macchine virtuale. Quali sono le principali differenze:
Un container usa lo stesso kernel del SO principale cosi' come le librerie e la memoria e questo genera un risparmio sensibile di risorse delle macchina
In generale un Container utilizza un solo applicativo (Web Server, Sql Server) ed come regola generale i dati non sono contenuti nel container; da cio' deriva che non e' necessario delle immagini disco (con poi la necessita' di espanderle) e i Container hanno dimensioni di qualche decina di Mb e non delle centinaia di Mb come accade per le immagini
Un problema serio e' pero' il grado di isolamento. Se viene compromesso un servizio di una macchina virtuale la macchina host risulta salva. Vi sono invece notizie di compromissioni d container che permettono di attaccare il sistema operativo host
1) Don’t store data in containers 2) Don’t ship your application in two pieces 3) Don’t create large images 4) Don’t use a single layer image 5) Don’t create images from running containers (questo vuol dire di non usare i commit ma i dockerfile per creare un nuovo container) 6) Don’t use only the “latest” tag 7) Don’t run more than one process in a single container 8) Don’t store credentials in the image. Use environment variables 9) Don’t run processes as a root user 10) Don’t rely on IP addresses
per installare Docker su Centos 7 si inizia aggiungendo il repository
yum -y install docker-engine makecache fast
si avvia quindi il servizio
service docker start
una volta installata la engine si inizia ad installare i container.
In generale un container si puo' installare mediante il comando pull ma se si lancia il comando run ed il container non e' installato allora sara' automaticamente installato
Per vedere che tutto funzioni la base e' installare questi due container docker run hello-world docker run docker/whalesay cowsay boo
il secondo mostra semplicemente il logo di Docker
dei container gia' pronti con le applicazioni piu' comuni si possono scaricare da Docker Store
la lista dei container si ottiene mediante docker images
mentre il carico di lavoro mediante docker ps
per entrare in shell sulla container si usa docker run -i -t [nome_container] /bin/bash
i container si stoppano con
docker stop [nome_container]
per aggiornare un container, visto che i dati risiedono nel file system normale dell'host, e' sufficiente stoppare il container, distruggerlo ed effettuare il pull della nuova immagine
Due esempi di comandi per lanciare dei servizi container Apache (container httpd:alpine docker pull httpd:alpine) docker run -d -p 8080:80 --name apache -v /home/linnocenti/docker/:/usr/local/apache2/htdocs/ httpd:alpine
La prima cosa da notare e' il forwarding della porta 80 del container verso la porta 8080 dell'host (per questo il container e' raggiungibile su http://localhost:8080)
La seconda e' che i file html statici sono depositati nel filesystem dell'host (/home/linnocenti/docker)
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
Nel caso in cui si dovesse fare una installazione LAMP il container Httpd deve riuscire ad interagire con Mysql..questo e' effettuato mediante lo switch link
docker run --name lamp --link some-mysql -d httpd:alpine
Per registrare i dati raw dal microfono di Android e' necessario utilizzare AudioRecord (non MediaRecord)
quello che viene riportato in calce e' il codice per utilizzare questa libreria (e' un copia/incolla da piu' fonti...di mio non c'e' praticamente niente se non il fatto di avere messo insieme i pezzi per farlo funzionare da Android 6 in poi)
Un paio di trucchi: non e' sufficiente aggiungere i permessi di accedere al microfono (RECORD AUDIO) dentro al file Manifest ma devono essere anche esplicitamente i permessi a livello di codice (la funzione requestRecordAudioPermission)
i dati vengono inseriti in un buffer per poi essere post processati e sono in formato di short signed (32768/-32767)
------------------------------
public class MainActivity extends AppCompatActivity {
private Button play;
final int SAMPLE_RATE = 8000;
boolean mShouldContinue;
String LOG_TAG = "Audio";
private Button stop;
@Overrideprotected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
requestRecordAudioPermission();
play = (Button) findViewById(R.id.button);
stop = (Button) findViewById(R.id.button2);
play.setOnClickListener(new View.OnClickListener() {
@Overridepublic void onClick(View view) {
mShouldContinue = true;
recordAudio();
}
});
stop.setOnClickListener(new View.OnClickListener() {
@Overridepublic void onClick(View view) {
mShouldContinue = false;
}
});
}
private void requestRecordAudioPermission() {
//check API version, do nothing if API version < 23!int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion > android.os.Build.VERSION_CODES.LOLLIPOP){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.RECORD_AUDIO)) {
// Show an expanation to the user *asynchronously* -- don't block // this thread waiting for the user's response! After the user // sees the explanation, try again to request the permission.} else {
// No explanation needed, we can request the permission.ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, 1);
}
}
}
}
@Overridepublic void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case 1: {
// If request is cancelled, the result arrays are empty.if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the // contacts-related task you need to do.Log.d("Activity", "Granted!");
} else {
// permission denied, boo! Disable the // functionality that depends on this permission.Log.d("Activity", "Denied!");
finish();
}
return;
}
// other 'case' lines to check for other // permissions this app might request}
}
synchronized void recordAudio() {
new Thread(new Runnable() {
@Overridepublic void run() {
Log.d(LOG_TAG, "Start ");
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO);
// buffer size in bytesint bufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
Log.d(LOG_TAG, "Buffer Size " + Integer.toString(bufferSize));
if (bufferSize == AudioRecord.ERROR || bufferSize == AudioRecord.ERROR_BAD_VALUE) {
bufferSize = SAMPLE_RATE * 2;
}
short[] audioBuffer = new short[bufferSize / 2];
AudioRecord record = new AudioRecord(MediaRecorder.AudioSource.MIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize);
if (record.getState() != AudioRecord.STATE_INITIALIZED) {
Log.e(LOG_TAG, "Audio Record can't initialize!");
return;
}
record.startRecording();
Log.v(LOG_TAG, "Start recording");
long shortsRead = 0;
while (mShouldContinue) {
int numberOfShort = record.read(audioBuffer, 0, audioBuffer.length);
shortsRead += numberOfShort;
for(int i = 0; i < numberOfShort; i++){
Log.d(LOG_TAG,String.valueOf(audioBuffer[i]));}
}
record.stop();
record.release();
Log.v(LOG_TAG, String.format("Recording stopped. Samples read: %d", shortsRead));
}
}).start();
}
}
Nonostante non sia ancora in vendita in Italia (piu' che altro perche' manca localizzazione in italiano...su Amazon Italia si puo' comprare ma e' un po' inutile se non si e' madrelingua inglesi) ho provato ad usare l'emulatore di Google Home perche' e' possibile creare i propri comandi vocale e le proprie azioni mediante Api.ai
L'idea e' quella, un po' banale, di fare un gioco carta/sasso/forbice, usando i tre comandi vocali ed ottenendo dal sistema una risposta ovvero la contromossa vincente
Ovviamente per come e' congegnato il sistema vince sempre..
Google ha lanciato, a modo suo, la data del nuovo Google IO...per sapere il posto ed il luogo e' necessario risolvere 5 puzzle.
Premetto che non intendo spoilerare i risultati (anche se le soluzioni sono gia' disponibili su Internet su Reddit) ..questo e' solo un racconto dei miei due successi e degli insuccessi
Si parte da questo link http://goo.gl/oqro8L. (attenzione a disattivare uBlock e simili)
Da notare che la soluzione per ogni quiz e' una coppia di coordinate geografiche
basta leggere il codice Javascript per ottenere la prima coordinata
Data la prima soluzione viene fornito il primo indizio e si ha il link per il secondo quesito
Il secondo passo e' un video di Youtube pubblico ma non negli elenchi. L'immagine e' fissa senza audio
Il titolo del video e' See What Cannot Be Heard
attivando i sottotitoli si ottiene la sequenza
Magic I.see_a beach,-yes._i explore daylight
Non sono riuscito a risolverlo..certo che sapere che la soluzione doveva essere una coordinata mi ha dato la certezza che la virgola non era messa li' a caso
Ecco il secondo indizio
Il terzo quiz e' decisamente piu' facile. Una radio ed un microscopio pulsante play (si tratta di una slide di una presentazione)
salta subito all'occhio lo 032 centrale e sapendo che si tratta del codice di una coordinata si desume che 032 indichi la virgola separatrice. Basta un confronto col codice ASCII della virgola (32) per capire che la coordinata e' una semplice codifica ascii dei numeri
Il
ed arriviamo ai due quiz per me impossibili
il quarto puzzle rimanda ad una cartella GDrive con alcune immagini
da notare anche il proprietario delle immaigni ovvero Pei Xiu , cartografo cinese
queste sono le immagin
caves.jpg
pillar.jpg
shrine.jpg
spire.jpg
ho provato a vedere se per caso negli Exif ci fosse il geotag con le coordinate. Niente da fare.
Ho provato a cercare le immagini con TinEye ma niente da fare
con Google Image (anche con l'immagine corrotta) si arriva a capire che le immagini sono relative al tempio di Gunung Kawi
pensavo di avere vinto una volta trovate le coordinate del tempio
ma e' tutto sbagliato....non si sono andato nemmeno vicino
con l'aiuto della rete comunque questo e' il quarto indizio
ed arriviamo al quinto quiz..inutile dire che su questo non sono riuscito nemmeno a partire
e questa e' la soluzione finale
2 su 5 e' sempre meglio che 0 su 5 (impegnandomi avrei potuto fare 3 su 5 ma l'enplein era praticamente impossibile)
Un esempio su come visualizzare dati realtime dell'accelerometro su Android
E' stata impiegata la libreria GraphView (per aggiungere la libreria, invece di usare Gradle, ho scaricato il file .jar, ho creato una directory libs nel progetto con Project Clean finale)
Mi e' capitato di avere a che fare con un Pentium 166 con la batteria del BIOS esaurita
Facile...basta cambiarla con una nuova CR2032...peccato che non riuscivo a trovarla.
L'attenzione e' stata catturata da una componente a me sconosciuto ovvero ODIN OEC12C887A.
Da una ricerca su questo link e' emerso che Odin e' un RTC (Real Time Clock) con all'interno la batteria tampone. I componenti sono ancora in commercio ma il fatto di essere saldato sulla mother board e' una difficolta' di non poco conto.
Sul medesimo sito sono riportate tecniche, piuttosto intrusive, per far rivivere l'RTC del computer ma vista la scarsa possibilita' di successo forse e' meglio lasciare tutto com'e' ed aggiornare i parametri ad ogni accensione
Le Message API permettono di scambiare messaggi tra dispositivi Android, nel caso specifico tra il telefono e l'orologio mediante Android Wear
Nell'esempio in esame vengono sincronizzati due NumberPicker