martes, 8 de octubre de 2013

OpenHAB en Raspberry Pi: Configurando RFXCOM (parte 4)

NOTA: Este blog se ha trasladado a trasteandoarduino.com.

En esta entrada vamos a explicar como configurar el transceptor RFXtrx433 de RFXCOM para funcionar con openHAB.

Módulo RFXtrx433

En primer lugar hay que decir que el módulo RFXtrx433 es un emisor/receptor de señales RF en la banda de 433.92Mhz con conexión USB, que es capaz de decodificar muchos protocolos usados por interruptores, enchufes, estaciones meteorológicas, medidConfigurando el dispositivoores de energía... Entre todos esos protocolos se encuentra el usado por los enchufes que analicé aquí, aquí y aquí. El protocolo usado lo identifica como Impuls.

Configurando el dispositivo

Como se trata de un dispositivo USB cuando lo conectemos al equipo lo reconocerá como /dev/ttyUSB0 unas veces, otras como /dev/ttyUSB1... dependiendo de los dispositivos USB que tengamos en ese momento conectados. Para evitar ese baile de nombres vamos a definir una regla udev para que siempre lo tengamos como /dev/rfxcom.

Lo primero que hay que hacer es identificar nuestro dispositivo univocamente, que no haya posibilidad de error. Para ello usamos el comando:

udevadm info -a -p  $(udevadm info -q path -n /dev/ttyUSBx)

cambiando la x por el número que tenga nuestro dispositivo en el momento de conectarlo. Obtendremo un listado largo que contendrá algo así:

  ...
  looking at parent device '/devices/platform/bcm2708_usb/usb1/1-1/1-1.2':
    KERNELS=="1-1.2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{devpath}=="1.2"
    ATTRS{idVendor}=="0403"
    ATTRS{speed}=="12"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{busnum}=="1"
    ATTRS{devnum}=="4"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}==" 90mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="a0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="0600"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{serial}=="A1WR621M"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="16"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="RFXCOM"
    ATTRS{removable}=="removable"
    ATTRS{idProduct}=="6001"
    ATTRS{bDeviceClass}=="00"
    ATTRS{product}=="RFXtrx433"
  ...

De entre toda esta información del dispositivo debemos elegir algo que nos identifique al dispositivo. Se puede elegir el serial, o la combinación idVendor/idProduct... Lo más normal es elegir esto último.

Creamos el fichero /etc/udev/rules.d/10-local.rules con el siguiente contenido:
ACTION=="add",ATTRS{idVendor}=="0403",ATTRS{idProduct}=="6001",SYMLINK+="rfxcom"

Si desconectamos el dispositivo y lo volvemos a conectar nos debería aparecer el enlace /dev/rfxcom automágicamente enlazado al correspondiente /dev/ttyUSBx.

El addon RFXCom para openHAB utiliza la librería RxTx para acceder a los puertos serie del equipo, la cual no funciona demasiado bien con los dispositivos no estandares en /dev. Para solventar este inconveniente hay que decirle a openHAB que le diga a la librería RxTx que /dev/rfxcom es un dispositivo serie válido. Y ¿cómo lo hacemos? Fácil, hay que ir a los archivos start.sh y start_debug.sh para añadir en la última linea, la que inicia el programa con java... el siguiente parámetro:

-Dgnu.io.rxtx.SerialPorts=/dev/rfxcom

Tenéis mas informacion sobre la forma en que la librería RxTx detecta o lista los puertos serie del equipo aquí.

 

Primeras pruebas

Una vez que tenemos el dispositivo listo, y localizado, necesitamos hacer alguna prueba para ver si funciona correctamente. Para ello nos bajamos el software rfxcmd de aquí, y lo descomprimimos en una carpeta:

mkdir rfxcmd
cd rfxcmd
wget http://rfxcmd.googlecode.com/files/rfxcmd-v024.zip
unzip rfxcmd-v024.zip -d v024
cd v024

Al intentar ejecutarlo nos dice que falta la extensión Serial de python. La instalamos:

apt-get install python-serial


y continuamos con las pruebas poniendo el modulo en escucha continua:

./rfxcmd.py -d /dev/rfxcom

nos da la siguiente salida si todo ha ido bien:


RFXCMD version 0.24
------------------------------------------------
Received        = 0D 01 00 00 02 53 43 00 40 00 01 01 00 00
Date/Time        = 2013-10-02 12:22:50
Packet Length        = 0D
Packettype        = Interface Message
Subtype            = Interface response
Sequence nbr        = 00
Response on cmnd    = Get Status, return firmware versions and configuration of the interface.
Transceiver type    = 433.92MHz (Transceiver)
Firmware version    = 67
Display undecoded    = Off
Protocols:
Disabled        AE (433.92)
Disabled        Rubicson (433.92)
Disabled        FineOffset / Viking (433.92)
Disabled        RFU3
Disabled        RFU4
Disabled        RFU5
Disabled        RFU6
Disabled        Mertik (433.92)
Disabled        AD (433.92)
Disabled        Hideki/UPM (433.92)
Disabled        La Crosse (433.92/868.30)
Disabled        FS20 (868.35)
Disabled        ProGuard (868.35 FSK)
Enabled            BlindsT0 (433.92)
Disabled        BlindsT1/T2/T3 (433.92)
Disabled        X10 (310/433.92)
Disabled        ARC (433.92)
Disabled        AC (433.92)
Disabled        HomeEasy EU (433.92)
Disabled        Meiantech (433.92)
Disabled        Oregon Scientific (433.92)
Disabled        ATI (433.92)
Disabled        Visonic (315/868.95)



Configuración del addon RFXCom

Para que funcione el addon tenemos copiar el archivo jar en la carpeta de addons, y modificar en el fichero de configuración openhab.cfg el nombre del puerto serie que se usará para conectar con el dispositivo:

rfxcom.serialPort=/dev/rfxcom

Ahora podemos arrancar openHAB en modo depuración con start_debug.sh y ver los registros del addon, que serán algo parecido a esto:


root@raspberrypi:/opt/openhab# ./start_debug.sh
Launching the openHAB runtime in debug mode...
Listening for transport dt_socket at address: 8001
osgi> 08:49:54.236 DEBUG o.o.c.s.i.SchedulerActivator[:56] - Scheduler has been started.
08:49:54.866 INFO  o.q.impl.StdSchedulerFactory[:1175] - Using default implementation for ThreadExecutor
08:49:55.208 INFO  o.q.core.SchedulerSignalerImpl[:61] - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
08:49:55.215 INFO  o.quartz.core.QuartzScheduler[:243] - Quartz Scheduler v.2.1.7 created.
08:49:55.244 INFO  org.quartz.simpl.RAMJobStore[:154] - RAMJobStore initialized.
08:49:55.268 INFO  o.quartz.core.QuartzScheduler[:268] - Scheduler meta-data: Quartz Scheduler (v2.1.7) 'openHAB-job-scheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 2 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

08:49:55.281 INFO  o.q.impl.StdSchedulerFactory[:1324] - Quartz scheduler 'openHAB-job-scheduler' initialized from specified file: './etc/quartz.properties'
08:49:55.287 INFO  o.q.impl.StdSchedulerFactory[:1328] - Quartz scheduler version: 2.1.7
08:49:55.297 INFO  o.quartz.core.QuartzScheduler[:534] - Scheduler openHAB-job-scheduler_$_NON_CLUSTERED started.
08:49:55.342 DEBUG o.o.c.core.ConfigDispatcher[:166] - Processing openHAB default configuration file '/opt/openhab/configurations/openhab_default.cfg'.
08:49:55.979 DEBUG o.o.c.core.ConfigDispatcher[:188] - Processing openHAB main configuration file '/opt/openhab/configurations/openhab.cfg'.
08:49:56.262 DEBUG o.o.c.internal.CoreActivator[:124] - UUID file already exists at '/opt/openhab/webapps/static/uuid' with content '0e3715df-824e-475d-8b46-539284ae5210'
08:49:59.126 DEBUG o.o.c.internal.CoreActivator[:146] - Created file '/opt/openhab/webapps/static/version' with content '1.3.1'
08:49:59.132 INFO  o.o.c.internal.CoreActivator[:92] - openHAB runtime has been started (v1.3.1).
08:49:59.521 DEBUG o.o.c.a.i.AutoUpdateActivator[:51] - AutoUpdate binding has been started.
08:50:20.086 DEBUG o.o.m.p.i.PersistenceModelActivator[:43] - Registered 'persistence' configuration parser
08:50:20.279 DEBUG o.o.c.t.i.TransformationActivator[:58] - Transformation Service has been started.
08:50:20.904 DEBUG o.o.i.g.internal.GCalActivator[:54] - Google Calendar IO has been started.
08:50:21.213 DEBUG o.o.i.m.i.MultimediaActivator[:54] - Multimedia I/O bundle has been started.
08:50:21.553 DEBUG o.o.i.s.i.DiscoveryServiceActivator[:47] - Discovery service has been started.
08:50:21.694 DEBUG o.o.i.t.mqtt.MqttService[:138] - Starting MQTT Service...
08:50:24.361 DEBUG o.o.m.i.i.ItemModelActivator[:44] - Registered 'item' configuration parser
08:50:26.163 DEBUG o.o.c.i.items.ItemRegistryImpl[:157] - Item provider 'GenericItemProvider' has been added.
08:50:35.668 INFO  o.o.m.c.i.ModelRepositoryImpl[:99] - Loading model 'casa.items'
08:50:39.939 DEBUG o.o.m.i.i.GenericItemProvider[:154] - Read items from model 'casa.items'
08:50:42.213 DEBUG o.o.m.s.i.SitemapModelActivator[:43] - Registered 'sitemap' configuration parser
08:50:43.127 DEBUG o.o.i.r.internal.RESTActivator[:53] - REST API has been started.
08:50:43.681 INFO  o.o.i.s.i.DiscoveryServiceImpl[:92] - mDNS service has been started
08:50:46.249 INFO  o.a.cpr.AtmosphereFramework[:742] - Installing BroadcastFilter class(es) org.atmosphere.client.FormParamFilter
08:50:46.531 INFO  o.a.cpr.AtmosphereFramework[:1118] - Auto detecting atmosphere handlers /WEB-INF/classes/
08:50:46.668 WARN  o.a.cpr.AtmosphereFramework[:814] - Missing META-INF/atmosphere.xml but found the Jersey runtime. Starting Jersey
08:50:47.025 INFO  o.a.cpr.AtmosphereFramework[:364] - Installed AtmosphereHandler org.atmosphere.handler.ReflectorServletProcessor mapped to context-path: /*
08:50:47.033 INFO  o.a.cpr.AtmosphereFramework[:1173] - Auto detecting WebSocketHandler in /WEB-INF/classes/
08:50:47.314 INFO  o.a.cpr.AtmosphereFramework[:1099] - Atmosphere is using async support: org.atmosphere.container.JettyAsyncSupportWithWebSocket running under container: jetty/8.1.3.v20120522 with WebSocket enabled.
08:50:47.324 INFO  o.a.cpr.AtmosphereFramework[:902] - Installed WebSocketProtocol org.atmosphere.websocket.protocol.SimpleHttpProtocol 
08:50:47.494 INFO  o.a.h.ReflectorServletProcessor[:126] - Installing Servlet com.sun.jersey.spi.container.servlet.ServletContainer
08:50:49.212 INFO  c.s.j.s.i.a.WebApplicationImpl[:791] - Initiating Jersey application, version 'Jersey: 1.11 12/09/2011 11:05 AM'
08:50:49.234 INFO  c.s.j.s.i.a.WebApplicationImpl[:802] - Adding the following classes declared in META-INF/services/jersey-server-components to the resource configuration:
  class org.atmosphere.jersey.AtmosphereResourceConfigurator
08:50:50.061 INFO  c.s.j.s.i.a.DeferredResourceConfig[:97] - Instantiated the Application class org.openhab.io.rest.internal.RESTApplication
08:50:52.236 INFO  o.o.m.c.i.ModelRepositoryImpl[:99] - Loading model 'casa.sitemap'
08:51:06.022 INFO  o.a.cpr.AtmosphereFramework[:589] - Installed Default AtmosphereInterceptor [Android Interceptor Support, SSE Interceptor Support, JSONP Interceptor Support]. Set org.atmosphere.cpr.AtmosphereInterceptor.disableDefaults in your xml to disable them.
08:51:06.029 WARN  o.a.cpr.AtmosphereFramework[:509] - No BroadcasterCache configured. Broadcasted message between client reconnection will be LOST. It is recommended to configure the HeaderBroadcasterCache.
08:51:06.043 WARN  o.a.cpr.AtmosphereFramework[:533] - Neither TrackMessageSizeInterceptor or TrackMessageSizeFilter are installed. atmosphere.js may receive glued and incomplete message.
08:51:06.049 INFO  o.a.cpr.AtmosphereFramework[:537] - HttpSession supported: false
08:51:06.055 INFO  o.a.cpr.AtmosphereFramework[:538] - Using BroadcasterFactory: org.atmosphere.cpr.DefaultBroadcasterFactory
08:51:06.061 INFO  o.a.cpr.AtmosphereFramework[:539] - Using WebSocketProcessor: org.atmosphere.websocket.DefaultWebSocketProcessor
08:51:06.066 INFO  o.a.cpr.AtmosphereFramework[:540] - Using Broadcaster: org.atmosphere.jersey.JerseyBroadcaster
08:51:06.085 INFO  o.a.cpr.AtmosphereFramework[:541] - Atmosphere Framework 1.0.4 started.
08:51:06.091 INFO  o.o.i.r.i.RESTApplication[:158] - Started REST API at /rest
08:51:06.106 DEBUG o.o.i.s.i.DiscoveryServiceImpl[:63] - Registering new service _openhab-server._tcp.local. at port 8080
08:51:08.742 DEBUG o.o.i.s.i.DiscoveryServiceImpl[:63] - Registering new service _openhab-server-ssl._tcp.local. at port 8443
08:51:11.929 INFO  o.o.u.w.i.s.WebAppServlet[:99] - Started Classic UI at /openhab.app
08:51:18.037 DEBUG o.o.m.r.i.RuleModelActivator[:62] - Registered 'rules' configuration parser
08:51:18.151 DEBUG o.o.m.r.i.engine.RuleEngine[:98] - Started rule engine
08:51:22.341 DEBUG o.o.b.r.i.RFXComActivator[:54] - RFXCOM binding has been started.
08:51:22.538 DEBUG o.o.b.r.i.RFXComConnection[:68] - Activate
08:51:22.551 DEBUG o.o.b.r.i.RFXComConnection[:94] - Configuration updated, config true
08:51:22.562 INFO  o.o.b.r.i.RFXComConnection[:127] - Connecting to RFXCOM [serialPort='/dev/rfxcom' ].08:51:22.690 DEBUG o.o.m.i.i.GenericItemProvider[:312] - Start processing binding configuration of Item 'Salon_Lampara (Type=SwitchItem, State=Uninitialized)' with 'RFXComGenericBindingProvider' reader.
08:51:22.769 DEBUG o.o.m.i.i.GenericItemProvider[:312] - Start processing binding configuration of Item 'Cargador_Aspiradora (Type=SwitchItem, State=Uninitialized)' with 'RFXComGenericBindingProvider' reader.
08:51:22.782 DEBUG o.o.m.i.i.GenericItemProvider[:312] - Start processing binding configuration of Item 'Dormitorio_TV (Type=SwitchItem, State=Uninitialized)' with 'RFXComGenericBindingProvider' reader.
08:51:22.796 DEBUG o.o.m.i.i.GenericItemProvider[:312] - Start processing binding configuration of Item 'Cocina_Cafetera (Type=SwitchItem, State=Uninitialized)' with 'RFXComGenericBindingProvider' reader.
08:51:22.813 DEBUG o.o.m.i.i.GenericItemProvider[:312] - Start processing binding configuration of Item 'Salon_TV (Type=SwitchItem, State=Uninitialized)' with 'RFXComGenericBindingProvider' reader.
RXTX Warning:  Removing stale lock file. /var/lock/LCK..rfxcom
08:51:22.897 DEBUG o.o.b.r.internal.RFXComBinding[:78] - Activate
08:51:22.998 DEBUG o.o.b.r.i.RFXComConnection[:133] - Reset controller
08:51:23.013 DEBUG o.o.b.r.i.c.RFXComSerialConnector[:172] - Data listener started
08:51:24.129 DEBUG o.o.b.r.i.RFXComConnection[:161] - Data received:
Raw data = 0D0100010253431F8FFD01010000
 - Packet type = INTERFACE_MESSAGE
 - Seq number = 1
 - Sub type = INTERFACE_RESPONSE
 - Command = GET_STATUS
 - Transceiver type = _443_92MHZ_TRANSCEIVER
 - Firmware version = 67
 - Hardware version = 1.1
 - Undecoded packets = false
 - RFU6 packets = false
 - RFU5 packets = false
 - RFU4 packets = true
 - RFU3 packets = true
 - FineOffset / Viking (433.92) packets = true
 - Rubicson (433.92) packets = true
 - AE (433.92) packets = true
 - BlindsT1/T2/T3 (433.92) packets = true
 - BlindsT0 (433.92) packets = false
 - ProGuard (868.35 FSK) packets = false
 - FS20 (868.35) packets = false
 - La Crosse (433.92/868.30) packets = true
 - Hideki/UPM (433.92) packets = true
 - AD (433.92) packets = true
 - Mertik (433.92) packets = true
 - Visonic (315/868.95) packets = true
 - ATI (433.92) packets = true
 - Oregon Scientific (433.92) packets = true
 - Meiantech (433.92) packets = true
 - HomeEasy EU (433.92) packets = true
 - ARC (433.92) packets = false
 - X10 (310/433.92) packets = true
08:51:27.282 DEBUG o.o.b.r.i.RFXComConnection[:161] - Data received: - AC (433.92) packets = true
Raw data = 0A520700320E00FE300140
 - Packet type = TEMPERATURE_HUMIDITY
 - Seq number = 0
 - Sub type = WT260_WT260H_WT440H_WT450_WT450H
 - Id = 12814
 - Temperature = 25.400000000000002
 - Humidity = 48
 - Humidity status = COMFORT
 - Signal level = 4
 - Battery level = 0

De momento esto es todo por hoy... En la siguiente entrada iremos un poco mas allá: configuraremos los enchufes RF y crearemos un pequeño sitemap con unos cuantos items para gestionarlo todo por web o con el teléfono móvil. Espero que os guste :)

¡Un saludo a todos!

PUEDE COMENTAR ESTA ENTRADA AQUÍ

martes, 1 de octubre de 2013

OpenHAB en la Raspberry Pi (parte 3): Inicio automático

NOTA: Este blog se ha trasladado a trasteandoarduino.com.

En la anterior entrada dejamos el sistema openHAB configurado con el sitemap demo funcionando. En esta entrada vamos a ver como podemos hacer para que se inicie automáticamente con el sistema, como un servicio más.

En Raspbian, como en los derivados de Debian, los servicios que se inician durante el arranque del sistema lo hacen mediante unos ficheros que se guardan en la carpeta /etc/init.d. Necesitaremos crear uno para que nos inicie openHAB. Como no somos los primeros a los que se nos presenta esta necesidad, si buscamos en la página del proyecto openHAB, vemos que hay una sección dedicada a ejemplos de configuración, y entre ellos hay uno para hacer justo lo que queremos (aquí).

Tan solo deberemos copiar el código que nos muestra, guardarlo en /etc/init.d/openhab, darle permisos de ejecución con sudo chmod a+x /etc/init.d/openhab, y finalmente añadirlo a la lista de servicios que se deben arrancar en el inicio con sudo update-rc.d openhab defaults (tened cuidado si estáis siguiendo la guía oficial porque hay una errata en este comando, no es sudo update-rc.d /etc/init.d/openhab defaults).

¿Tan fácil? Bueno, no. Como siempre que reusamos cualquier código hay que echarle un vistazo por si hay algo incorrecto, o algo que modificar como es nuestro caso. Al principio del fichero que acabamos de crear tenemos unas variables de configuración, la que nos interesa es ECLIPSEHOME, que especifica dónde tenemos la instalación de openHAB. Podemos cambiarla a /root/openhab, o podemos mover los archivos a esa ubicación.  En nuestro caso, optamos por mover todos los ficheros a /opt/openhab como nos sugiere el valor de la variable. Para ello ejecutamos el siguiente comando:

mv /root/openhab/runtime /opt/openhab

Además vemos que hay una variable RUN_AS que nos dice el nombre del usuario con el que se ejecutará openHAB. Como no tenemos ningún usuario ben en el sistema vamos a crear uno nuevo:

useradd openhab
chown -R openhab:openhab /opt/openhab

Con estos simples pasos ya podemos reiniciar nuestra Raspberry Pi y comprobar como se inicia openHAB automáticamente, conectando con un navegador a http://192.168.1.216:8080/openhab.app?sitemap=demo.

Como openHAB está desarrollado en Java y es bastante pesado, es posible que cuando intentéis acceder a la URL anterior, obtengáis un error 404. No os preocupéis, ese error significa que openHAB aun no ha terminado de cargar. En mi Raspberry tarda casi dos minutos en iniciarse... De todas formas si existiese algún error podéis ver los logs en /opt/openhab/logs.
 
PUEDE COMENTAR ESTA ENTRADA AQUÍ