Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Materiales
MicroSD
Cable ethernet
Fuente de 5V 2amp
Raspberry pi
PC
Software Putty
Cable HDMI(opcional)
Teclado(opcional)
Mouse(opcional)
Usb Wifi(opcional)
Instalación de SO
1. SO Raspbian, descargarlo de la página oficial de Raspberry Pi desde aquí
2. una memoría microSD de al menos 4Gb (recomiendo que sea de clase 10)
3. software para grabar el SO en la memoria microSD, en este caso optaremos por
Win32DiskImager
Primera conexión:
Formaremos una red local entre el Rpi y la PC para poder acceder a esta sin necesidad de
una pantalla y teclado ni demás conectores.Los materiales que se necesitaremos son:
Despues de grabar la memoría microSD con Raspbian, lo insertamos en la pc y vamos a
editar el archivo cmdline.txt:
ip address: your.rpi.ip.another_address
netmask: 255.255.255.0
gateway: your.rpi.ip.address
Desde https://www.raspberrypi.org/documentation/remote-access/ssh/ :
As of the November 2016 release, Raspbian has the SSH server disabled by default.
You will have to enable it manually. This is done using raspi-config: Enter sudo raspi-
config in the terminal, first select Interfacing options, then navigate to ssh, press Enter
and select Enable or disable ssh server. For headless setup, SSH can be enabled by
placing a file named 'ssh', without any extension, onto the boot partition of the SD card.
Segun un aviso de la actualización, se removio el acceso ssh por defecto por lo que no se
podrá seguir el manual para versiones posteriores a Noviembre del 2016.
En los foros nos muestra una solución para la version Lite de raspbian. Primero debemos
ingresar al archivo cmdline.txt añadir lo siguiente:
ip=192.168.1.200::192.168.1.1:255.255.255.0:rpi:eth0:off
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
Despues de esto para habilitar la conexión ssh solo es necesario crear un archivo vacio
llamado ssh.
En el caso de nuestra computadora debemos configurarlo como:
$ ip address: 192.168.1.xxx
$ netmask: 255.255.255.0
$ gateway: 192.168.1.1
Nota: La creación del archivo ssh o ssh.txt habilta el protócolo ssh en RASPBIAN JESSIE
WITH PIXEL pero la configuración de ip estática genera que el boot no se complete.
Cableada(IP Dinámica)
No editamos nada pero necesitaremos un software que escanee la red como Advanced IP
Scanner donde buscaremos la red que tenga como fabricante a Raspberry Pi Foundation.
Cableada(IP Estática)
Editamos el archivo interfaces:
y cambiamos a:
auto eth0
#iface eth0 inet dhcp
iface eth0 inet static
address 192.168.1.11
netmask 255.255.255.0
gateway 192.168.1.1 #dirección ip del router
Inalámbrica
Editamos el archivo wpa_supplicant.conf: :
y cambiamos a:
network={
ssid="Your ssid"
psk="your wifi password"
}
Y sino tendremos que configurar el DNS, para ello editamos el archivo /etc/resolv.conf
Con ello ya deberiamos poder acceder a internet, comprobamos ello con el comando
anteriormente descrito
El Kernel Linux, parte fundamental del Sistema Operativo, fue desarrollado por Linus
Torvals, utilizando como modelo a UNIX. Una de las diferencias fundamentales entre los
núcleos Linux y UNIX, es que el primero, es Software Libre, mientras que el segundo no lo
es.
Por otra parte, mientras existe un único Kernel Linux (con versiones diferentes), existen
decenas y hasta cientos de distribuciones GNU/Linux, es decir, diferentes Sistemas
Operativos basados en el Kernel Linux, entre las cuales se destacan: Debian, Ubuntu,
Lbuntu, Fedora, Gentoo, Slackware, CentOS, ArchLinux, Asturix, entre otros cientos.
Un sistema Linux reside bajo un árbol jerárquico de directorios muy similar a la estructura
del sistema de archivos de plataformas Unix.
Todo esto hizo pensar a la comunidad que, posteriormente, desarrollarían el proyecto FHS
(Filesystem Hierarchy Standard) en 1993.
Organización de Archivos
El contenido de este directorio debe ser el adecuado para reiniciar, restaurar, recuperar y/o
reparar el sistema, es decir, debe proporcionar métodos, herramientas y utilidades
necesarias para cumplir estas especificaciones.
/bin
En este directorio se ubica el código binario o compilado de los programas y comandos que
pueden utilizar todos los usuarios del sistema.
/boot
Este directorio contiene todo lo necesario para que funcione el proceso de arranque del
sistema.
/boot almacena los datos que se utilizan antes de que el kernel comience a ejecutar
programas en modo usuario.
El núcleo del sistema operativo (normalmente se guarda en el disco duro como un fichero
imagen llamado vmlinuz-versión _ núcleo) se debe situar en este directorio o, en el
directorio raíz.
Uno de ellos está reservado para el propio kernel, denominado el modo núcleo; y el otro
está reservado para el resto de programas, llamado el modo usuario.
Realmente se crean dos entornos totalmente separados, es decir, cada uno tiene su propia
zona de memoria y procesos independientes.
Démonos cuenta que esta técnica ofrece mucha seguridad y estabilidad al sistema.
Cuando un proceso del modo usuario necesita recursos del modo kernel (por ejemplo,
acceder a la memoria USB) se hacen uso de las famosas llamadas al sistema (interface que
ofrece el núcleo para la comunicación del modo usuario con el modo kernel).
/dev
Por ejemplo, el contenido de la sexta partición del disco duro será /dev/hda5.
Además, es importante saber que los dispositivos pueden ser de bloque o de carácter.
Normalmente los dispositivos de bloque son los que almacenan datos y, los de carácter los
que transfieren datos.
/etc
Archivos que son propios del ordenador y que se utilizan para controlar el funcionamiento
diversos programas.
Deben ser ficheros estáticos y nunca pueden ser archivos binarios y/o ejecutables.
X11 Sistema de ventanas graficas originario de UNIX en su versión 11. Este sistema
tiene la peculiaridad de ser totalmente independiente del sistema operativo. Es una
estructura cliente-servidor.
En definitiva, /etc mantiene los archivos de configuración del sistema para un ordenador
específico.
/home
Directorio que contiene los subdirectorios que son directorios origen para cada uno de los
usuarios del sistema.
Cada subdirectorio /home/user de cada usuario proporciona el lugar para almacenar sus
ficheros, así como los archivos de configuración propios de cada uno.
Es importante saber que también algunos servicios, y no solo usuarios, crean aquí su
directorio origen, por ejemplo: el servicio de transferencia de ficheros (FTP).
/lib
El directorio /lib contiene librerías compartidas (similar a las dlls para los usuarios de
Windows) necesarias para arrancar el sistema y para los ficheros ejecutables contenidos
en, por ejemplo, /bin.
También contiene módulos del kernel esenciales que permiten el funcionamiento de muchos
elementos Hardware. Se ubicarán normalmente en /lib/modules/versión-del-kernel/.
En el apartado /usr/include se explica que son y como funcionan las librerías y los archivos
cabecera.
/media
Este directorio contiene los subdirectorios que se utilizan como puntos del montaje para los
medios de almacenamiento, tales como disquetes, CD-ROM y memorias USBs.
/mnt
Este directorio contiene sistemas de archivos externos que hayan sido montados.
Las entidades que aparecen dentro de /mnt representan recursos externos a los que se
puede acceder a través de este directorio.
/opt
Las aplicaciones crean un subdirectorio dentro de /opt denominado con el mismo nombre
del programa.
/root
/sbin
Los programas y comandos que se utilizan para la administración del sistema se almacenan
en /sbin, /usr/sbin y /usr/local/sbin.
Contiene los archivos de datos específicos para cada servicio instalado en el sistema.
/tmp
El directorio /usr
Es la segunda sección más grande o estructura jerár quica (después del directorio raíz) del
sistema de ficheros.
Este directorio está pensado para almacenar datos que se puedan compartir con otros
hosts.
Estructura de /usr
/usr/bin
/usr/include
En C es posible utilizar funciones que ya estén predefinidas (como otros muchos lenguajes
de programación) para incluirlas en el programa que estemos haciendo. Esta técnica se
denomina programación modular.
Estas funciones se llaman comúnmente archivos cabecera (.h de header) y contienen las
declaraciones externas de una librería.
/usr/lib
Este directorio incluye librerías compartidas y ficheros binarios pensados para no ser
ejecutados directamente por los usuarios del sistema.
/usr/local/
/usr/local/ es para uso del administrador del sistema cuando instala software localmente.
Puede usarse para programas y datos que son compartibles entre un grupo de máquinas
/usr/sbin
/usr/src
Por lo general, en /usr/src (src de source o, fuente en castellano) se guarda el código fuente
del Kernel del sistema.
Para comprobar si tenemos en nuestra distribución los fuentes del kernel instalados,
deberíamos ver un enlace simbólico llamado linux.
El directorio /var
Este directorio va ha contener ficheros de datos variables y temporales, así como archivos
spool (ficheros almacenados en fila en espera a ejecutarse, como por ejemplo colas de
impresión).
Todos los log del sistema y los generados por los servicios instalados, se ubican dentro de
la estructura jerárquica de /var. Esto quiere decir que el tamaño global de este directorio va
ha crecer constantemente.
/var/cache
El sistema de paquetes de Debian (apt-get), mantiene y almacena todos los paquetes que
nos hemos instalado con el gestor de paquetes Apt-get. Por ejemplo, si ejecutamos:
Posteriormente lo podemos borrar. Por defecto Debian almacena aquí todo los paquetes
que nos hemos instalado con su gestor de paquetes Apt-get.
/var/lib
/var/lock
/var/log
En /var/log se guardan los mensajes de registro generados por el sistema operativo y por
diversos servicios.
Por ejemplo:
/var/mail
Linux enviará aquí los archivos de correos de cada usuario del sistema.
/var/run
/var/run contiene archivos con información del sistema que lo describen desde que se
arrancó. Generalmente, se borrará todos los archivos que cuelgan de este subdirectorio al
comenzar el proceso de arranque.
Estos archivos con información del sistema son los llamados archivos identificados de
procesos ó PID, que guardan el identificador del proceso (Process ID).
/var/spool
Un ejemplo claro puede ser los trabajos que guarda la impresora para, posteriormente,
ejecutarlos por un orden de llegada y/o prioridad.
/var/tmp
Existen otra serie de directorios que no especifica el estándar FSH, pero que son
importantes.
Las herramientas y utilidades para restaurar y/o reparar el sistema de archivos almacenan
los datos en este directorio.
Es un espacio temporal donde se guardan los datos que se recuperan después de una
caída del sistema.
Por último, decir que este directorio existe sólo en distribuciones que tengan como sistemas
de archivos ext2 o ext3.
Directorio /proc
Comandos en GNU-Linux
Algunos de los miles de comandos de linux!!!
ls listing $ ls /home/pi
cd change directory $ cd ..
rm remove $ rm archivo.txt
$ nano name_of_file
raspi-config
La herramienta Raspi-config le ayuda a configurar su Raspberry Pi; varios ajustes se
pueden cambiar con esta herramienta sin tener que conocer los comandos correctos para
su uso.
$ sudo raspi-config
Instalar sublime
1. Instalar sublime desde aquí
2. Instalar Package Control Ejecutar View/Console y pegar
import urllib2,os,hashlib; h = '2915d1851351e5ee549c20394736b442' + '8bc59f460fa15
48d1514676163dafc88'; pf = 'Package Control.sublime-package'; ipp = sublime.instal
led_packages_path(); os.makedirs( ipp ) if not os.path.exists(ipp) else None;
urll ib2.install_opener( urllib2.build_opener( urllib2.ProxyHandler()) ); by =
urllib2. urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh
= hashli b.sha256(by).hexdigest(); open( os.path.join( ipp, pf), 'wb' ).write(by)
if dh == h else None; print('Error validating download (got %s instead of %s),
please try m anual install' % (dh, h) if dh != h else 'Please restart Sublime
Text to finish in stallation')
Instalar rmate
Configurar Putty
1. Ejecutar como administrador putty
2. Seleccionar Connection/SSH/tunnels
3. Colocar en Source port: 52698, en Destination:127.0.0.1:52698 y seleccionar
Remote
USO
Resumen
GPIO
Instalación
Datasheet
Descargado por Isra Chango (fran.chango@gmail.com)
Uso de GPIO con Python
LED
Un led es un componente electrónico cuya función principal es convertir la energía
eléctrica en una fuente luminosa, la palabra led proviene del acrónimo ingles Light
Emmiting Diode o diodo emisor de luz.
Blink
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
led = 18 #GPIO18 delay = 1 #one second
GPIO.setwarnings(False) #disable warnings
GPIO.setmode(GPIO.BCM) # mode BCM or Board
GPIO.setup(led, GPIO.OUT) # input or output
while True:
GPIO.output(led, True)
time.sleep(delay)
GPIO.output(led, False)
time.sleep(delay)
PWM
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
led = 18 #GPIO18
GPIO.setwarnings(False) #disable warnings
GPIO.setmode(GPIO.BCM) # mode BCM or Board
GPIO.setup(led, GPIO.OUT) # input or output
pwm_led = GPIO.PWM(led, 500)
pwm_led.start(100)
while True:
duty_s = raw_input("Enter Brightness (0 to 100): ")
duty = int(duty_s)
pwm_led.ChangeDutyCycle(duty)
Pulsador
Los pulsadores (PUSHBUTTONS), son interruptores que al ser accionados de forma
manual cambian de estado y al soltarlo regresan a su estado inicial
#!/usr/bin/python
import RPi.GPIO as GPIO
import time
led = 18 #GPIO18
switch = 23
GPIO.setwarnings(False) #disable warnings
GPIO.setmode(GPIO.BCM) # mode BCM or Board
GPIO.setup(led, GPIO.OUT) # input or output
GPIO.setup(switch, GPIO.IN, pull_up_down=GPIO.PUD_UP)
led_state = False
old_input_state = True
while True:
new_input_state = GPIO.input(switch)
if new_input_state == False and old_input_state == True:
led_state = not led_state
old_input_state = new_input_state
GPIO.output(led, led_state)
Ultrasonido
root = Tk()
root.wm_title('Servo Control')
app = App(root)
root.geometry("200x50+0+0")
root.mainloop()
DHT22
Instalación
$ sudo apt-get -y update
$ sudo apt-get -y install python-pip
$ sudo pip install adafruit_python_dht
import Adafruit_DHT
import time
while True:
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 4)
if humidity is not None and temperature is not None:
print('Temp={0:0.1f}* Humidity={1:0.1f}%'.format(temperature, humidity))
else:
print('Failed to get reading. Try again!')
time.sleep(1)
Resumen
sudo apt-get -y update
sudo apt-get -y upgrade
sudo apt-get install -y python-dev
sudo apt-get install -y python-rpi.gpio
sudo apt-get install -y python-pip
sudo pip install adafruit_python_dht
lOMoARcPSD|4807011
2. Servicio o Demonio: Este se encarga de leer los datos que proporciona los sensores y
guardarlo en la base de datos.
Usaremos como framework django , para implementar con facilidad el servicio restful
añadiremos django rest framework .
Lo activamos con:
Para verificar que vamos por buen camino ejecutamos el siguiente comando para visualizar
la estructura de carpetas generadas:
.
├── db.sqlite3
├── Domo
│ ├── admin.py
│ ├── apps.py
│ ├── init .py
│ ├── migrations
│ │ └── init .py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── DomoProject
│ ├── init .py
│ ├── init .pyc
│ ├── settings.py
│ ├── settings.pyc
│ ├── urls.py
│ ├── urls.pyc
│ └── wsgi.py
├── manage.py
└── rpi-env
├── bin
Vamos a hacer una pequeña prueba para ello editamos el archivo settings.py y añadimos la
ip del raspberry(en mi caso '192.168.2.9') en la linea ALLOWED_HOSTS = []
(rpi-env) pi@raspberrypi:~/projects $ nano DomoProject/settings.py
ALLOWED_HOSTS = ['192.168.2.9']
Lo primero que haremos es crear un modelo de la base de datos, para ello usaremos la
ORM de django, editamos el archivo models.py que se encuentra dentro de la carpeta
Domo. Hacemos los mismo con serializers.py
Domo/models.py
from future import unicode_literals
class Sensor(models.Model):
date_created = models.DateTimeField(auto_now=True)
temperature = models.FloatField()
humidity = models.FloatField()
Domo/serializers.py
class SensorSerializer(serializers.ModelSerializer):
class Meta:
model = Sensor
fields = ('date_created', 'temperature', 'humidity')
Domo/views.py
class SensorViewSet(viewsets.ModelViewSet):
queryset = Sensor.objects.all().order_by('-id')[:40]
serializer_class = SensorSerializer
def home(request):
return render(request, 'index.html')
router = routers.DefaultRouter()
router.register(r'sensors', SensorViewSet)
urlpatterns = router.urls
Domo/admin.py
@admin.register(Sensor)
class SensorAdmin(admin.ModelAdmin):
list_display = ('date_created', 'temperature', 'humidity')
DomoProject/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'Domo',
]
....
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], # modificamos esta parte
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
...
DomoProject/urls.py
"""DomoProject URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('Domo.urls', namespace='core')),
url(r'^$', home),
]
templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Proyecto</title>
</head>
<body>
<div id="header">
<h2 style="text-align: center">Proyecto</h2>
</div>
<div id="content">
<div class="demo-container">
<div id="placeholder" style="margin:0 auto;"></div>
<br>
<div style="width:1000px;margin:0 auto;">
Actualizar: <input type="checkbox" id="myCheck" checked>
<br>
Time : <input type="number" id="interval" value="1000">
<br>
<label id="lblLast"></label>
</div>
</div>
</div>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var temperature = {
x: [],
y: [],
fill: 'tonexty',
type: 'scatter',
name: 'Temperatura'
};
var humidity = {
x: [],
y: [],
fill: 'tonexty',
type: 'scatter',
name: 'Humedad',
yaxis: 'y2'
};
var layout = {
title: 'Sensores',
showlegend: true,
legend: {
x: 0,
y: 1,
traceorder: 'normal',
font: {
family: 'sans-serif',
size: 12,
color: '#000'
},
bgcolor: '#E2E2E2',
},
yaxis: {
title: '°C',
range: [0, 100]
},
yaxis2: {
title: '%',
side: 'right',
overlaying: 'y',
range: [0, 100]
}
};
humidity['x'] = [];
humidity['y'] = [];
humidity['x'].push(new Date(value['date_created']));
humidity['y'].push(value['humidity']);
});
},
// handle a non-successful response
error: function (xhr, errmsg, err) {
}
});
};
function update() {
GetData();
if (document.getElementById("myCheck").checked) {
Plotly.newPlot('placeholder', data, layout);
document.getElementById('lblLast').innerHTML = "Temperatura Actual: "
+
temperature['y'][0] + "<br>Humedad Actual: " + humidity['y'][0];
}
var interval = Number(document.getElementById("interval").value);
if (!isNaN(interval)) {
updateInterval = interval;
}
setTimeout(update, updateInterval);
}
update();
})
;
</script>
</html>
Servicio o Demonio
Creamos un archivo llamado myservice.py
myservice.py
#!/usr/bin/env python
import logging
import logging.handlers
import argparse
import sys
from datetime import datetime
import sqlite3
import Adafruit_DHT
def getSensors():
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 4)
t = datetime.utcnow()
return t, temperature, humidity
# Deafults
LOG_FILENAME = "/tmp/myservice.log"
LOG_LEVEL = logging.INFO # Could be e.g. "DEBUG" or "WARNING"
# If the log file is specified on the command line then override the default
args = parser.parse_args()
if args.log:
LOG_FILENAME = args.log
# Configure logging to log to a file, making a new file at midnight and keeping the la
st 3 day's data
# Give the logger a unique name (good practice)
logger = logging.getLogger( name )
# Set the log level to LOG_LEVEL
logger.setLevel(LOG_LEVEL)
# Make a handler that writes to a file, making a new file at midnight and keeping 3 ba
ckups
handler = logging.handlers.TimedRotatingFileHandler(LOG_FILENAME, when="midnight", bac
kupCount=3)
# Format each log message like this
formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s')
# Attach the formatter to the handler
handler.setFormatter(formatter)
# Attach the handler to the logger
logger.addHandler(handler)
# Make a class we can use to capture stdout and sterr in the log
class MyLogger(object):
def init (self, logger, level):
"""Needs a logger and a logger level."""
self.logger = logger
self.level = level
while True:
curs.execute("INSERT INTO Domo_sensor(date_created, temperature, humidity) VALUES(
(?), (?), (?))", getSensors())
conn.commit()
conn.close()
myservice.sh
#!/bin/sh
# Change the next 3 lines to suit where you install your script and what you want to c
all it
DIR=/usr/local/bin/myservice
DAEMON=$DIR/myservice.py
DAEMON_NAME=myservice
# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO
from Python.
DAEMON_USER=root
. /lib/lsb/init-functions
do_start () {
log_daemon_msg "Starting system $DAEMON_NAME daemon"
start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $D
AEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
log_end_msg $?
}
do_stop () {
log_daemon_msg "Stopping system $DAEMON_NAME daemon"
start-stop-daemon --stop --pidfile $PIDFILE --retry 10
log_end_msg $?
}
case "$1" in
start|stop)
do_${1}
;;
restart|reload|force-reload)
do_stop
do_start
;;
status)
status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
;;
*)
echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
exit 1
;;
esac
exit 0
Clientes
Python
GET method:
import requests
import datetime
url = 'http://192.168.2.9/api/sensors/'
response = requests.get(url)
assert response.status_code == 200
POST method:
import requests
import datetime
import json
import time
url = 'http://192.168.2.9/api/sensors/'
for i in range(100):
date = datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')
Resumen
Para los alumnos del curso es necesario ejecutar los siguientes comandos:
Fuente
https://www.digitalocean.com/community/tutorials/how-to-serve-django-applications-
with-apache-and-mod_wsgi-on-ubuntu-14-04
http://blog.scphillips.com/posts/2013/07/getting-a-python-script-to-run-in-the-
background-as-a-service-on-boot/
lOMoARcPSD|4807011
Configuración de motion
Creamos un directorio para guardar las imagenes:
stream_localhost off
webcontrol_localhost off
framerate 60
target_dir /home/pi/Monitor
start_motion_daemon=yes
Obteniendo lo siguiente:
Las imagenes y videos pueden llenar el almacenamiento, por ello configuramos que pasada
los 15 minutos despues de cada hora borre todos excepto las 20 ultimas imagenes:
Configurando el Servidor
Implementamos el servidor para que provea y guarde los datos, para ellos creamos el
modelo Motor que contiene 2 atributos: date_created que guarda la fecha de creación del
comando y status que contiene el comando respectivo. Además de los serializers y vistas
respectivas.
Domo/models.py
from future import unicode_literals
STATUS_CHOICES = (
('F', 'Forward'),
('B', 'Backward'),
('L', 'Left'),
('R', 'Right'),
('S', 'Stop')
)
class Motor(models.Model):
date_created = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=1, choices=STATUS_CHOICES, default='S')
Domo/serializers.py:
class MotorSerializer(serializers.ModelSerializer):
class Meta:
model = Motor
fields = ('date_created', 'status')
Domo/views.py:
class MotorViewSet(viewsets.ModelViewSet):
queryset = Motor.objects.all()
serializer_class = MotorSerializer
Domo/admin.py
from django.contrib import admin
from Domo.models import Motor
Domo/urls.py
router = routers.DefaultRouter()
router.register(r'motors', MotorViewSet)
urlpatterns = router.urls
templates/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Proyecto</title>
</head>
<body>
<div style="text-align:center;margin:auto;">
<button onclick="forward()">Avanzar</button>
</div>
<div style="text-align:center;margin:auto;">
<button onclick="backward()">Retroceder</button>
</div>
<div style="text-align:center;margin:auto;">
<button onclick="left()">Izquierda</button>
</div>
<div style="text-align:center;margin:auto;">
<button onclick="right()">Derecha</button>
</div>
<div style="text-align:center;margin:auto;">
<button onclick="stop()">Parar</button>
</div>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript">
var ip = location.host;
document.getElementById("ip_link").src = "http://"+ip+":8081";
},
data: {
'date_created': new Date(),
'status': state
},
// handle a non-successful response
error: function (xhr, errmsg, err) {
}
});
};
function forward(){
move('F');
};
function backward(){
move('B');
};
function left(){
move('L');
};
function right(){
move('R');
};
function stop(){
move('S');
};
</script>
</html>
Luego implementamos la clase Car que se encarga de manejar los movimientos del
vehículo.
Car.py
class Car:
def init (self, motorL, motorR):
"""
Manejar los motores
:param pins:
[in1, in2, in3, in4]
"""
GPIO.setmode(GPIO.BCM)
self._pinsA = motorL
self._pinsB = motorR
def forward(self):
self.stop()
self.motorOn(self._pinsA)
self.motorOn(self._pinsB)
time.sleep(0.2)
self.stop()
def backward(self):
self.stop()
self.motorReverse(self._pinsA)
self.motorReverse(self._pinsB)
time.sleep(0.2)
self.stop()
def left(self):
self.stop()
self.motorOn(self._pinsB)
self.motorReverse(self._pinsA)
time.sleep(0.2)
self.stop()
def right(self):
self.stop()
self.motorOn(self._pinsA)
self.motorReverse(self._pinsB)
time.sleep(0.2)
self.stop()
def stop(self):
self.motorOff(self._pinsA)
self.motorOff(self._pinsB)
Ahora creamos la clase Data que se encarga de obtener los datos, filtrar el último y verificar
si este ha sido creado en menos de 1 segundo. Si cumple lo anterior obtenemos el
comando status y realizamos la tarea respectiva.
main.py
from datetime import datetime, timedelta
from Car import Car
import requests
class Data:
def init (self, url, timeout=1):
self.url = url
self.before = None
self.timeout = timeout
def load(self):
response = requests.get(self.url)
assert response.status_code == 200
data = response.json()[-1]
date = datetime.strptime(data['date_created'][:-1], "%Y-%m-%dT%H:%M:%S.%f")
if self.before == date:
return
self.before = date
u = datetime.utcnow()
diff = u - date
if diff < timedelta(seconds=self.timeout):
return data['status']
while True:
resp = data.load()
if resp == 'F':
car.forward()
elif resp == 'B':
car.backward()
elif resp == 'L':
car.left()
elif resp == 'R':
car.right()
elif resp == 'S':
car.stop()