Proyecto 1 2018 I

Acceso a las instalaciones del gimnasio Universidad Santo Tomás

Participantes

Eddy Santiago González López
Juan Pablo Contreras Gaitán
Mariana Medina Castaño
Omar Ricardo Vega Aguirre

Abstract

On this page, you found the documentation of the processes that led to the final project of the subject of new technologies at the faculty of telecommunications engineering at Santo Tomás University. The project is focused on the problem of access control to the gyms in the different venues of the university (Central, Campus and Aquinate), so we use the concepts of class on databases, cloud computing with amazon web services (AWS) and knowledge applied on previous courses like circuits, digital systems and telematics. The project was carried out during class hours with the teacher's guide and all the elements were compiled by the students to develop.

Problema

En la universidad Santo Tomás actualmente se realiza el control del uso de gimnasios con la inscripción de datos (de los estudiantes que quieren utilizarlos) en una base de datos en excel la cuál no se encuentra en conexión con las diferentes sedes de la universidad y además recae el trabajo de bienestar revisar que cada uno de los estudiantes se encuentre activo y con su revisión médica al día, lo cuál no genera una optimización de trabajo para la universidad. Por lo que se plantea automatizar el control de ingreso a los gimnasios de la universidad con una base de datos interactiva para el administrador en cualquiera de las sedes de la universidad.

Diseño (Arquitectura HW)

Arquitectura.PNG

Diseño detallado (Casos de uso)

Caso de uso búsqueda administrador
Caso de uso eliminar administrador
Caso de uso estadísticas
Caso de uso búsqueda registro
Caso de uso registro ingreso/salida usuario

Desarrollo

El proyecto se divide en tres principales tareas que se realizaron distribuidas en el grupo. La primera tarea corresponde a la configuración del hardware: sensor de lectura del carné de los estudiantes para los módulos de hardware que interactúan con el backend (registro de datos en DynamoDB). La segunda tarea corresponde a la configuración del fronte-end: página web que realiza solicitudes al servicio web desarrollado en el API Gateway por lo cual se debe usar el comando curl que corre sobre php y se debe instalar un servidor php en un pc con el fin de que los comandos funcionen. Y la última tarea corresponde a la configuración del back-end: funciones lambda que almacenan los datos en DynamoDB.

Funcionamiento

Hardware

El hardware consiste en
Lector RFID
Arduino
ENC28J60

Lector RFID

Se utiliza un lector RFID el cual su principio de funcionamiento consiste en pasar un TAG, cerca del lector RFID, el TAG tiene la capacidad de enviar información al lector. Dicha información puede ser desde un simple código o todo un paquete de información guardo en la memoria del TAG. Los TAGs viene en diferentes modelos, los más comunes son en tarjetas y en llaveros, pero también vienen como etiquetas adhesivas e incluso ya viene incrustados en algunos productos, en este caso se utiliza en los carné de estudiantes para el acceso a las instalaciones de la universidad por lo que se pretende utilizar esto para el ingreso a las instalaciones del gimnasio para facilitar el control de acceso.

modulorfid.jpg

Este módulo utiliza un sistema de modulación y demodulación de 13.56MHz, frecuencia que en la actualidad utiliza la tecnología RFID. EL módulo se comunica por SPI, por lo que se puede implementar con cualquier microcontrolador con interfaz SPI, como un Arduino.

Arduino

Arduino dispone de una amplia variedad de placas y shields para usar dependiendo de nuestras necesidades. Un shield es una placa compatible que se puede colocar en la parte superior de los arduinos y permite extender las capacidades del arduino. La placa que se utiliza para el proyecto es la arduino UNO la cual es la placa estándar y la más conocida y documentada. Salió a la luz en septiembre de 2010 sustituyendo su predecesor Duemilanove con varias mejoras de hardware que consisten básicamente en el uso de un USB HID propio en lugar de utilizar un conversor FTDI para la conexión USB. Es 100% compatible con los modelos Duemilanove y Diecimila. Viene con un Atmega328p con 32Kbytes de ROM para el programa.

arduino-uno.jpg

Tiene 14 pines digitales de entrada / salida (de los cuales 6 se pueden usar como salidas PWM), 6 entradas analógicas, un cristal de cuarzo de 16 MHz, una conexión USB, un conector de alimentación, un encabezado ICSP y un botón de reinicio. Contiene todo lo necesario para soportar el microcontrolador; simplemente conéctelo a una computadora con un cable USB o con un adaptador de CA a CC o batería para comenzar.

ENC28J60

Es un módulo controlador de ethernet diseñado para sistemas embebidos fabricado por Microchip Technology Inc. el cual se controla a través de bus SPI, por lo que la conexión con Arduino es muy sencilla. Este opera a 3.3, pero es tolerante a señales de 5V, por lo que su integración es aún más sencilla y soporta velocidades de 10Mbits/s y los modos Dúplex (Full-Duplex) y Semi-dúplex (Half-Duplex) con detección y corrección automática de la polaridad. El ENC28J60 cumple con las especificaciones IEEE 802.3 10BASE-T por lo que el ENC28J60 incorpora filtrado de paquetes para limitar el número de paquetes entrantes, un módulo DMA interno para facilitar el flujo de datos y hardware especifico para el cálculo de las sumas de control (IP checksums).

enc.jpg

Es uno de los procesadores más baratos para dotar conectividad a nuestros proyectos, y es más barato que otras alternativas como el W5100. Sin embargo, el ENC28J60 carece de una pila de TCP/IP por hardware como sí que incluye el W5100. Por tanto, su uso es más complejo y requiere una mayor carga del procesador.

Front-end

Para el front-end se hizo el diseño en Balsamiq, el cual se descargo directamente desde la página https://balsamiq.com/ , se hicieron 8 front-end para los procesos que el proyecto maneja.

Pagina de inicio

login.PNG

Menú de Opciones

menu.PNG

Registro de Usuario

registro.PNG

Respuesta de Registro de Usuario

rta_registro.PNG

Entrada y Salida de los Usuarios

IN_OUT.PNG

Tabla de Datos con la Información de los Usuarios

Edit.PNG

Editar la Información de un Usuario

EDIT_USER.PNG

Mirar las Estadísticas del uso del Gimnasio

stat.PNG

Luego se uso NOTEPAD++ para editar los códigos html en donde se trabajaron las páginas.
Por último se instalo un servidor PHP (AppServ), descargado desde www.appserv.org, para poder cargar los datos CURL a la base de datos creada en amazon aws.

Back-end

Para el Back-end realizamos las principales tablas de datos que se van a trabajar en el proyecto. Definimos una de administrador la cuál contiene la información de log in del usuario, una de usuario en donde se cargan los datos de los usuarios del gimnasio y la última del registro de entrada y salida de estos a las instalaciones como podemos observar a continuación.

backend.JPG

Esquemático del montaje

Posibles aplicaciones

Las aplicaciones de este proyecto pueden escalar a proyectos de mayor magnitud debido a que el control de acceso es una de las principales aplicaciones en las diferentes instalaciones que lo requieran.

Dificultad encontrada

La primera dificultad que se presentó en el proyecto fue el cambio de los servicios de amazon debido a que se requerían utilizar de forma local, por lo que se cambió la implementación de estos.

Otra dificultad que se presento fue en el momento de mandar los datos desde el front-end a la base de datos, por lo que se debió validar los datos con PHP y Curl e instalar un servidor en el computador para poder procesar de manera correcta las solicitudes de PHP.
Al enviar los datos configurados ya con PHP y curl salia el siguiente error:

error.jpg

Para solucionarlo se debió descargar la última versión de los certificados de Curl del siguiente link: https://curl.haxx.se/ca/cacert.pem. Se debe guardar el archivo descargado en la carpeta del servidor php/extras/ssl
Luego se debió editar el archivo php.ini en la parte de curl para darle los permisos del archivo descargado, editando la linea de curl.cainfo y agregarle la ubicación del archivo cacert.pem, como se muestra en la imagen:

curl_pem.PNG

Finalmente se debe reiniciar el servidor y los datos ya se pudieron enviar de manera correcta.
La última dificultad encontrada es referente a la conexión entre Arduino y los servidores de amazon. Los servidores de amazon proveen seguridad en sus sitios y servicios por lo que las direcciones asignadas a los API Gateway tienen denominación https y Arduino no soporta páginas de esta denominación sino http.

Configuración - paso a paso

Configuración Hardware

Para el sensor de lectura del carné de los estudiantes se utilizó el sensor RFID conectado con Arduino como se muestra a continuación.

rfidarduino.jpg

Para la configuración se ingresa el siguiente script en el entorno de programación de arduino:

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN    9    //Pin 9 para el reset del RC522
#define SS_PIN    10   //Pin 10 para el SS (SDA) del RC522
MFRC522 mfrc522(SS_PIN, RST_PIN); //Creamos el objeto para el RC522

void setup() {
    Serial.begin(9600); //Iniciamos la comunicación  serial
    SPI.begin();        //Iniciamos el Bus SPI
    mfrc522.PCD_Init(); // Iniciamos  el MFRC522
    Serial.println("Lectura del UID");
}

void loop() {
    // Revisamos si hay nuevas tarjetas  presentes
    if ( mfrc522.PICC_IsNewCardPresent()) 
        {  
          //Seleccionamos una tarjeta
            if ( mfrc522.PICC_ReadCardSerial()) 
            {
                  // Enviamos serialemente su UID
                  Serial.print("Card UID:");
                  for (byte i = 0; i < mfrc522.uid.size; i++) {
                          Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
                          Serial.print(mfrc522.uid.uidByte[i], HEX);   
                  } 
                  Serial.println();
                  // Terminamos la lectura de la tarjeta  actual
                  mfrc522.PICC_HaltA();         
            }      
    }    
}

En el sketch, el código de identificación lo enviamos por el puerto serial, para visualizar el código es necesario abrir el Monitor Serial del IDE de Arduino.
serial.PNG

Efectivamente está leyendo cada vez que se pone la tarjeta, luego configuramos el modulo de ethernet para el envío de datos desde el sensor hacia la base de datos de Dynamo DB.
La conexión de los dos módulos es de la siguiente forma:

circuito.JPG

Luego la configuración del código que hace un post hacia la página del API Gateway.

 #include <EtherCard.h>

// your variable

#define PATH    "example.php"
#define VARIABLE    "test"

// ethernet interface mac address, must be unique on the LAN
byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };

const char website[] PROGMEM = "https://hif9tjc128.execute-api.us-west-2.amazonaws.com/beta/db-api";

byte Ethernet::buffer[700];
uint32_t timer;
Stash stash;

void setup () {
  Serial.begin(57600);
  Serial.println("\n[webClient]");

  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) 
    Serial.println( "Failed to access Ethernet controller");
  if (!ether.dhcpSetup())
    Serial.println("DHCP failed");

  ether.printIp("IP:  ", ether.myip);
  ether.printIp("GW:  ", ether.gwip);  
  ether.printIp("DNS: ", ether.dnsip);  

  if (!ether.dnsLookup(website))
    Serial.println("DNS failed");

  ether.printIp("SRV: ", ether.hisip);
}

void loop () {
  ether.packetLoop(ether.packetReceive());

  if (millis() > timer) {
    timer = millis() + 10000;

    byte sd = stash.create();
    stash.print("variable=");
    stash.print(VARIABLE);
    stash.print("&action=Submit");
    stash.save();

    // generate the header with payload - note that the stash size is used,
    // and that a "stash descriptor" is passed in as argument using "$H"
    Stash::prepare(PSTR("POST http://$F/$F.csv HTTP/1.0" "\r\n"
                        "Host: $F" "\r\n"
                        "Content-Length: $D" "\r\n"
                        "\r\n"
                        "$H"),
            website, PSTR(PATH), website, stash.size(), sd);

    // send the packet - this also releases all stash buffers once done
    ether.tcpSend();
  }
}

Configuración Front-end

Para la configuración de la página web primero se hicieron los códigos HTML de cada front-end, para cada cdigo html se uso un style.css para darle el estilo a las páginas.
El código de style.css se muestra a continución:

/*BOTON HOME*/
.btn {
    background-color: DodgerBlue;
    border: none;
    color: white;
    padding: 12px 16px;
    font-size: 16px;
    cursor: pointer;
}
.btn:hover {
    background-color: RoyalBlue;
}
/* Avatar image */
img.avatar {
    width: 15%;
}
/* Change styles for span and cancel button on extra small screens */
@media screen and (max-width: 300px) {
    span.psw {
        display: block;
        float: none;
    }
    .cancelbtn {
        width: 100%;
    }
}
/* Set a style for all buttons */
button {
    background-color: #0000b3;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    cursor: pointer;
}

/* Add a hover effect for buttons */
button:hover {
    opacity: 0.8;
}

/*BASE DE DATOS STYLE*/
/*BARRA BUSQUEDA*/
.topnav {
    overflow: hidden;
    background-color: #a3c2c2;
}
/* Style the links inside the navigation bar */
.topnav a {
    float: left;
    display: block;
    color: black;
    text-align: center;
    padding: 14px 16px;
    text-decoration: none;
    font-size: 17px;
}
/* Change the color of links on hover */
.topnav a:hover {
    background-color: #ddd;
    color: black;
}

/* Style the search box inside the navigation bar */
.topnav input[type=text] {
    float: right;
    padding: 6px;
    border: none;
}
/*ESTILO DE LA TABLA*/
table {
    width:100%;
}
th, td {
    padding: 15px;
    text-align: left;
}
table#t01 tr:nth-child(even) {
    background-color: #e1eaea;
}
table#t01 tr:nth-child(odd) {
   background-color: #fff;
}
table#t01 th {
    background-color: #527a7a;
    color: white;
}
/*INVALID FORMAT*/
input:invalid {
    border-color: red;
}
input,
input:valid {
    border-color: #33cc33;
}

select:invalid {
    border-color: red;
}
select,
select:valid {
    border-color: #33cc33;
} 
/*BOTON ENVIAR EDIT USER*/
.input_btn {
    background-color: #08088A;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    cursor: pointer;
}
/*BOTON SEND USER REGISTER*/
.btn_send {
    background-color: #08088A;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    cursor: pointer;
} 
.btn_send:hover {
    opacity: 0.8;
}
/*MENU BOTON STYLE MENU*/
/* Bordered form */
form {
    border: 3px solid #f1f1f1;
}

.btn-group input {
    background-color: #0431B4; /* blue background */
    border: 1px solid blue; /* blue border */
    color: white; /* White text */
    padding: 10px 24px; /* Some padding */
    cursor: pointer; /* Pointer/hand icon */
    width: 50%; /* Set a width if needed */
    display: block; /* Make the buttons appear below each other */
}
.btn-group button:not(:last-child) {
    border-bottom: none; /* Prevent double borders */
}
/* Add a background color on hover */
.btn-group button:hover {
    background-color: #99ccff;
}
/*LOGIN FORMAT STYLE*/
body {font-family: Arial, Helvetica, sans-serif;}
form {border: 3px solid #f1f1f1;}

input[type=text], input[type=password] {
    width: 100%;
    padding: 12px 20px;
    margin: 8px 0;
    display: inline-block;
    border: 1px solid #ccc;
    box-sizing: border-box;
}
input:invalid {
    border-color: red;
}
input,
input:valid {
    border-color: #33cc33;
}
.cancelbtn {
    width: auto;
    padding: 10px 18px;
    background-color: #f44336;
}

.loginput {
    background-color: #08088A;
    color: white;
    padding: 14px 20px;
    margin: 8px 0;
    border: none;
    cursor: pointer;
    width: 100%;
}
.imgcontainer {
    text-align: center;
    margin: 30px 0 12px 0;
}
img.avatar {
    width: 30%;
    border-radius: 10%;
}
.container {
    padding: 16px;
}
span.psw {
    float: right;
    padding-top: 16px;
}

Para iniciar sesión se usa el siguiente código en html, y este manda el request de post a un script .php(send.php) que conecta con el servidor y manda los datos con curl a la base de datos en amazon.
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <!-- STYLE CSS --> 
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h2><center>Gimnasio Universidad Santo Tomás</center></h2>

<form method="post" action=send.php >
  <div class="imgcontainer">
    <img src="C:\AppServ\www\EJEMPLO\santoto.PNG" alt="Avatar" class="avatar">
  </div>

  <div class="container">
    <label for="ID_Usuario"><b>ID Usuario</b></label>
    <input type="text" placeholder="Ingrese ID Usuario" name="ID_Usuario" id="ID_Usuario" required="required">

    <label for="psw"><b>Password</b></label>
    <input type="password" placeholder="Enter Password" name="psw" id="psw" required="required">
    <button type="submit" >Login</button>  
  </div> 
</form>
</body>
</html>

Página Iniciar Sesión
loginhtml.PNG

A continuación se muestra el codigo .php que permite que se conecte al servidor y posteriormente se manden a la base de datos en amazon:

<?php
$ID_Usuario = $_POST['ID_Usuario'];
$psw = $_POST['psw'];
//API Url
$url = 'https://hif9tjc128.execute-api.us-west-2.amazonaws.com/beta/db-api';

//Initiate cURL.
$ch = curl_init($url);

//The JSON data.
$jsonData = array(
    'id' => 'ID_Usuario',
    'password' => 'psw'
);

//Encode the array into JSON.
$jsonDataEncoded = json_encode($jsonData);

//Tell cURL that we want to send a POST request.
curl_setopt($ch, CURLOPT_POST, 1);

//Attach our encoded JSON string to the POST fields.
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded);

//Set the content type to application/json
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); 

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
//Execute the request
$result = curl_exec($ch);

if(curl_errno($ch)){
    echo 'Request Error:' . curl_error($ch);
}else{
    echo $ID_Usuario . "<br>" . $psw;
}
?>

Al oprimir el botón de ingreso se envia la solicitud post de php al servidor, y se obtiene que fue exitosa al obtener la respuesta mostrada en la siguiente imagen, ya que en el anterior código se especificó que si el envió era exitoso se imprimieran los datos enviados en la página.
rta_login.PNG

Código html menu

<form action="action_page.php">
  <div class="imgcontainer">

    <!-- <center><img src="C:\Users\usuario\Documents\MARIANA\9 Semestre\Nuevas_Tecnologia\NOTEPAD++\u_santo.PNG" alt="Avatar" class="avatar"></center> -->
    <img src="C:\AppServ\www\EJEMPLO\santoto.PNG" alt="Avatar" class="avatar">
  </div>

<h1><center>Escoja un Opción</center></h1>

    <div class="btn-group">
        <center>
        <a href="3_User_Register.html"><input type="button" class="btn-group button" value="Registrar Usuario"></a>
        <a href="5_IN_OUT.html"><input type="button" class="btn-group button" value="Registro Entrada/Salida"></a>
        <a href="Base_Datos.html"><input type="button" class="btn-group button" value="Editar Usuario"></a>
        <a href="7_Statistics.html"><input type="button" class="btn-group button" value="Ver Estadísticas"></a>
        </center>
    </div>
    <button class="btn"><i class="fa fa-home"></i> Home</button> 
</body>
</html>

Menu Front-end
menuhtml.PNG

Código html registro

<h2><center>Registro de Usuario</center></h2>
<form action="server.php" method="post">

  ID:
  <input name="ID" type="text" pattern=".{10,}$" title="Ingrese un número de ID valido" required>
  <br><br>

  Tipo de ID:
  <select name="tipo_id" required>
  <option value=""></option>
  <option value="cedula">CC</option>
  <option value="tarjeta_identidad">TI</option>
  <option value="No_Pasaporte">No Pasaporte</option>
</select>
<br><br>
    Cargo:
  <select name="cargo" required>
  <option value=""></option>
  <option value="estudiante">E</option>
  <option value="profesor">P</option>
  <option value="administrativo">A</option>
  <option value="directivo">D</option>
  <option value="orden_predicadores">OP</option>
</select>
<br><br>
    Nombre:
  <input name="nombre" type="text" pattern="[A-Za-z]+" title="Ingrese un nombre valido" required>
  <br><br>
  Apellido:
  <input name="apellido" type="text"  title="Ingrese un apellido valido" pattern="[A-Za-z]+" required>
  <br><br>
  Programa:
  <select name="programa" required>
  <option value=""></option>
  <option value="Teleco">Ingeniería de Telecomunicaciones</option>
  <option value="electronica">Ingeniería Electrónica</option>
  <option value="cultura">Cultura Física</option>
  <option value="mecanica">Ingeniería Mecánica</option>
  <option value="ambiental">Ambiental</option>
</select>
  <br><br>
  Nivel:
  <select name="nivel" required>
  <option value=""></option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
  <option value="10">10</option>
</select>
  <br><br>
   Jornada:
  <select name="jornada" required>
  <option value=""></option>
  <option value="diurna">Diurna</option>
  <option value="nocturna">Nocturna</option>
</select>
    Género:
  <select name="genero" required>
  <option value=""></option>
  <option value="femenino">Femenino</option>
  <option value="masculino">Masculino</option>
</select>
<br><br>
    Estado:
  <select name="estado" required>
  <option value=""></option>
  <option value="femenino">Activo</option>
  <option value="masculino">Inactivo</option>
</select>
<br><br>
    Examén:
  <select name="examen" required>
  <option value=""></option>
  <option value="si">Sí</option>
  <option value="no">No</option>
</select>
<br><br>
    Observaciones:
  <textarea name="observaciones" rows="10" cols="30" pattern="[A-Za-z]"></textarea>
<br><br>
<button type="submit" >ENVIAR</button>
</form>
</body>
</html>

Código html respuesta registro
<h2><center>Registro de Usuario</center></h2>
<center>
<canvas id="myCanvas" width="500" height="200" style="border:1px solid #d3d3d3;">
</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Informacion relevante del usuario",10,50);
</script>
</center>
</body>
</html>

Front-end Registro y Respuesta Registro
registrohtml.PNG
rta_registrohtml.PNG

Para el el registro de los datos de los usuarios se maneja a través de un .php llamado server.php, el cual contiene las variables necesarias tipo curl del formulario correspondiente al registro.
Código server.php

<?php
$id = $_POST['ID'];
$tipo_id = $_POST['tipo_id'];
$cargo = $_POST['cargo'];
$nombre = $_POST['nombre'];
$apellido = $_POST['apellido'];
$programa = $_POST['programa'];
$nivel = $_POST['nivel'];
$jornada = $_POST['jornada'];
$genero = $_POST['genero'];
$estado = $_POST['estado'];
$examen = $_POST['examen'];
$observaciones = $_POST['observaciones'];

//API Url
$url = 'https://hif9tjc128.execute-api.us-west-2.amazonaws.com/beta/db-api';

//Initiate cURL.
$ch = curl_init($url);

//The JSON data.
$jsonData = array(
    'ID' => 'ID',
    'tipo_id' => 'tipo_id',
    'cargo' => 'cargo',
    'nombre' => 'nombre',
    'apellido' => 'apellido',
    'programa' => 'programa',
    'nivel' => 'nivel',
    'jornada' => 'jornada',
    'genero' => 'genero',
    'estado' => 'estado',
    'examen' => 'examen',
    'observaciones' => 'observaciones'
);

//Encode the array into JSON.
$jsonDataEncoded = json_encode($jsonData);

//Tell cURL that we want to send a POST request.
curl_setopt($ch, CURLOPT_POST, 1);

//Attach our encoded JSON string to the POST fields.
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonDataEncoded);

//Set the content type to application/json
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); 

curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
//Execute the request
$result = curl_exec($ch);

if(curl_errno($ch)){
    echo 'Request Error:' . curl_error($ch);
}else{

    echo "ENVIO EXITOSO";
    echo  $ID . "<br>" . $tipo_id . "<br>" . $cargo . "<br>" . $nombre . "<br>" . $apellido;
}
?>

Este código también procesa las solicitudes correspondientes a cuando se edita la información de un usuario.
Código html registro entrada y salida usuarios
<a href="2_menu.html"><input type="button" class="btn" value="Home"></a>
<div class="imgcontainer">

   <img src="C:\AppServ\www\EJEMPLO\santoto.PNG" alt="Avatar" class="avatar">
  </div>
<h2><center>Registro Entrada/Salida</center></h2>
<center>
<canvas id="myCanvas" width="500" height="200" style="border:1px solid #d3d3d3;">
</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Informacion relevante del usuario",10,50);
</script>
</center>
<center><button type="submit" onclick="alert('Bievenido')">Entrada</button></center>
<center><button type="submit" onclick="alert('Adios Popo')">Salida</button></center>
</body>
</html>

Front-endregistro entrada y salida usuarios
IN_OUThtml.PNG

Código edición de usuario

<form action="server.php">
<!-- EL BOTON DE HOME -->
<a href="2_menu.html"><input type="button" class="btn" value="Home"></a>

  <div class="imgcontainer">

    <img src="C:\AppServ\www\EJEMPLO\santoto.PNG" alt="Avatar" class="avatar">

  </div>
<h2><center>Registro de Usuario</center></h2>
<form action="server.php" method="post">
  <!-- CARNÈ:
  <input name="Carne" type="text" pattern=".{10,}$" title="Ingrese un número de ID valido" required>
  <br><br>     -->

  ID:
  <input name="ID" type="text" pattern=".{10,}$" title="Ingrese un número de ID valido" required>
  <br><br>

  Tipo de ID:
  <select name="tipo_id" required>
  <option value=""></option>
  <option value="cedula">CC</option>
  <option value="tarjeta_identidad">TI</option>
  <option value="No_Pasaporte">No Pasaporte</option>
</select>
<br><br>
    Cargo:
  <select name="cargo" required>
  <option value=""></option>
  <option value="estudiante">E</option>
  <option value="profesor">P</option>
  <option value="administrativo">A</option>
  <option value="directivo">D</option>
  <option value="orden_predicadores">OP</option>
</select>
<br><br>
    Nombre:
  <input name="nombre" type="text" pattern="[A-Za-z]+"  title="Ingrese un nombre valido" required>
  <br><br>
  Apellido:
  <input name="apellido" type="text" pattern="[A-Za-z]+" title="Ingrese un apellido valido" required>
  <br><br>
  Programa:
  <select name="programa" required>
  <option value=""></option>
  <option value="Teleco">Ingeniería de Telecomunicaciones</option>
  <option value="electronica">Ingeniería Electrónica</option>
  <option value="cultura">Cultura Física</option>
  <option value="mecanica">Ingeniería Mecánica</option>
  <option value="ambiental">Ambiental</option>
</select>
  <br><br>
  Nivel:
  <select name="nivel" required>
  <option value=""></option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
  <option value="10">10</option>
</select>
  <br><br>
   Jornada:
  <select name="jornada" required>
  <option value=""></option>
  <option value="diurna">Diurna</option>
  <option value="nocturna">Nocturna</option>
</select>
    Género:
  <select name="genero" required>
  <option value=""></option>
  <option value="femenino">Femenino</option>
  <option value="masculino">Masculino</option>
</select>
<br><br>
    Estado:
  <select name="estado" required>
  <option value=""></option>
  <option value="femenino">Activo</option>
  <option value="masculino">Inactivo</option>
</select>
<br><br>
    Examén:
  <select name="examen" required>
  <option value=""></option>
  <option value="si">Sí</option>
  <option value="no">No</option>
</select>
<br><br>
    Observaciones:
  <textarea name="observaciones" rows="10" cols="30" pattern="[A-Za-z]"></textarea>
<br><br>
<!-- EL BOTON DE ENVIAR -->
<a href="Base_Datos.html"><input type="button" class="input_btn" value="Volver a Base de Datos"></a>
<button type="submit" >Guardar Cambios</button>
<button type="submit" >Eliminar Usuario</button>
</form>
</body>
</html>

Front end Edición de Usuario y Tabla de datos
EDIT_USERhtml.PNG
base_datoshtml.PNG

Configuración Back-end

Para la configuración en AWS previamente se debe instalar el AWS CLI (Command Line Interface) que utiliza una estructura multiparte en la línea de comando. Comienza con la llamada base a aws. La siguiente parte especifica un comando de nivel superior, que a menudo representa un servicio de AWS admitido en AWS CLI. Cada servicio de AWS tiene subcomandos adicionales que especifican la operación a realizar todo desde un powershell o CMD. Para el proyecto se instaló en una máquina con Windows 7 de 32 bit.
Instalamos el instalador MSI, se corre y luego se configura en el CMD enviando el comando:

aws configure - El cuál nos pedirá información de la llave de acceso y la llave secreta. En este caso utilizamos las llaves de acceso de la cuenta de amazon así:

AWS Access Key ID [None]: AKIAICLDVJYAGWT7FAQQ
AWS Secret Access Key [None]: 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
Default region name [None]: us-west-2
Default output format [None]: json

Configuración en AWS

Los servicios que se utilizan de AWS son:
DynamoDB
IAM
AWS Lambda
API Gateway

Se configura una API REST utilizando una arquitectura sin servidor con AWS Lambda para acceder y ejecutar CRUD (Create, Read, Upload and Delete) en tablas de base de datos noSQL en DynamoDB, debido a que las funciones de AWS Lambda se cobran solo cuando funcionan no como las máquinas virtuales (por ejemplo, instancias de EC2) que se cobran siempre que se ejecutan.
Se crea un servicio lambda CRUD para guardar los datos en DynamoDB, luego se construye una API REST para todas las tablas, no solo una. Más adelante, se podría crear una autenticación y validar la solicitud y respuesta de la API Gateway pero no se hace debido a que aumentaría los parámetros del proyecto.

DynamoDB

Primero se crean las tablas en AWS DynamoDB. DynamoDB es una base de datos-valor-como-servicio NoSQL desarrollada y ofrecida por Amazon Web Services. Solo hay una instancia de DynamoDB por región, por lo que no es necesario crear una base de datos como lo haríamos con MySQL RDS, pero es necesario crear las tablas en DynamoDB antes de que podamos comenzar a guardar datos en la función Lambda. Entonces el comando para crear las tablas desde AWS CLI es:

aws dynamodb create-table --table-name login --attribute-definitions AttributeName=id,AttributeType=S --key-schema AttributeName=id,KeyType=HASH --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5

con table-name el nombre de la tabla y los demás parámetros son de capacidad de lectura y escritura. Al enviar esta línea de código nos muestra la respuesta de creación así:

{
    "TableDescription": {
        "TableArn": "arn:aws:dynamodb:us-west-1:161599702702:table/login", 
        "AttributeDefinitions": [
            {
                "AttributeName": "id",
                "AttributeType": "N"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 5,
            "ReadCapacityUnits": 5
        },
        "TableSizeBytes": 0,
        "TableName": "login",
        "TableStatus": "CREATING",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "id"
            }
        ],
        "ItemCount": 0,
        "CreationDateTime": 1493219395.933
    }
}

Realizamos este paso con las otras dos tablas del Back-end (registroes y usuario) y corroboramos en la página de amazon si se crearon.

tablasdb.JPG

Efectivamente se crearon, así que procedemos al siguiente servicio de AWS.

IAM

Creamos un rol de IAM (Identity and Access Managment) con la "trust policy" para que la función lambda pueda acceder a DynamoDB. El archivo se guarda en la carpeta donde se está trabajando en el CMD bajo el nombre de lambda-trust-policy.json y contiene la siguiente información:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "lambda.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Se crea un rol con la "trust policy" usando el comando aws iam que apunta al archivo asi:

aws iam create-role --role-name LambdaServiceRole1 --assume-role-policy-document file://lambda-trust-policy.json

Luego le asignamos el arn de nuestra cuenta y le dejamos total acceso a DynamoDB así:

aws iam attach-role-policy --role-name LambdaServiceRole1 --policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess

Así tenemos creado el rol de IAM para poder crear las funciones lambda.

AWS Lambda

Primero debemos descargar un archivo que es muy similar al controlador de solicitud express. Un archivo que comprueba los métodos HTTP y realiza CRUD en la tabla DynamoDB en consecuencia. El nombre de la tabla proviene de la cadena de consulta o del cuerpo y contiene lo siguiente:

'use strict'

console.log('Loading function')
const doc = require('dynamodb-doc')
const dynamo = new doc.DynamoDB()

// All the request info in event
// "handler" is defined on the function creation
exports.handler = (event, context, callback) => {

    // Callback to finish response
    const done = (err, res) => callback(null, {
        statusCode: err ? '400' : '200',
        body: err ? err.message : JSON.stringify(res),
        headers: {
            'Content-Type': 'application/json',
        }
    })
    // To support mock testing, accept object not just strings
    if (typeof event.body == 'string')
        event.body = JSON.parse(event.body)
    switch (event.httpMethod) {
        // Table name and key are in payload
        case 'DELETE':
            dynamo.deleteItem(event.body, done)
            break
        // No payload, just a query string param    
        case 'GET':
            dynamo.scan({ TableName: event.queryStringParameters.TableName }, done)
            break
        // Table name and key are in payload
        case 'POST':
            dynamo.putItem(event.body, done)
            break
        // Table name and key are in payload   
        case 'PUT':
            dynamo.updateItem(event.body, done)
            break
        default:
            done(new Error(`Unsupported method "${event.httpMethod}"`))
    }
}

Este archivo se guarda como index.js y se comprime en una archivo con nombre db-api.zip para que se guarde en la nube. Con la información del arn del rol IAM ingresamos el siguiente comando para crear la primera función de login:

aws lambda create-function --function-name db-api-login --runtime nodejs6.10 --role arn:aws:iam::703430453096:role/LambdaServiceRole1--handler index.handler --zip-file fileb://db-api.zip --memory-size 512 --timeout 10

El resultado debe salir algo así:

{
    "CodeSha256": "bEsDGu7ZUb9td3SA/eYOPCw3GsliT3q+bZsqzcrW7Xg=",
    "FunctionName": "db-api-login",
    "CodeSize": 778,
    "MemorySize": 512,
    "FunctionArn": "arn:aws:lambda:us-west-1:161599702702:function:db-api-login",
    "Version": "$LATEST",
    "Role": "arn:aws:iam::161599702702:role/LambdaServiceRole",
    "Timeout": 10,
    "LastModified": "2017-04-26T21:20:11.408+0000",
    "Handler": "index.handler",
    "Runtime": "nodejs6.10",
    "Description": ""
}

Luego se modifica el comando para las otras dos funciones lambda (registroes y usuario). Para comprobar si cada una de las funciones funciona se realiza una prueba HTTP con un json llamado db-api-test.json el cual contiene:

{
    "httpMethod": "GET",
    "queryStringParameters": {
        "TableName": "login"
     }
}

Teniendo en cuenta el nombre de cada tabla en "TableName", se envía el comando:

aws lambda invoke --invocation-type RequestResponse --function-name db-api-login --payload file://db-api-test.json output.txt

También teniendo en cuenta el nombre de cada función lambda en —function-name y nos debe crear un texto plano en la carpeta que estamos trabajando con la siguiente información:

{"statusCode":"200","body":"{\"Items\":[],\"Count\":0,\"ScannedCount\":0}","headers":{"Content-Type":"application/json"}}

Por último comprobamos si se crearon las funciones en la página de amazon:

funciones.JPG

Efectivamente se crearon las funciones, por último queda crear el API Gateway.

API Gateway

Para la creación del API Gateway se va a tener en cuenta los parámetros:
Crear API REST en eñ API Gateway
Crear un recurso (es decir, / db-api, p. Ej., / Usuarios, / cuentas)
Definir el método HTTP sin autenticación
Definir la integración a Lambda (proxy)
Crear despliegue
Dar permisos para el recurso y el método de la puerta de enlace API para invocar a Lambda

Para la creación del API Gateway si lo hacemos por medio de la interfaz gráfica debido a que estamos trabajando en Windows y no se pueden configurar archivos .sh en este. De igual forma se tienen en cuenta los parámetros para crear el API Gateway, la ventaja es que solo se pone la información necesaria y queda creado. Para este caso se llama api-for-db-api. En resources creamos la acción de POST sin autorizaciones y observamos el esquema que crea:

api.JPG

Para observar el funcionamiento hacemos una prueba con postman si se pueden enviar datos a través de este con el link: https://hif9tjc128.execute-api.us-west-2.amazonaws.com/beta/db-api y enviamos información de esta forma:

-d '{"TableName": "messages",
    "Item": {
      "id": "'$(uuidgen)'",
      "author": "Neil Armstrong",
      "text": "That is one small step for (a) man, one giant leap for mankind"
    }
  }'

Luego observamos la tabla si recibió la información en la página de Amazon:

prueba.JPG

Efectivamente funciona luego se procede a continuar con el proyecto.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License