Giusto ieri stavo giocando con l'autenticazione Web di Firebase.
Si tratta di un sistema piuttosto semplice. Prima si copia il codice Javascript con i codici di accesso e li si inserisce nella pagina HTML di login
Per prima cosa ho modificato la pagina di tutorial eliminando la possibilita' di registrarsi con la mail. L'idea e' che l'amministratore inserisce a mano gli utenti che possono loggarsi eliminando gli accessi anonimi
Questa e' la pagina di login ed il relativo codice (in giallo nel codice i comandi per l'autenticazione con Firebase)
email3.html
-------------------
<!DOCTYPE html>
<!--
Copyright (c) 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email/Password Authentication Example</title>
<!-- Material Design Theming -->
<link rel="stylesheet" href="https://code.getmdl.io/1.1.3/material.orange-indigo.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<script defer src="https://code.getmdl.io/1.1.3/material.min.js"></script>
<link rel="stylesheet" href="main.css">
<!-- Firebase -->
<script src="https://www.gstatic.com/firebasejs/3.6.4/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "AIzaSyAchx8oVeLUgYnGujAXXXXXXXXXXXXXXX",
authDomain: "notifXXXXXXXXX.firebaseapp.com",
databaseURL: "https://notiXXXXXXXX.firebaseio.com",
storageBucket: "notifXXXXXXX.appspot.com",
messagingSenderId: "392XXXXXXXX"
};
firebase.initializeApp(config);
</script>
<script type="text/javascript">
/**
* Handles the sign in button press.
*/
function toggleSignIn() {
if (firebase.auth().currentUser) {
// [START signout]
firebase.auth().signOut();
// [END signout]
} else {
var email = document.getElementById('email').value;
var password = document.getElementById('password').value;
// Sign in with email and pass.
// [START authwithemail]
firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode === 'auth/wrong-password') {
alert('Wrong password.');
} else {
alert(errorMessage);
}
console.log(error);
});
}
}
function initApp() {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
window.location.href = "email3.html";
}
});
document.getElementById('quickstart-sign-in').addEventListener('click', toggleSignIn, false);
}
window.onload = function() {
initApp();
};
</script>
</head>
<body>
<div class="demo-layout mdl-layout mdl-js-layout mdl-layout--fixed-header">
<!-- Header section containing title -->
<header class="mdl-layout__header mdl-color-text--white mdl-color--light-blue-700">
</header>
<main class="mdl-layout__content mdl-color--grey-100">
<div class="mdl-cell mdl-cell--12-col mdl-cell--12-col-tablet mdl-grid">
<!-- Container for the demo -->
<div class="mdl-card mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-cell--12-col-tablet mdl-cell--12-col-desktop">
<div class="mdl-card__title mdl-color--light-blue-600 mdl-color-text--white">
<h2 class="mdl-card__title-text">Firebase Email & Password Authentication</h2>
</div>
<div class="mdl-card__supporting-text mdl-color-text--grey-600">
<p>Enter an email and password below and either sign in to an existing account or sign up</p>
<input class="mdl-textfield__input" style="display:inline;width:auto;" type="text" id="email" name="email" placeholder="Email"/>
<input class="mdl-textfield__input" style="display:inline;width:auto;" type="password" id="password" name="password" placeholder="Password"/>
<br/><br/>
<button class="mdl-button mdl-js-button mdl-button--raised" id="quickstart-sign-in" name="signin">Sign In</button>
</div>
</div>
</div>
</main>
</div>
</body>
</html>
-------------------
Se l'autenticazione e' corretta allora passa automaticamente alla pagina 2. Se si accede direttamente alla pagina 2 senza autenticazione questa rimanda indietro alla pagina di login.
email3.html
------------------
<!DOCTYPE html>
<!--
Copyright (c) 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email/Password Authentication Example</title>
<!-- Material Design Theming -->
<link rel="stylesheet" href="https://code.getmdl.io/1.1.3/material.orange-indigo.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
<script defer src="https://code.getmdl.io/1.1.3/material.min.js"></script>
<link rel="stylesheet" href="main.css">
<!-- Firebase -->
<script src="https://www.gstatic.com/firebasejs/3.6.4/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "AIzaSyAchx8oVeLUgYnGujAEfXXXXXXXXXXXXX",
authDomain: "XXXXXXXXX.firebaseapp.com",
databaseURL: "https://XXXXXXXX5.firebaseio.com",
storageBucket: "XXXXXXXXX.appspot.com",
messagingSenderId: "39272XXXXXXXX"
};
firebase.initializeApp(config);
</script>
<script type="text/javascript">
/**
* Handles the sign in button press.
*/
function toggleSignIn() {
if (firebase.auth().currentUser) {
// [START signout]
firebase.auth().signOut();
window.location.href = "email2.html";
// [END signout]
} else {
var email = document.getElementById('email').value;
// Sign in with email and pass.
// [START authwithemail]
firebase.auth().signInWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// [START_EXCLUDE]
if (errorCode === 'auth/wrong-password') {
alert('Wrong password.');
} else {
alert(errorMessage);
}
console.log(error);
document.getElementById('quickstart-sign-in').disabled = false;
// [END_EXCLUDE]
});
// [END authwithemail]
}
document.getElementById('quickstart-sign-in').disabled = true;
}
/**
* initApp handles setting up UI event listeners and registering Firebase auth listeners:
* - firebase.auth().onAuthStateChanged: This listener is called when the user is signed in or
* out, and that is where we update the UI.
*/
function initApp() {
// Listening for auth state changes.
// [START authstatelistener]
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var displayName = user.displayName;
var email = user.email;
var emailVerified = user.emailVerified;
var photoURL = user.photoURL;
var isAnonymous = user.isAnonymous;
var uid = user.uid;
var providerData = user.providerData;
// [START_EXCLUDE silent]
document.getElementById('quickstart-sign-in-status').textContent = 'Signed in';
document.getElementById('quickstart-sign-in').textContent = 'Sign out';
document.getElementById('quickstart-account-details').textContent = JSON.stringify(user, null, ' ');
// [END_EXCLUDE]
} else {
window.location.href = "email2.html";
}
});
// [END authstatelistener]
document.getElementById('quickstart-sign-in').addEventListener('click', toggleSignIn, false);
}
window.onload = function() {
initApp();
};
</script>
</head>
<body>
<div class="demo-layout mdl-layout mdl-js-layout mdl-layout--fixed-header">
<!-- Header section containing title -->
<header class="mdl-layout__header mdl-color-text--white mdl-color--light-blue-700">
<div class="mdl-cell mdl-cell--12-col mdl-cell--12-col-tablet mdl-grid">
<div class="mdl-layout__header-row mdl-cell mdl-cell--12-col mdl-cell--12-col-tablet mdl-cell--8-col-desktop">
<a href="/"><h3>Firebase Authentication</h3></a>
</div>
</div>
</header>
<main class="mdl-layout__content mdl-color--grey-100">
<div class="mdl-cell mdl-cell--12-col mdl-cell--12-col-tablet mdl-grid">
<!-- Container for the demo -->
<div class="mdl-card mdl-shadow--2dp mdl-cell mdl-cell--12-col mdl-cell--12-col-tablet mdl-cell--12-col-desktop">
<div class="mdl-card__title mdl-color--light-blue-600 mdl-color-text--white">
<h2 class="mdl-card__title-text">Firebase Email & Password Authentication</h2>
</div>
<div class="mdl-card__supporting-text mdl-color-text--grey-600">
<button class="mdl-button mdl-js-button mdl-button--raised" id="quickstart-sign-in" name="signin">Sign In</button>
<!-- Container where we'll display the user details -->
<div class="quickstart-user-details-container">
Firebase sign-in status: <span id="quickstart-sign-in-status">Unknown</span>
<div>Firebase auth <code>currentUser</code> object value:</div>
<pre><code id="quickstart-account-details">null</code></pre>
</div>
</div>
</div>
</div>
</main>
</div>
</body>
</html>
------------------
Stamani riprendendo in mano la cosa mi sono accorto di un nuovo utente che si era registrato (vedi l'ultima riga della tabella sottostante) senza nessun intervento. Visto che i codici di autenticazione sono inclusi in Javascript e non sono mascherabili e' abbastanza semplice fare un codice HTML che crei un login anonimo via email
a quanto pare non e' possibile limitare questo comportamento. L'unica possibilita' di filtro e' a livello di permessi di accesso alla base dati
martedì 20 dicembre 2016
venerdì 16 dicembre 2016
Ricarica solare per Particle Electron
La Particle Electron si puo' ricaricare con pannello solare tramite il pin VIN (con una tensione massima di 12 V) oppure dal connettore USB. Per quanto indicato dal sito il pannello solare deve erogare almeno 10 W altrimenti e' sempre necessario l'utilizzo di una LiPo (quindi per ricaricare la LiPo e' necessaria una potenza superiore ai 10 W)
Usando un pannello solare da 7W della Levin ed un ciclo di deep-sleep ed attivita' di circa 9 ad 1 e' stato verificata una ricarica di circa il 5% della batteria da 2000 mAh in circa un'ora di insolazione (la prova e' stata quindi sospesa per l'arrivo di copertura nuvolosa)
Usando un pannello solare da 7W della Levin ed un ciclo di deep-sleep ed attivita' di circa 9 ad 1 e' stato verificata una ricarica di circa il 5% della batteria da 2000 mAh in circa un'ora di insolazione (la prova e' stata quindi sospesa per l'arrivo di copertura nuvolosa)
giovedì 15 dicembre 2016
Debian su Compaq R4006EA
Un amico mi ha chiesto di rimettere in vista un vetusto Compaq R4006EA (anno 2005)
Non mi era mai capitato di averne uno per le mani e la prima cosa che salta all'occhio e' la robustezza ed il peso...infatti non era venduto come un portatile ma come un desktop replacement.
Si tratta di una macchina con processore Sempron 3000+ con la batteria e' ancora funzionante (seppure con un tempo di carica molto ridotto..circa 20 minuti) ed il piu' fuori standard tra tutti i connettori di alimentazione che abbia visto
Il disco da 40 Gb e'
Vista l'eta ho montato una Debian LXDE che con i 384 Mb installati (256+128 in parte utilizzati dalla memoria video) che funziona decisamente bene. In fase di boot viene segnalata solo l'impossibilita' a a caricare il firmware r300_cp.bin per cui viene disabilitata l'accelerazione della GPU...si tratta di un problema della scheda ATI Radeon R300 e che e' discusso in questo post Francamente non ho tanta voglia di perdere tempo con una macchina cosi' vecchia ed in ogni caso il sistema funziona
Non mi era mai capitato di averne uno per le mani e la prima cosa che salta all'occhio e' la robustezza ed il peso...infatti non era venduto come un portatile ma come un desktop replacement.
Si tratta di una macchina con processore Sempron 3000+ con la batteria e' ancora funzionante (seppure con un tempo di carica molto ridotto..circa 20 minuti) ed il piu' fuori standard tra tutti i connettori di alimentazione che abbia visto
Il disco da 40 Gb e'
Vista l'eta ho montato una Debian LXDE che con i 384 Mb installati (256+128 in parte utilizzati dalla memoria video) che funziona decisamente bene. In fase di boot viene segnalata solo l'impossibilita' a a caricare il firmware r300_cp.bin per cui viene disabilitata l'accelerazione della GPU...si tratta di un problema della scheda ATI Radeon R300 e che e' discusso in questo post Francamente non ho tanta voglia di perdere tempo con una macchina cosi' vecchia ed in ogni caso il sistema funziona
ThingSpeak con Particle Electron
Per pubblicare i dati di Particle Electron puo' essere utile il servizio Thingspeak
E' possibile registrarsi con un profilo gratuito per le prove.
Per prima cosa si deve registrare il proprio canale a cui sara' associata una API Key per la scrittura dei dati
in seguito si devono impostare le variabili da visualizzare nei grafici
per utilizzare ThingSpeak nel firmware si deve modificare il programma (vedi righe evidenziate in giallo) importando la libreria, impostando poi il proprio numero di canale e la WriteAPIKey, inizializzare il client e poi pubblicare i valori (le variabili non hanno un nome ma sono indicate con un numero progressivo nello stesso ordine con cui sono state configurate nella schermata web)
------------------------------------
#include "cellular_hal.h"
#include "ThingSpeak/ThingSpeak.h"
STARTUP(cellular_credentials_set("ibox.tim.it", "", "", NULL));
int status;
int counter = 0;
double batteria = 0.0;
int sleepInterval = 10; //Specify minutes between each reading sent
int analogPin0 = A0;
double mm = 0.0;
/* Thingspeak */
TCPClient client;
unsigned long myChannelNumber = 203125;
const char * myWriteAPIKey = "4MHFO3D4XXXXXXXX";
void fuel()
{
FuelGauge fuel;
batteria = static_cast<double>(fuel.getSoC());
mm = analogRead(analogPin0);
}
void connect_status()
{
RGB.control(false);
Cellular.on();
Cellular.connect();
delay(10000);
Particle.connect();
//waitUntil(Particle.connected);
delay(20000);
Particle.connect();
while(status < 3)//send one reading
{
if(Cellular.ready() && Particle.connected() == true)
{
delay(10000);
fuel();
ThingSpeak.setField(1, (float)batteria);
ThingSpeak.setField(2, (float)mm);
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
if(Particle.publish("batteria", "batteria") == true)
{
delay(10000);
status++;
}
else if(Particle.publish("batteria", "batteria") == false)
{
Cellular.on();
Cellular.connect();
delay(20000);
Particle.connect();
status=status -1;
delay(20000);
}
}
else
{
Cellular.on();
Cellular.connect();
delay(10000);
Particle.connect();
status=0;
delay(10000);
}
}
}
void setup() {
Time.zone(+1);
RGB.control(false);
Particle.variable("batteria", &batteria, DOUBLE);
ThingSpeak.begin(client);
}
void loop() {
RGB.control(false);
if(counter == 0)
{
delay(5000);
fuel();
Particle.publish("batteria", "batteria");
delay(5000);
counter =1;
}
System.sleep(D0, RISING, sleepInterval * 60); //Puts device in stop mode
delay(1500);
status=0;
connect_status();
}
E' possibile registrarsi con un profilo gratuito per le prove.
Esempio di pubblicazione dati ThingSpeak |
Per prima cosa si deve registrare il proprio canale a cui sara' associata una API Key per la scrittura dei dati
in seguito si devono impostare le variabili da visualizzare nei grafici
per utilizzare ThingSpeak nel firmware si deve modificare il programma (vedi righe evidenziate in giallo) importando la libreria, impostando poi il proprio numero di canale e la WriteAPIKey, inizializzare il client e poi pubblicare i valori (le variabili non hanno un nome ma sono indicate con un numero progressivo nello stesso ordine con cui sono state configurate nella schermata web)
------------------------------------
#include "cellular_hal.h"
#include "ThingSpeak/ThingSpeak.h"
STARTUP(cellular_credentials_set("ibox.tim.it", "", "", NULL));
int status;
int counter = 0;
double batteria = 0.0;
int sleepInterval = 10; //Specify minutes between each reading sent
int analogPin0 = A0;
double mm = 0.0;
/* Thingspeak */
TCPClient client;
unsigned long myChannelNumber = 203125;
const char * myWriteAPIKey = "4MHFO3D4XXXXXXXX";
void fuel()
{
FuelGauge fuel;
batteria = static_cast<double>(fuel.getSoC());
mm = analogRead(analogPin0);
}
void connect_status()
{
RGB.control(false);
Cellular.on();
Cellular.connect();
delay(10000);
Particle.connect();
//waitUntil(Particle.connected);
delay(20000);
Particle.connect();
while(status < 3)//send one reading
{
if(Cellular.ready() && Particle.connected() == true)
{
delay(10000);
fuel();
ThingSpeak.setField(1, (float)batteria);
ThingSpeak.setField(2, (float)mm);
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
if(Particle.publish("batteria", "batteria") == true)
{
delay(10000);
status++;
}
else if(Particle.publish("batteria", "batteria") == false)
{
Cellular.on();
Cellular.connect();
delay(20000);
Particle.connect();
status=status -1;
delay(20000);
}
}
else
{
Cellular.on();
Cellular.connect();
delay(10000);
Particle.connect();
status=0;
delay(10000);
}
}
}
void setup() {
Time.zone(+1);
RGB.control(false);
Particle.variable("batteria", &batteria, DOUBLE);
ThingSpeak.begin(client);
}
void loop() {
RGB.control(false);
if(counter == 0)
{
delay(5000);
fuel();
Particle.publish("batteria", "batteria");
delay(5000);
counter =1;
}
System.sleep(D0, RISING, sleepInterval * 60); //Puts device in stop mode
delay(1500);
status=0;
connect_status();
}
mercoledì 14 dicembre 2016
Particle Electron Sleep Mode
Dopo il precedente post ho provato ad utilizzare le funzioni di risparmio energietico di Particle Electron in modo da massimizzare il tempo di durata della batteria
Nel precedente tentativo la batteria (da 2000 mAh) si esauriva dopo circa 24 ore
Usando la modalita' di sleep e spengendo l'apparato di trasmissione cellulare pur inviando un dato ogni 10 minuti (vedi grafico sottostante) l'autonomia e' passata ad oltre 4 giorni (piu' precisamente 4.3)
utilizzando un risparmio piu' aggressivo (tipo un dato ogni ora) si puo' tranquillamente superare una settimana di autonomia in sola alimentazione da batteria per arrivare a quasi un mese utilizzando batterie piu' capienti.
---------------------------------------
#include "cellular_hal.h"
STARTUP(cellular_credentials_set("ibox.tim.it", "", "", NULL));
int status;
int counter = 0;
double batteria = 0.0;
int sleepInterval = 10; //Specify minutes between each reading sent
void fuel()
{
FuelGauge fuel;
batteria = static_cast<double>(fuel.getSoC());
}
void connect_status()
{
RGB.control(false);
Cellular.on();
Cellular.connect();
delay(10000);
Particle.connect();
//waitUntil(Particle.connected);
delay(20000);
Particle.connect();
while(status < 3)//send one reading
{
if(Cellular.ready() && Particle.connected() == true)
{
delay(10000);
fuel();
if(Particle.publish("batteria", "batteria") == true)
{
delay(10000);
status++;
}
else if(Particle.publish("batteria", "batteria") == false)
{
Cellular.on();
Cellular.connect();
delay(20000);
Particle.connect();
status=status -1;
delay(20000);
}
}
else
{
Cellular.on();
Cellular.connect();
delay(10000);
Particle.connect();
status=0;
delay(10000);
}
}
}
void setup() {
Time.zone(+1);
RGB.control(false);
Particle.variable("batteria", &batteria, DOUBLE);
}
void loop() {
RGB.control(false);
if(counter == 0)
{
delay(5000);
fuel();
Particle.publish("batteria", "batteria");
delay(5000);
counter =1;
}
System.sleep(D0, RISING, sleepInterval * 60); //Puts device in stop mode
delay(1500);
status=0;
connect_status();
}
---------------------------------------
lunedì 12 dicembre 2016
Backup/Restore profili su Thunderbird e Firefox
Trasportare i propri file da un computer ad un altro per le applicazioni ThunderBird (posta elettronica) e Firefox (Web Browser) e' quanto mai semplice
Per prima cosa sul computer di origine si deve individuare dove salvati i file (per esempio le mailbox) e le impostazioni relative al proprio profilo. Su Windows XP la directory e' dentro la propria home\Dati applicazioni\Thunderbird\Profiles ed ha una forma del tipo nomecasuale.default (o nome profilo)
Si copia quindi la directory su un disco e ci si sposta nella nuova macchina su cui effettuare il restore
Sulla macchina di destinazione si copiano i file e poi si avvia il programma con lo switch -p (esempio nell'immagine sottostante)
Cosi' facendo si apre il gestore dei profili. Si aggiunge un nuovo profilo e si indica dove e' stata copiata la directory con il backup. Finito
Estensimetro Gefran su Arduino
Ho avuto modo di provare un estensimetro Gefran ZP-34-A-050 in accoppiamento con una Arduino
Di fatto il sensore non e' altro che un potenziometro con una resistenza di ottima qualita' che offre una buona linearita' su tutto l'arco di lavoro
La resistenza e' da 2 KOhm con una corsa utile (nel modello esaminato) di 50 mm. Con il comodo adesivo riportato sullo chassis si vede chiaramente che i cavi blu e marrone possono essere attaccati a 5V e GND dell'Arduino mentre il cavo giallo relativo al segnale puo' essere collegato ad una entrata digitale (tipo A0)
Visto che l'Arduino ha 1024 livelli nell'ADC si che la minima variazione misurabile e' 50mm/1023 e' circa 0.05 mm (5 centesimi di millimetro). In realta', viste le fluttazioni e' piu' ragionevole dire che si riescono a misurare variazioni dell'ordine del decimo di millimetro (che non e' niente male)
Di fatto il sensore non e' altro che un potenziometro con una resistenza di ottima qualita' che offre una buona linearita' su tutto l'arco di lavoro
La resistenza e' da 2 KOhm con una corsa utile (nel modello esaminato) di 50 mm. Con il comodo adesivo riportato sullo chassis si vede chiaramente che i cavi blu e marrone possono essere attaccati a 5V e GND dell'Arduino mentre il cavo giallo relativo al segnale puo' essere collegato ad una entrata digitale (tipo A0)
Visto che l'Arduino ha 1024 livelli nell'ADC si che la minima variazione misurabile e' 50mm/1023 e' circa 0.05 mm (5 centesimi di millimetro). In realta', viste le fluttazioni e' piu' ragionevole dire che si riescono a misurare variazioni dell'ordine del decimo di millimetro (che non e' niente male)
Iscriviti a:
Post (Atom)
Debugger integrato ESP32S3
Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede nell'ID USB della porta Jtag. Nel modulo...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...