Hola Amig@s,
Hoy les traigo un proyecto personal que estuve pensando hacer durante bastante tiempo. Se trata de un dispositivo utilizando una MCU NodeMCU basado en el chip ESP8266, un lector RFID y un relay que permite controlar cualquier tipo de dispositivo que funcione a 220v. En este artículo utilizaré una lampara de mesa en reemplazo de una cerradura electrónica.
Intentaré documentar todo el proceso, que a priori parece muy simple pero de simple tiene muy poco.
Esquema funcional
A continuación podrán ver un pequeño esquema de todos los sistemas que intervienen en el proyecto.
Funcionamiento
El lector RFID recibe el valor almacenado en la llave rfid o tarjeta rfid. Ese valor se lo envía al NODEMCU, el MCU dispone de un pequeño cliente web que se conecta a la ip del servidor que está en la nube y le pasa mediante un comando GET, el valor de la key al web service, disponible en dicho servidor. El webservice a su vez se conecta a una base de datos Oracle XE que está instalada localmente en el servidor de la nube de Azure y consulta si dicha KEY está en los registros. Si la KEY existe, el web service devuelve el resultado en una estructura JSON. El JSON viaja de vuelta al MCU y éste lo deserializa (descompone en valores), teniendo así la posibilidad de realizar acciones. Eso cuando el resultado es correcto. Cuando el WS consulta una KEY y la BBDD no devuelve datos, también se devuelve una estructura JSON, aunque distinta a la correcta. Por ende, podemos controlar que debe hacer el NODEMCU según que respuestas.
Si el resultado es válido, es decir si la key existe, el NODEMCU activará un relay y hará un beep largo utilizando el buzzer.
Por el contrario emitirá dos beeps pero no activará nada mas.
Esquema API
Ahora Bien, lo siguiente es diseñar un pequeño circuito para interconectar el NODEMCU, el lector RFID, un soporte para colocar el relay, un buzzer y un par de accesorios.
Esquema de conexión
Como pueden observar el esquema es super sencillo, solo hay que interconectar los GPIO’s en los puntos correspondientes y poco más.
Una vez que me ha llegado el PCB desde la fábrica, he reunido todos los componentes que voy a utilizar en una foto.
Restful API PHP
Para que el cliente del NODEMCU pueda comunicarse, debemos crear un pequeño webservice en PHP. Su tarea será, recibir un valor desde el cliente con un GET, guardarlo y utilizarlo como BIND en una consulta SQL que estará conectada a una base de datos Oracle XE. Dependiendo de su valor generará uno u otro resultado con salida en formato JSON.
if(isset($_GET['myhashkey']))
{
$mihaskey = $_GET['myhashkey'];
}
$db = new \Oracle\Db("LLAVECLOUD", "CONSULTA");
$sql = "SELECT NOMBRE, APELLIDO, HASHKEY, STATUS FROM USUARIOS WHERE HASHKEY = :varmihashkey";
$res = $db->execFetchAll($sql, "",
array(
array(":varmihashkey", $mihaskey, -1)));
$i=0;
$return_arr = array();
$row_array = array();
if(count($res)>0){ //HAY DATOS?
foreach ($res as $rows) {
$row_array['NOMBRE'] = $rows['NOMBRE'];
$row_array['APELLIDO'] = $rows['APELLIDO'];
$row_array['HASHKEY'] = $rows['HASHKEY'];
$row_array['STATUS'] = $rows['STATUS'];
if ($row_array['STATUS']==100) $row_array['ACCEDER']='SI';
$row_array['BEEP']='1';
$row_array['MOTIVO']='HASH VALIDA';
array_push($return_arr,$row_array);
}}
else { //SINO
$row_array['MOTIVO'] = 'NO EXISTE ESA HASHKEY O NO HAY DATOS';
$row_array['ACCEDER'] = 'NO';
$row_array['BEEP'] = '2';
array_push($return_arr,$row_array);
}
echo str_replace('[', '', str_replace(']', '', json_encode($return_arr, JSON_PRETTY_PRINT)));
Resultado correcto
{
"NOMBRE": "Eduardo",
"APELLIDO": "Arana",
"HASHKEY": "15411017826",
"STATUS": "100",
"ACCEDER": "SI",
"BEEP": "1",
"MOTIVO": "HASH VALIDA"
}
Resultado incorrecto
{
"MOTIVO": "NO EXISTE ESA HASHKEY O NO HAY DATOS",
"ACCEDER": "NO",
"BEEP": "2"
}
Seguridad en la conexión
Obviamente no hemos tenido en cuenta la seguridad para este EJEMPLO, dado que para hacerlo bien, deberíamos validar el cliente (NODEMCU) contra el webservice utilizando un TOKEN o usuario y contraseña, una conexión SSL y un puerto específico.
Código del MCU
A continuación podrán encontrar un pequeño código de ejemplo donde puede verse como se realiza la petición, se recibe la respuesta, y se deserializa el json para obtener los valores de dicha respuesta. Este ejemplo está basado en el que se incluye en la librería del Arduino IDE llamado BasicHTTPClient.ino, lo he utilizado como prueba de concepto.
if (tag != NULL)
{
Serial.println("Consultando la hashkey: " + tag);
Serial.print("[HTTP] begin...\n");
// configure traged server and url
http.begin(client, "http://" SERVER_IP "/key.php?myhashkey=" + tag); //HTTP
http.addHeader("Content-Type", "application/json");
Serial.print("[HTTP] POST...\n");
// start connection and send HTTP header and body
int httpCode = http.POST("{\"hashkey\":\"764EB1A6FE9D4809\"}");
// httpCode will be negative on error
if (httpCode > 0) {
//Serial.printf("[HTTP] POST... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK) {
const String& payload = http.getString();
//json definition
DynamicJsonDocument doc(1024);
deserializeJson(doc, payload);
//json array
const char* minombre = doc["NOMBRE"];
const char* miapellido = doc["APELLIDO"];
const char* mihashkey = doc["HASHKEY"];
const char* miestado = doc["STATUS"];
const char* miacceder = doc["ACCEDER"];
int buzzer = doc["BEEP"];
const char* mimotivo = doc["MOTIVO"];
//serial output
Serial.print("Nombre:");
Serial.println(minombre);
Serial.print("Apellido:");
Serial.println(miapellido);
Serial.print("Hashkey:");
Serial.println(mihashkey);
Serial.print("Estado:");
Serial.println(miestado);
Serial.print("Acceso:");
Serial.println(miacceder);
Serial.print("buzzer:");
Serial.println(buzzer);
Serial.print("Motivo:");
Serial.println(mimotivo);
if (buzzer > 1) { //if key not found
digitalWrite(redled, LOW) ; //Turn on the red led
tone(Passive_buzzer, 987) ; //LA note ...
delay (200);
tone(Passive_buzzer, 687) ; //LA note ...
delay (200);
noTone(Passive_buzzer) ; //Turn off tone()
digitalWrite(redled, HIGH) ; //Turn off the red led
} else { //if key found
digitalWrite(greenled, LOW) ; //Turn on the green led
tone(Passive_buzzer, 523) ; //DO note 523 Hz
delay (200);
noTone(Passive_buzzer) ; //Turn off tone()
digitalWrite(greenled, HIGH) ; //Turn off the green led
digitalWrite(relay, HIGH);
delay(10000);
digitalWrite(relay, LOW);
noTone(Passive_buzzer) ; //Turn off tone()
}
}
} else {
Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
Video demostrativo
He subido un video donde puede verse el funcionamiento del dispositivo. He utilizado una lampara para simular una cerradura eléctrica, pero es muy sencillo de conectar cualquier otra cosa que necesitemos controlar y validar contra un web service.
Espero que les haya resultado curioso.
Salu2.
Edu.