Accedi al database dal linguaggio di programmazione PHP
In questo ultimo articolo della serie sul Utilizzo di un server web per archiviare dati da dispositivi connessi all'Internet delle cose, spiega come registrare in un database MySQL le informazioni che i nodi IoT inviano al server effettuando richieste HTTP POST. I lettori di questo articolo, dell'intero blog, potrebbero non avere particolare familiarità con la programmazione in formato Linguaggio PHP ma sicuramente sì con la programmazione di microcontrollori nelle lingue C o C++ quindi, salvo alcuni dettagli, come ad esempio far precedere le variabili dal segno del dollaro ($), potrete seguire gli esempi senza bisogno di ulteriori spiegazioni poiché sono stati realizzati seguendo uno stile di programmazione molto neutro, non specifico per PHP.
Memorizzare le informazioni nel database
Come spiegato nell'articolo sul Archiviazione dei dati IoT effettuando richieste HTTP POST a un server web, alla fine delle intestazioni, il corpo della richiesta POST contiene i dati che vengono inviati al server. Il modo più comune per inviare queste informazioni al server è in formato testo semplice perché è più semplice analizzarle anche "manualmente". Quando i dati inviati al server sono complessi, sicuramente sarà conveniente strutturarli utilizzando, ad esempio, il formato XML o JSON. Nell'uso consueto di un server web per gestire le informazioni provenienti da dispositivi connessi all'Internet of Things, non è comune aver bisogno di una struttura dati, quindi è normale inviarli in testo semplice nel formato variable=valor
.
Nella richiesta HTTP POST dell'esempio seguente, viene richiesta la risorsa (normalmente una pagina web) /iot/grabar_temperatura dal server polaridad.es e vengono inviate tre variabili: ne, tp e cr, che contengono rispettivamente i valori " 12", "10.26 » e «2.18» È inoltre importante ricordare che esiste una riga vuota per separare le intestazioni dai dati.
1
2
3
4
|
POST /iot/grabar_temperatura HTTP/1.1
Host: polaridad.es
ne=12&tp=10.26&cr=2.18
|
L'obiettivo finale del codice seguente PHP invierà al server del database MySQL l'ordine SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
INSERT
INTO `calefacciones`
(
numero_estancia,
temperatura,
corriente
)
VALUES
(
12,
10.26,
2.18
);
|
Con il quale verrà creato un nuovo record (INSERT
)
nel database del riscaldamento (INTO
)calefacciones
assegnazione ai campi (numero_estancia,temperatura,corriente)
i valori corrispondenti alla richiesta HTTP POST VALUES (12, 10.26, 2.18)
La connessione al database viene effettuata con la funzione mysqli_connect
secondo il formato: mysqli_connect($servidor,$usuario,$clave,$base_datos)
che restituisce un puntatore all'oggetto-connessione e che utilizza le variabili che definiscono l'accesso (come utente, password...) e che sono state precedentemente assegnate per futuri ipotetici usi nello script.
Per rilevare se la connessione è andata a buon fine, viene utilizzata la funzione mysqli_connect_errno()
che restituisce il numero dell'errore che può essersi verificato oppure zero (falso) se la connessione è stata stabilita correttamente. Per notificare gli errori, all'applicazione che effettua la richiesta HTTP viene risposto con un valore pari a zero, in questo caso il programma che viene eseguito nel µC del nodo IoT.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
$fin_linea=PHP_EOL;
$servidor=‘localhost’;
$usuario=‘pelaez’;
$clave=‘1234’;
$base_datos=‘base_datos_temperaturas’;
$conexion=mysqli_connect($servidor,$usuario,$clave,$base_datos);
if(mysqli_connect_errno())
{
echo 0; // Devolver el valor 0 para indicar que se ha producido un error
}
else
{
$numero_estancia=(int)$_POST[‘ne’];
$temperatura=(float)$_POST[‘tp’];
$corriente=(float)$_POST[‘cr’];
$consulta_sql =‘INSERT INTO calefacciones (numero_estancia,temperatura,corriente) ‘;
$consulta_sql.=‘VALUES (‘.$numero_estancia.‘,’.$temperatura.‘,’.$corriente.‘);’;
$resultado=mysqli_query($conexion,$consulta_sql);
if($resultado) // Si no se ha producido un error al realizar la consulta…
{
echo mysqli_insert_id($conexion); // Devolver el índice del nuevo registro (¡>0!)
}
else
{
echo 0; // Devolver el valor 0 para indicar que se ha producido un error
}
mysqli_close($conexion);
}
echo $fin_linea;
|
Prima di aggiungere al testo memorizzato in $consulta_sql
con cui è composto l'ordine SQL cioè viene inviato al server del database le informazioni arrivate nelle variabili di richiesta POST vengono preelaborate, come minimo, per evitare un attacco da parte SQL Injection. Nell'esempio precedente viene forzata la conversione nel tipo di dati corrispondente (int)
(intero) o (float)
(decimale in virgola mobile) che sarebbe sufficiente per eliminare l'eventuale codice dannoso aggiunto ai dati della richiesta server web.
Come si può vedere, nel Linguaggio PHP Il simbolo del punto (.) viene utilizzato per concatenare i testi che compongono l'ordine SQL oppure l'operatore punto e segno uguale (.=) per aggiungere testo a destra di quello che già memorizza una variabile e la virgoletta singola (') viene utilizzata anche per racchiudere costanti di testo, non solo caratteri. Sebbene in questo caso si possano utilizzare anche le virgolette doppie («), in Linguaggio PHP vengono utilizzati per elaborare il contenuto, ad esempio includendo variabili all'interno del testo nel formato $texto="Me llamo $nombre";
in alternativa al formato $texto='Me llamo '.$nombre;
permettendoti inoltre di includere virgolette di un tipo in un altro senza dover usare segni di escape ogni volta che si alternano doppi all'interno di singoli o singoli all'interno di doppi come nell'assegnazione $texto='esto no hay que "escaparlo" en PHP';
.
Per eseguire la query sul server MySQL viene utilizzata la funzione mysqli_query
con il formato mysqli_query($conexion,$consulta_sql)
che prende come parametri l'oggetto-connessione al database ed il testo con l'ordine SQL che è stato composto.
La funzione mysqli_query($conexion,$consulta_sql)
restituisce un oggetto-cursore che può essere utilizzato per attraversare eventualmente i dati restituiti o, come nell'esempio precedente, per ottenere informazioni sull'operazione, in particolare per conoscere l'indice assegnato al nuovo record che l'operazione ha creato nella tabella " riscaldatori" con la funzione mysqli_insert_id($conexion)
Il valore restituito da mysqli_query($conexion,$consulta_sql)
può restituire false in un'operazione booleana per determinare che si è verificato un errore. Nell'esempio precedente serve per restituire, come nel caso dell'errore di connessione, uno zero all'applicazione che effettua la richiesta POST. In questo modo il programma restituirà un numero maggiore di zero che rappresenta l'indice del nuovo record se l'operazione è corretta oppure uno zero se l'operazione produce un errore.
Per liberare le risorse assegnate alla connessione al database, questa viene "chiusa" utilizzando la funzione mysqli_close($conexion)
Leggere le informazioni dal database
Tranne che nelle architetture per calcolo della nebbia La maggior parte dei nodi IoT si limita a inviare le informazioni catturate dai propri sensori al server, cioè al server web Comunica con loro solo per archiviare le informazioni, quindi con l'esempio precedente buona parte dei casi che si presenteranno in questa applicazione sono già stati risolti. Il prossimo passo potrebbe essere quello di creare un sito web che mostri i dati monitorati dai dispositivi connessi all'Internet of Things, un lavoro di frontend che esula da quanto trattato in questa serie di tutorial.
Quello che può succedere è che un nodo IoT abbia una certa interattività e si comporti diversamente in base ad un dato storico oppure preveda la possibilità di alterare il suo comportamento in base ad una configurazione che gli arriva da un server o ancora il nodo è una schermata che mostra un grafico con i dati recentemente monitorati rispetto a quelli acquisiti in date precedenti. Per tutte queste situazioni è interessante anche poter leggere i dati dal server MySQL attraverso server web come illustrato nell'esempio seguente che simula di ottenere un elenco delle date degli stati di allarme determinati dagli istanti in cui la temperatura ha superato i 40°C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
$fin_linea=PHP_EOL; // Fin de línea. Usar <br> para HTML si se va a mostrar la salida en algún tipo de pantalla o consola no es necesario
$servidor=‘localhost’;
$usuario=‘pelaez’;
$clave=‘1234’;
$base_datos=‘base_datos_temperaturas’;
$conexion=mysqli_connect($servidor,$usuario,$clave,$base_datos);
if(mysqli_connect_errno())
{
echo ‘Error al conectar a la base de datos: ‘ . mysqli_connect_error();
}
else
{
$consulta_sql=‘SELECT ‘;
$consulta_sql.=‘estancia, temperatura, DAY(fecha), MONTH(fecha), YEAR(fecha), TIME(fecha) ‘;
$consulta_sql.=‘FROM valor_temperaturas ‘;
$consulta_sql.=‘WHERE temperatura>40.0 ‘;
$consulta_sql.=‘ORDER BY fecha DESC;’;
$resultado=mysqli_query($conexion,$consulta_sql); // El tercer parámetro de mysqli_query, no usado, es el modo MYSQLI_STORE_RESULT por defecto o MYSQLI_USE_RESULT para grandes cantidades de datos
if($resultado) // Si no se ha producido un error al realizar la consulta
{
$total_resultado=mysqli_num_rows($resultado);
if($total_resultado) // Si se ha encontrado algún resultado
{
echo ‘Se han encontrado ‘.$total_resultado.‘ estados de alarma:’.$fin_linea;
for($numero_resultado=0;$numero_resultado<$total_resultado) // Recorrer los resultados
{
mysqli_data_seek($resultado,$numero_resultado); // Mover el cursor al registro correspondiente (no tendría por qué ser consecutivo)
$registro=mysqli_fetch_row($resultado); // Almacenar en un vector los datos del registro
echo ‘El ‘.$registro[2]; // Tercer campo de la consulta (día)
echo ‘ del ‘.$registro[3]; // Cuarto campo de la consulta (mes)
echo ‘ de ‘.$registro[4]; // Quinto campo de la consulta (año)
echo ‘ a las ‘.$registro[5]; // Sexto campo de la consulta (hora)
echo ‘ en la estancia “‘.$registro[0].‘”‘; // Primer campo de la consulta (estancia)
echo ‘ la temperatura superó el máximo de 40°C (‘.$registro[1].‘)’; // Segundo campo de la consulta (temperatura)
echo $fin_linea;
}
}
else
{
echo ‘No se ha encontrado ningún estado de alarma’.$fin_linea;
}
mysqli_free_result($resultado);
}
mysqli_close($conexion);
}
|
Nell'esempio sopra, per interrogare il database viene utilizzato il comando SQL SELECT
secondo il formato base SELECT campos FROM tabla WHERE condición ORDER BY campo DESC
con l'unica particolarità di aggiungere le funzioni al campo data DAY
, MONTH
, YEAR
y TIME
in modo da ottenere separatamente il giorno, il numero del mese, l'anno e l'ora. La condizione imposta è che la temperatura sia maggiore di 40.0 e viene ordinata utilizzando il campo data dalla più alta (la più attuale) alla più bassa (la più vecchia) indicandolo con la clausola DESC
Per scorrere i valori restituiti dalla query da un ciclo for
con una dimensione nota viene utilizzata la funzione mysqli_num_rows($resultado)
che indica il numero di record trovati. Con la funzione mysqli_data_seek($resultado,$numero_resultado)
il cursore dei risultati può essere spostato in una posizione specifica espressa dal contatore del loop for
, $numero_resultado
, nell'esempio.
Per memorizzare in un vettore i campi del record puntati dal cursore del risultato si utilizza la funzione mysqli_fetch_row($resultado)
che è assegnato alla variabile $registro
che verrà successivamente utilizzato per formare una frase con i diversi valori, accedendovi tramite i loro indici.
Una volta attraversati tutti i valori, vengono rilasciate le risorse assegnate al risultato della query SQL con funzione mysqli_free_result($resultado)
Elaborare le informazioni dal database. Confronta i valori.
In alcune occasioni è conveniente che l'elaborazione delle informazioni sia centralizzata sul server anche se fosse possibile farlo nei nodi IoT in stile calcolo della nebbia. Nell'esempio seguente i motivi simulati per farlo sono la sicurezza; Il nodo ha informazioni sulla sua chiave (lock) e su una richiesta (key) ma non sa se è opportuno dare il via alla combinazione di entrambe, quindi deve consultare il server, che è quello che prende la decisione e informa il nodo rispondendo zero (per indicare un confronto fallito) o uno (per indicare che il confronto ha avuto successo) in base al risultato di una query sul database.
Con questa scusa puoi vedere un esempio in cui vengono ricevuti dati dal dispositivo connesso all'Internet of Things (un codice chiave e un codice di blocco), viene restituito un risultato (uno o zero a seconda che il risultato sia vero o falso) e viene effettuata una piccola elaborazione delle informazioni consistente nel confrontare i risultati ottenuti durante la consultazione del database con quelli inviati dal nodo IoT.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
$fin_linea=PHP_EOL;
$servidor=‘localhost’;
$usuario=‘pelaez’;
$clave=‘1234’;
$base_datos=‘base_datos_puertas’;
$conexion=mysqli_connect($servidor,$usuario,$clave,$base_datos);
if(mysqli_connect_errno())
{
echo 0; // Devolver el valor 0 para indicar que la comparación no es válida o que se ha producido un error (en este caso es un error)
}
else
{
$cerradura=hexdec($_POST[“c”]);
$llave=hexdec($_POST[“l”]);
$consulta_sql=‘SELECT llave FROM cerraduras WHERE cerradura=”.$cerradura.“;’;
$resultado=mysqli_query($conexion,$consulta_sql);
if($resultado) // Si no se ha producido un error al realizar la consulta
{
$total_resultado=mysqli_num_rows($resultado);
if($total_resultado) // Si se ha encontrado algún resultado
{
$numero_resultado=0;
$buscando_cerradura=TRUE;
while($buscando_cerradura&&$numero_resultado<$total_resultado)
{
mysqli_data_seek($resultado,$numero_resultado);
$registro=mysqli_fetch_row($resultado);
if($registro[0]==$llave)
{
$buscando_cerradura=FALSE;
}
else
{
$numero_resultado++;
}
}
// echo !$buscando_cerradura;
if($buscando_cerradura)
{
echo 0; // Devolver el valor 0 para indicar que la comparación no es válida (o que se ha producido un error; y aquuí no es el caso)
}
else
{
echo 1; // Devolver el valor 1 para indicar que la comparación SÍ es válida
}
}
else
{
echo 0; // Devolver el valor 0 para indicar que la comparación no es válida o que se ha producido un error
}
}
else
{
echo 0; // Devolver el valor 0 para indicar que la comparación no es válida o que se ha producido un error
}
mysqli_close($conexion);
}
echo $fin_linea;
|
Nell'esempio precedente la funzione hexdec viene utilizzata per ottenere un numero decimale da un testo che rappresenta un numero esadecimale ed è quello inviato dal dispositivo IoT. Il vantaggio aggiuntivo dell'utilizzo di questa funzione è quello di evitare, come spiegato prima, un attacco tramite l'aggiunta di codice SQL dannoso per i dati della richiesta POST.
Invia commento