Draft Idea

Proyectos, ideas y demás :D

En este cuarto artículo tiene como objetivo comentar el script en Python que hará la función de servidor de escaneado en la Raspberry Pi. La segunda parte habla sobre como convertir este script en un servicio de Linux.

En los artículos anteriores se configuró CUPS y se programó el script del servidor de impresión de PDF. Ahora ya contamos con opciones para imprimir desde ordenadores y dispositivos móviles, pero aún no podemos utilizar todo el potencial de la impresora multifunción ya que aún no podemos utilizar la función de escaneado. Para solucionar este problema, el siguiente script crea un sencillo servidor web, muy parecido al que se utilizó en el artículo anterior para el servidor de impresión, con el que realizar un escaneado del documento que se encuentre en la bandeja de escaneado. Una vez que el escaneado llega a su fin, el servidor web envía al cliente un archivo de imágen en formato TIFF con el documento escaneado.

NOTA: La parte en HTML ha sido modificada por problemas con el CMS. Recomiendo descargar el ZIP (al final del artículo)  y consultar la versión correcta. Este problema ha sido solucionado.

Nota: Se ha corregido un problema importante que permitía la ejecución de código aleatorio a través de una petición POST especial.

Interfaz web de escaneado.

Captura de la web de escaneado.

 

En el script anterior se utilizan los siguientes módulos de Python:

  • BaseHTTPServer: Se utiliza para obtener la funcionalidad de servidor web.
  • os: Se utiliza para interactuar con el sistema.
  • cgi: Se utiliza para trabajar con formularios en la web.
  • time: Se utiliza para crear un archivo temporal único.

 

La funcionalidad del script anterior es muy similar a la que se explico en el artículo anterior. El script inicia el servidor de escaneado en el puerto 1479, que se queda esperando a recibir una petición. Si se desea realizar un escaneado, el usuario debe abrir un navegador y escribir en la barra de direcciones web la dirección IP de la Raspberry Pi y el puerto en el que está alojado el servidor (debería ser algo así 100.101.102.103:1479 siendo 100.101.102.103 la dirección IP de la Raspberry Pi) realizando una petición . Una vez que se recibe la petición desde el cliente, se lanza la función do_GET que responde al cliente con lo que tengamos en esa función. A continuación el usuario puede, o no, contestar a lo que acabamos de enviarle usando una petición tipo POST. En caso de que ocurra, esta petición se procesará en la función do_POST y se realizaran las operaciones necesarias y se enviará de vuelta al usuario la imagen escaneada, si ha habido algún problema, la imágen devuelta será de 0 bytes. A continuación se explica esto un poco más pormenorizado.

En el script anterior el main() inicializa el servidor web y la clase StoreHandler contiene las tres funciones (do_POST, do_GET y respond) que implementan la funcionalidad del servidor web.

  • do_GET: Cada vez que se recibe una petición web, este sencillo servidor responde al cliente que ha hecho una petición con lo que este determinado en ella a través de la función respond (Se debe tener en cuenta que a cualquier tipo de petición siempre se responde esto, da igual que el cliente pida una imagen, una página web o cualquier otra cosa).
  • do_POST: Esta función es la responsable de procesar la información que se recibe desde el usuario (que envía una petición POST) cuando realiza la petición de escaneado. En esta función se procesa la petición (con todas las opciones seleccionadas) y se crea el comando con el que se escaneará el documento.
  • respond: Es la responsable de enviar datos al cliente (se usa en do_GET y en do_POST)

 

El script anterior lo he situado en /opt/pyscan/scanserver.py (solo se puede acceder a este directorio como superusuario). Os recomiendo utilizar el mismo directorio que yo si queréis utilizar el script para convertirlo en servicio de GNU/Linux sin modificar nada.

En esta ocasión, para dar compatibilidad a vuestro escáner primero debe ser reconocido y estar configurado (si fuese necesario) en el sistema en el que se implemente el servidor de impresión (en este caso en la Raspberry Pi). A continuación se puede averiguar si vuestra impresora es reconocida por el sistema con el siguiente comando (en modo superusuario):

 

Nota: Dispositivos webcam y algunos otros también son reconocidos como dispositivos válidos. Esto obliga a obtener el nombre del dispositivo a mano en caso de que tengais más de un dispositivo compatible (en la Raspberry Pi, no existia ningún otro, por lo que este detalle no se tiene en cuenta)

Para obtener todas las opciones con las que el sistema permite trabajar al escanear documentos con un dispositivo determinado se puede utilizar el siguiente comando:

 

Sustituyendo DEVICE por el dispositivo que se quiera utilizar como impresora obtenemos la ayuda y las opciones para ese dispositivo.

Una vez que se conocen estos datos, es necesario editar do_GET para que se muestren las opciones correspondientes al escáner que se desea configurar en la interfaz web y luego es necesario modificar do_POST para que se lean las opciones y se genere el comando de escaneado de forma correcta.

En la función do_POST se reciben todas las opciónes de configuración del escaneado (blanco y negro o color, resolución…). Es importante generar bien el comando de escaneado y guardar el fichero generado al escanear para poder enviarlo de vuelta.

En el script el archivo escaneado se guarda en un archivo en el que el nombre es generado a partir de la fecha y hora actual (para evitar problemas) y se escribe en el directorio /tmp.

 

Para escanear desde consola se puede utilizar algo como lo siguiente:

 

El parámetro -d nos permite seleccionar el dispositivo con el que se va a escanear. El parámetro mode nos permite decidir si deseamos escanear en color (Color) o en blanco y negro (Gray), el parámetro resolution nos permite seleccionar la resolución (en DPI) con la que escanear, el parámetro format nos permite seleccionar el formato de salida. Un ejemplo concreto podría ser algo como lo siguiente:

 

Establecer el script como un servicio en GNU/Linux.

.El siguiente script debe guardarse en /etc/init.d/scanweb.sh para que funcione (Al final del artículo está el archivo ZIP con todos los archivos y la estructura de directorios)

 

Para dar de alta el servidor de escaneado como servicio, lo que implica que el script en Python del servidor de impresión se lance al iniciar la Raspberry Pi, se debe ejecutar en ese directorio el siguiente comando:

 

Automáticamente creará enlaces simbólicos a los niveles de ejecución (runlevels) correspondientes.

Si en algún momento deseas dar de baja el servicio y que por lo tanto NO se ejecute al inicio deberías usar el siguiente comando:

 

Ficheros del servidor: Archivos del servidor de escaneado v2

Ante cualquier duda, sugerencia, mejora o queja podéis dejarla en los comentarios.

Este es el último artículo de este proyecto. Los anteriores puedes encontrarlos aquí:

 

Bibliografía:
http://www.linuxtopia.org/online_books/programming_books/python_programming/python_ch36s02.html
http://www.stuffaboutcode.com/2012/06/raspberry-pi-run-program-at-start-up.html

En este tercer artículo se tratará la realización de un script sencillo en Python que hará la función de servidor de impresión de archivos PDF en la Raspberry Pi. La segunda parte habla sobre como convertir este script en un servicio de Linux.

Una vez que contamos con nuestro CUPS instalado y funcionando en la Raspberry Pi, ya podemos imprimir desde los ordenadores de nuestra red. El problema reside es que actualmente contamos en nuestra vida cotidiana con muchos dispositivos en los que no podemos configurar CUPS para imprimir como por ejemplo móviles y tablets. Para dar capacidades de impresión a estos dispositivos se ha realizado el script que se comenta a continuación, aunque actualmente cuenta con la restricción de que solo se permite la impresión de archivos PDF.

A continuación se muestra el script del servidor de impresión web (Al final del artículo está el archivo PDF con todos los archivos y la estructura de directorios). Debe tenerse en cuenta que el script está escrito de forma que tenga compatibilidad únicamente con la impresora multifunción DX4800 (en la descripción aparece como DX6000). Para que el script funcione con otros modelos de impresora más adelante se tratará que cosas deberían cambiarse y como obtener la información de las opciones disponibles.

NOTA: La parte en HTML ha sido modificada por problemas con el CMS. Recomiendo descargar el ZIP (al final del artículo)  y consultar la versión correcta. Este problema ha sido solucionado.

Nota: Se ha corregido un problema importante que permitía la ejecución de código aleatorio a través de una petición POST especial.

Interfaz web de impresión

Captura de la interfaz web de impresión

 

En el script anterior se utilizan los siguientes módulos de Python:

  • BaseHTTPServer: Se utiliza para obtener la funcionalidad de servidor web.
  • pyPdf: Se utiliza para comprobar si el archivo recibido es un archivo PDF.
  • cgi: Se utiliza para trabajar con formularios en la web.
  • time: Se utiliza para crear un archivo temporal único.
  • os: Se utiliza para interactuar con el sistema.

 

El script anterior lo que hace básicamente es iniciar el servidor de impresión en el puerto 1478, que se queda esperando a recibir una petición. Si se desea imprimir un documento PDF el usuario debe abrir un navegador y escribir en la barra de direcciones web la dirección IP de la Raspberry Pi y el puerto en el que está alojado el servidor (debería ser algo así 100.101.102.103:1478 siendo 100.101.102.103 la dirección IP de la Raspberry Pi) realizando una petición . Una vez que se recibe la petición desde el cliente, se lanza la función do_GET que responde al cliente con lo que tengamos en esa función. A continuación el usuario puede, o no, contestar a lo que acabamos de enviarle usando una petición tipo POST. En caso de que ocurra, esta petición se procesará en la función do_POST y se realizaran las operaciones necesarias y enviando de vuelta al usuario información indicando si ha habido algún problema o no. A continuación se explica esto un poco más pormenorizado.

En el script anterior el main() inicializa el servidor web y la clase StoreHandler contiene las tres funciones (do_POST, do_GET y respond) que implementan la funcionalidad del servidor web.

  • do_GET: Cada vez que se recibe una petición web, este sencillo servidor responde al cliente que ha hecho una petición con lo que este determinado en ella a través de la función respond (Se debe tener en cuenta que a cualquier tipo de petición siempre se responde esto, da igual que el cliente pida una imagen, una página web o cualquier otra cosa).
  • do_POST: Esta función es la responsable de procesar la información que se recibe desde el usuario (que envia una petición POST) cuando envía el fichero a imprimir. En esta función se procesa el fichero y se crea el comando con el que mandaremos el fichero a imprimir.
  • respond: Es la responsable de enviar datos al cliente (se usa en do_GET y en do_POST)

 

El script anterior lo he situado en /opt/pyprint/printserver.py (solo se puede acceder a este directorio como superusuario). Os recomiendo utilizar el mismo directorio que yo si queréis utilizar el script para convertirlo en servicio de GNU/Linux sin modificar nada.

Básicamente para dar compatibilidad a vuestra impresora se debe averiguar que opciones os da el comando lp para imprimir. Esto se puede averiguar escribiendo en la terminal del ordenador donde la impresora lo siguiente:

lpoptions -d $(lpstat -a|sed -n 1p|cut -d ‘ ‘ -f 1)

 

Con el comando lpoptions -d IMPRESORA se listan todas las opciones que permite utilizar el driver que este cargado para esa impresora. Con el comando lpstat -a se listan todas las impresoras conectadas al equipo. Con sed -n 1p se imprime la primera linea de la salida estándar. Con cut -d ‘ ‘ -f 1 se parte la cadena que recibe utilizando como separador un espacio en blanco y el parámetro -f 1 indica que nos interesa escribir en la salida el primer elemento en los que se dividió la cadena de entrada. La línea vertical | se conoce como pipe y lo que hace es concatenar las operacioes (se ejecuta la primera, lo que escribe la primera se le pasa a la segunda)

Una vez que se conocen estos datos, es necesario editar do_GET para que se muestren las opciones correspondientes a la impresora que se quiere configurar y luego es necesario modificar do_POST para que se lean las opciones de forma correcta y se genere el comando de impresión de forma correcta.

En la función do_POST se recibe el fichero que se quiere imprimir y todos las opciónes de configuración de la impresora. Es importante generar bien el comando de impresión y guardar el fichero recibido para imprimirlo luego.

En el script el archivo PDF se guarda en un archivo en el que el nombre es generado a partir de la fecha y hora actual (para evitar problemas) y se escribe en el directorio /tmp.

 

Para imprimir desde consola se puede utilizar en linux el comando lp. Este comando es el que he utilizado para imprimir en la Raspberry Pi.

 

El parámetro -d permite seleccionar la impresora, se debe escribir el nombre. El parámetro -o permite establecer las opciones, que deben ir entre comillas (las que aparecen en el listado de lpoptions). El último parámetro (obligatorio) es el fichero a imprimir. Un ejemplo sería el siguiente:

 

Establecer el script como un servicio en GNU/Linux.

El siguiente script debe guardarse en /etc/init.d/printweb.sh para que funcione (Al final del artículo está el archivo ZIP con todos los archivos y la estructura de directorios).

 

Para dar de alta el servidor de impresión como servicio, lo que implica que el script en Python del servidor de impresión se lance al iniciar el sistema en la Raspberry Pi, se debe ejecutar en ese directorio el siguiente comando:

 

Automáticamente creará enlaces simbólicos a los niveles de ejecución (runlevels) correspondientes.

Si en algún momento deseas dar de baja el servicio y que por lo tanto NO se ejecute al inicio deberías usar el siguiente comando:

En el siguiente artículo se tratara el script para el servidor de escaneado.

Ficheros del servidor: Archivos del servidor de impresión de PDF v2

Ante cualquier duda, sugerencia, mejora o queja podéis dejarla en los comentarios.

A continuación puedes encontrar los artículos de este proyecto:

 

Bibliografía:
http://www.linuxtopia.org/online_books/programming_books/python_programming/python_ch36s02.html
http://stackoverflow.com/questions/13146064/simple-python-webserver-to-save-file
http://www.stuffaboutcode.com/2012/06/raspberry-pi-run-program-at-start-up.html

Una impresora multifunción (impresora y escáner) es un aparato muy útil tanto para casa como para oficina. Si queremos utilizar la multifunción para imprimir o escanear desde muchos dispositivos distintos puede ser una tarea poco práctica o imposible. Para sortear este inconveniente he desarrollado esta solución que, aunque es muy mejorable, ofrece la funcionalidad básica.

En mi caso, contamos en casa con una impresora multifunción y varios ordenadores desde los que sería interesante poder imprimir y escanear. Hasta hace poco para imprimir o escanear era necesario ir al ordenador en el que la impresora estuviera conectada y realizar la operación deseada, siempre que el ordenador no estuviera ocupado en ese momento. Otra cosa que también resulta molesta es no poder imprimir desde una tablet o un móvil.

Para solucionar este problema una posible solución es aprovechar la red interna de casa o de la oficina para conectar la impresora multifunción en red. Para ello es necesario utilizar un ordenador como servidor de impresion y escaneado para poder ofrecer estos servicios a todos los dispositivos conectados a la red.

En concreto, para este proyecto se ha utilizado una multifunción de la marca Epson y se ha elegido como servidor un mini ordenador llamado Raspberry Pi que ofrece un rendimiento razonable con un bajo precio y un bajo consumo. En particular, se ha usado una Raspberry Pi modelo B con 256 megabytes de RAM con el sistema operativo Debian y la impresora es una Epson DX4800.

El software utilizado en este proyecto ha sido el servidor de impresión CUPS y dos sencillos scripts en Python que ofrecen la funcionalidad de servidor de impresión de PDF y de servidor de escaneado.

Ejemplo de configuración de red.

Esquema de ejemplo de configuración de red.

 

En el esquema anterior se muestra un ejemplo de la configuración de red que se puede utilizar en este proyecto y es la que se ha tenido en cuenta al realizar esta serie de artículos.

 

Esquema Raspberry Pi

Esquema de conexiones en la Raspberry Pi

 

En la imagen anterior se ilustra las conexiones de la Raspberry Pi que se han utilizado en este proyecto. Como se puede observar se ha utilizado uno de los puertos USB para conectar la impresora y el puerto Ethernet para conectar el Raspberry Pi al router (al que se conectan el resto de dispositivos).

También es posible conectar el Raspberry Pi por red inalámbrica al router utilizando un adaptador inalámbrico en el segundo USB, pero para ello es necesario realizar un poco de configuración extra.

En los siguientes artículos se explica todo lo refente a la implementación de esta solución:

Se agradecen los comentarios ante cualquier duda, sugerencia o corrección.

Copyright © 2009 Draft Idea. Theme by THAT Agency powered by WordPress.