Wednesday 26 September 2012

Habilitando y deshabilitando la opción de cambio de usuario en Windows 7

Al instalar windows 7 en el laboratorio de ordenadores del colegio, nos encontramos con el problema de que por defecto, windows 7 permite cambiar de usuario sin tener que desloguearse. Esto presenta un problema debido a que si los usuarios empiezan a utilizar esta opción en lugar de la de cerrar sesión o log off, al final del día podríamos tener pcs con múltiples usuarios logueados con la consiguiente bajada de rendimiento de los mismos.

Los pasos a seguir para deshabilitar el cambio rápido de usuario, son los siguientes:

e damos a inicio y escribimos regedit:

 
 
Esto nos abrirá el registro de windows:
 
 
 
A continuación, nos abrirá el registro de windows e iremos abriendo poco a poco el árbol de la siguiente forma:
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System

Dentro de system buscamos la entrada HideFastUserSwitching:
 

Ahora modificaremos el valor del registro haciendo doble click en la entrada y cambiando el 0 por un 1, quedando así:


Si en el futuro queremos volver a habilitar  el cambio de usuario solo tendremos que volver a cambiar el 1 por un 0. Por último, reiniciamos el equipo, y cuando volvamos a hacer login la opción de cambio de usuarios aparecerá deshabilitado:




 

Monday 30 July 2012

Cambiando el disco duro de un iMac


Es la primera vez que abro este tipo de iMac así que decidí hacer un pequeño foto-tutorial por si a alguien le dan ganas de poner un disco duro más grande o cambiarlo por un ssd.

En mi caso el disco duro no respondía y no había forma de formatearlo por lo que he tenido que cambiarlo por otro.

Lo primero que hay que hacer es desatornillar la trampilla que nos da acceso a los módulos de memoria que se encuentra en la parte inferior del iMac.



Una vez hecho esto, retiramos el cristal protector del lcd, el cual viene sujeto por un sistema de imanes; para retirarlo tenemos dos opciones o bien nos hacemos con unos chupones de los que usan los cristaleros o bien, con dos destornilladores muy finitos y con cuidado de no dañar la carcasa también podemos levantarlo:






A continuación retiramos todos los tornillos que vemos, para ello necesitaremos un destornillador con cabeza tipo torx.



Para que luego no haya confusiones a la hora de montar es recomendable etiquetar los tornillos que vamos quitando o al menos ir colocándolos de forma que luego podamos volver a montar sin perdernos.


Una vez hecho esto, ya podemos desprender la carcasa que rodea al lcd para ello hacemos una pequeña presión con los dedos tal como se ve en la imagen y la carcasa saldrá sin problemas. A tener en cuenta el conector de la webcam que tendremos que desconectar con cuidado para poder desprender la carcasa.


 He aquí el resultado de retirar la carcasa frontal.


Ya solo nos queda retirar el lcd y ya tendremos acceso al disco duro, para ello usando de nuevo el destornillador torx retiramos todos los tornillos que hay alrededor, estos son todos del mismo tamaño por lo que no hay lugar a equivocarse.



Terminando de quitar los tornillos tenemos que volver a ser cuidadosos ya que el lcd solo quedará sujeto al resto del equipo por varios cables, de ellos los únicos que es imprescindible retirar son dos grupos de dos cables (rojo y azul), en estos el conector hembra no lleva colores por lo que le he escrito a boli una A en el conector donde va el azul. Tras desconectar estos cuatro cables, ya podemos (siempre con sumo cuidado) doblar el lcd hacia adelante y tendremos acceso al disco duro, un par de fotos más:



Ya hemos terminado con la parte difícil, desde aquí ya solo nos queda desmontar el disco duro que cuenta con dos tornillos en la parte superior (para acceder a ellos quitamos la barrita de plástico que lo cubre):




La inferior está sujeta por dos pezoncillos. Vemos también que el disco duro tiene algo pegado, esto es un sensor de temperatura que usa el sistema para determinar la temperatura de funcionamiento del disco duro. 
Habremos de despegar dicho sensor y pegarlo en el disco duro nuevo, lo ideal es intentar pegarlo aproximadamente a la misma altura que se encuentra el otro.



Los pezoncillos del disco duro orignal también tendremos que ponerlos en el nuevo para poder encajarlo en el hueco donde estaba alojado el otro.




Aquí vemos el nuevo ya montado, si el sensor pierde el pegamento, se le puede echar una gotita para fijarlo al nuevo.



Pues ahora solo nos queda volver a montarlo todo de la misma forma que lo desmontamos, primero el lcd con sus conectores, a continuación la carcasa con el conector de la cámara web y por último el cristal protector del lcd. Aquí un pequeño vídeo del desmontaje y montaje, en el vídeo he omitido el cambio del disco duro ya que lo hice antes de grabar el vídeo.




En nuestro centro, ya que no tenemos servidor mac solemos resintalar los equipos usando una imagen creada con carbon copy cloner. Lo que hacemos es una vez está el sistema completamente instalado y actualizado, conectamos un disco duro portátil (usb or firewire) y volcamos la imagen en el disco duro portátil, así cuando tenemos problemas como este, solo hay que recuperar el sistema usando el disco duro usb. Para ello conectamos el disco por usb arrancamos el ordenador y ya que nuestro disco de sistema está completamente en blanco el sistema arranca desde el usb directamente y una vez dentro del sistema arrancamos el Carbon Copy Cloner y hacemos un volcado completo del disco usb al disco recien instalado:




Pues hasta aquí la entrada, espero que si has dado con esta página preguntándote como abrir un Mac para reemplazar el disco duro te haya servido de ayuda,





Tuesday 12 June 2012

Control de temperatura v2 (sin necesidad de ordenador)

En el primer post, vimos como controlar la temperatura a través de arduino y hacer que nos enviase un correo electrónico usando processing.

En esta segunda versión, vamos a prescindir del ordenador ya que no siempre tendremos la posibilidad de tener un ordenador conectado en la sala que queremos controlar la temperatura. Para ello, he adquirido una placa de arduino llamada arduino ethernet, la diferencia de esta con el arduino uno que hemos usado anteriormente, es que esta en lugar de traer un conector usb viene con una toma de red, por lo demás es todo más o menos igual.

Arduino Ethernet 
Aclarar que esto no es un shield como el que utilizamos para el lcd, sino que es una placa arduino completa, la única cosa que echaremos de menos es que no trae el puerto usb para programarla por lo que tendremos que tirar de un conversor USB a TTL que cuesta unos 8€.

Conversor USB to TTL

Como ventajas, podemos decir que si vamos a dotar de alguna funcionalidad de red a nuestro arduino, esta es la mejor opción: primero, ahorramos espacio al  no tener que colocar un shield encima; segundo, es más barato comprar esta placa que comprar el arduino y el shield por serparado; y por último, lo que me terminó de convencer y es que venden un módulo que puede soldarse a esta placa y que nos permitirá utilizar POE en caso de que nuestra red disponga de esta característica, por lo que no necesitaremos conectar una fuente de alimentación externa:

Módulo POE
Para nuestro proyecto incial habíamos utilizado un sensor de temperatura TMP36 para recoger los datos de la temperatura ambiental, en esta versión reutilizaremos el mismo sensor y puesto que las entradas analógicas del  arduino ethernet son iguales que las de arduino uno el esquema queda exactamente igual que en la versión anterior.

Antes de poner el código, cabe explicar que para poder enviar correos electrónicos desde arduino ethernet, tenemos que hacerlo utilizando telnet. Esto se hacía mucho antiguamente cuando los  servidores de correo no solían estar protegidos contra el reenvío de emails y cualquiera podía conectarse al puerto  25 de un servidor de correo y enviar un correo con un remitente falso... (aún recuerdo cuando le gastamos a un amigo la broma de que la guardia civil le había enviado un correo para reclamarle ciertas movidas :)
Hoy en día la gran mayoría de los servidores de correo requieren que nos autentiquemos por lo que se complica un poco el proceso de enviar correo a través de telnet pero esto no significa que no podamos hacerlo.
En mi caso he decidido utilizar mis cuentas de correo de gmail para enviar correo y esto presentaba otro problema añadido, google utiliza TLS como protocolo seguro para poder enviar correos y no he encontrado por ningún sitio la forma de hacerlo con arduino, si es que puede hacerse.
Para solucionarlo he tirado de una aplicación llamada stunnel, que es un software gratuito de tunneling ssl, lo que vamos a poder hacer con este programa es que nuestro arduino se conecte a él en lugar de conectarse directamente a google y usando una conexión al puerto 25 reenviar los comandos a google.

La configuración de stunnel es muy sencilla, solo hay que añadir estas líneas al archivo stunnel.conf y ya podemos enviar correos a través de conexiones al puerto 25 del ordenador donde hayamos instalado stunnel:


[ssmtp]
accept  = 25
connect = smtp.gmail.com:465

Por otro lado el proceso de autenticación no nos va a permitir utilizar nuestras credenciales utilizando texto plano, por lo que tendremos que hacer una transformación de nuestro usuario y contraseña a base64 para lo que he utilizado esta web. http://www.seguridadwireless.net/php/conversor-universal-wireless.php
Por poner un ejemplo si nuestro usuario para el correo fuese manolito.perez@gmail.com lo que tendríamos que mandar por telnet usando el arduino sería algo así: bWFub2xpdG8ucGVyZXpAZ21haWwuY29t
La opción a elegir dentro de la web de seguridadwireless es Encode64.

Bueno ya tenemos nuestro stunnel funcionando, tenemos nuestro usuario y nuestra password en base64 y tenemos una cuenta de gmail que es la que usaremos para enviar nuestros correos electrónicos. Por lo que el siguiente paso, será hacer el sketch que compruebe la temperatura y que si pasamos de Xº, nos envíe un correo electrónico:


//Como siempre empezamos llamando 
//las librerias necesarias
#include <SPI.h>
#include <Ethernet.h>
//Definimos las variables globales
//Variable de control para no enviar muchos emails seguidos
boolean correo=false;
//Pin donde conectaremos el sensor de temperatura
int anapin = 3;
//Mac address del arduinoethernet viene
//impreso por debajo de la placa, consta de 6 bytes en Hex
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xF2, 0xA6 };
//Servidor de email o en nuestro caso
//servidor donde hemos instalado el stunnel
byte server[] = { 10, 0, 0, 5 }; 
//Variable que guardara los valores leidos 
//en el sensor de temperatura
float val=0;
//Creamos una objeto de clase EthernetClient
EthernetClient client;

//iniciamos el setup
void setup()
{
  //Se inicia el puerto serie
  Serial.begin(9600);
  //Mostramos por pantalla un mensaje
  Serial.println("Conectando el arduino ethernet a la red...");
  //conectamos el ethernet a la red, solo le pasamos la mac
  //ya que tenemos un servidor de dhcp en nuestra red
  //si queremos especificar la ip tendriamos que hacerlo aqui
  if (Ethernet.begin(mac)==0) Serial.println("Fall´ la conexi´n ethernet");
  //Dejamos un pequeño retardo para que se asigne la ip y demas
  delay(5000);
}

//Iniciamos el loop
void loop(){
  //leemeos la temperatura del sensor llamando a la función getVoltage
  //y le aplicamos la formula para que aparezca en grados centígrados
  //en este sketch obviamos la conversión en grados F ya que no la vamos
  //a necesitar
  val = (getVoltage(anapin) - .5)*100;
  //Como método de control imprimimos al puerto serie el 
  //el valor del sensor
  Serial.println(val);
  //Dejamos una pausa para que las 
  //muestras se tomen cada 5 segundos
  delay(5000);
  //Comprobamos si el valor de la temperatura esta 
  //por debajo de 31ºC en cuyo caso no mandamos email
  if (val<31){
    Serial.println("NO SE MANDA EMAIL");
    if(correo) correo=false;
    //si la temp es superior mandamos el email
    //y cambiamos el valor de correo para que no vuelva a enviarse
  }else{
    //Comprobaos el valor de la variable correo
    //Si el valor de correo es falso mandamos el correo 
    //y ponemos el valor de correo a true
    if(!correo){
      //LLamamos a la función que enviara el correo
      sendEmail();
      correo=true;
      //Dejamos un retardo de 1' para que en el caso
      //de que la temperatura se esté moviendo 
      //entre 30 y 32º no envíe montones de correos
      delay(60000);
    }
  }
}

//Función que lee el voltaje del pin 3 de
//entradas analogicas
float getVoltage(int anapin){
  return (analogRead(anapin) * .004882814);
}

//Función que envia el email
byte sendEmail()
{
    //Conectamos el cliente al puerto 25
    //de nuestro servidor en caso de resultar
    //fallida la conexion nos devolverá un error
    //por pantalla
    if (client.connect(server,25)) {
      Serial.println("connected");
    } else {
      Serial.println("connection failed");
      return 0;
    }
    //Para cada comando llamamos la función
    //eRcv a fin de comprobar la respuesta del
    //servidor y de ir limpiando el buffer de recepción
    if(!eRcv()) return 0;
    //estos comandos son los que usariamos
    //en una conexion telnet, empezamos saludando
    //al servidor
    client.println("HELO google");
    if(!eRcv()) return 0;
    //Le decimos que queremos autenticarnos
    client.println("AUTH LOGIN");
    if(!eRcv()) return 0;
    //Enviamos el usuario en base64
    client.println("fjgkriemrerkEE54F=");
    if(!eRcv()) return 0;
    //Enviamos el password en base64    
    client.println("aGTvaiefSA==");
    if(!eRcv()) return 0;
    //especificamos el sender
    client.println("MAIL From:<mi@gmail.com>"); 
    if(!eRcv()) return 0;
    //especificamos el que recepciona el email
    client.println("RCPT To:<otro@gmail.com>");    
    if(!eRcv()) return 0;
    //indicamos que vamos a empezar a escribir el correo
    client.println("DATA");
    if(!eRcv()) return 0; 
    //Aquí ponemos todo el cuerpo del mensaje incluyendo
    //el from el to y el subject
    client.println("From: mi@gmail.com");                
    client.println("To: otro@gmail.com");                         
    client.println("Subject: Alerta de temperatura en el cuarto de servidores!!!!" + String(int(val)) + "ºC");
    client.println("");                              
    client.println("Se ha detectado una temperatura anormalmente alta en el cuarto de servidores, concretamente de " + String(int(val)) + "ºC");
    client.println(""); 
    //Cuando enviamos un punto indica el fin del mensaje
    client.println(".");
    if(!eRcv()) return 0;
    client.println("QUIT");
    //Cerramos la conexion telnet
    if(!eRcv()) return 0;
    //Paramos el cliente
    client.stop();
    return 1; 
}


//Esta función nos permite ir mostrando
//las respuestas del servidor para cada
//comando que enviamos, asi mismo va limpiando
//el buffer RX, hay servidores de correo que funcionan
//sin esta función pero con google es necesario.
byte eRcv()
{
  byte respCode;
  byte thisByte;
  while(!client.available()) delay(2000);
  respCode = client.peek();
  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }
  if(respCode >= '4')
  {
    efail();
    return 0;  
  }  
  return 1;
}

//Esta función nos dara un error en caso
//de que la respuesta del servidor sea un fallo
//y desconectara la sesion
void efail()
{
  byte thisByte = 0;
  client.write("QUIT\r\n");
  while(!client.available()) delay(1);
  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }
  client.stop();
  Serial.println("disconnected");
}




Pues con esto ya tendríamos nuestro controlador de temperatura avisador por email funcionando y listo para ponerlo en producción...






Wednesday 30 May 2012

LCD Shield with keypad para Arduino

Hola de nuevo, tengo en mente la creación de un sistema de control de accesos para la sala de servidores utilizando RFID para cuando sepa mejor como funciona arduino; una de las cosas que quiero ponerle es una pequeña pantalla LCD que muestre el nombre de la persona que se identifica, por lo que el otro día pedí una LCD Shield como la de la foto en dealextreme por unos 9$ que viene a ser unos 6€.


Un shield de arduino es una placa con una funcionalidad (las hay para wifi, controlador de motores, bluetooth, etc) que encaja perfectamente sobre la placa de arduino. por lo que no es necesario poner ningún tipo de cable para poder usar la funcionalidad inherente del shield.

Este tipo de pantalla no me servirá para mi proyecto ya que al ser un shield me limita las posibilidades de colocación de la pantalla, pero puede serme útil a la hora de entender como funcionan las pantallas LCD y como se comunica con Arduino.

La shield viene además de con la pantalla con una serie de botones que van todos conectados a una entrada analógica la A0 de arduino. Cada vez que se pulsa un botón arduino recibe un valor entre 0 y 1100 aproximadamente  en función del botón pulsado. Esto está muy bien ya que solo usaremos una entrada analógica para manejar un total de 5 botones si excluimos el reset.


Lo primero que intenté hacer al sacar el shield del sobre fue intentar probar el ejemplo que viene con el compilador de arduino que es tal que así:




// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop() {
  // set the cursor to column 0, line 1
  // (note: line 1 is the second row, since counting begins with 0):
  lcd.setCursor(0, 1);
  // print the number of seconds since reset:
  lcd.print(millis()/1000);
}

Al ver que no funcionaba, entendí que el problema eran los pines que utiliza el lcd, el sketch del ejemplo utiliza (12,11,5,4,3,2), pero con mi shield no venía info alguna que dijera que pines de arduino utilizaba, por lo que el siguiente paso fue buscar info en la página de delaextreme que pines utilizan y encontré que los pines a usar eran (8, 9, 4, 5, 6, 7).

Sin embargo tras cambiar el código del programa seguía sin funcionar... El shield trae un potenciómetro que regula el contraste de las letras que aparecen en la pantalla y tras chequear lo con el polímetro ví que el valor que devolvía siempre era el mínimo... la placa estaba defectuosa. Por suerte, tenía a mano un potenciómetro que soldé en lugar del antiguo y el programa de hola mundo, empezó a mostrar la frase por la pantalla del arduino..





Ahora que todo funciona, solo queda hacer un programita para poder explorar un poco las posibilidades de la pantalla y de los botones de nuestro shield.








//Incluimos la librería de LCD que trae arduino
#include <LiquidCrystal.h>
//Indicamos los pins que vamos a usar para 
//comunicarnos con la pantalla
//En mi caso, al usar una lcd shield los botones
//son los siguientes
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//Creamos una constante para tomar 
//indicar a que pin está conectado
const int analogInPin = A0; 
//Creamos una variable para almacenar los 
//valores tomados por los botones
int sensorValue = 0;  

//Inicia el void setup que solo se ejecuta
//una vez
void setup() {
  //iniciamos el puerto serie
  //lo hemos usado para debugginh
  //y así ver los valores que devuelve 
  //al pulsar cada uno de los botones
  Serial.begin(9600); 
  //iniciamos también la pantalla lcd y le 
  //indicamos el número de columnas x el número de filas
  lcd.begin(16, 2);
  //Imprimimos por pantalla la frase HOLA MUNDO!
  lcd.print("HOLA MUNDO!");
  //Movemos el cursor a la segunda línea
  lcd.setCursor(0, 2);
  //Ponemos un mensaje en la segunda línea
  //que nos pide que pulsemos un botón
  lcd.print("Pulse un boton");
}

//Inicia el loop que se ejecutará 
//mientras el arduino esté conectado
void loop() {
  //Recogemos el valor en el pin analógico
  //que nos dirá que botón hemos pulsado
  sensorValue = analogRead(analogInPin);
  //Para hacer el debuggin hemos usado esta instrucción
  //que nos va mostrando en la pantalla del ordenador
  //el valor devuelto al pulsar cada botón  
  Serial.println(sensorValue); 
  //Ponemos un pequeño retardo para que 
  //podamos leer los valores sin marearnos
  delay(100); 
  //En el debuggin hemos visto que al no tener ningún botón
  //pulsado los valores devueltos están entre 
  //1020 y 1025 por lo que cuando se den valores distintos 
  //a ese rango se ejecutará lo que hay dentro del if
  if (sensorValue <1000 ||  sensorValue>1100) {
    //llamamos a la función limpiar línea que veremos 
    //un poco más abajo
    limpiarLinea();
    //Imprimimos por pantalla lo que nos devuelve
    //la función opcion(int) que veremos más abajo
    //y que comprueba a cuanto equivale el valor del sensor 
    //y en función de éste, nos devuelve una cadena de texto
    lcd.print(opcion(sensorValue));
  }  
}


//Esta función comprobará el valor 
//del pin analógico conectado a los botones
//para determinar que botón hemos pulsado
//y devolver un texto en función de este
String opcion(int sensor){
  //Solo explicaré el primero, ya que el resto de ifs
  //son iguales.
  //En el debug vimos que al pulsar la tecla left, nos devolvía
  //un valor de aprox 479 por lo que cuando el valor del sensor esté 
  //entre 400 y 500 devolverá la cadena de texto izquierda
  if(sensor > 400 && sensor<500){
    return("Izquierda");
  }
  if(sensor > 600 && sensor<750){
    return("Select");
  }
  if(sensor > 300 && sensor<350){
    return("Abajo");
  }
  if(sensor > 100 && sensor<150){
    return("Arriba");
  }
  if(sensor < 10){
    return("Derecha");
  }
}

//Esta función la llamamos cuando queremos borrar 
void limpiarLinea(){
  //Colocamos el cursor la principio de la segunda
  //línea
  lcd.setCursor(0, 2);
  //Con este bucle recorremos toda la línea y la ponemos
  //en blanco
  for (int i = 0; i < 16; i = i + 1) {
    lcd.print(" ");
  }
  //Volvemos a colocar el cursor
  //al principio de la línea
  //para cuando volvamos a escribir algo
  //salga desde el principio de la línea
  lcd.setCursor(0, 2);
}


El resultado del programa es el siguiente:



Como veis es bastante soso, pero a partir de aquí podemos empezar a hacer otros sketchs o mezclar los resultados mostrados por pantalla con algún sensor como el de temperatura...


Thursday 17 May 2012

Control de temperatura usando arduino y processing

Hace un par de días, el aire acondicionado del cuarto de servidores dejó de funcionar por un problema de condesación; por suerte, me dí cuenta antes de irme a casa y pudimos instalar una máquina de aire acondicionado portátil para refrigerar la habitación mientras el equipo principal se reparaba. 


Las altas temperaturas pueden estropear desde los ventiladores hasta los procesadores o discos duros del servidor. Por tanto y ya que llevo un tiempo experimentando con arduino y sus sensores, me dispuse a crear un sistema que nos avisara mediante un email cuando la temperatura del cuarto de servidores suba por encima de lo normal, pudiendo así tomar medidas lo antes posible.


Seguramente, habrá formas mucho más eficientes y sencillas de hacer esto, pero con los conocimientos y los materiales que tengo a mano ésta me pareció la forma más adecuada.

Lo primero era utilizar arduino para que tomase la temperatura de ambiente. Por lo que preparamos el circuito, que queda de la siguiente forma:






Como vemos en el esquema se ha utilizado una placa de montaje, un arduino uno y un sensor de temperatura. El sensor de temperatura no es más que una resistencia que varía en función de la temperatura ambiental, por lo que la cantidad de corriente que pasa desde la pata izquierda que va pinchada a 5v hasta la pata central que va conectada a la entrada analógica A0 del arduino va a estar determinada por la temperatura lo que permite calcular los grados en función del voltaje.

Para que podamos enviar el correo electrónico de forma automática cuando la temperatura sobrepase el máximo marcado, necesitamos crear un programa en arduino que nos de la temperatura y nos la envía a través del puerto serie a un ordenador.

El programa en la parte de arduino queda de la siguiente forma:

int anapin = 0;
int gcent=0;
int gfar=0;
float val=0;
void setup(){
  Serial.begin(9600);
}
void loop(){
  val = getVoltage(anapin);
  val = (val - .5)*100;
  gcent=val;
  gfar=gcent*1.8+32;
  Serial.print(String(gcent)+","+String(gfar)+".");
  delay(50);
}
float getVoltage(int anapin){
  return (analogRead(anapin) * .004882814);
}


Como vemos, lo único que hace el programa es iniciar el uso del puerto serie dentro del void setup, y a contuniación dentro del void loop leer continuamente el valor del pin analógico y convertirlo mediante una sencilla fórmula a grados centigrados y luego mandar esto más los grados convertidos a farenheit al puerto serie separando los centigrados de los farenheit por una coma y el siguiente par de valores por un punto; si vemos el resultado en el puerto serie se verá algo como esto:




Hay otra forma de hacerlo que es usando la librería Wire donde no tendríamos que convertir el voltage en grados por lo que el código sería aún más sencillo.

Una vez tenemos nuestro arduino programado, pasaremos a processing, este lenguaje es mayormente gráfico por lo que lo vamos a utilizar para poder mostrar los datos recogidos por el puerto serie en la pantalla y así mismo usaremos la libería de mail de java para enviar el correo electrónico cuando se supere la temperatura umbral.

No he tenido tiempo de aprender mucho de processing, pero es un lenguaje muy intuitivo y en la página web del proyecto (http://www.processing.org/) hay mucha información además de foros donde resolver todas las dudas que puedan surgirnos.

La estructura de processing es muy similar a la de arduino, teniendo un void setup() que se ejecuta una vez y un void draw() que se ejecutará de forma recurrente y que será el encargado de dibujar en pantalla lo que queramos.

El código para coger los datos del puerto serie y mostrarlos por pantalla es el siguiente, intentaré poner comentarios para que el código se entienda:


//Importamos la librería para el uso del puerto serie, 
//en arduino se carga sola, aquí hay que llamarla.
import processing.serial.*; 
//Definimos todas las variables
Serial port;
String tempC="";
String tempF="";
String Data="";
PFont font;
int index=0;
//Este void setup() es similar al de arduino solo se ejecuta al inicio
void setup() 
{
  //Aquí definimos el tamaño de la ventana que 
  //mostraremos por pantalla
  size(600,500);
  //Inicializamos el puerto serie y decimos 
  //que se haga lectura hasta encontrar el punto
  port = new Serial(this, puertoCom, 9600);
  port.bufferUntil('.');
  //Esto es para cargar la fuente por defecto que usaremos en el programa, 
  //la fuente tendrá que estar en la carpeta data del proyecto
  font = loadFont("AgencyFB-Reg-200.vlw");
  textFont(font, 200);}
//Este evento se llama cuando hay entrada en el puerto serie
void serialEvent (Serial port)
{
  //Leemos hasta que se encuentre un punto y guardamos lo leido en Data
  Data = port.readStringUntil('.');
  //Este comando nos sirve para eliminar 
  //el punto del final ya que si no nos lo mostraría por pantalla   
  Data = Data.substring(0,Data.length()-1);
  //buscamos la posición de la coma que separa 
  //los dos valores y guardamos la posición en index
  index = Data.indexOf(",");
  //almacenamos la primera parte del texto en tempC
  tempC= Data.substring(0,index);
  //Almacenamos la segunda parte en tempF
  tempF= Data.substring(index+1,Data.length());
}

//Éste sería el equivalente a void loop() de arduino,
//se ejecuta como un loop constante
void draw()
{
  //definimos el color del fondo negro 0,0,0 es el color negro en RGB
  background (0,0,0);
  //Si la temperatura es inferior a 30 º C
  if (parseInt(tempC)<=30){
    //Pongo el color de los textos en verde fill usa un valor en RGB
    fill(0, 204, 51);
    //Coloco el texto Temp Ok en la posición 20x 150y
    text("Temp OK",20,150); 
  //Si la temperatura es superior a 30ºC
  }else{
    //Pongo el color del texto en ROJO 
    //como señal de advertencia y cambio el  texto
    fill(204, 51, 0);
    text("TEMP!! SM",20,150);
  }
  //Por último colocamos los valores de 
  //temperatura en ºC y ºF, el color será el que traigamos
  //de arriba, es decir en Rojo si es mayor de 30ºC y en Verde si es menor.
  text(tempF+"F",300,340);
  text(tempC+"C",300,499);
}




A continuación una prueba de la salida del programa para valores superiores e inferiores a 30º:



Una vez hecho esto, solo nos quedaría implementar el envío de un correo electrónico. Así mismo, y preveyendo que cuando lo pongamos en producción la conexión se hará mediante cable serie a uno de los servidores en lugar de por usb, vamos a dejar preparada la opción de poder seleccionar el puerto com8 que es el que nos está cogiendo por defecto arduino para el usb, para un puerte serie suele usarse los puertos de com1 a com3 ,por lo que dotaremos al programa de un botón radio que permita elegir entre los puertos com 1, 2, 3 y 8.

Para la primera parte, el envío del correo, encontré en la red esta página (http://www.shiffman.net/2007/11/13/e-mail-processing/) en la que se explica de forma detallada como implementar la librería de mail de java dentro de processing. Para ello vamos a la página de oracle y descargamos la api de email (http://www.oracle.com/technetwork/java/javamail/index.html)l Una vez descargado esto pasamos el fichero mail.jar al processing pinchando en Sketch-> add file.



Una vez hecho esto ya podremos importar las librerías de javax.mail. Shiffman nos da 3 funciones de las que solo usaremos dos auth y sendMail, la tercera CheckMail no la necesitamos para nuestro proyecto por lo que no la usaremos. El código que agregaremos a nuestro programa será el que copiamos de la web de shiffman quedando lo siguiente:


//importamos las librerías
import processing.serial.*;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.*;import javax.mail.internet.*;
//Creamos una variable que nos sirva de interruptor para no 
//enviar infinitos emails cuando la temperatura esté por encima de los 30º
boolean correo=false;

//Creamos la función que servirá para autenticarnos
public class Auth extends Authenticator { 
public Auth() {
super();
}
public PasswordAuthentication getPasswordAuthentication() {   
String username, password;
username = "mi@correo.es";   
password = "MiPasswordDeCorreo";   
//System.out.println("authenticating. . ");   
return new PasswordAuthentication(username, password);
}
}

//Esta función es la que se encarga de enviar el correo
void sendMail() {  
// Create a session String host="smtp.gmail.com"; Properties props=new Properties(); // SMTP Session props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.host", host); props.put("mail.smtp.port", "587"); props.put("mail.smtp.auth", "true"); // We need TTLS, which gmail requires props.put("mail.smtp.starttls.enable","true"); // Create a session Session session = Session.getDefaultInstance(props, new Auth());try { // Make a new message MimeMessage message = new MimeMessage(session); // Who is this message from message.setFrom(new InternetAddress("mi@correo.es", "Nombre del que envía")); // Who is this message to (we could do fancier 
// things like make a list or add CC's)
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("it@sis.gl", true));   
// Subject and body
message.setSubject("Problema en el cuarto de servidores");
message.setText("La temperatura está demasiado alta, ha superado los 30º");
// We can do more here, set the date, the headers, etc.    
Transport.send(message);
}  catch(Exception e)  {
e.printStackTrace();
}
}


Luego modificamos la función de void draw() para que llame a la función sendMail cuando supere la temperatura límite. Quedando así:

void draw(){
background (0,0,0); 
if (parseInt(tempC)<=30){ 
fill(0, 204, 51);
text("Temp OK",20,150);
//si el boolean correo estaba en  true lo pongo a false para que no se envíen correos
 if (correo==true){
    correo = false; 
  }
}else{
//Aqui la temp>30
  if (correo){
    fill(204, 51, 0);
    text("TEMP!! SM",20,150);
  }else{
    //Envio el correo y pongo la variable a false
    sendMail();   
    correo=true;
    //retardo para evitar que el mensaje se envíe muchas veces por estar
    // la temperatura en valores entre 30 y 31ºC
    delay(100000);
  } 
}
text(TempF+"F",300,340);
text(tempC+"C",300,499);
}

Como vemos usamos el boolean correo para que cuando pasemos de por ejemplo 20 a 31ºC solo se envíe un email, y no volverá a mandarse otro hasta que vuelva a darse tal circunstancia, de otra forma, enviaría correos continuamente cuando se pasaran los 30ºC. 

Así mismo tras el envío, dejamos un delay de 100 segundos ya que hay veces que la temperatura puede bailar entre los 30 y 31ºC durante un rato, de esta forma nos aseguramos que mínimo pasarán 100 segundos hasta que volvamos a recibir otra notificación.

Con esto prácticamente tenomos nuestro proyecto terminado, pero como dijimos antes vamos a dotar a nuestro programa de un botón radio que nos permita elegir el puerto com que queremos usar para la recogida de datos. Para ello, vamos a utilizar otra librería llamada controlP5, con esta librería tal como se detalla en su web podemos crear multitud de botonos, deslizadores y botones radio.

Siguiendo las instrucciones del creador de la librería, importamos usando igual que antes la opción Sketch-> add file de processing para importar el fichero controlP5.jar acto seguido, ya podremos importar la librería en nuestro programa usando el comando import controlP5.*; además de el código correspondiente en void setup() y una función llamada controlEvent() que controlará cuando cambiamos el radio de posición. A continuación os dejo el código completo de la aplicación:

//Importamos la librería para el uso del puerto serie, 
//en arduino se carga sola, aquí hay que llamarla.
import processing.serial.*;
//Importamos las librerias de mail y controlP5
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.*;
import javax.mail.internet.*;
import controlP5.*;

//Definimos todas las variables
Serial port;
String tempC="";
String TempF="";
String Data="";
PFont font;
int index=0;
boolean correo=false;
String puertoCom="COM8";
ControlP5 cp5;
RadioButton r;

//Este void setup() es similar al de arduino solo se ejecuta al inicio
void setup() {
    //Aquí definimos el tamaño de la ventana que mostraremos por pantalla
    size(600,500);
    //Inicializamos el puerto serie y decimos que se haga lectura hasta encontrar el punto
    port = new Serial(this, puertoCom, 9600);
    port.bufferUntil('.');
    cp5 = new ControlP5(this);
    r = cp5.addRadioButton("radioButton")         
        .setPosition(20,400)         
        .setSize(20,20)         
        .setColorForeground(color(020))         
        .setColorActive(color(255))         
        .setColorLabel(color(255))         
        .setItemsPerRow(1)         
        .setSpacingColumn(50)         
        .addItem("serial 1",1)         
        .addItem("serial 2",2)         
        .addItem("serial 3",3)         
        .addItem("serial 8",8)         
    ;
    //Esto es para cargar la fuente por defecto que usaremos en el programa,
    //la fuente tendrá  que estar en la carpeta data del proyecto
    font = loadFont("AgencyFB-Reg-200.vlw");
    textFont(font, 200);
}

//Función que detecta cuando cambiamos el botón radio 
void controlEvent(ControlEvent theEvent) 
{   
    //Cogemos el valor del botón  y lo guardamos en opcion   
    int opcion = parseInt(theEvent.getValue());     
    //Cambiamos el valor de puertoCom a COM1, COM2, COM3 o COM8   
    puertoCom = "COM" + opcion;    
    //Paramos la lectura por puerto serie    
    port.stop();    
    //Limpiamos el caché    
    port.clear();    
    //Volvemos a inicializar el puerto com ahora con el puerto cambiado    
    port = new Serial(this, puertoCom, 9600);    
    port.bufferUntil('.'); 
}


//Creamos la función que servirá para autenticarnos
public class Auth extends Authenticator 
{ 
     public Auth() 
     {  
       super();
     }
     public PasswordAuthentication getPasswordAuthentication() 
     {  
       String username, password;    username = "mi@correo.es";  
       password = "MiPasswordDeCorreo";  
       //System.out.println("authenticating. . ");  
       return new PasswordAuthentication(username, password);
     }
}

//Esta función es la que se encarga de enviar el correo
void sendMail() {  
     // Create a session  
     String host="smtp.gmail.com";  
     Properties props=new Properties();  
     // SMTP Session  
     props.put("mail.transport.protocol", "smtp");  
     props.put("mail.smtp.host", host);  
     props.put("mail.smtp.port", "587");  
     props.put("mail.smtp.auth", "true"); 
    // We need TTLS, which gmail requires  
    props.put("mail.smtp.starttls.enable","true");  
    // Create a session  
    Session session = Session.getDefaultInstance(props, new Auth());
    try  {    
      // Make a new message    
      MimeMessage message = new MimeMessage(session);    
      // Who is this message from    
      message.setFrom(new InternetAddress("mi@correo.es", "Nombre del que envía"));     
      // Who is this message to  
      //(we could do fancier things like make a list or add CC's)  
      message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("it@sis.gl", true));  
      // Subject and body    
      message.setSubject("Problema en el cuarto de servidores");    
      message.setText("La temperatura está demasiado alta, ha superado los 30º");    
      // We can do more here, set the date, the headers, etc.    
      Transport.send(message);  
    }  catch(Exception e)  {    
      e.printStackTrace();  
    }
}

//Este evento se llama cuando hay entrada en el puerto serie
void serialEvent (Serial port){
    //Leemos hasta que se encuentre un punto y guardamos lo leido en Data
    Data = port.readStringUntil('.');
    //Este comando nos sirve para eliminar 
    //el punto del final ya que si no nos lo mostraría por pantalla   
    Data = Data.substring(0,Data.length()-1);
    //buscamos la posición de la coma 
    //que separa los dos valores y guardamos la posición en index
    index = Data.indexOf(",");
    //almacenamos la primera parte del texto en tempC
    tempC= Data.substring(0,index);
    //Almacenamos la segunda parte en tempF
    tempF= Data.substring(index+1,Data.length());
}

//Éste sería el equivalente a void loop() de arduino,
//se ejecuta como un loop constante
void draw()
{
    background (0,0,0);  
    //Si la temperatura no sobrepasa los 30º
    if (parseInt(tempC)<=30){  
      fill(0, 204, 51);
      text("Temp OK",20,150);
      //si el boolean correo estaba en  
      //true lo pongo a false para que no se envíen correos
      if (correo==true){  
          correo = false;  
      }
    }else{
        //Aqui la temp>30
        if (correo){  
            fill(204, 51, 0);  
            text("TEMP!! SM",20,150);
        }else{  
            //Envio el correo y pongo la variable a false  
            sendMail();      
            correo=true;  
            //retardo para evitar que el mensaje se envíe muchas veces por estar     
            // la temperatura en valores entre 30 y 31ºC  
            delay(100000);
        }
    }
    text(TempF+"F",300,340);
    text(tempC+"C",300,499);
}


Pues creo que con esto ya está todo, espero que os haya gustado y que se entienda todo bien, si tenéis alguna duda no dudéis en preguntar. Os dejo con un pequeño vídeo del funcionamiento del programa.




Un saludo y hasta la próxima.