Megacurso programación en Python3 | 4. Conexión con Raspberry en red local mediante SSH y SFTP

in #raspberry7 years ago (edited)

En la clase de hoy vamos a aprender a realizar conexiones SSH y SFTP para enviar archivos y ejecutar scripts desde una Raspberry conectada por red local.

Todo el código mostrado a continuación se encuentra en este archivo.

En la carpeta del curso encontrarás el índice con las clases publicadas.

Importacion de los módulos y configuración

Para realizar este trabajo usaremos la bilioteca paramiko. Esta nos proporciona unos sencillos métodos de apertura e interacción mediante conexiones vía SSH y SFTP.

Desde aquí puedes acceder a un pequeño tutorial de cómo instalarla y su uso básico.

from paramiko import SSHClient, AutoAddPolicy
from os import environ
Configuración

Ahora añadimos las variables de entorno que usaremos para conectarnos a la raspberry:

Si no sabes cómo funciona el modulo environ puedes aprenderlo desde aquí.

RASPBERRY_LOCAL_IP = environ.get('RASPBERRY_LOCAL_IP', '')
RASPBERRY_LOCAL_USERNAME = environ.get('RASPBERRY_LOCAL_USERNAME', '')
RASPBERRY_LOCAL_PASSWORD = environ.get('RASPBERRY_LOCAL_PASSWORD', '')

Debemos asegurarnos de establecer la IP de nuestra Raspberry como fija. Si no sabes cómo hacerlo aquí tienes un tutorial.

Inicialización

Instanciamos el cliente SSH y abrimos la conexión.

ssh = SSHClient()
ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect(RASPBERRY_LOCAL_IP, 
            username=RASPBERRY_LOCAL_USERNAME, 
            password=RASPBERRY_LOCAL_PASSWORD)

La clase Raspberry

Luego creamos el objeto principal que usaremos para comunicarnos con nuestra Raspberry. Vamos a incorporarle un método para enviarle archivos y otro para descargarlos.

class Raspberry:
    """Crea una conexión con una raspberry en local por SSH y SFTP."""
    def __init__(self):
        pass
        
    def upload(self, filepath_in, filepath_out):
        ftp = ssh.open_sftp()
        ftp.put(filepath_in_filepath_out)
        return True
    
    def download(self, filepath):
        ftp = ssh.open_sftp()
        ftp.get(filepath)
        return True

Añadiendo más funcionalidad

Podemos añadir otros métodos para ejecutar scripts en remoto:

    def execute(self, command):
        stdin, stdout, stderr = ssh.exec_command(command)
        return (stdout.readlines(), stderr.readlines())
        
    def run_script(self, filepath, language='python3'):
        command = '{} {}'.format(language, filepath)
        return self.execute(command)
        
    def send_script(self, filepath_in, filepath_out, imports=[],
                    execute=False, language='python3'):
        self.upload(filepath_in, filepath_out)
        filepath_curt = filepath_out.split('/')
        filename = filepath_cut.pop()
        storage_dir = '/'.join(filepath_cut)
        if type(imports) in (list, set):
            for ipath in imports:
                import_filename = ipath.split('/')[-1]
                self.upload(ipath, {}/{}.format(storage_dir,
                                                import_filename))
        elif type(imports) is str:
            import_filename = imports.split('/')[-1]
                self.upload(imports, {}/{}.format(storage_dir,
                                                import_filename))
        else:
            raise TypeError(str(type(imports)) + "is not a valid/ 
                type for the parameter 'imports'"
        if execute == True:
            response = self.run_script(filepath_out, language=language)
            return response
        return True
  • execute ejecuta un comando desde la raspberry. Toma un parámetro:
    • command (str): el comando a ejecutar.
  • run_script ejecuta un script en la raspberry. Toma dos parámetros:
    • filepath (str): ruta hacia el script en la raspberry.
    • language (str): comando para ejecutar el script.
  • send_script envía un script con sus dependencias. Toma cinco parámetros:
    • filepath_in (str): ruta hacia el script en nuestro ordenador.
    • filepath_in (str): ruta donde almacenar el script en la raspberry.
    • imports (array/str) rutas hacia los archivos que necesita importar (las dependencias se colocarán en el mismo directorio del script).
    • execute (bool) Elige si quieres ejecutar el script tras enviarlo o no.
    • language (str): comando para ejecutar el script.