Telegram como interfaz IoT

Descripción del prototipo

Se desea controlar una placa pi a través de un bot de telegram. Tanto para enviar comandos como para recibir avisos de la misma a través de este canal.

Para la configuración y puesta a punto del prototipo tendremos que aprender a instalar y configurar el sistema operativo para la raspberry pi, así como preparar el entorno de programación para hacer nuestra aplicación.

En este prototipo vamos a configurar dos acciones:

Materiales

Raspberry pi 3 = 36,90€

Sensor DHT11 con cables = 0,93€

Camara pi = 31,96€

Creación de prototipo

Instalar y configurar el sistema operativo

En la página web dietpi podemos encontrar las versiones del sistema operativo para nuestra raspberry. http://dietpi.com/

También encontraremos información para instalarla en la memoria de nuestra raspberry.

http://dietpi.com/phpbb/viewtopic.php?f=8&t=9#p9

El procedimiento es el siguiente:

  1. bajar el archivo con el sistema operativo
  2. copiarlo en la memoria SD de la raspberry        

        En linux buscaremos en que dispositivo se montó la memoria

        # mount

Y desmontamos las particiones si las hubiera.

# umount /dev/sdb1

        Seguidamente copiamos el archivo .img bajado en el dispositivo de la SD

        # sudo dd if=DietPi_v150_RPi-armv6-\(Jessie\).img of=/dev/sdb

  1. arrancar el sistema con el, configurar el wifi y acceso por ssh para poder trabajar remotamente.

        dietpi tiene su propio menu de configuracion:

        

        tambien podemos configurar esto directamente desde el archivo dietpi.txt en la particion BOOT:

        CODIGO

# >> Networking Options -----------------------------

#If both Ethernet and Wifi are enabled, Wifi will take priority and Ethernet will be disabled.

#   1=enabled

Ethernet_Enabled=0

Wifi_Enabled=1

#Enter your Wifi details below, if applicable (Case Sensitive).

Wifi_SSID=FuzonWifi

Wifi_KEY=MyAccessKey        

Una vez tenemos el sistema operativo instalado y funcionando podemos acceder a el por SSH. Con dietpi se requieren un par de reinicios para terminar de espandir el sistema en la memoria SD, etc.

Instalar y preparar el entorno de programación

Nuestro prototipo ha sido programado en el lenguaje python, por consiguiente instalamos la librería para trabajar las conexiones GPIO con este lenguaje.

Con el sistema operativo dietpi es tan fácil como arrancar el menu de configuracion y buscar en software PRi.GPIO para python.

 

Comprender el sistema bot de telegram

Para obtener una api y debemos crear un Bot en el sistema Telegram. Es a The Botfather a quien tenemos que pedir crear uno y el nos dara un identificador de API para poder trabajar. https://telegram.me/botfather

438317034_35377.jpg435823876_188516.jpg

Programar lectura de sensor DHT11

Como anteriormente hemos descrito vamos a utilizar la libreria RPi.GPIO para trabajar con los conectores GPIO de la raspberry con el lenguaje python. En el sistema operativo que hemos instalado es tan facil como ejecutar en el terminar dietpi-software e instalarlo.

Para facilitarnos trabajar con el sensor DHT11 hemos elegido la siguiente libreria para acceder al sensor y obtener los resultados: https://github.com/szazo/DHT11_Python

Conectando apropiadamente el sensor:

Y con el siguiente codigo podemos comprobar como funciona el sensor.

CODIGO

root@DietPi:~# cat temperatura.py

import RPi.GPIO as GPIO

import dht11

# initialize GPIO

GPIO.setwarnings(False)

GPIO.setmode(GPIO.BCM)

GPIO.cleanup()

# read data using pin 14

instance = dht11.DHT11(pin = 14)

result = instance.read()

if result.is_valid():

        print("Temperature: %d C" % result.temperature)

        print("Humidity: %d %%" % result.humidity)

else:

        print("Error: %d" % result.error_code)

Programar lectura de camara

Para la lectura de la cámara utilizaremos la librería OpenCV.

#apt-get install python-opencv

instalar libpng

activarraspcamara

dietpi-config > Display > GPU/Memory split

Con el siguiente programa probamos que todo funciona:

CODIGO

import cv2

c = cv2.VideoCapture(0)

for i in xrange(9):

  s, im = c.read()

s, im = c.read()

cv2.imwrite("temp.png", im)

del(c)

Es importante recordar que si tenemos problemas con la raspberry pi al conectar más componentes. Debemos comprobar que fuente de alimentación de la misma es suficientemente potente.

Programar sistema de comunicación con Bot Telegram

Nuestro primer programa bot de telegram consistirá en conectarnos a telegram a través del API, ver los mensaje que tenemos sin contestar, revisarlos, y los que sean un mensaje que contenga la palabra “hola”, contestaremos con un “cómo te va”.

CODIGO

import json

import requests

import time

import urllib

import cv2

import pickle

import re

from pprint import pprint

TOKEN = "450629301:AAFzkOzTpA6rrink97jzWxCSd9NMMjxGfJ8"

URL = "https://api.telegram.org/bot{}/".format(TOKEN)

def get_url(url):

        response = requests.get(url)

        content = response.content.decode("utf8")

        return content

def get_json_from_url(url):

        content = get_url(url)

        js = json.loads(content)

        return js

def get_updates(offset=None):

        url = URL + "getUpdates?timeout=100"

        if offset:

              url += "&offset={}".format(offset+1)

        js = get_json_from_url(url)

        print "get_updates:"+url

        return js

def get_last_update_id(updates):

        update_ids = []

        for update in updates["result"]:

              update_ids.append(int(update["update_id"]))

        return max(update_ids)

def get_last_chat_id_and_text(updates):

        num_updates = len(updates["result"])

        last_update = num_updates - 1

        text = updates["result"][last_update]["message"]["text"]

        chat_id = updates["result"][last_update]["message"]["chat"]["id"]

        return (text, chat_id)

def send_message(text, chat_id):

        from urllib import quote_plus

        text = quote_plus(text)

        url = URL + "sendMessage?text={}&chat_id={}".format(text, chat_id)

        get_url(url)

def chating(updates, last_update_id):

        update_id_max = 0

        for update in updates["result"]:

              try:

                    text = update["message"]["text"]

                    chat = update["message"]["chat"]["id"]

                    update_id = int(update["update_id"])

                    if update_id > update_id_max:

                    update_id_max = update_id                

                    print last_update_id

                    if re.match("^(.*)?(hola)", text):

                         do_saludo(chat)

              except Exception as e:

                    print(e)                

        return update_id_max

def do_saludo(chat):

        send_message("como te va?", chat)

        print "chat: "+str(chat)

def main():

        last_update_id = None

        f = open('lastid.obj', 'rb')

        last_update_id = pickle.load(f)

        f.close()

        print "comienza el programa, last_update_id:"+str(last_update_id)

        while True:

              updates = get_updates(last_update_id)

              if len(updates["result"]) > 0:

                    update_id_max = chating(updates, last_update_id)

                    print "despues de chating, last_update_id:"+str(update_id_max)

                    last_update_id = update_id_max

                    f = open('lastid.obj', 'wb')

                    pickle.dump(last_update_id, f)

                    f.close()

              print "esperamos 5 segundos"

              print "++++++++++++++++++++"

              time.sleep(5)

if __name__ == '__main__':

        main()

Crear prototipo

Para crear el prototipo final vamos a añadir a nuestro las opciones de contestar a comandos que pidan “temperatura” y “foto”. Donde mandaremos la información oportuna.

def sendImage(chat_id, dir_photo):

        url = URL + "sendPhoto"

        files = {'photo': open(dir_photo, 'rb')}

        data = {'chat_id': chat_id}

        r = requests.post(url, files=files, data=data)

        print(r.status_code, r.reason, r.content)

def chating(updates, last_update_id):

        update_id_max = 0

        for update in updates["result"]:

            try:

                text = update["message"]["text"]

                chat = update["message"]["chat"]["id"]

                update_id = int(update["update_id"])

                if update_id > update_id_max:

                    update_id_max = update_id                

                print last_update_id

                #pprint(update)

                if re.match("^(.*)?(foto.?)", text):

                       do_image(chat)

                elif re.match("^(.*)?(hola)", text):

                   do_saludo(chat)

                elif re.match("^(.*)?(temperatura|calor|tiempo)", text):

                   do_temperature(chat)

                else:

               do_quote(chat)

            except Exception as e:

                print(e)                

        return update_id_max

def do_image(chat):

        c = cv2.VideoCapture(0)

        for i in xrange(9):

            s, im = c.read()

            print "prueba foto "+str(i)

        s, im = c.read()

        cv2.imwrite("temp.png", im)

        del(c)

        sendImage(chat, "temp.png")

def do_temperature(chat):

        # initialize GPIO

        GPIO.setwarnings(False)

        GPIO.setmode(GPIO.BCM)

        GPIO.cleanup()

        # read data using pin 14

        instance = dht11.DHT11(pin = 14)

        result = 0

        count = 0

        while (count < 4):

            result = instance.read()

            if result.is_valid():

                send_message("En el comedor hace "+str(result.temperature)+" grados y "+str(result.humidity)+"% de humedad", chat)

                count = 20

            else:

                print("Error en DHT11: %d" % result.error_code)

            count = count + 1

        if count == 9:

            send_message("No hace ni frio ni calor", chat)    

def do_quote(chat):

        response = urllib.urlopen(URL_QUOTE)

        data = json.loads(response.read())

        soup = BeautifulSoup(data[0]['content'].replace(u"\u2018","'").replace(u"\u2019", "'"))

        text = soup.get_text()

        send_message(text, chat)

Referencias

Pagina web con multiples ejemplos de visión artificial utilizando la libreria OpenCV

https://www.pyimagesearch.com

Oscar Cantero Lopez - oscar@pulpaticien.fr