MySensors integrated in openHAB

As i wrote in previous post, I have temporarily ditched my own server process for bridging MySensors to MQTT and then integrate it in openHAB, with a setup that means that openHAB is used as the controller. Below, I describe more in details how my setup is configured.

This is a ”connection” which is based on that you hook up an ethernet or serial gateway to openHAB. In my setup I have previously (obviously) built a serial gateway. This serial gateway is attached to the Raspberry Pi and then the serial device is shared (and bridged) via ser2net so it’s accessible on a network port. So for the openHAB part, I added an Item that is ”the arduino gateway”. In the items configuration it looks like:

String Arduino "Arduino" { serial="/dev/virtualcom0" }

For others trying this setup with a MySensors gateway attached to openHAB over tcp/ip, I recommend using the tool ”socat” which makes a virtual device that is actually a connection to the ip daemon (in my case – the Raspberry Pi with MySensors GW attached). The console command string would look like:

sudo socat pty,link=/dev/virtualcom0,raw  tcp:192.168.0.40:2002&

This makes a device named virtualcom0. In openHAB startup script, I added

-Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0:/dev/virtualcom0 \

This was added in order to make openHAB ”see” the new virtual serial device. The complete start.sh command would look like:

echo Launching the openHAB runtime...
java \
 -Dosgi.clean=true \
 -Declipse.ignoreApp=true \
 -Dosgi.noShutdown=true \
 -Dgnu.io.rxtx.SerialPorts=/dev/ttyUSB0:/dev/virtualcom0 \
 -Djetty.port=$HTTP_PORT \
 -Djetty.port.ssl=$HTTPS_PORT \
 -Djetty.home=. \
 -Dlogback.configurationFile=configurations/logback.xml \
 -Dfelix.fileinstall.dir=addons -Dfelix.fileinstall.filter=.*\\.jar \
 -Djava.library.path=lib \
 -Djava.security.auth.login.config=./etc/login.conf \
 -Dorg.quartz.properties=./etc/quartz.properties \
 -Dequinox.ds.block_timeout=240000 \
 -Dequinox.scr.waitTimeOnBlock=60000 \
 -Dfelix.fileinstall.active.level=4 \
 -Djava.awt.headless=true \
 -jar $cp $* \
 -console

Now, when the gateway prints out data it has received over the radio net, the Item gets ”the input string” which triggers an item update. The item update is then handled within a rule.

My rule file for handling the data is as follows:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.joda.time.*
import java.util.*
import org.eclipse.xtext.xbase.lib.*
import org.openhab.core.items.*


var String ArduinoUpdate = ""
var String sketchName = ""

var int ACK_NOACK = 0
var int ACK_ACK = 1

//Sensor TYPES
var int S_DOOR=0
var int S_MOTION=1
var int S_SMOKE=2
var int S_LIGHT=3
var int S_BINARY=3
var int S_DIMMER=4
var int S_COVER=5
var int S_TEMP=6
var int S_HUM=7
var int S_BARO=8
var int S_WIND=9
var int S_RAIN=10
var int S_UV=11
var int S_WEIGHT=12
var int S_POWER=13
var int S_HEATER=14
var int S_DISTANCE=15
var int S_LIGHT_LEVEL=16
var int S_ARDUINO_NODE=17
var int S_ARDUINO_REPEATER_NODE=18
var int S_LOCK=19
var int S_IR=20
var int S_WATER=21
var int S_AIR_QUALITY=22
var int S_CUSTOM=23
var int S_DUST=24
var int S_SCENE_CONTROLLER=25
var int S_RGB_LIGHT=26
var int S_RGBW_LIGHT=27
var int S_COLOR_SENSOR=28
var int S_HVAC=29
var int S_MULTIMETER=30
var int S_SPRINKLER=31
var int S_WATER_LEAK=32
var int S_SOUND=33
var int S_VIBRATION=34
var int S_MOISTURE=35


var int V_TEMP = 0
var int V_HUM = 1
var int V_LIGHT = 2
var int V_DIMMER = 3
var int V_PRESSURE = 4
var int V_FORECAST = 5
var int V_RAIN = 6
var int V_RAINRATE = 7
var int V_WIND = 8
var int V_GUST = 9
var int V_DIRECTION = 10
var int V_UV = 11
var int V_WEIGHT = 12
var int V_DISTANCE = 13
var int V_IMPEDANCE = 14
var int V_ARMED = 15
var int V_TRIPPED = 16
var int V_WATT = 17
var int V_KWH = 18
var int V_SCENE_ON = 19
var int V_SCENE_OFF = 20
var int V_HEATER = 21
var int V_HEATER_SW = 22
var int V_LIGHT_LEVEL = 23
var int V_VAR1 = 24
var int V_VAR2 = 25
var int V_VAR3 = 26
var int V_VAR4 = 27
var int V_VAR5 = 28
var int V_UP = 29
var int V_DOWN = 30
var int V_STOP = 31
var int V_IR_SEND = 32
var int V_IR_RECEIVE = 33
var int V_FLOW = 34
var int V_VOLUME = 35
var int V_LOCK_STATUS = 36
var int V_DUST_LEVEL = 37
var int V_VOLTAGE = 38
var int V_CURRENT = 39

//Message types
var int msgPresentation = 0
var int msgSet = 1
var int msgReq = 2
var int msgInternal = 3
var int msgStream = 4



var int alarmArmor = 1

// Internal Commands
var int I_BATTERY_LEVEL = 0
var int I_TIME = 1
var int I_VERSION = 2
var int I_ID_REQUEST = 3
var int I_ID_RESPONSE = 4
var int I_INCLUSION_MODE = 5
var int I_CONFIG = 6
var int I_FIND_PARENT = 7
var int I_FIND_PARENT_RESPONSE = 8
var int I_LOG_MESSAGE = 9
var int I_CHILDREN = 10
var int I_SKETCH_NAME = 11
var int I_SKETCH_VERSION = 12
var int I_REBOOT = 13
var int I_GATEWAY_READY = 14

// Mappings
var HashMap<String, String> sensorToItemsMap = newLinkedHashMap(
 "50;0;" -> "Humid_Sensor_Office",
 "Humid_Sensor_Office" -> "50;0;",
 "50;1;" -> "Temp_Sensor_Office",
 "Temp_Sensor_Office" -> "50;1;",
 "50;2;" -> "Lumin_Sensor_Office",
 "Lumin_Sensor_Office" -> "50;2;",
 "52;1;" -> "Power_Consumption_",
 "Power_Consumption_" -> "52;1;",
 "53;1;" -> "Water_Consumption_",
 "Water_Consumption_" -> "53;1;"

)
 

//receiving msg from mysensors gateway
rule "Arduino sends to Openhab"
 when
 Item Arduino received update
 then
 var String lineBuffer = Arduino.state.toString.split("\n")
 for (String line : lineBuffer) {
 var String[] message = line.split(";")
 var Integer nodeId = new Integer(message.get(0))
 var Integer childId = new Integer(message.get(1))
 var Integer msgType = new Integer(message.get(2))
 var Integer ack = new Integer(message.get(3))
 var Integer subType = new Integer(message.get(4))
 var String msg = ""
 try{
 msg = message.get(5)
 } catch(Exception e){
 println("Message contained no payload!")
 msg = ""
 }

 if(msgType == msgSet ){
 if (subType == V_TEMP){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";"), msg)
 }
 if (subType == V_HUM){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";"), msg)
 }
 if (subType == V_LIGHT_LEVEL){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";"), msg)
 }
 if (subType == V_VOLTAGE){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";"), msg)
 }
 if (subType == V_LOCK_STATUS){
 var String lockstatus="OPEN"
 if (msg=="1"){
 lockstatus="CLOSED"
 }
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";"), lockstatus)
 }
 if (subType == V_TRIPPED){
 var String tripped="OFF"
 if (msg=="1"){
 tripped="ON"
 }
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";"), tripped)
 }
 if (subType == V_LIGHT){
 var String light="OFF"
 if (msg=="1"){
 light="ON"
 }
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";"), light)
 }
 if (subType == V_WATT){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";")+"WATT", msg)
 }
 if (subType == V_KWH){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";")+"kWH", msg)

 }
 if (subType == V_FLOW){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";")+"FLOW", msg)
 }
 if (subType == V_VOLUME){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";")+"VOLUME", msg)
 }
 if(subType == V_VAR1){
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";")+"VAR1", msg)
 }


 }
 
 //Request a variable!
 if((msgType == msgReq) && (msg=="")){
 if(subType == V_VAR1){

 println("Will return VAR1 variable for sensor with node ID " + nodeId + " and childId " + childId )
 println("V_VAR1 item: " + sensorToItemsMap.get( nodeId + ";" + childId + ";")+"VAR1")
 
 var var1_state = RequestVariables.members.findFirst[name.equals( (sensorToItemsMap.get( nodeId + ";" + childId + ";")+"VAR1" )) ].state
 var var1 = "1";
 if(var1_state!= Uninitialized){
 var1 = (var1_state as DecimalType).toString()
 }
 sendCommand(Arduino, nodeId + ";" + childId + ";"+msgReq+";"+ACK_NOACK+";" + V_VAR1 + ";" + var1)
 }
 }
 
 
 //Presentation message!
 if(msgType == msgPresentation){
 var item_presentation = SensorPresentation.members.findFirst[name.equals( (sensorToItemsMap.get( nodeId + ";" + childId + ";")+"PRESENTATION" )) ]
 if(item_presentation != null){
 postUpdate(item_presentation, msg) 
 }
 }
 
 
 // Internal Command
 if(msgType == msgInternal){
 if(subType == I_SKETCH_NAME){
 println("Sketch name: " + msg )
 sketchName=msg
 }
 if(subType == I_SKETCH_VERSION){
 println("Sketch version: " + msg )
 postUpdate(sensorToItemsMap.get( nodeId + ";" + childId + ";"), sketchName+" " +msg )
 sketchName=""
 }
 if(subType == I_CONFIG){
 sendCommand(Arduino, nodeId + ";" + childId + ";"+msgInternal+";"+ACK_NOACK+";" + I_CONFIG + ";" + "M") 
 }
 if(subType == I_LOG_MESSAGE){
 postUpdate(MySensors_Controller_Log, msg);
 }
 if(subType == I_GATEWAY_READY){
 if(msg=="Gateway startup completed."){
 postUpdate(MySensors_Gateway_Ready, ON)
 } else {
 postUpdate(MySensors_Gateway_Ready, OFF)
 }
 }
 }
 } 
end

This is not written by me. I have added some code in order to reply with last known data value – but originally this script is from MySensors webpage for openHAB controller.

 The rest is pretty basic – incoming data values updates the items they are configured for.

Kommentera

E-postadressen publiceras inte. Obligatoriska fält är märkta *