Alimentador de Mascotas Automatizado por Chatbot

Por: Josue Soriano Publicado el: 2017-12-23 23:31:29, 23170

Hace poco mas de tres meses que publique como poder hacer un alimentador de mascotas utilizando Un Motor controlado por medio de una computadora Raspberry Pi y poco después publique un pequeño script de Python que permite crear chatbots pode medio de Telegram por lo que se me ocurrió unir estos dos elementos para poder hacer un script que en lugar de usar E-Mails pueda hacer una comunicación mas directa utilizando un Chatbot.

La idea es muy básica, los Chatbots en Telegram utilizan la programación multi-Hilo la cual, a diferencia de la programación lineal tradicional, el chatbot utiliza un ciclo infinito que corre en un hilo paralelo al ciclo infinito del programa principal; lo que hace especial este tipo de programación es que los hilos se pueden comunicar entre ellos para llamar funciones en común. La idea aquí es sustituir la función que revisa el correo electrónico por un hilo que revise comandos enviados al por medio del Telegram.

Los Comandos que utilizaremos serán básicamente los mismos que se utilizaban por medio de E-Mail, pero aprovechando las virtudes de un chatbot de Telegram agregue algunas funciones de monitoreo en tiempo real:

Comando Acción realizada
/alimentar Inicia el proceso de alimentación siempre y cuando haya pasado el periodo de tiempo parametrizado.
/cuando Retorna información sobre cuando fue la ultima alimentación y una foto del plato de comida.
/foto Retorna una foto del plato de comida.
/reiniciar Reinicia el sistema, establece la variable de ultima alimentación a 0 para poder hacer una alimentación de inmediato.
/estado Informa sobre el estado de conexión a Internet: SSID del Wireless conectado y la dirección IP que tiene el sistema dentro de la red.

Voy a reestructurar el Tutorial anterior para poder hacer un Alimentador de Mascotas Ahora Automatizado por medio de Telegram junto con toda la configuración necesaria a realizar en una Raspberry PI:

Como lo comente en el post anterior esta no es una Idea original Mia, lo encontre en Instructables asi que los creditos realmente son del autor de la misma.

Se necesita armar un pequeño circuito que activa un Motor de Alto torque, y como mis conocimientos de electronica son muy pero muy escasos me tuve que pasar un par de dias aprendiendo las cosas basicas, asi que les recomiendo que vean los canales de Youtube de TerrazoCultor y sobre todo vean los videos de electornica basica de Charly Labs

El Script de automatizacion original esta escrito en Python y utiliza conexion a GMail para consultar los comandos, nunca habia usado este lenguaje de programacion pero la verdad no es tan diferente de los demas, lo he modificado un poco para que se adapte mejor a las nuevas librerias de Python y el proceso de automatizacion junto con las configuraciones del sistema operativo permiten parametrizar lo siguiente:

  • Interaccion por medio de comandos enviados a Chat controlado por medio de ChatBots
  • Permite hacer un seguimiento de estado de la comida dispensada.
  • Controla cuanta comida se va a dispensar
  • Dispone de botones que permite hacer la alimentacion de manera manual.
  • No permite la sobrealimentacion deshabilitando la alimentacion en intervalos de 8 Horas.
  • Tiene una pantalla LCD de estatus que muestra los datos como la fecha y hora tiempo regresivo para la sisguiente aliemtacion, SSID al que esta conectado al WiFi y la direccion IP del equipo.
  • Opcional: Muestra algunos Chistes Random de Chuck Norris y/o trivias de Numeros utilizando un par de APIS publicas (Ingenioso por parte del autor original).
  • El Sistema es inmune a reinicios por cortes de electricidad ya que guarda un archivo de estado.
  • El Sistema Detecta cuando hay perdida de conexion e intenta reconectarse hasta que tiene exito.

Materiales Utilizados

Todos los materiales anteriores a excepcion de los ultimos dos no se pueden conseguir localmente (o por lo menos no sabia donde conseguirlos), sin embargo la varilla y el acoplador probablemente se encuntren en algun taller de soldadura pero al ser la primera vez que hago algo asi, no tenia idea de como debia ser para que se acoplara al motor asi que lo pedi a la pagina de los links descritos anteriomente; acontinuacion los materiales que pude comprar en tiendas locales en San Pedro Sula:

  • Una caja de madera, yo utilice una de 20.3 cm ancho × 26.7 cm de alto x 13cm de profundidad. la caja tiene una puerta que abre hacia la derecha con un agujero de 10cm x 4cm para colocar la pantalla LCD (Ebanisteria local)
  • 3 botones (Comercial Lino)
  • 1 Protoboard pequeña (Comercial Lino)
  • 1 LED de 3.3 Voltios (No importa el color pero por el voltaje suelen ser Rojos) (Comercial Lino)
  • 1 transistor NPN PN2222 (Comercial Lino)
  • 1 Resistencia de 270 Ω (Comercial Lino)
  • 1 Resistencia de 10 KΩ (Comercial Lino)
  • 1 Potenciometro de 10 KΩ (Comercial Lino)
  • 1 Diodo IN4003 (Puede funcionar un IN4001 o IN4004) (Comercial Lino)
  • 1 adaprador de 12V 3A (Sycom)
  • 1 adaptador de 5V 2A (Sycom)
  • 4 tornillos con tuerca de mariposa de 1.5 pulgadas a 2 pulgadas (depende del grosor de la madera usada, son para fijar el bracket del motor a la caja de madera)
  • Cables Jumper hebras de diversos colores (Comercial Lino)
  • 1 tubo plegable o un lance de PVC de 4Pulg, este depende de la altura a la que estara colocada la caja de madera. (La Mundial)
  • un codo de PVC que se acople al lance anterior. (La Mundial)
  • 3 abrazaderas para tuberias de carro (La Mundial)
  • 4 Pies de Cable UTP (necesitamos los pares trenzados para hacer las conexiones) (Network Place o Sycom)
  • 1 WebCam USB, no es necesario que sea de alta resolucion. Yo encontre una agiler AGI-4186 en Caribecom que tiene leds que hacen la funcion extra de iluminar el plato.

Alguinos materiales micelaneos que se pueden conseguir en ferreterias o posiblemente ya tengamos:

  • Tape Industrial
  • Cautin
  • Estaño
  • Taladro
  • Broca 5/16
  • Tornillos S8 con expansores

Armando la estructura

La idea principal es sustituir la manija dispensadora que viene en el ZEVRO por la varilla D que luego se conectara al Motor por medio del Acoplador. El dispensador se sujetara de la caja de madera y la caja de madera a la Pared. Como no se mucho de electrónica no utilicé ninguna placa de baquelita para montar el circuito así que use la protoboard para poder poner todos los componentes así que en el fondo de la caja va sujeta con tornillos la Rapberry Pi y la protoboard la cual ya tenía un adhesivo en la parte de atrás así que solo fue de pegarla.  La caja debe de tener tres botones los cuales tendrán la función de Reiniciar el temporizador, activar el alimentador y el último será un paso directo para activar el motor sin pasar por el circuito. El motor se sujetara dentro de la caja por medio del braket por lo que, de la caja, solo sobresaldrá la varilla D que se conecta al dispensador, en la parte de abajo de la caja fije y ajuste la webcam para que en cada correo de consulta y confirmacion me envie una foto de como esta el plato, esto para no sobre alimentar en caso de que no se hayan terminado la ultima tanda de comida.

De la parte inferior del dispensador se colocara el tubo  que bajara hasta el plato y en la base se colocara el codo de PVC, yo coloque un poco de Tape Industrial en la salida para minimizar la velocidad del flujo de comida e hice una base dispensadora para evitar que la comida salga disparada por todos lados. Para fijar el tubo a la pared utilice abrazaderas metálicas que fije a la pared con los tornillos para taco S8.

En la puerta de la caja sujete la placa de la pantalla LCD y utilice los pares trenzados del cable UTP para llevarlos directamente a la Raspberry, en el otro extremo de los cables empalme las puntas hembras de los jumpers para hacer más fácil la conexión en los puertos GPIO de la Raspberry. Este sería el diagrama de circuitos. Voy a tratar de explicarlo con lo poco lo que logre captar de Electrónica.

El motor se conecta directamente al polo positivo del transformador de 12 voltios pero para que la corriente fluya debe pasar por el circuito en el polo neutro del motor, para ello se utiliza el transistor N2222. Los transistores tienen normalmente 3 patitas las cuales corresponden a un colector, una base y un emisor, dependiendo del modelo del transistor la ubicación de estas patitas pueden variar; este transistor hace la función de Switch aquí es donde conectamos el polo neutro del motor al colector del transistor, el pin #19 de la rapberry se conecta a la base por medio de una resistencia de 270Ω y el emisor se conecta a la terminal neutra del transformador de 12V junto con uno de los polos Tierra de la raspberry; el transistor dejara fluir la corriente entre colector y emisor siempre y cuando la base se estimule con suficiente voltaje; mas adelante programaremos las rapberry para que según ciertas ordenes el puerto 19 emitirá 3.3 voltios, lo suficiente para que el circuito continúe y active el motor.

Para la pantalla LCD se utiliza otra parte de la protobard en un circuito diferente donde conecte el potenciómetro  de 10KΩ el cual recula el contraste del texto que aparece en la pantalla LCD, así que si no aparece nada en la pantalla es porque probablemente el potenciómetro este totalmente cerrado; en  mi caso yo lo deje totalmente abierto para que se visualice mejor el texto. Al final las conexiones en la protoboard quedarían de la siguiente manera.

Configuración de la Raspberry

Para configurar la rapberry utilice la versión Lite del Rapbian (no necesitamos la carcasa grafica) y aplique la configuración básica que muestra el raspbian una vez que se instala o utilizando el comando raspi-config: expandi el espacio al 100% y habilite el SSH pero sobre todo lo mas importante es cambiar la contraseña y el nombre de usuario al usuario pi que viene por defecto (De lo contrario, como me paso a mi, pueden sufrir un ataque por el puerto 22 si tienen una IP publica direccionada a la raspberry). Aparte de eso la configuracion para que se conecte automaticamente a mi red WiFi (Suponiendo que mi red se llama "BlogSoriano" y mi password es "$eguridad123!") generamos y guardamos la clave en el archivo de conexiones Wireless con el siguiente comando:

$ sudo wpa_passphrase "BlogSoriano" "$eguridad123!" | sudo tee -a /etc/wpa_supplicant/wpa_supplicant.conf > /dev/null

lo siguiente es actualizar e instalar el sistema de instalacion de python "pip" para ello vamos a loguearnos como root, actualizar e instalar los paquetes necesarios:

$ sudo -i
$ apt-get update
$ apt-get install build-essential python-dev python-smbus python-pip

Con esto ya tenemos acceso a la libreria de clases de python, para el script que vamos a usar se necesita instala lo siguiente:

$ pip install RPi.GPIO Adafruit-CharLCD httplib2 html2text netifaces wireless telepot cv2 

Una vez terminada la instalacion de dependencias vamos a escribir el siguiente script, yo lo guarde en la ruta /opt/petfeeder.py el archivo lo pueden crear mediante el comando nano /opt/petfeeder.py  y dentro de este archivo pegamos el siguiente codigo, aclaro que este codigo no lo escribi yo ya que nunca habia programado en Python, unicamene lo modifique para que funcione con las nuevas librerias y con la pantalla LCD de 20x4; tambien inclui una funcion para leer tweets random desde algunas cuentas que yo sigo desde una API que programe en PHP la cual compartire mas tarde:

 # coding=utf8
import md5
import time
import os
import sys
import RPi.GPIO as GPIO
from Adafruit_CharLCD import Adafruit_CharLCD
import httplib2
import json
import html2text
import cv2
import netifaces as ni
from wireless import Wireless
import telepot
from telepot.loop import MessageLoop

MOTORON = True
SYSTEMRESET = False #Inicia el proceso de Reseteo para forzar la alimentacion
CHUCKNORRIS = False #activa para que adjunte un chiste de Chuck Norris en ingles en los correos
NUMBERTRIVIA = False #active para que mande dentro de los correos una trivia de un numero aleatorio.

#Sistema de seguridad, para evitar que cualquier persona active los comandos
SYSPASSWORD = "B7F93DGE2G5CB3C0F89A41A1A354F386" #password para poder enviar comandos al sistema Encriptado en MD5
CHATSFILE = os.getcwd() + "/authchats.txt" #Archivo donde se guardan los chats que se han autorizados a enviar comandos.
AUTHCHATS = [] #Arreglo que guarda los chats que se han autorizado
TRYAUTH = [] #Arreglo de los chats que estan intentando autizarse


# Archivos para guardar estados de Ultima Alimentacion
LOGFILE = os.getcwd() + "/petfeeder.log"
PHOTOFILE = '/tmp/foodstatus.jpg'
RECORDAR = True


# Variables Para conectar al Chatbot
BOTKEY = '123456789:cdufiwe23rqnlkajscdu5alnlkajsc'
bot = telepot.Bot(BOTKEY)

# GPIO pins para el control de alimentacion
MOTORCONTROLPIN = 19
FEEDBUTTONPIN = 6
RESETBUTTONPIN = 13

# GPIO pins para 20x4 HD44780
lcd_rs = 27
lcd_en = 22
lcd_d4 = 25
lcd_d5 = 24
lcd_d6 = 23
lcd_d7 = 18
lcd_bl = 4

lcd_cols = 20
lcd_rows = 4

#Variables para evaluacion de la red Inalambrica
CURRENTIP = "0.0.0.0"
CURRENTSSID = "None"

# Variables para la informacion de la alimentacion
feedInterval = 28800 # 8 Horas en segundos
FEEDFILE = os.getcwd() + "/lastfeed.log"
cupsToFeed = 1.2
motorTime = cupsToFeed * 27 # Toma 27 Segundos al motor para poder dar 1 Taza de comida.


# Function that gets Chuck Norris jokes from the internet. It uses an HTTP GET and then a JSON parser
def getChuckNorrisQuote():
	# The database where the jokes are stored
	ICNDB="http://api.icndb.com/jokes/random"
	# Doing a HTTP request to get the response (resp) and content (content)
	resp, content = httplib2.Http().request(ICNDB)
	# The content is in the following JSON format and needs to be parsed
	# {u'type': u'success', u'value' : {u'joke': 'Text of the joke', u'id': 238, u'categories': []}}
	parsed_content = json.loads(content)
	joke = "\n\n** Chiste Random de Chuck Norris **:\n" + html2text.html2text(parsed_content['value']['joke'])
	return str(joke)
	

# Function that gets a number trivia from the internet. It uses an HTTP GET and then a JSON parser
def getNumberTrivia():
	# The database where the trivia are stored
	NUMDB="http://numbersapi.com/random/trivia?json"
	# Doing a HTTP request to get the response (resp) and content (content)
	resp, content = httplib2.Http().request(NUMDB)
	# The content is in the following JSON format and needs to be parsed
	# {u'text': u'Text of trivia', u'type' : u'trivia, u'number': , u'found': True}
	parsed_content = json.loads(content)
	trivia = "\n\n** Curiosidad del Numero " + str(parsed_content['number']) + " **\n"
	trivia = trivia + parsed_content['text']
	return str(trivia)

def handle(msg):
	global SYSTEMRESET
	content_type, chat_type, chat_id = telepot.glance(msg)
	#print(content_type, chat_type, chat_id)

	if content_type == 'text':
		MENSAJE = msg['text']
		UNICODE = MENSAJE.encode('unicode-escape').decode('ascii')
		if str(chat_id) in AUTHCHATS:
			if MENSAJE == "Cuando" or UNICODE == "\u2753":
				msgBody = "La ultima alimentación se realizo el " + time.strftime("%b %d at %I:%M %P", time.localtime(lastFeed))
				if (time.time() - lastFeed) > feedInterval:
					msgBody = msgBody + "\nListo para alimentar ahorita!"
				else:
					msgBody = msgBody + "\nLa siguiente alimentación comenzara el " + time.strftime("%b %d at %I:%M %P", time.localtime(lastFeed + feedInterval))
				
				if NUMBERTRIVIA:
					msgBody = msgBody + getNumberTrivia()

				if CHUCKNORRIS:
					msgBody = msgBody + getChuckNorrisQuote()

				
				getPhoto()
				bot.sendPhoto(chat_id, open(PHOTOFILE, 'rb'))			
				bot.sendMessage(chat_id, msgBody)

			elif MENSAJE == "Alimentar" or UNICODE == "\U0001f37d":
				msgBody = "La ultima alimentación se realizo el " + time.strftime("%b %d at %I:%M %P", time.localtime(lastFeed))
				proceder = False
				if (time.time() - lastFeed) > feedInterval:
					msgBody = msgBody + "\nLa alimentación comenzara en breves momentos"
					proceder = True
				else:
					msgBody = msgBody + "\nLa próxima alimentación se realizara el " + time.strftime("%b %d at %I:%M %P", time.localtime(lastFeed + feedInterval))

				if NUMBERTRIVIA:
					msgBody = msgBody + getNumberTrivia()

				if CHUCKNORRIS:
					msgBody = msgBody + getChuckNorrisQuote()

					
				bot.sendMessage(chat_id, msgBody)
				if proceder:
					feednow()
					proceder=False

			elif MENSAJE == "Foto" or UNICODE == "\U0001f4f7":
				getPhoto()
				bot.sendPhoto(chat_id, open(PHOTOFILE, 'rb'))
			elif MENSAJE == "Estado" or UNICODE == "\U0001f4a1":
				IPDIR = getIP()
				SSID = getSSID()
				msgBody = "Sistema Activo"
				msgBody = msgBody + "\nWireless: " + SSID
				msgBody = msgBody + "\nDirección IP Local: " + IPDIR
				bot.sendMessage(chat_id, msgBody)
			elif MENSAJE == "Reiniciar" or UNICODE == "\U0001f504":
				SYSTEMRESET = True
			else:
				bot.sendMessage(chat_id, "Comando no definido")
		else:
			if chat_id in TRYAUTH:
				TRYAUTH.remove(chat_id)
				m = md5.new()
				m.update(MENSAJE)
				CRYPTED = m.hexdigest().upper()
				if CRYPTED == SYSPASSWORD:
					with open(CHATSFILE, "a") as myfile:
						myfile.write(str(chat_id)+"\n")
					myfile.close()
					AUTHCHATS.append(str(chat_id))
					bot.sendMessage(chat_id, "Autorización correcta, proceda a enviar comandos")
				else:
					bot.sendMessage(chat_id, "Contraseña Incorrecta")
				
			else:
				if MENSAJE == "Autorizar":
					bot.sendMessage(chat_id, "Envié la contraseña de autorización")
					TRYAUTH.append(chat_id)
				else:
					msgbody = "Este Chat no esta autorizado para poder enviar comandos"
					msgbody = msgbody + "\npara autorizar envié Autorizar y siga las instrucciones"
					bot.sendMessage(chat_id, msgbody)
	
def buttonpressed(PIN):
	# Check if the button is pressed
	global GPIO
	
	# Cheap (sleep) way of controlling bounces / rapid presses
	time.sleep(0.2)
	button_state = GPIO.input(PIN)
	if button_state == False:
		return True
	else:
		return False


def printlcd(row, col, LCDmesg):
	# Set the row and column for the LCD and print the message
	global logFile
	global lcd
	
	lcd.set_cursor(row, col)
	
	lcd.message(LCDmesg)

	lcd.set_cursor(0,2)
	lcd.message("Wifi: " + CURRENTSSID)
	lcd.set_cursor(0,3)
	lcd.message("IP: " + CURRENTIP)

	


def feednow():
	# Run the motor for motorTime, messages in the LCD during the feeeding
	global GPIO
	global MOTORCONTROLPIN
	global motorTime
	global lastFeed
	global AUTHCHATS
	global bot

	lcd.clear()
	printlcd(0,0,"Alimentando.....")
	#print "Alimentando...."
	if MOTORON:
		GPIO.output(MOTORCONTROLPIN, True)
		time.sleep(motorTime)
		GPIO.output(MOTORCONTROLPIN, False)
		lastFeed = time.time()
		saveLastFeed()
		printlcd(0,1, "Terminado!")

	msgBody = "Alimentación terminada Exitosamente!"
	getPhoto()
	for CHAT in AUTHCHATS:
		bot.sendPhoto(CHAT, open(PHOTOFILE, 'rb'), msgBody)

	time.sleep(2)
	return time.time()

def saveLastFeed():
	global FEEDFILE
	global lastFeed
	with open(FEEDFILE, 'w') as feedFile:
		feedFile.write(str(lastFeed))
	feedFile.close()

def getPhoto():
	global PHOTOFILE
	camera_port = 0 
	camera = cv2.VideoCapture(camera_port) 
	time.sleep(0.1) 
	return_value, image = camera.read() 
	cv2.imwrite(PHOTOFILE, image)
	del(camera)

def getIP():
	global ni
	try:
		ni.ifaddresses('wlan0')
		ip = ni.ifaddresses('wlan0')[ni.AF_INET][0]['addr']
	except:
		ip = "0.0.0.0"

	return str(ip)
		
def getSSID():
	try:
		wireless = Wireless()
		ssid = wireless.current()
	except:
		ssid = "Ninguno"

	return str(ssid)


# This is is the main program, essentially runs in a continuous loop looking for button press
try:
	#print "Iniciando Servicio de Alimentacion"
	#### Begin initializations #########################
	####################################################
	
	# Initialize the logfile
	logFile = open(LOGFILE, 'a')

	# Initialize the LCD
	lcd = Adafruit_CharLCD(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7, lcd_cols, lcd_rows, lcd_bl)
	# lcd.begin(16,2)
	lcd.clear()
	lcd.show_cursor(False)
	

	# Initialize the GPIO system
	GPIO.setwarnings(False)
	GPIO.setmode(GPIO.BCM)

	# Initialize the pin for the motor control
	GPIO.setup(MOTORCONTROLPIN, GPIO.OUT)
	GPIO.output(MOTORCONTROLPIN, False)

	# Initialize the pin for the feed and reset buttons
	GPIO.setup(FEEDBUTTONPIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
	GPIO.setup(RESETBUTTONPIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)

	#obtenemos los datos de conexion a la red inalambrica
	CURRENTIP = getIP()
	CURRENTSSID = getSSID()
	
	# Initialize lastFeed
	if os.path.isfile(FEEDFILE):
		with open(FEEDFILE) as feedFile:
			lastFeed = float(feedFile.read())
		feedFile.close()
	else:
		lastFeed = time.time()
		saveLastFeed()
		
	# Inicializando Chats Autorizados
	if os.path.isfile(CHATSFILE):
		with open(CHATSFILE) as f:
			AUTHCHATS = f.read().splitlines()
		f.close()
	

	#### End of initializations ########################
	####################################################

	
	#Inicia Hilo escucha del chatbot
	MessageLoop(bot, handle).run_as_thread()
	
	#### The main loop ####
	while True:
		try:
			if CURRENTIP != getIP() or CURRENTIP == "0.0.0.0":
				CURRENTIP = getIP()
				CURRETSSID = getSSID()	
				if CURRENTIP == "0.0.0.0":
					#Reactivamos la interfaz de red
					os.system("ifup wlan0")
					os.system("wpa_cli reconfigure")
					time.sleep(5)
					CURRENTIP = getIP()
					CURRENTSSID = getSSID()
					lcd.clear()
				
			
				
			#### If reset button pressed, then reset the counter
			if buttonpressed(RESETBUTTONPIN) or SYSTEMRESET:
				SYSTEMRESET = False
				lcd.clear()
				printlcd(0,0, "Reiniciando...   ")
				time.sleep(2)
				lastFeed = time.time() - feedInterval + 5
				saveLastFeed()
				for CHAT in AUTHCHATS:
					bot.sendMessage(CHAT, "El sistema se reinicio Correctamente a las " + time.strftime("%m/%d %I:%M:%S%P", time.localtime(time.time())))

		
			#### Check if we are ready to feed
			if (time.time() - lastFeed) > feedInterval:
				printlcd(0,0, time.strftime("%m/%d %I:%M:%S%P", time.localtime(time.time())))
				printlcd(0,1, "Listo para Alimentar")
				if RECORDAR:
					RECORDAR = False
					for CHAT in AUTHCHATS:
						getPhoto()
						bot.sendPhoto(CHAT, open(PHOTOFILE, 'rb'), "La ultima alimentación se realizo a las " + time.strftime("%m/%d %I:%M:%S%P", time.localtime(lastFeed)) + ", la alimentación ya esta activa.")

				if buttonpressed(FEEDBUTTONPIN):
					feednow()

			#### Since it is not time to feed yet, keep the countdown going
			else:
				RECORDAR = True
				timeToFeed = (lastFeed + feedInterval) - time.time()
				printlcd(0,0, time.strftime("%m/%d %I:%M:%S%P", time.localtime(time.time())))
				printlcd(0,1, 'Proxima: ' + time.strftime("%Hh %Mm %Ss", time.gmtime(timeToFeed)))
				if buttonpressed(FEEDBUTTONPIN):
					lcd.clear()
					printlcd(0,0, "Ahora no, intenta el")
					printlcd(0,1, time.strftime("%b/%d %H:%M", time.localtime(lastFeed + feedInterval)))
					time.sleep(2)
			time.sleep(.6)
		except Exception as e:
			logError = time.strftime("%m/%d %I:%M:%S%P", time.localtime(time.time())) + " Error inesperado: " + str(e) + "\n"
			for CHAT in AUTHCHATS:
				bot.sendMessage(CHAT, logError)
			logFile.write(logError)

#### Cleaning up at the end
except KeyboardInterrupt:
	logFile.close()
	lcd.clear()
	GPIO.cleanup()

except SystemExit:
	logFile.close()
	lcd.clear()
	GPIO.cleanup()

Una vez que tengamos el Script hay que cambiar los valores de las variables con la llave para el bot; para ello es necesario poder crear un nuevo Bot de Telegram, con eso solo quedaria guardar el archivo y salir (con Ctrl+o se guarda y ctrl+x se sale del editor nano), solo nos hace falta que sea a prueba de reinicios; el script por si ya guarda la ultima vez que se activo el sistema de alimentacion, por lo que solo debemos hacer que el script se ejecute cada vez que se inicie el sistema operativo, para ello encontre una solucion muy particular con un programa llamado supervisor, el cual se instala desde los repositorios del Debian:

$ apt-get install supervisor

y una vez instalado solamente necesitamos crear un archivo de configuracion en /etc/supervisor/conf.d/petfeeder.conf, al igual que el caso anterior lo podemos crear y guardar con nano, este archivo tendra lo siguiente:

[program:petfeederd]
directory=/opt
command=python petfeeder.py
autostart=true
autorestart=true

Una vez guardado el archivo podemos usar el comando supervisorctl [start|stop|restart] petfeederd, como en este caso el servicio no se ha iniciado lo ejecutamos con start:

$ supervisorctl start petfeederd

Y con esto ya deberia funcionar el sistema, la pantalla LCD deberia mostrar informacion de cuando deberia ser la siguiente alimentacion o si ya esta listo para alimentar deberia decirlo. Tambien debe mostrar el nombre de la Red inalambrica a la que se esta conectado y la direccion IP que se esta utilizando por si necesitamos conectarnos por medio de SSH, comparto un pequeño video que hice, me disculpo por la calidad del mismo, no soy muy bueno es este tema de los vlogs.

 

Si te Gusto compartelo:

Comentar

Debes ingresar para poder comentar, accede AQUI. Registrate AQUI

Comentarios