Titulo
BiciParqueadero
Participantes
Sebastián Candela Herrera
Juan Sebastián Romero Ulloa
Juan Felipe Gozalez perez
Santiago Vega Burgos
Abstract
The project of biciparquadero, focuses on the report of the condition of the parking lots to the users, through a smart device with the access to the internet, it is possible to access an online platform that reports the status of entry and exit of each one of The parking places where the user has a registration with a personal account for the use of the platform.
Problema
El uso de bicicletas como medio de trasporte alternativo se hace mucho más frecuente en especial en las grandes ciudades, los espacios de parqueaderos de bicicletas en estacionamientos privados y públicos está tomando gran importancia, pero ¿cómo los usuarios saben de la disponibilidad de estos parqueaderos, sin la necesidad de desplazarse hasta el lugar? O ¿Cómo los administradores de estos parqueaderos ejercen un control sobre el estado de los puestos de parqueo?
Diseño (Arquitectura HW)
Desarrollo
Funcionamiento
Para el desarrollo del proyecto se estableció el montaje de 4 shitches los cuales irán conectados a una tarjeta beaglebone que reportara el estado de los puestos de parqueo a Bucket, una base de datos en la nube.
Desde un dispositivo inteligente podemos acceder a la página de inicio de inicio de BiciParquedero en donde nos ofrecerá la posibilidad de registrarnos o acceder a la cuenta del usuario, después del registro el usuario podrá acceder a la página en donde se encontrara toda la información de los puestos de parqueo tomad desde Buket, esta información se actualizara en tiempo real y se observa en la página cada vez que el usuario la cargue o refresque.
Caracterización del sensor
Un interruptor o switch es el causante del reporte del estado del puesto de parqueo, este se caracteriza por ser el responsable por el paso de flujo eléctrico, cuando se oprime corta flujo de corriente eléctrica o permite el paso de esta dependiendo de la aplicación y del tipo de sensor, en su mayoría está compuesto de dos terminales de acero inoxidable que se conectado a una fuente de corriente continua, al momento en el que el puesto de parqueo se ocupe el interrultor se activa emitiendo una seña directo a Buket cambiando el estado en la base de datos.
Esquemático del montaje
Posibles aplicaciones
Este proyecto está pensado para la implementación en sitios de parqueo para toda tipo de vehículos en donde se ayude no solo a los administradores de estos lugares, teniendo una mejor organización de su infraestructura, sino a los usuarios como principales beneficiarios, ya que con este proyecto la búsqueda de parqueadero será mucho más cómoda y águila en zonas de alta concentración vehicular.
Dificultad encontrada
Al determinar el uso de un sensor se tiene que tener demasiadas consideraciones, entre ellas el tipo de vehículo para el cual el sensor va a detectar su presencia, las condiciones del terreno son importantes a tener en cuenta el tipo de sensor a elegir debido a su deterioro, por este motivo para este proyecto se propuso un switch dejando abierta la posibilidad para cualquier tipo de sensor.
La conexión de la página en HTML con la base de datos en BUCKET no permite una actualización en tiempo real de la página sin necesidad de estar refrescándola constantemente.
Configuración - paso a paso
Primero se debe realizar la siguiente configuración en la beaglebone
Configuración en Beaglebone
Para configurar la tarjeta inicialmente es necesario descargar un sistema operativo a su tarjeta de memoria SD sobre la cual lo va a correr y almacenar los cambios que se vayan a realizar para ello es recomendable visitar la siguiente pagina que contiene ejemplos de intalacion: http://elinux.org/BeagleBoardUbuntu#BeagleBone_White.2FBlack.2FGreen
Se procedera a identificar la tarjeta:
(la tarjeta implementada es una tarjeta beaglebone black sin embargo su configuracion es similar)
Para llevar a cabo al configuracion de la tarjeta Beaglebone, es necesario configurar el internet, la tarjeta se va a comportar como un enrutador por lo tanto debemos configurar una direccion Ipv4 en la interfaz, es necesario tener el nombre correcto de la interfaz ya que no en todos los dispositivos es igual, se creó un script ejecutable en bash con las siguientes lineas de codigo:
#!bin/bash
sudo ifconfig enx1cba8ca2ed6a 192.168.7.1/30 broadcast 192.168.7.3
sudo route add default gw 192.168.7.1
ping 192.168.7.1 -c 4
sudo iptables -A FORWARD -o wlp3s0 -i enx1cba8ca2ed6a -s 192.168.0.0/24 -m conn$
sudo iptables -t nat -F POSTROUTING
sudo iptables -t nat -A POSTROUTING -o wlp3s0 -j MASQUERADE
sudo iptables-save | sudo tee /etc/iptables.sav
route del default gw 192.168.7.1
En el cual se añaden rutas estaticas, cabe aclarar que es necesario tener acceso root al sistema operativo implementado en la tarjeta.
En segunda instancia se accedera a la beaglebone implementando el siguiente comando en la pantalla de comandos: sudo screen /dev/ttyUSB0 115200 luego ingresar el usuario y contraseña designados para acceder al sistema operativo de la tarjeta. Luego desde la pantalla de comandos de la tarjeta Beaglebone se debe implementar el siguiente codigo que terminará de implementar la configuracion de internet:
sudo /etc/init.d/networking stop
sudo ip route add default via 192.168.7.1
sudo /etc/init.d/networking restart
ping 8.8.8.8 -c 4
Debe crearse un script igualmente en bash y se debera ejecutar para finalizar la configuracion en internet de la tarjeta.
Configuración en PC
Para poder realizar todas las configuraciones necesarias se necesitan de ciertas librerias
import commands
import time
import MySQLdb
import requests
import sys
import json
from wtforms import Form, BooleanField, StringField, PasswordField, validators
from flask import Flask, request, render_template, redirect, flash, url_for
Es necesario tener instalado MySQL para crear las bases de datos que se van a usar para almacenar todos los datos recopilados.
Para poder realizar este proyecto se hizo necesario el uso de dos tablas, una para guardar los registros de nuevos usuarios en una base de datos, y otra para el control de ingreso y salida de las bicicletas a el parqueadero.
Para poder crear una base de datos en MySQL desde python se ha de usar el siguiente código.
import commands
import MySQLdb
db=MySQLdb.connect("localhost","root","12345","TEST_DB3")
cursor=db.cursor()
cursor.execute("DROP TABLE IF EXIST BICI2")
sql="""CREATE TABLE BICI2 (PUESTO INT PRIMARY KEY,LLEGADA CHAR(20) NOT NULL,ESTADO CHAR(20) NOT NULL )"""
cursor.execute("SELECT * FROM REGISTER")
try:
cursor.execute(sql)
db.commit()
except:
db.rollback()
La parte de conexión define el usuario, su contraseña y la base de datos donde se va a crear la tabla, lo siguiente seria la operación de insertado de valores en esta.
Primero se crea una clase de registro, donde el usuario va a digitar su nombre de usuario, su correo, su contraseña y debe aceptar los términos y servicios.
class RegistrationForm(Form):
username = StringField('UserName', [validators.Length(min=4, max=25)])
email = StringField('Email Address', [validators.Length(min=6, max=35)])
password = PasswordField('New Password', [
validators.DataRequired(),
validators.EqualTo('confirm', message='Passwords must match')
])
confirm = PasswordField('Repeat Password')
accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])
Existe una clase de Ingreso donde se autentifica un usuario ya registrado
class LoginForm(Form):
email = StringField('Email Address')
password = PasswordField('New Password')
Existen varias funciones en el programa, la primera es la de register, donde se almacena en una base de datos los datos que los nuevos usuarios ingresan, los guarda en la base de datos de MYSQL para posteriomente extraerlos y hacer una comprobacionde datos, si la contraseña corresponde con el email registrado.
def register():
form = RegistrationForm(request.form)
if request.method == 'POST' and form.validate():
db=MySQLdb.connect("localhost","root","12345","TEST_DB3")
cursor=db.cursor()
try:
cursor.execute("INSERT INTO REGISTER(USERNAME,EMAIL,PASSWORD,TOS)VALUES(%s,%s,%s,'1')",(form.username.data,form.email.data,form.password.data))
db.commit()
sql = "SELECT * FROM REGISTER"
cursor = db.cursor()
cursor.execute(sql)
db.commit()
i=0;
a=0;
z=0;
while ( a < 100 ):
results = cursor.fetchone()
print(results)
i=results.count(form.email.data)
a=a+1;
if ( i == 1 ):
z=z+1;
except:
db.rollback()
flash('You are registered')
if ( z > 1 ):
print("repetido")
bandera=0;
flash('You are registered')
return render_template('registererror.html', form=form)
else:
print("no repetido")
return redirect(url_for('login'))
return render_template('register.html', form=form)
también verifica si hay un usuario ya registrado o con información errónea y no lo deja continuar el proceso de registro hasta que todos los datos estén en correcta forma.
Luego esta la función de Login la cual deja ingresar a la pagina del parqueadero a los usuarios que ya estén correctamente registrados de no ser así, estos no pueden ingresar.
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm(request.form)
if request.method == 'POST' and form.validate():
db=MySQLdb.connect("localhost","root","12345","TEST_DB3")
cursor=db.cursor()
try:
sql = "SELECT * FROM REGISTER"
cursor = db.cursor()
cursor.execute(sql)
i1=0;
a1=0;
z1=1;
poliutre=1;
rows=[]
for row in cursor:
rows.append(row)
print(row)
while ( a1 < 100 ):
results1 = cursor.fetchone()
i1=results1.count(form.email.data)
a1=a1+1;
if ( i1 == 1 ):
z1=z1+1;
print(results1[1])
print(form.email.data)
if( results1[1] == form.email.data ):
if (results1[2]==form.password.data):
poliutre=2;
print(poliutre)
except:
db.rollback()
print(poliutre)
data = cursor.fetchall()
if ( z1 > 1 ):
print("EMAIL REGISTRADO")
if ( poliutre > 1 ):
print("pagina bici")
return render_template('db.html',data=data) #pagina bici
else:
return render_template('loginerror.html', form=form)
else:
return render_template('error.html', form=form) #email no registrado
print("NO REGISTRADO")
return render_template('login.html', form=form)
Finalmente esta la clase dB la cual es la pagina oficial del parqueadero, esta muestra una tabla con las posiciones su ocupancia y la hora de ingreso al parqueadero.
@app.route('/db', methods=['GET', 'POST'])
def db():
db=MySQLdb.connect("localhost","root","12345","TEST_DB3")
cursor= db.cursor()
cursor.execute("SELECT * FROM BICI2")
rows= []
a=requests.get('https://bucket.usantotomas.edu.co:8443/api/sensors/5909ecec7be12b09d0148a66/captures?userToken=?24afosdsv0lgq07a3546huapf8')
y = json.loads(a.text)
bo=str(y)[43:44]
hora=time.strftime("%H:%M:%S")
print hora
print "primer sensor"
print bo
a1=requests.get('https://bucket.usantotomas.edu.co:8443/api/sensors/5939bc7c7be12b4cfb811188/captures?userToken=?24afosdsv0lgq07a3546huapf8')
y1 = json.loads(a1.text)
bo1=str(y1)[43:44]
print "segundo sensor"
print bo1
a2=requests.get('https://bucket.usantotomas.edu.co:8443/api/sensors/5939bcbc7be12b4cfb811189/captures?userToken=?24afosdsv0lgq07a3546huapf8')
y2 = json.loads(a.text)
bo2=str(y2)[43:44]
print "tercer sensor"
print bo2
a3=requests.get('https://bucket.usantotomas.edu.co:8443/api/sensors/5939bcc47be12b4cfb81118a/captures?userToken=?24afosdsv0lgq07a3546huapf8')
y3 = json.loads(a.text)
bo3=str(y3)[43:44]
print "cuarto sensor"
print bo3
for row in cursor:
rows.append(row)
print(row)
data=cursor.fetchall()
cursor.execute("INSERT INTO BICI2 VALUES(1,%s,%s) ON DUPLICATE KEY UPDATE LLEGADA = VALUES(LLEGADA), ESTADO = VALUES(ESTADO);",(hora,bo))
cursor.execute("INSERT INTO BICI2 VALUES(2,%s,%s) ON DUPLICATE KEY UPDATE LLEGADA = VALUES(LLEGADA), ESTADO = VALUES(ESTADO);",(hora,bo1))
cursor.execute("INSERT INTO BICI2 VALUES(3,%s,%s) ON DUPLICATE KEY UPDATE LLEGADA = VALUES(LLEGADA), ESTADO = VALUES(ESTADO);",(hora,bo2))
cursor.execute("INSERT INTO BICI2 VALUES(4,%s,%s) ON DUPLICATE KEY UPDATE LLEGADA = VALUES(LLEGADA), ESTADO = VALUES(ESTADO);",(hora,bo3))
db.commit()
return render_template('db.html',data=data)
En el main encontramos
if __name__ == '__main__':
app.run(debug = True)
Configuración en Bucket
Para realizar la configuración en bucket se tuvo que crear una cuenta en bucket con nuestro correo institucional y con una clave dada por el maestro. Luego de esto se siguieron los siguientes pasos:
El código ejecuta en la beagleBone, que nos permitía enviar los datos a Bucket fue el siguiente, el donde se tenia que importar las librerías:
import Adafruit_BBIO.GPIO as GPIO
import requests
import os
import sys
import commands
from time import sleep

GPIO.setup("P8_14", GPIO.IN) #PIN 1
GPIO.setup("P8_18", GPIO.IN) #PIN 2
GPIO.setup("P8_12", GPIO.IN) #PIN 3
GPIO.setup("P8_16", GPIO.IN) #PIN 4
Configuracion de la lógica del programa,
i=0
while (i == 0):
if GPIO.input("P8_14"): #CONDICIÓN SI EL PIN ESTA ACTIVO
print("HIGH")
#headers= { 'Content-Type': 'application/json', }
#data= {"sensorId":"5909ecec7be12b09d0148a66","captureTypeName":"cms","value":"10","captureDate":"2017-06-02 16:00:30"}
headers = { 'Content-Type': 'application/json', }
data = '{"sensorId":"5909ecec7be12b09d0148a66", "captureTypeName": "bool", "value":"1", "captureDate":"2017-02-10 1:00:30"}' #DATOS A ENVIAR
requests.post('https://bucket.usantotomas.edu.co:8443/api/sensors/5909ecec7be12b09d0148a66/captures?userToken=24afosdsv0lgq07a3546huapf8',headers=headers, data=data) # IMPRESIÓN EN BUCKET
#sleep(5)
else: #CONDICION SI EL PIN ESTA INACTIVO
headers = { 'Content-Type': 'application/json', }
data = '{"sensorId":"5909ecec7be12b09d0148a66", "captureTypeName": "bool", "value":"0", "captureDate":"2017-02-10 1:00:30"}'
requests.post('https://bucket.usantotomas.edu.co:8443/api/sensors/5909ecec7be12b09d0148a66/captures?userToken=24afosdsv0lgq07a3546huapf8',headers=headers, data=data)
#sleep(5)
print("LOW")
if GPIO.input("P8_18"): #Condición del segundo PIN
print("HIGH1")
headers = { 'Content-Type': 'application/json', }
data = '{"sensorId":5939bc7c7be12b4cfb811188", "captureTypeName": "bool", "value":"1", "captureDate":"2017-02-10 1:00:30"}'
requests.post('https://bucket.usantotomas.edu.co:8443/api/sensors/5939bc7c7be12b4cfb811188/captures?userToken=24afosdsv0lgq07a3546huapf8',headers=headers, data=data)
else:
print("LOW1")
headers = { 'Content-Type': 'application/json', }
data = '{"sensorId":"5939bc7c7be12b4cfb811188", "captureTypeName": "bool", "value":"0", "captureDate":"2017-02-10 1:00:30"}'
requests.post('https://bucket.usantotomas.edu.co:8443/api/sensors/5939bc7c7be12b4cfb811188/captures?userToken=24afosdsv0lgq07a3546huapf8',headers=headers, data=data)
if GPIO.input("P8_12"): #Condicion del TERCER PIN
print("HIGH2")
headers = { 'Content-Type': 'application/json', }
data = '{"sensorId":"5939bcbc7be12b4cfb811189", "captureTypeName": "bool", "value":"1", "captureDate":"2017-02-10 1:00:30"}'
requests.post('https://bucket.usantotomas.edu.co:8443/api/sensors/5909ecec7be12b09d0148a66/captures?userToken=24afosdsv0lgq07a3546huapf8',headers=headers, data=data)
else:
print("LOW2")
headers = { 'Content-Type': 'application/json', }
data = '{"sensorId":"5939bcbc7be12b4cfb811189", "captureTypeName": "bool", "value":"0", "captureDate":"2017-02-10 1:00:30"}'
requests.post('https://bucket.usantotomas.edu.co:8443/api/sensors/5909ecec7be12b09d0148a66/captures?userToken=24afosdsv0lgq07a3546huapf8',headers=headers, data=data)
if GPIO.input("P8_16"): #Condicion del CUARTO PIN
print("HIGH3")
headers = { 'Content-Type': 'application/json', }
data = '{"sensorId":"5939bcc47be12b4cfb81118a", "captureTypeName": "bool", "value":"1", "captureDate":"2017-02-10 1:00:30"}'
requests.post('https://bucket.usantotomas.edu.co:8443/api/sensors/5909ecec7be12b09d0148a66/captures?userToken=24afosdsv0lgq07a3546huapf8',headers=headers, data=data)
else:
print("LOW3")
headers = { 'Content-Type': 'application/json', }
data = '{"sensorId":"5939bcc47be12b4cfb81118a", "captureTypeName": "bool", "value":"0", "captureDate":"2017-02-10 1:00:30"}'
requests.post('https://bucket.usantotomas.edu.co:8443/api/sensors/5909ecec7be12b09d0148a66/captures?userToken=24afosdsv0lgq07a3546huapf8',headers=headers, data=data)
Para extraer los datos que se enviaban a la BeagleBone, se tuvo que crear un script en
import requests
import sys
import json
import commands
Para empezar a realizar el get de cada uno de los datos que se encontraba en bucket, se tuvo que crear un sensor ID, por cada entrada que sensor que le llegaba a ala beagle
i=0
while (i ==0): #Ciclo infinito
#El ID del primer sensor es 5909ecec7be12b09d0148a6
#El token dado por el profesor 24afosdsv0lgq07a3546huapf8
a=requests.get('https://bucket.usantotomas.edu.co:8443/api/sensors/5909ecec7be12b09d0148a66/captures?userToken=?24afosdsv0lgq07a3546huapf8')
#p= a.text
y = json.loads(a.text) #Con este codigo podiamos retirar lo que habia en la pagina en texto
#print y[0]
bo=str(y)[43:44] #Del texto se extrae el valor que envio la Beagle unicamente
print "primer sensor"
print bo
#p.find(1)
#print(a.text)
#
a1=requests.get('https://bucket.usantotomas.edu.co:8443/api/sensors/5939bc7c7be12b4cfb811188/captures?userToken=?24afosdsv0lgq07a3546huapf8') #Segundo sensor
#p= a.text
y1 = json.loads(a1.text)
#print y[0]
bo1=str(y1)[43:44]
print "segundo sensor"
print bo1
#p.find(1)
#print(a.text)
#
a2=requests.get('https://bucket.usantotomas.edu.co:8443/api/sensors/5939bcbc7be12b4cfb811189/captures?userToken=?24afosdsv0lgq07a3546huapf8') #Tercer sensor
#p= a.text
y2 = json.loads(a.text)
#print y[0]
bo2=str(y2)[43:44]
print "tercer sensor"
print bo2
#p.find(1)
#print(a.text)
#
a3=requests.get('https://bucket.usantotomas.edu.co:8443/api/sensors/5939bcc47be12b4cfb81118a/captures?userToken=?24afosdsv0lgq07a3546huapf8') #Cuarto sensor
#p= a.text
y3 = json.loads(a.text)
#print y[0]
bo3=str(y3)[43:44]
print "cuarto sensor"
print bo3
#p.find(1)
#print(a.text)
Código fuente - Scripts en la Beaglebone
sudo apt-get install python3.1