Documente Academic
Documente Profesional
Documente Cultură
2017
Sistema Antichoque
Proyecto N°4
Integrantes
2.Correcciones/Cambios de la Propuesta
● El vehículo se diseñó teniendo en cuenta que del banco de baterías que se instalaría
en el mismo, se podría obtener 5V para la alimentación de los sensores de distancia.
A causa de la dificultad para obtener baterías de 5V se decidió utilizar la salida de
5V que posee el doble puente H. Consecuencia de esto se reposicionaron los
componentes en el vehículo siguiendo las siguientes premisas: Primero, mantener
una correcta distribución del peso en el vehículo para que la fuerza entregadas por
los motores sean de magnitudes similares. Segundo, realizar un cableado prolijo y
reducido.
5 Alimentación HC_SR04
Conexionado ESP8266:
3 CH 3.3V(Arduino uno)
*Para la alimentación del módulo ESP8266 se utilizó un capacitor de 50V 10uF para otorgar
estabilidad al mismo.
Para las tareas del Control de distancia se utilizan las siguientes funciones:
● ”FrontMeasurement” de la librería HC_SR04X2.
● ”BackMeasurement” de la librería HC_SR04X2.
● ”parar” de la librería ControlMotor.
Para las tareas del Control de Desplazamiento se utilizan las siguientes funciones:
● ”parar” de la librería ControlMotor.
● ”avanzar” de la librería ControlMotor.
● ”girarIzquierda” de la librería ControlMotor.
● ”girarDerecha” de la librería ControlMotor.
● ”retroceder” de la librería ControlMotor.
Para las tareas del Control de Comunicación se utilizan las siguientes funciones:
● ”Receive_data” de la librería ESP8266.
● ”data_send” de la librería ESP8266.
Por otro lado, el sistema web presenta un sistema de usuarios, el cual permite
registro, login, logout y modificación de datos personales. Presenta un apartado de
preguntas frecuentes donde se listan algunos detalles del sistema, su uso, entre otros. En
relación al uso del autito, presenta tres grandes puntos.
● Un enlace en el menú desplegable para conectarse al autito: Permite la
conexión vía TCP al servidor montado en el autito.
● Una vista para el control y visualización del estado actual del autito: Utiliza
querys de ajax para el control del autito y para la consulta y actualización de
los estados. Dentro de los controles tenemos Marcha-, Frenar, Marcha+,
Avanzar, Izquierda, Derecha y Retroceder. Dentro del estado actual, es
posible visualizar la marcha(1, 2 o 3), el estado(Parado, Desconectado,
Avanzando, Retrocediendo, Derecha o Izquierda), la distancia que mide el
sensor frontal y la distancia que mide el sensor trasero.
● Una vista para visualizar las estadísticas/eventos más importantes medidos
por el autito: Es posible visualizar los últimos 10 eventos, con fecha, hora,
distancia y sentido, es decir si es en avance o retroceso. Estos eventos
deben ser menor a 75cm para ser tenidos en cuenta.
Ahora si procedemos dividir los casos de uso según las distintas partes que
componen el sistema antichoque desarrollado. Dentro de ellas se encuentran:
Sistema web:
1. El usuario accede al sitio: Una vez que el usuario accede al sitio a través de la URL
localhost:8000/, el controlador de la vista principal(index), la renderiza. En ella se
visualiza un botón para el registro, un link para iniciar sesión en la barra de
navegación, y ciertos elementos informativos acerca del proyecto, el grupo de
desarrollo, las preguntas frecuentes, entre otros.
2. El usuario presiona el boton “Registrese Ahora!” de la página principal: Una vez que
el usuario ha accedido a la página web y presiona el botón de “Regístrese Ahora!”,
accede a otra vista donde se le presenta un formulario, con cinco campos(Nombre,
Apellido, Email, Nombre de Usuario y Contraseña), el cual debe completar. Una vez
que ha completado todos los campos, presiona el botón “Registrarse”, y allí todos los
datos que el usuario ingresó son tomados por el controlador(signup) que detecta si
el email y nombre de usuario no se encuentran ya utilizados, procediendo a guardar
todos los datos del usuario en la base de datos, si no se encuentran estos campos
utilizados, o a informar al usuario de un error, en caso contrario. Si el usuario pudo
registrarse correctamente, será redirigido a la página donde se le permite el ingreso
a la web. Allí verá un cartel o mensaje indicando el correcto registro.
3. El usuario presiona el link “Iniciar Sesión” en la barra de navegación: Una vez que el
usuario ha accedido a la página web, presiona el link “Iniciar Sesión” en la barra de
navegación, más específicamente en la parte superior derecha. Acto seguido, es
redireccionado a la página que permite el ingreso a la web. Allí verá un formulario
con dos campos, el Nombre de Usuario y la Contraseña. Una vez que completa
dichos campos y presiona el botón “Ingresar”, los datos ingresados son tomados por
el controlador(login), que verifica contra los usuarios almacenados en la base de
datos, si se trata de un usuario registrado, y en tal caso, si la contraseña ingresada
corresponde al usuario. Si el usuario no existe, se informa de un error, al igual que si
la contraseña ingresada no corresponde con el nombre de usuario ingresado. Si, en
cambio, el ingreso fue correcto, el controlador cambiará el estado de la cuenta a
“semi-online”, indicando que se encuentra conectado a la página web, pero no
haciendo uso de la comunicación con el autito. El usuario, ahora ha ingresado a la
web, y es redireccionado a la página principal, donde verá cierta información del
autito y una serie de botones que le permiten controlarlo.
5. El usuario presiona el link FAQs: Una vez que el usuario ha accedido a la página
web y presiona el link FAQS, tanto en la página de inicio, como en el menú
desplegable de la barra de navegación(si es que el usuario inició sesión), esta
acción es tomada por el controlador(faqs), el cual renderiza la vista de las preguntas
frecuentes, a la cual el usuario es redirigido.
7. El usuario presiona el link “Mis Datos” en la barra de navegación: Una vez que el
usuario a ha accedido a la página web y ha ingresado a esta, presiona el link “Mis
Datos”, en el menú desplegable de la barra de navegación, y es redirigido a una
vista donde aparecerán cinco campos(los mismos del registro), para poder modificar
sus datos. Salvo la contraseña, los otros cuatros campos, están cargados con los
datos que el usuario posee en dicho momento en el sistema. Para poder visualizar
estos datos, el controlador(account), antes de renderizar dicha vista, realizó una
consulta a la base de datos para obtener todos los datos asociados al usuario, y así
pasarlos a la vista. Una vez en la vista, el usuario puede elegir cuales campos
modificar, ingresa la contraseña, aprieta el botón “Modificar”, y todos los datos son
pasados al controlador, el cual los almacena nuevamente en la base de datos,
previo chequeo que el nuevo nombre de usuario e email no se encuentren utilizados
por otro usuario. En tal caso, informa al usuario de un error, sino informa que los
cambios han sido guardados satisfactoriamente.
8. El usuario presiona el link “Estadísticas” en la barra de navegación: Una vez que el
usuario ha accedido e ingresado al sistema, presiona el link “Estadísticas” en el
menú desplegable de la barra de navegación, y es redirigido a una vista donde son
mostrados los últimos 10 eventos que midió el autito. Si hay menos de 10 eventos,
se muestran los que haya, y si no existen eventos se muestra un mensaje indicando
como hacer para obtener estadísticas. Para mostrar estos eventos, el
controlador(stats), realiza una consulta a la base de datos, obteniendo los últimos 10
eventos asociados al usuario ingresado, y luego los pasa a la vista.
10. El usuario presiona cualquiera de los botones de control del autito(Marcha -, Frenar,
Marcha +, Avanzar, Izquierda, Derecha, Retroceder): Una vez que el usuario ha
accedido a la web, iniciado en el sistema y conectado al autito, presiona los distintos
botones de control del mismo. Allí se realiza una consulta ajax, con un “POST”, al
controlador(control). Dependiendo del botón que fue presionado, es pasado al
controlador un String indicando la acción a realizar. Este envía mediante la
utilización del socket conectado al vehículo la correspondiente dirección, velocidad y
giro al autito. Por su parte, el vehículo recibe la información en su servidor TCP,
interpreta la misma y almacena los valores de desplazamientos en sus propias
variables.
@app.route('/')
def index():
Si el usuario no ingreso
renderizar vista de inicio
sí no
Consultar a la base de datos por el estado actual del usuario
Si el usuario no está conectado al autito
Renderizar la vista principal con los parámetros del autito
en cero y un error indicando que no se encuentra conectado
sí no
Renderizar la vista principal con los parámetros del autito
en cero y un mensaje indicando que la conexión fue exitosa
● Controlador del logout del sistema(logout): Este controlador permite que un usuario
ingresado deje el sistema. Simplemente modifica el estado del mismo en la base de
datos a “offline”, cierra el socket, si el usuario se encontraba conectado al autito, y
renderiza a la vista principal. Asociado al caso de uso número 4. El pseudocódigo es
el siguiente:
@app.route('/logout')
def logout():
Si el usuario NO esta logueado
Renderiza la vista principal
Si no
Termina la sesión
Si el usuario estaba conectado al autito
Cierra el socket
Modifica el estado del usuario en la base de datos a “offline”
Redirige al usuario a la vista principal
@app.route('/stats')
def stats():
Si NO hay usuario ingresado al sistema
Renderiza la vista principal
Caso contrario
Consulta a la base de datos por los últimos 10 eventos relacionados al
usuario
Renderiza la vista de las estadísticas con la lista de los últimos 10
eventos
● Controlador de las preguntas frecuentes del sistema(faqs): Este controlador permite
la visualización de las preguntas frecuentes del sistema. Simplemente renderiza la
vista donde se visualizan las preguntas frecuentes. Relacionado al caso de uso
número 5. Su pseudocódigo es:
@app.route('/faqs')
def faqs():
Si NO hay usuario ingresado al sistema
Renderiza la vista de las preguntas frecuentes
Caso contrario
Renderiza la vista de las preguntas frecuentes con parámetros de la
sesión del usuario
@app.route('/connect')
def connect():
Si NO hay usuario ingresado al sistema
Renderiza la vista principal
Caso contrario
Obtiene los datos de sesión del usuario
Consulta a la base de datos para verificar que el usuario está conectado
al autito
Si está conectado
Redirecciona al usuario a la página de control
Sí no
Intenta conectarse al socket del autito
Si es exitosa la conexión
Modifica el estado del usuario en la base de datos a
“online” para indicar que se encuentra conectado al
autito
Renderiza la vista de control con un mensaje de éxito
Sí no
Cierra el socket
Renderiza la vista de control con un mensaje de error
● Controlador del manejo del autito(control): Este controlador permite el manejo del
autito por parte del usuario. Detecta cuál fue la operación ingresada por el usuario y
envía parámetros de dirección, giro y velocidad al autito de acuerdo al tipo de
acción. Previo al envío de cualquier tipo de acción, consulta a la base de datos para
verificar que el usuario se encuentra conectado al autito. Relacionado al caso de uso
número 10. El pseudocódigo es el siguiente:
@app.route('/control', methods=['GET', 'POST'])
def control():
Si el método es “POST”
Obtiene los datos de sesión del usuario
Consulta a la base de datos para verificar que el usuario se encuentre
conectado al autito
Si se encuentra conectado
Verifica cual es la acción a enviar al autito y acomoda los
parámetros a enviar
Envía los parámetros al autito
Si el método es “GET”
Redirección a la vista principal
@app.route("/access")
def access():
Si el usuario está ingresado en el sistema
Obtiene los datos de sesión del usuario
Inicializa las variables correspondientes al estado del autito
Consulta a la base de datos para verificar que el usuario está conectado
al autito
Si está conectado
Envía pedido de información al autito
Espera respuesta
Si recibe la respuesta
Discrimina la información recibida para detectar el
estado actual
Si son eventos de importancia
Los almacena en la base de datos
Sí no
Cierra el socket
Actualiza el estado del usuario a “semi-online” para
indicar que ya no se encuentra conectado al autito
Envía un json a la query ajax con un error
Envía un json a la query ajax con la información recibida
Sí no
Envía un json a la query ajax indicando que no hay usuario logueado
● Query de AJAX que permite el control del autito(control): Esta consulta es activada
cada vez que se hace un click en alguno de los botones de la vista de control. Cada
botón, pasa a la query un parámetro distinto, que depende del comando a enviar.
Esta realiza un POST al controlador control, con el parámetro pasado. Su codigo es
el siguiente:
● Query de AJAX que permite la actualización de la información del estado actual del
autito(loadIndex): Se ejecuta cada 2 segundos, y realiza una petición al controlador
access. Recibe un json, y discrimina la información recibida para actualizar los
distintos campos del estado del vehículo(marcha, estado actual, distancia delantera
y distancia trasera). Su pseudocódigo es:
function loadIndex() {
$.get("/access", function(data) {
Si el usuario estaba conectado
Si hubo error de conexión al intentar pedir la información al
autito
Modifica el estilo del mensaje a “alert-danger”
Modifica el texto del mensaje a “Pérdida de conexión”
Sí no
Si el estado recibido es “Avanzando”
Modifica el estilo a “text-success”
Si el estado recibido es “Retrocediendo”
Modifica el estilo a “text-danger”
Sí no
Elimina los estilos
Modifica el texto a Estado Actual
Modifica el texto a Marcha
Si la distancia delantera recibida es mayor a 75cm
Modifica el estilo a “text-success”
Si la distancia delantera recibida es mayor a 50cm
Modifica el estilo a “text-warning”
Sí no
Modifica el estilo a “text-danger”
Si la distancia delantera recibida es mayor a 400cm
Modifica el texto Distancia Adelante: a >400cm
Sí no
Modifica el texto Distancia Adelante: al valor
recibido
Si la distancia trasera recibida es mayor a 75cm
Modifica el estilo a “text-success”
Si la distancia delantera recibida es mayor a 50cm
Modifica el estilo a “text-warning”
Sí no
Modifica el estilo a “text-success”
Si la distancia trasera recibida es mayor a 400cm
Modifica el texto Distancia Atrás: a >400cm
Sí no
Modifica el texto Distancia Atrás: al valor
recibido
● Usuario conectado:
● Pie de página: El pie de página muestra el nombre de los integrantes del grupo de
desarrollo en la parte inferior izquierda.
● Parte superior(Jumbotron):
● Filas del medio con información:
Si, en cambio el usuario está logueado, muestra la página de control del vehículo,
con una tabla indicando el estado actual del mismo y una serie de botones, posicionados
simulando un “joystick”.
● Vista del formulario de registro(/signup): Muestra 5 campos para ingresar nombre,
apellido, nombre de usuario, contraseña y mail, junto con un botón, que permite el
ingreso de dichos campos.
● Primeras preguntas:
● Últimas preguntas:
● Vista de la modificación de datos personales del usuario(/account): Esta vista
muestra un formulario con 5 campos, nombre, apellido, nombre de usuario,
contraseña y email, y un botón que permite el ingreso de dichos campos.
● Vista de las estadísticas(/stats): Esta vista muestra una tabla con los últimos 10
eventos/mediciones del usuario logueado. Cabe destacar, que el color en el que es
presentado cada elemento depende de la importancia de cada uno. Si la distancia
medida es mayor a 50cm, el valor es mostrado en verde, si se encuentra entre 25 y
50cm, el valor es mostrado en amarillo y si es menor a 25cm, es mostrado en rojo. Si
no hay eventos aparece un texto indicando como hacer para recibir
eventos/mediciones del autito.
ESP8266: Es una librería de uso libre disponible en la web que permite el manejo
del módulo WiFi. Particularmente, permite la conexión vía TCP/IP con la PC, para la
transmisión de datos referidos a estadísticas y control del autito. Es importante aclarar que
para la adaptarla al sistema se le agregaron funciones, las cuales se explican a
continuación.
ControlMotor: Permite el control de los motores por PWM. Permite avance en tres
velocidades, el retroceso en una velocidad, frenar y doblar en ambos sentidos.
FrontSetup:
BackSetup:
FrontMeasurement:
El código de la función BackMeasuramente es idéntico, por lo tanto no será copiado.
El mismo se puede obtener del repositorio de Github.
FrontMeasurement_for:
Librería desarrollada para el control PWM de los motores del autito, la cual posee 3
archivos:
ControlMotor(int md1, int md2, int mi1, int mi2, int pwmD, int pwmI): Es el
constructor de la libreria. Permite asignar los pines que van a controlar cada motor.
void girarDerecha(int velocidad): Gira a la derecha el vehículo con velocidad
“velocidad”.
void avanzar(int velocidad): Permite avanzar el autito con una cierta velocidad.
void parar(int velocidad): Permite frenar/detener el autito con una cierta velocidad.
Para las siguientes funciones es necesario saber que para indicar el sentido de giro
de las ruedas se requieren dos variables por motor, específicamente la variable A y B de
cada motor:
Si queremos que se gire hacia el frente, la variable del motor B se coloca en Alto y
la variable A del motor se coloca en Bajo.
Si queremos que se gire hacia atrás, la variable del motor B se coloca en bajo y la
variable A del motor se coloca en Alto.
La velocidad de giro de cada rueda depende del PWM con el cual se alimente al
motor, para modificar el ciclo de trabajo del PWM utilizamos la variable “velocidad”.
Sabiendo lo antes comentado, la interpretación de las funciones es sencilla
Avanzar:
Retroceder:
GirarIzquierda:
Configuration:
Receive_Data:
Send_Data:
6. Guía de Instalación Completa
a) Ambiente de desarrollo:
Instalación del Arduino IDE:
Se accede a la solapa “software” del sitio oficial de Arduino.
(https://www.arduino.cc/en/Main/Software). Luego se selecciona el SO operativo de nuestra
computadora y se procede con la descarga.
Finalizada la descarga se debe instalar de la manera que corresponde con cada SO,
en el caso de linux debemos descomprimir el archivo y mediante el intérprete de comandos
ejecutar “./install.sh”.
Lenguajes utilizados:
Las librerías en arduino se desarrollan en C++, para lo cual no es necesario la
instalación de ningún paquete.
Para el manejo de la base de datos, es necesario conocimientos en SQL pero no se
requiere la instalación de ningún lenguaje.
Para la programación del servidor HTTP se utiliza flask en Python, para lo cual son
necesarias sus librerías, que se pueden instalar siguiendo los siguientes comandos:
-sudo apt-get install python
-sudo apt-get install python-pip
-pip install flask
En caso de no estar en estado runing, abrir una terminal e ingresar service mysql
start y luego corroborar que se encuentre corriendo con ps -e | grep mysqld.
A partir de este momento se debe estar conectado a la red de vehículo, para ello
encender el auto, esperar 5 segundos y conectarse a ella.
b) Copia/Instalación de Código:
Las funciones que controlan cada hardware utilizado en el vehículo fueron detalladas con
anterioridad, sin embargo para afianzar la idea de la estructura de archivos se incorpora la
siguiente imagen:
El directorio del sistema web está compuesto de la siguiente manera:
● Directorio global: Aquí se encuentra almacenado el archivo antichoque.py y se
visualizan las subcarpetas correspondientes a las vistas(templates) y static, que
posee todo lo correspondiente a scripts, fotos(assets), estilos(stylesheets) y
bootstrap.
● Vistas: Aquí se pueden ver las 6 vistas previamente mencionadas a lo largo del
informe
● Scripts: Se visualizan los dos scripts mencionados a lo largo del informe index.js y
control.js
● Assets: Acá se encuentran todas las fotos y logos utilizados en el armado de las
vistas.
Sistema Antichoque
Proyecto N°4
Integrantes
-Autos a baterías para transportar niños: Un regalo común a los niños y niñas es el
auto de juguete en el cual el niño se puede subir y manejar. Si se incorporara este sistema
anti-choque se podría aumentar la vida útil del vehículo gracias a que se le evitarían golpes
innecesarios. Además se protegería de mejor manera tanto al niño que lo conduce como a
cualquier persona cerca.
2. Objetivo
El objetivo es la construcción de un sistema antichoque para un vehículo que posee
tres velocidades de avance y una velocidad de retroceso. El sistema se encontraría
configurado para moverse en ambos sentidos y para ello se utilizaría, en principio, 2
módulos de ultrasonido, uno detectando los obstáculos en el avance y el otro en el
retroceso.
Desde el punto de vista del usuario, el mismo deberá acceder a una aplicación web
donde encontrará los comandos necesarios para hacer funcionar el vehículo, además de la
información pertinente a la distancia del vehículo con los obstáculos, y otras características
y estados que serán explicados más en detalle. La mencionada aplicación será montada
sobre un servidor HTTP el cual se comunicará con el vehículo mediante el protocolo
TCP/IP. Para llevar a cabo este objetivo se le incorporará al vehículo un módulo wifi
ESP8266.
Cabe aclarar que como medida de seguridad el usuario accederá a la aplicación
haciendo uso de un token o contraseña privada generada por el mismo servidor, de modo
tal que otro usuario no pueda acceder al control del autito. Esto es, que un usuario deberá
primero generar el token o contraseña, accediendo al servidor, luego configurar su autito
para que en la conexión TCP/IP con el servidor, este provea al servidor del token para
poder establecer la conexión. De no existir ese token, la conexión no será posible. Los
tokens serán únicos. Un mismo usuario podría generar más de un token.
Chasis de 3 ruedas(incluye dos Chasis plástico del autito, $585. Disponible en:
motores de cc) con dos ruedas a motor https://articulo.mercadoli
de corriente continua y bre.com.ar/MLA-640018
una libre. 267-kit-chasis-smart-car
-auto-robot-2-ruedas-ard
uino-_JM
<!-- Bootstrap JS
<script src="{{url_for('static',
filename='bootstrap/js/popper.min.js')}}"></script>-->
<script src="{{url_for('static',
filename='bootstrap3/js/bootstrap.min.js')}}"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"
aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Sistema Antichoque</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
{% if session_user_name %}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">Mi cuenta <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="">Control</a></li>
<li><a href="/stats">Estadisticas</a></li>
<li><a href="/account">Mis datos</a></li>
<li><a href="/connect">Conectarse</a></li>
<li><a href="/faqs">FAQs</a></li>
<li role="separator" class="divider"></li>
<li><a href="/logout">Logout</a> </li>
</ul>
</li>
{% else %}
<li><a href="/login">Iniciar Sesion</a></li>
{% endif %}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{% if session_user_name %}
<div class="container">
{% if error %}
<div class="alert alert-danger"
style="text-align: center">{{ error }}</div>
{% elif inform %}
<div class="alert alert-success"
style="text-align: center" id="error">{{ inform }}</div>
{% endif %}
<br>
<ul class="list-group">
<li class="list-group-item"><b><span
id="marcha">Marcha: {{marcha}}</span></b></li>
<li class="list-group-item"><b><span
id="state">Estado: {{state}}</span></b></li>
<li class="list-group-item"><b><span
id="front_distance">Distancia Adelante: {{front_distance}}cm</span></b></li>
<li class="list-group-item"><b><span
id="back_distance">Distancia Atras: {{back_distance}}cm</span></b></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<br>
<br>
<br>
<br>
<div class="container">
<br>
<!-- Primer rectangulo -->
<div class="row">
<div class="col-md-8" style="text-align: center;
margin:auto;">
<h1 class="parTitle"><strong>Basado en
Arduino</strong></h1>
<p class="lead"><i>Se trata de un sistema de control de
un autito de tres ruedas basado en la plataforma Arduino Uno.</i></p>
</div>
<div class="col-md-4" style="text-align: center;
margin:auto;">
<img class="d-block img-fluid"
src="static/assets/arduino-logo.png" alt="First Use" width="220"
height="220">
</div>
</div>
<hr>
<br>
<!-- Segundo rectangulo -->
<div class="row">
<div class="col-md-4" style="text-align: center;
margin:auto;">
<img class="d-block img-fluid"
src="static/assets/wifi.jpeg" alt="Second Use" width="250" height="250">
</div>
<div class="col-md-8" style="text-align: center;
margin:auto;">
<h1 class="parTitle"><strong>Control por
WiFi</strong></h1>
<p class="lead"><i>El autito posee un modulo WiFi ESP8266
que le permite comunicarse con el servidor para ser comandado por el
usuario.</i></p>
</div>
</div>
<hr>
<br>
</div>
</div>
</div>
{% endif %}
<br>
<br>
<!--Footer-->
<footer class="footer">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
<img class="img-fluid footerImg"
src="static/assets/logo1.jpg" alt="Logo" height="90" width="100">
</div>
<div class="col-sm-2 col-sm-offset-8">
<p class="float-right"><strong>Alvarez - Cristofano
2017</strong></p>
</div>
</div>
</div>
</footer>
</body>
</html>
Vista signup.html:
<!DOCTYPE html>
<html>
<head>
<title>Sistema Antichoque</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- JQuery -->
<script src="{{url_for('static',
filename='jquery/jquery-3.2.1.min.js')}}"></script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="{{url_for('static',
filename='bootstrap3/css/bootstrap.min.css')}}" />
<link rel="stylesheet" href="{{url_for('static',
filename='stylesheets/main.css')}}"/>
<!-- Bootstrap JS -->
<script src="{{url_for('static',
filename='bootstrap3/js/bootstrap.min.js')}}"></script>
</head>
<body>
<!-- Barra -->
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"
aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Sistema Antichoque</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li><a href="/login">Iniciar Sesion</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<!-- Titulo de arriba -->
<div class="container text-center login">
<h1 class="parTitle"><strong>Formulario de Registro</strong></h2>
</div>
<br>
{% if error %}
<div class="row justify-content-md-center">
<div class="col-md-12 col-xs-12">
<div class="alert alert-danger">{{ error }}</div>
</div>
</div>
<br>
{% endif %}
<div class="row">
<div class="col-md-6 col-xs-12">
<div class="form-group">
<label for="nombre">Nombre de Usuario</label>
<input type="text" class="form-control" id="username"
name="username" aria-describedby="usernameHelp" placeholder="Ingrese su
nombre de usuario" required/>
<small id="nombreHelp" class="form-text
text-muted">Aquí debe ingresar su nombre de usuario.</small>
</div>
</div>
<div class="col-md-6 col-xs-12">
<div class="form-group">
<label for="nombre">Contraseña</label>
<input type="password" class="form-control"
id="password" name="password" aria-describedby="passwordHelp"
placeholder="Ingrese su contraseña" required/>
<small id="apellidoHelp" class="form-text
text-muted">Aquí debe ingresar su contraseña.</small>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<div class="form-group">
<label for="email">Email</label>
<input type="text" class="form-control" id="email"
name="email" aria-describedby="emailHelp" placeholder="email@example.com"
required>
<small id="emailHelp" class="form-text
text-muted">Aquí debe ingresar su email.</small>
</div>
</div>
</div>
<br>
<div class="row justify-content-md-center">
<div class="col-md-2 col-md-offset-5 col-xs-12">
<div class="text-center">
<button type="submit" class="btn btn-dark
btn-lg"">Registrarse</button>
</div>
</div>
</div>
</form>
</div>
<br>
<br>
<!--Footer-->
<footer class="footer">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
<img class="img-fluid footerImg"
src="static/assets/logo1.jpg" alt="Logo" height="90" width="100">
</div>
<div class="col-sm-2 col-sm-offset-8">
<p class="float-right"><strong>Alvarez - Cristofano
2017</strong> </p>
</div>
</div>
</div>
</footer>
</body>
</html>
Vista login.html:
<!DOCTYPE html>
<html>
<head>
<title>Sistema Antichoque</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- JQuery -->
<script src="{{url_for('static',
filename='jquery/jquery-3.2.1.min.js')}}"></script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="{{url_for('static',
filename='bootstrap3/css/bootstrap.min.css')}}" />
<link rel="stylesheet" href="{{url_for('static',
filename='stylesheets/main.css')}}" />
<!-- Bootstrap JS -->
<script src="{{url_for('static',
filename='bootstrap3/js/bootstrap.min.js')}}"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="/">Sistema Antichoque</a>
</div>
<br>
<div class="container">
<!-- Titulo de arriba -->
<div class="container text-center login">
<h1 class="parTitle"><strong>Login</strong></h2>
</div>
<br>
{% if error %}
<div class="row justify-content-md-center">
<div class="col-md-4 col-md-offset-4 col-xs-12">
<div class="alert alert-danger">{{ error }}</div>
</div>
</div>
<br>
{% elif inform %}
<div class="row justify-content-md-center">
<div class="col-md-4 col-md-offset-4 col-xs-12">
<div class="alert alert-success">{{ inform }}</div>
</div>
</div>
<br>
{% endif %}
<form action="/login" method="POST">
<div class="row justify-content-md-center">
<div class="col-md-4 col-md-offset-4 col-xs-12">
<div class="form-group">
<label for="nombre">Nombre de Usuario</label>
<input type="text" class="form-control" id="username"
name="username" aria-describedby="usernameHelp" placeholder="Ingrese su
nombre de usuario" required/>
<small id="nombreHelp" class="form-text
text-muted">Aquí debe ingresar su nombre de usuario.</small>
</div>
</div>
</div>
<div class="row justify-content-md-center">
<div class="col-md-4 col-md-offset-4 col-xs-12">
<div class="form-group">
<label for="nombre">Contraseña</label>
<input type="password" class="form-control"
id="password" name="password" aria-describedby="passwordHelp"
placeholder="Ingrese su contraseña" required/>
<small id="apellidoHelp" class="form-text
text-muted">Aquí debe ingresar su contraseña.</small>
</div>
</div>
</div>
<br>
<div class="row justify-content-md-center">
<div class="col-md-2 col-md-offset-5 col-xs-12">
<div class="text-center">
<button type="submit" class="btn btn-dark
btn-lg"">Ingresar</button>
</div>
</div>
</div>
</form>
</div>
<br>
<br>
<!--Footer-->
<footer class="footer" style="margin-top: 75px">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
<img class="img-fluid footerImg"
src="static/assets/logo1.jpg" alt="Logo" height="90" width="100">
</div>
<div class="col-sm-2 col-sm-offset-8">
<p class="float-right"><strong>Alvarez - Cristofano
2017</strong> </p>
</div>
</div>
</div>
</footer>
</body>
</html>
Vista faqs.html:
<!DOCTYPE html>
<html>
<head>
<title>Sistema Antichoque</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- JQuery -->
<script src="{{url_for('static',
filename='jquery/jquery-3.2.1.min.js')}}"></script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="{{url_for('static',
filename='bootstrap3/css/bootstrap.min.css')}}" />
<link rel="stylesheet" href="{{url_for('static',
filename='stylesheets/main.css')}}" />
</head>
<body>
<!-- Barra -->
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"
aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Sistema Antichoque</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
{% if session_user_name %}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">Mi cuenta <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/">Control</a></li>
<li><a href="/stats">Estadisticas</a></li>
<li><a href="/account">Mis datos</a></li>
<li><a href="/connect">Conectarse</a></li>
<li><a href="/faqs">FAQs</a></li>
<li role="separator" class="divider"></li>
<li><a href="/logout">Logout</a> </li>
</ul>
</li>
{% else %}
<li><a href="/login">Iniciar Sesion</a></li>
{% endif %}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<div class="container text-center">
<h1 class="parTitle"><strong>Preguntas frecuentes</strong></h1>
</div>
<br>
<hr>
<br>
<!-- Segundo rectangulo -->
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-8" style="text-align: center; margin:auto;">
<h1 class="parTitle"><strong>¿Que debo hacer para controlar
un autito con este sistema?</strong></h1>
<p class="lead"><i>Primero usted debe registrarse en la
pagina. Una vez registrado, usted debe acceder a la pestaña de control en su
cuenta, donde dispondra de los botones que le permitiran comandar el
autito.</i></p>
</div>
</div>
<hr>
<br>
<!-- Tercer rectangulo -->
<div class="row">
<div class="col-md-8" style="text-align: center; margin:auto;">
<h1 class="parTitle"><strong>¿Debo conectarme al
autito?</strong></h1>
<p class="lead"><i>Si, usted se debe dirigir a la pestaña de
conectarse. Una vez que la conexion fue exitosa, usted estara en condiciones
de comandar al autito. En caso de perdida de conexion o error en la misma,
usted sera informado, para que pueda conectarse nuevamente.</i></p>
</div>
<div class="col-md-4"></div>
</div>
<hr>
<br>
</div>
</div>
<br>
<br>
<!--Footer-->
<footer class="footer">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
<img class="img-fluid footerImg"
src="static/assets/logo1.jpg" alt="Logo" height="90" width="100">
</div>
<div class="col-sm-2 col-sm-offset-8">
<p class="float-right"><strong>Alvarez - Cristofano
2017</strong> </p>
</div>
</div>
</div>
</footer>
</body>
</html>
Vista account.html:
<!DOCTYPE html>
<html>
<head>
<title>Sistema Antichoque</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- JQuery -->
<script src="{{url_for('static',
filename='jquery/jquery-3.2.1.min.js')}}"></script>
</head>
<body>
<!-- Barra -->
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"
aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Sistema Antichoque</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">Mi cuenta <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/">Control</a></li>
<li><a href="/stats">Estadisticas</a></li>
<li><a href="/account">Mis datos</a></li>
<li><a href="/connect">Conectarse</a></li>
<li><a href="/faqs">FAQs</a></li>
<li role="separator" class="divider"></li>
<li><a href="/logout">Logout</a> </li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<!-- Titulo de arriba -->
<div class="container text-center login">
<h1 class="parTitle"><strong>Mis Datos</strong></h1>
</div>
<br>
{% if error %}
<div class="row justify-content-md-center">
<div class="col-md-3 col-xs-12">
<div class="alert alert-danger">{{ error }}</div>
</div>
</div>
<br>
{% elif inform %}
<div class="row justify-content-md-center">
<div class="col-md-3 col-xs-12">
<div class="alert alert-success">{{ inform }}</div>
</div>
</div>
<br>
{% endif %}
<div class="row">
<div class="col-md-6 col-xs-12">
<div class="form-group">
<label for="nombre">Nombre de Usuario</label>
<input type="text" class="form-control" id="username"
name="username" aria-describedby="usernameHelp" value={{username}} required/>
<small id="nombreHelp" class="form-text
text-muted">Aquí debe ingresar su nombre de usuario.</small>
</div>
</div>
<div class="col-md-6 col-xs-12">
<div class="form-group">
<label for="nombre">Contraseña</label>
<input type="password" class="form-control"
id="password" name="password" aria-describedby="passwordHelp"
placeholder="Ingrese su contraseña" required/>
<small id="apellidoHelp" class="form-text
text-muted">Aquí debe ingresar su contraseña.</small>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<div class="form-group">
<label for="email">Email</label>
<input type="text" class="form-control" id="email"
name="email" aria-describedby="emailHelp" value={{email}} required>
<small id="emailHelp" class="form-text
text-muted">Aquí debe ingresar su email.</small>
</div>
</div>
</div>
<br>
<div class="row justify-content-md-center">
<div class="col-md-2 col-md-offset-5 col-xs-12">
<div class="text-center">
<button type="submit" class="btn btn-dark
btn-lg">Registrarse</button>
</div>
</div>
</div>
</form>
</div>
<br>
<br>
<!--Footer-->
<footer class="footer">
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
<img class="img-fluid footerImg"
src="static/assets/logo1.jpg" alt="Logo" height="90" width="100">
</div>
<div class="col-sm-2 col-sm-offset-8">
<p class="float-right"><strong>Alvarez - Cristofano
2017</strong> </p>
</div>
</div>
</div>
</footer>
</body>
</html>
Vista stats.html
<!DOCTYPE html>
<html>
<head>
<title>Sistema Antichoque</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- JQuery -->
<script src="{{url_for('static',
filename='jquery/jquery-3.2.1.min.js')}}"></script>
<!-- <script type="text/javascript" src="{{url_for('static',
filename='scripts/stats.js')}}"></script> -->
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="{{url_for('static',
filename='bootstrap3/css/bootstrap.min.css')}}" />
<link rel="stylesheet" href="{{url_for('static',
filename='stylesheets/main.css')}}" />
</head>
<body>
<!-- Barra -->
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"
aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Sistema Antichoque</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse"
id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
role="button" aria-haspopup="true" aria-expanded="false">Mi cuenta <span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/">Control</a></li>
<li><a href="/stats">Estadisticas</a></li>
<li><a href="/account">Mis datos</a></li>
<li><a href="/connect">Conectarse</a></li>
<li><a href="/faqs">FAQs</a></li>
<li role="separator" class="divider"></li>
<li><a href="/logout">Logout</a> </li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<br>
<div class="container">
</div>
<!--Footer-->
{% if eventos %}
<footer class="footer" style="margin-top: 10px">
{% else %}
<footer class="footer" style="margin-top: 230px">
{% endif %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
<img class="img-fluid footerImg"
src="static/assets/logo1.jpg" alt="Logo" height="90" width="100">
</div>
<div class="col-sm-2 col-sm-offset-8">
<p class="float-right"><strong>Alvarez - Cristofano
2017</strong> </p>
</div>
</div>
</div>
</footer>
</body>
</html>
Hojas de estilos:
index.css:
.jumbotronHeader {
background-image: url("Fondo.jpg");
background-repeat: no-repeat;
background-size: cover;
height: 600px;
margin-top: -20px;
}
.pageTitle {
color: white;
text-align: center;
margin-top: 140px;
}
.parTitle {
color: #2d7eff !important;
font-size: 35px !important;
}
.footer {
background-color: #101010;
color: white;
margin-bottom: 0px;
}
.footerImg {
padding: 15px;
border-radius: 30%;
}
.float-right {
padding-top: 20%;
}
.btn-dark{
background-color: #333 !important;
color: white;
}
.btn-dark:hover{
color:grey !important;
}
main.css:
.footer {
background-color: #101010;
color: white;
margin-bottom: 0px;
}
.login{
margin-top: 4rem;
}
.footerImg {
padding: 15px;
border-radius: 30%;
}
.float-right {
padding-top: 20%;
}
.parTitle {
color: #2d7eff;
}
.btn-dark{
background-color: #333 !important;
color: white;
}
.btn-dark:hover{
color:grey !important;
}
Scripts:
index.js:
function loadIndex() {
$.get("/access", function(data) {
if(data.error!= "Sin conexion"){
if(data.error == 'Perdida de conexion'){
$('#error').removeClass("alert-success");
$('#error').addClass("alert-danger");
$('#error').text(data.error);
}
else{
if(data.state == "Avanzando")
$('#state').addClass("text-success");
else if(data.state == "Retrocediendo")
$('#state').addClass("text-danger");
else{
$('#state').removeClass("text-danger");
$('#state').removeClass("text-success");
}
$( document ).ready(function () {
setInterval(loadIndex, 2500);
});
control.js:
function control(action) {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "/control", true);
xhttp.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
xhttp.send("action=" + action);
}
Controladores(antichoque.py):
from flask import Flask, session, redirect, url_for, escape, request,
render_template
from hashlib import md5
from flask import jsonify
import MySQLdb
import socket
import math
import datetime
app = Flask(__name__)
if __name__ == '__main__':
db = MySQLdb.connect(host="localhost", user="root", passwd="root",
db="antichoque")
cur = db.cursor()
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
class ServerError(Exception):pass
@app.errorhandler(404)
def page_not_found(e):
return redirect(url_for('index'))
@app.route('/')
def index():
global sock
if not 'username' in session:
return render_template('index.html')
else:
# Definiciones locales
username_session = escape(session['username']).capitalize()
username_session = username_session.lower()
cur.execute("SELECT COUNT(1) FROM users WHERE state = 'online' &&
username = %s;", [username_session])
if not cur.fetchone()[0]:
error = request.args.get("error")
if not error:
error = "Usted no esta conectado"
return render_template('index.html', error=error,
session_user_name=username_session, state='Desconectado', direction=0,
marcha=0 , turn=0, back_distance=0, front_distance=0)
else:
inform = request.args.get("inform")
return render_template('index.html', inform=inform,
session_user_name=username_session, state='Desconectado', direction=0,
marcha=0, turn=0, back_distance=0, front_distance=0)
@app.route("/access")
def access():
global sock
global turn
global direction
global speed
if 'username' in session:
# Definiciones locales
username_session = escape(session['username']).capitalize()
username_session = username_session.lower()
f_distance = ''
b_distance = ''
front_distance = 0
back_distance = 0
state = 'Desconectado'
cur.execute("SELECT COUNT(1) FROM users WHERE state = 'online' &&
username = %s;", [username_session])
#Si estoy conectado al servidor del autito puedo utilizarlo sino no
if cur.fetchone()[0] == 1:
try:
sock.settimeout(3)
sock.sendall('1'); #Envio un pedido de informacion, es decir
un solo byte envio
recibido = sock.recv(15)
j = 0
for i in range(0, 5):
while recibido[j] != '/':
if i == 0:
f_distance = f_distance + recibido[j]
elif i == 1:
b_distance = b_distance + recibido[j]
elif i == 2: # Analisis del avance
direction = int(recibido[j])
if recibido[j] == '0':
state = 'Parado'
elif recibido[j] == '1':
state = 'Avanzando'
elif recibido[j] == '2':
state = 'Retrocediendo'
elif i == 3: # Analisis de la velocidad
speed = int(recibido[j])
else: # Analisis de la direccion(si es cero es
porque va hacia adelante o hacia atras)
turn = int(recibido[j])
if recibido[j] == '1':
state = 'Izquierda'
elif recibido[j] == '2':
state = 'Derecha'
j=j+1
j=j+1
#Verificamos que la marcha sea 0 para indicar que el vehiculo
esta parado
if speed == 0:
state = 'Parado'
front_distance = int(f_distance)
back_distance = int(b_distance)
#Agregamos los eventos, si son de importancia
fecha = datetime.date.today()
hora = str(datetime.datetime.now().time())
hora = hora.split(".")[0]
if front_distance < 100:
cur.execute('INSERT INTO eventos(username, fecha, hora,
dist, type) VALUES (%s,%s,%s,%s,%s)', ([username_session], [fecha], [hora],
[front_distance], 'Avance'))
db.commit()
if back_distance < 100:
cur.execute('INSERT INTO eventos(username, fecha, hora,
dist, type) VALUES (%s,%s,%s,%s,%s)', ([username_session], [fecha], [hora],
[back_distance], 'Retroceso'))
db.commit()
except socket.error as socketerror:
sock.close()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
error = 'Perdida de conexion'
print(error)
cur.execute("UPDATE users SET state = 'semi-online' WHERE
username = %s;", [username_session])
result = {"error": error}
return jsonify(result)
result = {"error": "Ninguno", "state": state, "direction":
direction, "marcha": speed, "turn": turn, "front_distance": front_distance,
"back_distance": back_distance}
return jsonify(result)
result = {"error": "Sin conexion"}
return jsonify(result)
password = request.form['password']
cur.execute("SELECT password FROM users WHERE username = %s;",
[username])
# Si la contrasena es correcta permitimos el login
for row in cur.fetchall():
if md5(password).hexdigest() == row[0]:
session['username'] = request.form['username']
cur.execute("UPDATE users SET state = 'semi-online' WHERE
username = %s;", [username])
db.commit()
return redirect(url_for('index'))
@app.route('/connect')
def connect():
global sock
if not 'username' in session:
return render_template('index.html')
else:
username_session = escape(session['username']).capitalize()
username_session = username_session.lower()
cur.execute("SELECT COUNT(1) FROM users WHERE state= 'online' &&
username = %s;", [username_session])
if cur.fetchone()[0]:
return redirect(url_for('index'))
else:
try:
sock.connect(server_address)
cur.execute("UPDATE users SET state = 'online' WHERE username
= %s;", [username_session])
inform = 'Conexion exitosa'
return redirect(url_for('index', inform=inform))
except socket.error as socketerror:
print(socketerror)
error = 'Error al conectarse'
sock.close()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
return redirect(url_for('index', error=error))
@app.route('/logout')
def logout():
global sock
if not 'username' in session:
return render_template('index.html')
else:
username = escape(session['username']).capitalize()
username = username.lower()
session.pop('username', None)
cur.execute("SELECT COUNT(1) FROM users WHERE state = 'online' &&
username = %s;", [username])
if cur.fetchone()[0]:
sock.close()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@app.route('/stats')
def stats():
if not 'username' in session:
return render_template('index.html')
else:
username = escape(session['username']).capitalize()
username = username.lower()
cur.execute('SELECT * FROM eventos WHERE username = %s ORDER BY id
DESC LIMIT 10;', [username])
lista=[row for row in cur.fetchall()]
return render_template('stats.html', eventos=lista)
@app.route('/faqs')
def faqs():
if not 'username' in session:
return render_template('faqs.html')
else:
username_session = escape(session['username']).capitalize()
return render_template('faqs.html',
session_user_name=username_session)
if __name__ == '__main__':
app.run(host='localhost', port=8000)
Apéndice C:
A continuación se adjunta el código correspondiente al archivo autito.ino
Sketch actual
/*FUNCIONES ORIGINALES*/
#include <Arduino.h>
#include <HC_SR04X2.h>
#include <ControlMotor.h>
#include "ESP8266.h"
/*DEFINICIONES DE CONFIGURACION*/
#define BAUDRATE 115200
#define HC_SR04FRONT_OUT 12 // Numero de pin por el cual se envia el pulso
de START
#define HC_SR04FRONT_IN 13 // Numero de pin por el cual se recibe
informacion de la medioción
#define HC_SR04BACK_OUT 9 // Numero de pin por el cual se envia el pulso
de START
#define HC_SR04BACK_IN 8 // Numero de pin por el cual se recibe
informacion de la medioción
#define TAM_BUFFER 128
#define CRITIC_DISTANCE 40
void setup(void)
{
Serial.begin(BAUDRATE);
Serial.print("setup begin\r\n");
wifi.Configuration();
sensor_distance.BackSetup(HC_SR04BACK_OUT,HC_SR04BACK_IN);
sensor_distance.FrontSetup(HC_SR04FRONT_OUT,HC_SR04FRONT_IN);
Serial.print("setup end\r\n");
}
void loop(void)
{
}
}
// FIN MEDICION DE DISTANCIA Y FRENO DE EMEGENCIA
// DEZPLAZAMIENTO
if (frecuency % F_Movement == 0 ){ //Si es momento de realizar un
movimiento
if( direction == 1 && speed != 0 ) { // Si voy hacia adelante
Serial.print("ADELANTE\r\n");
if( turn==0){ // si voy hacia adelante en linea recta
control.avanzar(speed);
}
if( turn==1){ // si voy hacia adelante en hacia la izqueirda
control.girarIzquierda();
}
if( turn==2){ // si voy hacia adelante en hacia la izqueirda
control.girarDerecha();
}
}
if( direction == 2 && speed != 0 ) { // Si voy hacia atrás
Serial.print("ATRAS\r\n");
control.retroceder();
}
if (direction == 0 || speed == 0){
control.parar();
}
Serial.print(direction);
Serial.print(speed);
Serial.print(turn);
Serial.print("\r\n");
}
// FIN DEZPLAZAMIENTO
// COMUNICACION
if (frecuency % F_Communication == 0 ){ //SI es momento de procesar la
comunicacion
len=wifi.Receive_data(buffer);
if (len == 3){ //SI SE RECIBE ORDEN
Serial.print("ORDEN");
Serial.print("\r\n");
//REcibí un mensaje de desplazamiento, almacenamiento de los
movimientos que decidió el usuario
direction=buffer[0]-48; //se resta 48, pues el valro que
se recibe está en ascci
speed=buffer[1]-48;
turn=buffer[2]-48;
Serial.print(direction);
Serial.print(speed);
Serial.print(turn);
}
if (len == 1){ //SI PIDE INFORMACION
Serial.print("Estadisticas");
Serial.print("\r\n");
data_send=(String(distance_front, 0)+'/'+String(distance_back,
0)+'/'+String(direction,DEC)+'/'+String(speed,DEC)+'/'+String(turn,DEC)+'/');
//preparación de la informacio na enviar
for(len=0; len<data_send.length();len++){ // Se coloca el
string en el buffer para su proximo envio
if(data_send[len]!= 32){ //en el caso de que la
conversion a string me de un caracater espacio, lo reemplazo por '0'(En la
práctica sucede)
buffer[len]=data_send[len];
}else{
buffer[len]='0';
}
//Serial.print((char)buffer[len]);
}
//Serial.print("\r\n");
//envio del estado
Serial.print(data_send.length());
Serial.print("\r\n");
wifi.Send_data(buffer,data_send.length());
Serial.print("Envio de datos");
Serial.print("\r\n");
for (len=0;len<data_send.length();len++){
Serial.print((char)buffer[len]);
}
Serial.print("\r\n");
}
// FIN COMUNICACION
/*FUNCIONES ORIGINALES*/
#include <Arduino.h>
Sketch para vehículo con motores similares.
/*DEFINICIONES DE CONFIGURACION*/
#define BAUDRATE 115200
#define HC_SR04FRONT_OUT 12 // Numero de pin por el cual se envia el pulso
de START
#define HC_SR04FRONT_IN 13 // Numero de pin por el cual se recibe
informacion de la medioción
#define HC_SR04BACK_OUT 9 // Numero de pin por el cual se envia el pulso
de START
#define HC_SR04BACK_IN 8 // Numero de pin por el cual se recibe
informacion de la medioción
#define TAM_BUFFER 128
#define CRITIC_DISTANCE 40
#define SPEED_RELATIONSHIP 80 //relacion para auto con 3 marchas
void setup(void)
{
Serial.begin(BAUDRATE);
Serial.print("setup begin\r\n");
wifi.Configuration();
sensor_distance.BackSetup(HC_SR04BACK_OUT,HC_SR04BACK_IN);
sensor_distance.FrontSetup(HC_SR04FRONT_OUT,HC_SR04FRONT_IN);
Serial.print("setup end\r\n");
}
void loop(void)
{
}
}
// FIN MEDICION DE DISTANCIA Y FRENO DE EMEGENCIA
// DEZPLAZAMIENTO
if (frecuency % F_Movement == 0 ){ //Si es momento de realizar un
movimiento
if( direction == 1 && speed != 0 ) { // Si voy hacia adelante
Serial.print("ADELANTE\r\n");
if( turn==0){ // si voy hacia adelante en linea recta
control.avanzar(SPEED_RELATIONSHIP*speed);
}
if( turn==1){ // si voy hacia adelante en hacia la izqueirda
control.girarIzquierda(SPEED_RELATIONSHIP*speed);
}
if( turn==2){ // si voy hacia adelante en hacia la izqueirda
control.girarDerecha(SPEED_RELATIONSHIP*speed);
}
}
if( direction == 2 && speed != 0 ) { // Si voy hacia atrás
Serial.print("ATRAS\r\n");
control.retroceder(SPEED_RELATIONSHIP);
}
if (direction == 0 || speed == 0){
control.parar(3);
}
Serial.print(direction);
Serial.print(speed);
Serial.print(turn);
Serial.print("\r\n");
}
// FIN DEZPLAZAMIENTO
// COMUNICACION
if (frecuency % F_Communication == 0 ){ //SI es momento de procesar la
comunicacion
len=wifi.Receive_data(buffer);
if (len == 3){ //SI SE RECIBE ORDEN
Serial.print("ORDEN");
Serial.print("\r\n");
//REcibí un mensaje de desplazamiento, almacenamiento de los
movimientos que decidió el usuario
direction=buffer[0]-48; //se resta 48, pues el valro que
se recibe está en ascci
speed=buffer[1]-48;
turn=buffer[2]-48;
Serial.print(direction);
Serial.print(speed);
Serial.print(turn);
}
if (len == 1){ //SI PIDE INFORMACION
Serial.print("Estadisticas");
Serial.print("\r\n");
data_send=(String(distance_front, 0)+'/'+String(distance_back,
0)+'/'+String(direction,DEC)+'/'+String(speed,DEC)+'/'+String(turn,DEC)+'/');
//preparación de la informacio na enviar
for(len=0; len<data_send.length();len++){ // Se coloca el
string en el buffer para su proximo envio
if(data_send[len]!= 32){ //en el caso de que la
conversion a string me de un caracater espacio, lo reemplazo por '0'(En la
práctica sucede)
buffer[len]=data_send[len];
}else{
buffer[len]='0';
}
//Serial.print((char)buffer[len]);
}
//Serial.print("\r\n");
//envio del estado
Serial.print(data_send.length());
Serial.print("\r\n");
wifi.Send_data(buffer,data_send.length());
Serial.print("Envio de datos");
Serial.print("\r\n");
for (len=0;len<data_send.length();len++){
Serial.print((char)buffer[len]);
}
Serial.print("\r\n");
}
// FIN COMUNICACION
// CONFIGURACION DE TIEMPOS
frecuency++;//Aumento de la iteracion realizada
if (frecuency == 6300){
frecuency=0;
}
// FIN CONFIGURACION DE TIEMPOS
}