Configuración servidor de impresión y escaner con Raspberry Pi

Con una impresora antigua y una Raspberry es posible crear un servidor de impresión, estos son los pasos:

Primero como siempre actualizar Raspberry.

sudo apt-get update
sudo apt-get upgrade

Ahora instalamos CUPS, el servidor de impresión por excelencia de UNIX.

sudo apt-get install cups

Esto nos creará un grupo de administración de impresoras llamado lpadmin, agregamos el usuario pi a este grupo, se puede elegir cualquier usuario y cuando se acceda a través de web será este el usuario que se tendrá que validar.

sudo usermod -a -G lpadmin pi

Tenemos que habilitar el acceso remoto más allá de localhost, para que se puedan administrar las impresoras desde otra máquina en la red de área local.

sudo cupsctl --remote-any
sudo /etc/init.d/cups restart

Ahora podemos probar la web, usando la dirección de la Raspberry y el puerto 631 que es el de defecto, si quisiéramos cambiar el puerto se puede editar desde /etc/cups/cupsd.conf en la línea marcada como Port.

Si no tenemos instalado samba, estos serían los pasos rápidos:

sudo apt-get install samba

Ahora hay que editar el archivo de configuración de samba para agregar la entrada de la impresora, realmente esta entrada ya está creada solo hay que verificar que sea igual que esta:

# CUPS printing.  
[printers]
comment = All Printers
browseable = no
path = /var/spool/samba
printable = yes
guest ok = yes
read only = yes
create mask = 0700

# Windows clients look for this share name as a source of downloadable
# printer drivers
[print$]
comment = Printer Drivers
path = /var/lib/samba/printers
browseable = yes
read only = no
guest ok = no

También tenemos que establecer correctamente el valor del parámetro workgroup y de wins support:

workgroup = my_workgroup
wins support = yes

Ahora reiniciamos samba para hacer efectivos estos cambios.

sudo /etc/init.d/samba restart

Ahora a través de la web accedemos a la sección de administración, desde allí agregamos una impresora con el botón «Add printer» posiblemente haya que acceder con la cuenta que hemos agregado anteriormente al grupo lpadmin, si CUPS es capaz de detectar la impresora la veremos aquí como una impresora local, la seleccionamos y continuamos, cambiamos nombre y descripción o aceptamos las que vienen por defecto y marcamos compartir impresora «Share this printer» con esto ya tendremos una impresora configurada en red.

Esta es una configuración por defecto que funcionará tanto para pcs como para dispositivos móviles.

Mas info:

https://pimylifeup.com/raspberry-pi-print-server/

 

Configuración servidor de impresión y escaner con Raspberry Pi

Crítica velada a TDD

Empezaré diciendo que no he sido nunca un gran practicante de TDD pero sin embargo no critico las pruebas unitarias y si creo que son útiles por multiples razones.

TDD ha calado entre la comunidad poco más o menos como «la solución definitiva» a la calidad del software ganando un montón de adeptos que se han hecho fanáticos de este sistema como es habitual entre la comunidad cuando llega una nueva teoría que gana adeptos muy rapidamente y arrasa haciendo que todo el mundo tenga que aceptarla so pena de parecer un ignorante, aunque hablar de estas olas que más parecen modas que realmente grandes avances sería tema de otro artículo.

TDD surgió como un método para proporcionar una alta calidad a las aplicaciones algo en lo que no pongo dudas ya que todo el desarrollo está centrado en las pruebas, lo cual proporciona el rol dominante a las pruebas por encima de otras consideraciones.

Esto implica varias cosas, TDD impone algunos requisitos de una forma más o menos explícita, por ejemplo cosas obvias como que es necesario tener un buen conocimiento de frameworks de tests unitarios pero tambien otras no tan obvias.

Por ejemplo la refactorización constante, el test siempre va primero esto quiere decir que durante el desarrollo a medida que se implementen nuevos requisitos o cambien algunos habrá que ajustar la aplicación respetando las pruebas unitarias que constituyen la parte principal en este sistema, esto implica continuos cambios en el código para evitar que quede disperso y sin estructura, para mantener la calidad del código a este nivel hace falta tener buenos desarrolladores.

Tambien cualquier sistema de pruebas, no solo TDD, implica tener que hacerlas esto quiere decir una inversión de tiempo, obviamente más pruebas implica más tiempo y cuanto más centrado este el sistema en las pruebas más tiempo conlleva.

Aquí llegamos a un punto clave, la combinación tiempo y recursos, estos dos factores conllevan inevitablemente un aumento del coste y con TDD este coste no es precisamente bajo, necesitas buenos desarrolladores y tiempo para hacer la aplicación.

Habrá quien diga que este sistema no excluye programadores junior que pueden estar realizando otras tareas de bajo nivel y que en el futuro aprenderán un buen sistema de desarrollo, habrá también quien diga que el producto de calidad implica tiempo y no se pueden pedir las cosas «de un día para otro», incluso dirán que un equipo disciplinado en TDD no implica una variación sustancial en tiempo.

La realidad no es esa, no todos los clientes van a aceptar algo así y no todas las empresas pueden permitirse ofertar ese tipo de desarrollos, independientemente de que se vendan como productos de alta calidad.

Tampoco pretendo quitar valor a TDD, simplemente que no sirve para todos los desarrollos, en mi opinión tiene cabida en sectores críticos, por ejemplo: defensa, sanidad, … donde la calidad ha de ser máxima y los errores implican grandes pérdidas ya sean materiales o humanas.

A fin de cuentas la conclusión es, si para que TDD funcione necesitas, aparte de una gran comprensión por parte del cliente,  tiempo y recursos, ¿cómo de malo tendría que ser para que aún asi no funcionase?

Crítica velada a TDD

Configurando Raspberry Pi como servidor de música [Spotify]

Actualizado el 26 de Septiembre de 2022

Para configurar una Raspberry Pi y que funcione como servidor de música usando una cuenta de Spotify usaremos el paquete mopidy. Existen distribuciones ya preparadas con el servidor de música configurado pero en este caso estas instrucciones son para hacerlo sobre una distribución ya existente.

Primero hay que agregar el repositorio de mopidy y para ello primero agregamos las claves:
wget -q -O – https://apt.mopidy.com/mopidy.gpg | sudo apt-key add –

Ahora el repositorio (en este caso para una distribución jessie, habría que cambiar por la que corresponda):
sudo wget -q -O /etc/apt/sources.list.d/mopidy.list https://apt.mopidy.com/jessie.list

A continuación actualizar e instalar:

sudo apt-get update
sudo apt-get install python-spotify

Ahora instalamos el paquete de Spotify, según la página solo funciona para cuentas premium aunque hay gente que comenta que lo ha usado también para cuentas gratuitas:
sudo python3 -m pip install Mopidy-Spotify

Existen varias formas de arrancarlo, vamos a optar por hacerlo como servicio. Con este comando lo arrancaremos al inicio como servicio:
sudo systemctl enable mopidy

Otra opción para sistemas Debian es:
sudo dpkg-reconfigure mopidy

Estos son los clásicos comandos para arrancar, parar y reiniciar:

sudo service mopidy start
sudo service mopidy stop
sudo service mopidy restart

Ahora solo queda configurar el servidor web, viene instalado por defecto y lo configuramos en la siguiente ruta:
sudo nano /etc/mopidy/mopidy.conf

Creamos una sección [http]

[http]
enabled = true
hostname = ::
port = 6680

Lo único destacable aquí es que el nombre de host es «::» esto indica que escuchará en todas las direcciones IP, no hay validación de usuario así que cualquiera podrá acceder.

Y una sección para el usuario y contraseña de Spotify , los datos de client_id y client_secret se pueden obtener aquí.


username = hola
password = caracola
client_id = XXX
client_secret = YYY

Ahora si intentamos acceder al servidor y al puerto nos dirá que no hay cliente web instalado, existen varias alternativas.

Para poder instalar estos paquetes primero hay que instalar pip, un instalador de paquetes en Python:
sudo apt-get install python-pip

En este caso opto por Mopify y se instala con:
sudo pip install Mopidy-Mopify

Y en el fichero de configuración añadimos

[mopify]
enabled = true
debug = false

Si lo queremos actualizar:
sudo pip install –upgrade Mopidy-Mopify

También existe este otro cliente, más parecido a la interfaz de Spotify y más sencillo:
sudo pip install Mopidy-Iris

Para actualizar
sudo pip install –upgrade Mopidy-Iris

Y como configuración

[iris] 
enabled = true 
country = ES 
locale = es_ES

Es necesario reiniciar el servicio para ver los cambios, al acceder al servidor (http://servidor:6680) veremos el cliente.

Si queremos comprobar primero que el sonido está bien configurado podemos usar este comando:
aplay /usr/share/sounds/alsa/Front_Center.wav

Se pueden cambiar la salida de audio usando raspi-config (System->Audio)  o de forma manual junto con algunas otras opciones con alguno de estos dos métodos dependiendo de la versión:

Versión antigua

Usar HDMI si está conectado, sino jack de 3.5» (si este comando da un error probar con la versión nueva):
sudo amixer cset numid=3 0

Forzar usar solo jack de 3.5:
sudo amixer cset numid=3 1

Forzar usar solo HDMI:
sudo amixer cset numid=3 2

Para controlar el volumen se puede poner estos alias en ~/.bashrc
# Increase volume by 5%
alias volu=’amixer set PCM — $[$(amixer get PCM|grep -o [0-9]*%|sed ‘s/%//’)+5]%’
# Decrease volume by 5%
alias vold=’amixer set PCM — $[$(amixer get PCM|grep -o [0-9]*%|sed ‘s/%//’)-5]%’

O establecer directamente el valor con (donde 90% es el volumen deseado):
amixer sset PCM,0 90%

Version nueva

Para cambiar las opciones de audio hay que editar el fichero .asoundrc que tendremos en el directorio home del usuario, también podemos guardarlo en la ruta /etc/asound.conf en cuyo caso será para todos los usuarios, sino lo tenemos lo creamos:

pcm.!default {
  type asym
  playback.pcm {
    type plug
    slave.pcm "output"
  }
  capture.pcm {
    type plug
    slave.pcm "input"
  }
}

pcm.output {
  type hw
  card 0
}

ctl.!default {
  type hw
  card 0
}

Donde indica card 0 si ponemos card 1 usaremos la salida Headphones sino card 0 usará HDMI después de crear este fichero hay que reiniciar la sesión usando su pi si no lo hemos hemos en /etc/asound.conf

Para controlar el volumen se puede poner estos alias en ~/.bashrc, este ejemplo es para el jack de 3.5» sino se ha establecido la salida de jack usando el fichero anterior este comando dará error (igual para HDMI).
# Increase volume by 5%
alias volu=’amixer set Headphone — $[$(amixer get Headphone|grep -o [0-9]*%|sed ‘s/%//’)+5]%’
# Decrease volume by 5%
alias vold=’amixer set Headphone — $[$(amixer get Headphone|grep -o [0-9]*%|sed ‘s/%//’)-5]%’

Para HDMI haríamos:
# Increase volume by 5%
alias volu=’amixer set HDMI — $[$(amixer get HDMI |grep -o [0-9]*%|sed ‘s/%//’)+5]%’
# Decrease volume by 5%
alias vold=’amixer set HDMI — $[$(amixer get HDMI |grep -o [0-9]*%|sed ‘s/%//’)-5]%’

O establecer directamente el valor con (donde 90% es el volumen deseado) para el jack de 3.5»
amixer sset Headphone,0 90%

O para HDMI
amixer sset HDMI,0 90%

Acceso a la Web

Ahora solo queda acceder a la web con la ip y puerto configurado y elegir el cliente, es posible que haya que echar un vistazo a la configuración del cliente para ver que todo está correcto como dar acceso a spotify.

A veces el refresco de algunas playlist no funciona correctamente y puede ser necesario borrar cookies o recargar la página, se puede probar desde otra máquina para verificar si realmente refresca o no.

Ahora vamos a ver como configurar estas rutas por algo más fácil de recordar, para ello en Apache creamos un virtual host que nos haga de proxy con el servidor de spotify, creamos un fichero en la carpeta /etc/apache2/sites-available/003-spotify.conf con el siguiente contenido, obviamente deberemos tener un sistema DNS que nos resuelva correctamente el nombre spotify, vamos a suponer que el servidor está en la dirección 192.168.1.4

<VirtualHost spotify:80>
  ServerName spotify.domain
  SererAlias spotify
  ProxyPreserveHost On
  ProxyPass / http://192.168.1.4:6680/
  ProxyPassReverse / http://192.168.1.4:6680/
  CustomLog /var/log/apache2/spotify.log combined
  ErrorLog /var/log/apache2/spotify.error.log
</VirtualHost>

Para habilitar el sitio ejecutamos:

sudo a2ensite 004-spotify.conf

Fuentes:

https://github.com/mopidy/mopidy-spotify

https://www.mopidy.com/

Configurando Raspberry Pi como servidor de música [Spotify]

Global Robot Expo 2017

Patrocinado por la FNAC tuve ocasión de echar un vistazo a la Expo Robot que se celebró este año en Madrid, un espacio amplio donde había varias áreas temáticas.

La primera sección dedicada a robótica industrial, robots que se mueven por ejemplo siguiendo una línea o que se dedican a automatizar ciertas tareas.

Img 1

Img 2

Después un paseo por las cada vez más pujantes impresoras 3D, se pueden apreciar creaciones de cierta complejidad.

Img 3

Los robots educativos que se puedan programar siguen apareciendo aunque es verdad que todavía sigue siendo un poco cara la gama alta.

Img 4

Img 5

Una sección dedicada a la domótica casera, por ejemplo el clásico ejemplo de la aspiradora:

Img 6

O un autónomo limpiador de cristales al más puro estilo spiderman:

Img 7

O algo un poco más complejo como un pequeño asistente casero:

Img 8

Ahora un espacio dedicado a los fans de los clásicos:

Img 9

Una de las secciones más grandes estuvo dedicada a los drones habiendo incluso competiciones entre ellos, siendo algunos de ellos de gama profesional necesitando sistemas de manejo en remoto.

Img 10

Img 11

Img 12

Una de las secciones más interesantes aunque no tuviera grandes máquinas a la vista, la UPV con su hyperloop de Elon Musk:

Img 13

Una sección dedicada a armazones asistidos, principalmente orientado a discapacidad, aunque más de uno estaría pensando en ser el próximo IronMan:

Img 14

Img 15

También se pudieron ver ejemplos de asistentes, cada vez un poco mejores:

Img 16

Img 17

Img 18

Interesantes de ver en acción:

Vid 1

O más interactivos:

Vid 2

O un ejemplo muy interesante de una araña artificial, muy logrado:

Vid 3

En general muy entretenido e interesante, habrá que volver el próximo año.

Global Robot Expo 2017

Desplegando en una Raspberry Pi Parte III (Depurando con XDebug)

Finalmente suele ser útil y práctico poder depurar las aplicaciones, principalmente he manejado dos sistemas de depuración en PHP, XDebug y Zend Debugger, Zend Debugger es propietario y XDebug es libre, el problema principal viene dado porque el binario de Zend Debugger no está disponible para la arquitectura arm de Raspberry así que optaremos por XDebug.

Así mismo hay varios editores que permiten depurar con XDebug, en este caso el ejemplo lo hago con PHPStorm, primero hay que hacer la configuración del lado servidor.

Una vez instalado el módulo de XDebug (verificar con phpinfo()) tendremos que configurarlo, editamos el fichero xdebug.ini y establecemos los siguientes valores.

zend_extension=/usr/lib/php5/20131226/xdebug.so
xdebug.remote_enable=1
xdebug.remote_handler=dbgp
zdebug.remote_mode=req
xdebug.remote_host=192.168.1.99
xdebug.remote_port=9000
xdebug.idekey="phpstorm"

Lo importante aquí es establecer como xdebug.remote_host la dirección IP del cliente, es decir donde está instalado PHPStorm que es desde desde donde queremos depurar y lo mismo para el puerto, estas opciones normalmente son configurables a partir del entorno pero el puerto por defecto 9000 es estándar.

xdebug.idekey es un valor que se pasa al depurador para identificar la sesión no es necesario establecerlo pero suele ser buena idea indicar el mismo que el IDE usado.

Si se quiere poder depurar desde cualquier máquina se puede usar el valor xdebug.remote_connect_back, para más detalles ver aquí.

Como ya vimos una buena opción es compartir vía Samba la carpeta de Apache de la Raspberry y usarla para editar directamente los ficheros eso nos ahorra de cara a PHPStorm el paso de desplegar, por lo tanto de cara a crear un nuevo proyecto en PHPStorm indicamos que trabajaremos en local con la ventaja añadida de que tendremos también git integrado (si está configurado git en la carpeta del servidor).

Ahora solo nos queda desde el menú «Run» usar la opción «Start Listening for PHP Debug Connections«.

Ahora desde aquí creamos los enlaces que se usará para arrancar el depurador y conectar al cliente, lo recomendable es arrastrarlos a la barra de navegación del navegador que estemos usando, principalmente usaremos «Start debugger«.

Una vez que empiece el sistema de depuración PHPStorm nos mostrará una ventana en la que nos indicará cual es el mapeo correspondiente entre el fichero a depurar y la ubicación física del mismo, si no puede realizar esta asociación al crear un punto de interrupción aparecerá éste con una X indicándolo, esto es muy probable que pase para los ficheros fuente que están fuera de las carpetas públicas (habitual si se usa frameworks tipo Symfony) en ese caso desde «Run -> Edit Configurations» veremos debajo de «PHP Remote Debug» el host detectado dentro de éste solo tenemos que indicar los mapeos correspondientes dentro del servidor (las rutas físicas de Linux), es necesario pulsar enter para que se quede la ruta establecida.

 

Desplegando en una Raspberry Pi Parte III (Depurando con XDebug)

Desplegando en una Raspberry Pi Parte II (Git && Symfony)

Ahora que tenemos el entorno vamos a descargar los fuentes en la carpeta, evidentemente la carpeta donde desplegamos tiene que estar configurada en Apache, nos colocamos en la carpeta de despliegue y lanzamos un git clone, en este caso suponemos un hosting en BitBucket que nos descargará todo el código.

# git clone https://usuario@bitbucket.org/acme/coyote.git

Siguiendo los consejos de Symfony2 vamos a verificar que está todo correcto, para esto primero tenemos que instalar composer y que nos ponga al día todos los paquetes, es recomendable tener accesible el fichero composer.json para evitar tener que repetir configuraciones.

# sudo curl -sS https://getcomposer.org/installer | sudo php
# sudo php composer.phar install --no-dev --optimize-autoloader

El fichero composer.json tiene que estar accesible en la misma ruta ya que es el fichero que usará para descargar los paquetes correctos.

Puede dar un error de «ErrorException: proc_open(): fork failed – Cannot allocate memory» una forma de arreglarlo es crear una unidad swap con los siguientes comandos:

# sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
# sudo /sbin/mkswap /var/swap.1
# sudo /sbin/swapon /var/swap.1

Es recomendable que el fichero parameters.yml esté fuera del código fuente pero es necesario mantener parameters.yml.dist ya que en esta es donde se establecen los nuevos parámetros con sus valores por defecto. Después de esto los valores concretos de los parámetros se podrán modificar en parameteres.yml.

Es necesario una vez que se descarga la nueva versión desde git limpiar la cache y establecer de nuevos los permisos en la cache, para todos estos procesos se puede usar el siguiente script ubicándolo en la localización correcta.

# sudo git pull
# sudo php app/console cache:clear --env=prod
# sudo chown -R www-data:coyote app/cache

 

Desplegando en una Raspberry Pi Parte II (Git && Symfony)

Desplegando en una Raspberry Pi Parte I (LAMP && Samba)

Hay muchas formas automatizadas de crear un servidor de desarrollo, en este caso vamos a usar una Raspberry Pi con sistema LAMP, primero configuraremos el sistema LAMP y después configuraremos las carpetas.

Vamos a considerar que tenemos una empresa Acme que tiene un proyecto de nombre Coyote.

Primero tenemos que actualizar la Raspberry para ponerlo todo en orden.

Se puede actualizar el kernel así como el firmware de Raspberry aunque no es estrictamente necesario, esto se realiza con el comando rpi-update, si no está instalado se puede descargar vía apt-get.

# sudo rpi-update

Ahora actualizamos la distribución, este paso es recomendable.

# sudo apt-get update
# sudo apt-get upgrade
# sudo apt-get dist-upgrade

Ahora instalamos primero la base de datos, en este caso MariaDB, durante el proceso de instalación se pedirá una contraseña para el usuario root, se recomienda indicar una.

# sudo apt-get install mariadb-server mariadb-client

Ahora instalamos el servidor Apache 2.

# sudo apt-get install apache2

Ahora instalamos PHP 5 y el módulo de PHP 5 para Apache 2.

# sudo apt-get install php5 libapache2-mod-php5

PHP 5 tiene muchos módulos pero uno de los más importantes y que va a ser necesario es el módulo de PHP 5 para base de datos, en este caso para MariaDB

# sudo apt-get install php5-mysqlnd

Como optimizador de código intermedio de PHP 5 vamos a instalar ACPu.

# sudo apt-get install php5-acpu

Ahora solo queda reiniciar Apache 2.

# sudo service apache2 restart

Ahora vamos a usar Samba para poder acceder a la carpeta de Apache desde Windows, si trabajamos en entornos híbridos es una comodidad para poder acceder al código fuente.

En Raspberry vamos a usar la carpeta por defecto de Apache para desplegar (/var/www/apache/html) en esta carpeta creamos la carpeta Acme y dentro de esta la carpeta Coyote.

#cd /var/www/html
#sudo mkdir acme
#cd acme
#sudo mkdir coyote

Ahora podemos instalar Samba.

#sudo apt-get install samba samba-common-bin

Una vez hecho esto vamos a crear un usuario por proyecto, en este caso creamos el usuario coyote, no nos interesa que tenga ni una shell ni una carpeta de usuario porque es un usuario que solo vamos a usar para acceder por red y así proporcionamos más seguridad al sistema, en resto de los valores que nos pida podemos establecer cualquier valor.

# sudo adduser -shell /bin/false --no-create-home coyote

Ahora añadimos el usuario a la lista de usuarios de Samba y le indicamos una contraseña para acceder por red.

# sudo smbpasswd -a coyote

Tenemos que dejar que el usuario de apache (www-data) pueda acceder a las carpetas para poder mostrarlas, pero también tenemos que dejar que el usuario coyote pueda acceder y realizar modificaciones desde el exterior a través de la red, así que vamos a crear el grupo acme y añadir a ambos usuarios a ese grupo.

# sudo addgroup acme
# sudo adduser coyote acme
# sudo adduser www-data acme

Empezamos con los permisos, vamos a asignar como propietario de los ficheros a www-data pero el grupo para la carpeta acme lo vamos a asociar al grupo acme, la carpeta html la dejamos como está (propietario y grupo para root para permisos 775).

# cd /var/www/html
# sudo chown -R www-data acme
# sudo chgrp -R acme acme

Ahora asignamos permisos, damos permiso total al usuario y grupo.

# sudo chmod -R 770 *

Tanto el usuario coyote como el usuario www-data necesitan acceder a la carpeta así que vamos a establecer el bit setgid para que los permisos se orienten por grupo y no por usuario así ambos usuarios podrán utilizar los ficheros indistintamente y también configuramos los permisos en la carpeta.

# sudo chmod g+s acme
# sudo chmod -R 755 acme

Ahora solo nos queda hacer visible la carpeta a través de la red, para eso modificamos el fichero /etc/samba/smb.conf y añadimos lo siguiente.

[coyote]
comment = El proyecto Coyote de Acme
path = /var/www/html/acme/coyote
read only = No
valid users = coyote
write list = coyote #Usuarios que pueden escribir
create mask = 0660 #Mascara de creación de archivos
directory mask = 0770 #Máscara de creación de directorios

Finalmente podemos comprobar que toda la configuración es correcta con el uso del comando testparm.

# testparm

Que debería indicarnos que todo es correcto, si es así reiniciamos Samba.

# sudo service smbd restart

 

Desplegando en una Raspberry Pi Parte I (LAMP && Samba)

Recopilatorio

Esta vez toca recopilatorio, sobre artículos que escribí en mi antigua empresa y que ahora agrupo para todos aquellos que les pueda resultar de utilidad o interés, tanto en castellano como inglés, los coloco cronológicamente aunque realmente se pueden leer en cualquier orden.

[Spanish]

Si … o no si ( To if or not to if )

Desmontando a imperativo (Deconstruyendo imperativo)

Bit veo, bit quiero

Quo vadis: Filosofía del programador

Cui bono? O el arte de la reutilización de código

[English]

Si … o no si ( To if or not to if )

Desmontando a imperativo (Deconstructing imperative)

Bit I see, bit I want

Quo vadis: Programmer’s Philosophy

Cui bono? Or the art of code reusing

Recopilatorio

Configurando MySQL en .NET

MySQL constituye una base de datos muy versátil para cierto tipo de aplicaciones, gratuita y con un gran número de opciones se ha convertido en un standard para aplicaciones de tamaño medio aunque también sea válida para aplicaciones de gran tamaño.

A pesar de que generalmente se asocia con aplicaciones de código libre y con otros lenguajes de programación actualmente también tiene desarrollado un conector para .NET que soporta Entity Framework 6.

En este caso vamos a ver su configuración para Code First en .NET 4.5.1, el proyecto de ejemplo será una aplicación MVC usando Visual Studio 2013 aunque cualquier tipo de proyecto es válido.

Lo primero es instalar el conector, se puede descargar directamente o usando NuGet, en este caso usaremos NuGet por ser el sistema más habitual  actualmente.

Hay que instalar dos paquetes:

  • Entity Framework 6.1.3
  • MySql.Data.Entity 6.9.8 (que instalará MySql.Data 6.9.8)

Una vez hecho esto agregamos en web.config la configuración de EF, algunas de estas secciones nos las incluirá el propio paquete NuGet, todas se incluyen dentro del raíz de configuración (nodo “configuration”)

Primero la sección de configuración,

<configSections>
  <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>

La sección propiamente dicha,

<entityFramework>
  <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
    <parameters>
      <parameter value="v12.0" />
    </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
      <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d">
      </provider>
    </providers>
</entityFramework>

El proveedor de datos,

<system.data>
  <DbProviderFactories>
    <remove invariant="MySql.Data.MySqlClient" />
    <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.9.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
  </DbProviderFactories>
</system.data>

Y la cadena de conexión,

<connectionStrings>
  <add name="MyContext" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;port=3306;database=DB;uid=user;password=password" />
</connectionStrings>

Después tenemos que indicar la clase DbConfiguration que usaremos, para esto hay varias opciones:

  • Se puede incluir en la sección de configuración de web.config a través de:
<entityFramework codeConfigurationType="MySql.Data.Entity.MySqlEFConfiguration, MySql.Data.Entity.EF6">

o en una clase que inicialice la aplicación a través de la sentencia:

DbConfiguration.SetConfiguration(new MySqlEFConfiguration());

Otra opción es como un atributo en la clase del contexto, este es el método que usaremos ya que dependiendo del tipo de proyecto (MVC en este caso) puede no ser posible por la forma en la que se inicializa la aplicación (si estamos usamos por ejemplo un atributo de inicialización) ya que nos dará un error indicando que la configuración por defecto ya ha sido cargada.

namespace XXX.Models
{
    [DbConfigurationType(typeof(MySqlEFConfiguration))]
    public class MyContext : DbContext
    {
        public PorraContext() : base("MyContext")
        {
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }
    }
}

Una vez hecho habilitamos las migraciones con el comando:

Enable-Migrations

En la clase Configuration que nos habrá creado incluiremos las siguientes dos líneas la primera nos generará el código MySQL correcto (sino al crear una migración nos dará error) y la segunda línea servirá para que nos generé la tabla _MigrationHistory correctamente (sino nos dará un error de longitud de clave).

    internal sealed class Configuration : DbMigrationsConfiguration<XXX.Models.PorraContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());
            SetHistoryContextFactory("MySql.Data.MySqlClient", (conn, schema) => new MySqlHistoryContext(conn, schema)); //here s the thing.
        }
        protected override void Seed(Porra.Models.MyContext context)        {        }
    }

Después de hacer esto ya podremos incluir y lanzar migraciones sin problemas, con los comandos.

Add-Migration XXX_1.0

Update-Database – Verbose

Configurando MySQL en .NET

Consultas MongoDb

En esta ocasión un pequeño recopilatorio sobre comandos básicos de MongoDb:

Las consultas se realizan con el comando find()

db.foo.find(query, projection)

query indica cual es el criterio a buscar.

projection  indica que campos hace falta, son campos que se pueden incluir o excluir.

db.foo.find({_id:1}, {_id:1})

El 1 indica que ese campo se incluye, un 0 no incluiría ese, hay una excepción y es el campo _id que siempre se incluye a no ser que se excluya de forma explícita, no se puede combinar o se incluyen todos o se excluyen todos (todos 1s o todo 0s).

A continuación una tabla tipo con los criterios de búsqueda más utilizados:

{$gt} Mayor que db.foo.find({_id: {$gt:5}},{_id:1})
{$lt} Menor que db.foo.find({_id: {$lt:5}},{_id:1})
{$lte} Menor que o igual db.foo.find({_id: {$lte:5}},{_id:1})
{$gte} Mayor que o igual db.foo.find({_id: {$gte:5}},{_id:1})
{$not} Negar la premisa db.foo.find({_id: {$not: {$gt:2}}}, {_id:1})
{$in} Valores en rango db.foo.find({_id: {$in: [1,3]}},{_id:1})
{$nin} Valores no en rango db.foo.find({_id: {$nin: [1,3]}},{_id:1})
{$all} Deben coincidir todos los valores db.foo.find({tags: {$all: [‘cute’,’ocean’]}}, {name:1})
{$exists} Verifica si el campo existe o no (true, false) db.foo.find({“info.canFly”: {$exists:false}},{name:1})

Se pueden concatenar filtros, aquí se estaría indicando todos los que sean mayores que uno y menores que 4 (2 y 3).

db.foo.find({_id: {$gte:2,$lt:4}},{_id:1})

Para buscar por texto hay que tener en cuenta que el texto es sensible a mayúsculas y minúsculas, tanto el nombre del campo como el valor.

db.foo.find({tags: ‘cute’}, {name:1})

 Para indicar un nulo se haría:

db.foo.find({“info.canFly”:null},{name:1})

 Esto devuelve tanto campos nulos como campos que no existen.

Consultas MongoDb