Cutremótica o domótica low-cost (II)

Como me ha recordado un lector tenía pendiente escribir una continuación al artículo donde expuse la problemática que tenía con la calefacción en casa y como lo solucioné con un poco de tecnología (no mucha tampoco).

Ya lo expliqué básicamente en su momento así que veamos detalles. Empecemos por una foto del invento. No pensé en hacer una foto durante el montaje así que esto se ve ya montado, os lo tendréis que imaginar. No es dificil, es una pequeña caja de plástico con un cable USB y otro que lleva la señal al relé.

El relé utilizado es un KMTronic activable por USB.

Al conectarlo a un Linux se detecta como un puerto serie USB y aparece como un dispositivo ttyUSB. En mi caso sólo tengo ese así que siempre será el primero (ttyUSB0).

Finalmente una pequeña aplicación Java interactua con el puerto. El código interesante de la misma es el que activa y desactiva el relé.

package net.sargue.domotica.io;

import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;

import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;

/**
 * KMTronic
 * http://www.sigma-shop.com/product/67/usb-relay-controller-one-channel-pcb.html
 *
 * 8 Data, 1 Stop, No Parity, Baud rate : 9600
 * OFF command: FF 01 00 (HEX) or 255 1 0 (DEC)
 * ON command: FF 01 01 (HEX) or 255 1 1 (DEC)
 *
 * Ojo que el puerto serie que se crea en el linux (/dev/ttyUSB0) va asociado a una velocidad, y si no es 9600 no funcionará.
 * Se puede ajustar con stty -F /dev/ttyUSB0 9600
 */
public class ReleCalefaccion {  
  private final Logger log = LoggerFactory.getLogger(ReleCalefaccion.class);

  private boolean activo;

  public ReleCalefaccion() {
    desactivar();
  }

  public synchronized void activar() {
    FileOutputStream fos = null;
    try {
      log.debug("Fixant la velocidad correcta del port serie USB.");
      Runtime.getRuntime().exec("/bin/stty -F /dev/ttyUSB0 9600");
      Thread.sleep(3000);
      log.debug("Activant relé.");
      fos = new FileOutputStream("/dev/ttyUSB0");
      fos.write(255);
      fos.write(1);
      fos.write(1);
      log.debug("Relé activat.");
      activo = true;
    } catch (FileNotFoundException e) {
      log.error("No trobo el port USB del relay.", e);
    } catch (IOException e) {
      log.error("Error d'E/S escribint al port USB del relay.", e);
    } catch (InterruptedException e) {
      log.error("Aquí no es pot dormir?", e);
    } finally {
      if (fos != null) try {
        fos.close();
      } catch (IOException e) {
        log.error("Error tancant el port USB del relay.", e);
      }
    }
  }

  public synchronized void desactivar() {
    FileOutputStream fos = null;
    try {
      log.debug("Fixant la velocidad correcta del port serie USB.");
      Runtime.getRuntime().exec("/bin/stty -F /dev/ttyUSB0 9600");
      Thread.sleep(3000);
      log.debug("Desactivant relé.");
      fos = new FileOutputStream("/dev/ttyUSB0");
      fos.write(255);
      fos.write(1);
      fos.write(0);
      log.debug("Relé desactivat.");
      activo = false;
    } catch (FileNotFoundException e) {
      log.error("No trobo el port USB del relay.", e);
    } catch (IOException e) {
      log.error("Error d'E/S escribint al port USB del relay.", e);
    } catch (InterruptedException e) {
      log.error("Aquí no es pot dormir?", e);
    } finally {
      if (fos != null) try {
        fos.close();
      } catch (IOException e) {
        log.error("Error tancant el port USB del relay.", e);
      }
    }
  }

  public String getEstadoHTML() {
    return "" + (activo ? "ON" : "Auto") + "";
  }

  private String getCssEstado() {
    return activo ? "estado-on" : "estado-off";
  }

  public boolean isActivo() {
    return activo;
  }
}

El único inconveniente que he encontrado es que a veces el puerto serie USB se ha vuelto "loco" y se ha desconfigurado. No me queda clara la razón, porque no es simplemente por un reinicio. Lo malo en ese caso es que al ser el relé con comunicación unidireccional no se puede saber si está o no activo.