UDP

Pierre Kil edited this page Jan 19, 2017 · 4 revisions
Clone this wiki locally

This document is the counterpart of the OpenRemote Razberry Integration document. That document decribes how to send commands to, and receive results from the RaZberry controller software (Z-Way). It uses the OpenRemote HTTP call. However some situations require instant response, where in the present context of OpenRemote, UDP seems more appropriate.

##Preparations It is assumed that you have at least a very basic familiarity with linux, and one its text editors. For novices nano is probably the easiest editor. In most cases you won't have a keyboard/screen to your Raspberry Pi. So you will need to make a SSH connection with the console. Here Putty was used.

###Push versus Poll In most Home Automation situations the collection of data is not very critical. Reading a room temperature every 15 minutes is just fine. However, if you switch a light using your tablet, instant confirmation is a must. If your method of data collection is through polling, the interval must be in the order of 1 second. Quite a waste for a basement light that is touched only once a week. So we rather let RaZberry push status updates in such occasions. Because OpenRemote happens to have a simple UDPListener, I did choose that standard protocol.

###Naming conventions RaZberry will send its updates as simple sensorname,value pair messages. All the messages from RaZberry are send through the same UDP channel. At the OpenRemote receiving end values are bound at the corresponding OpenRemote sensors. It is crucial that the sender is aware of the OpenRemote names. In order to parse the messages correctly, the OpenRemote sensor names must start with ZWay followed by the Device number and optionally an Instance number. Messages from respectively a binary switch and Fibaro Universal Sensor temperature sensor 3 will look like:

ZWay_21,on
ZWay_13_5,27.98

Be aware that this naming standard may change at a later moment.


#OpenRemote ##The Receiving end This section heavily relies on In memory Virtual Commands(ImVC). Please do familiarise yourself with that notion. First the interface to RaZberry is defined using the UDPListener protocol. In Designer create a new device with the name UDPListener. Next select add command. In that window first select the protocol: UDPListener. Next specify port 9091. If this port is in use by some other process, feel free to choose a different port. But do use the same port number on both ends! The name of the sensor must be RaZ-UDP-Status as specified. This name is expected by the message parser. All incoming status updat pass through this sensor.

UDP - RaZUDPStatus

UDP - RaZUDPStatusListener

###Parse incoming messages You are strongly advised to save the following rule in file: webapps/controler/rules/UDPListener.drl separate from the rules file that is created in that same folder by OpenRemote designer.

// Code provided by Michal Rutka 
package org.openremote.controller.protocol;
global org.openremote.controller.statuscache.CommandFacade execute;
 
rule "UDPListener"
                                                                                      
when
  Event(source=="RaZ-UDP-Status", $v: value!="")
then
  java.util.regex.Pattern regexPattern = java.util.regex.Pattern.compile("\\(?(ZWay.*),([\\d\\.+|on|off]+)\\)?");
  java.util.regex.Matcher matcher = regexPattern.matcher($v.toString());
  if (matcher.find()) {
    execute.command(matcher.group(1), matcher.group(2));
  }
 end

I hope this (Sensor,Value)-function will soon be available as a native UPDListener option (ORCJAVA-467)

NOTA BENE: If you have UDP messages coming from several RapberryPi devices, you have to create additional UDPListener commands and sensors with different port numbers. Take care that there is on interference with existing UDP ports. As a safety precaution, do use port nubers taht are 100 apart; 9092, 9192, etc. Also the rules file needs to be adapted. You probably can add an additional event to the when clause. I deciced to just copy the existing rule into a new rule, where only the sensor name RaZ-UDP-Status had to be changed in the name of the new sensor. For stability reasons, I do keep these rules in a separate file UDPListener.drl in the controller /webapps/controller/rules folder

###Example UDP driven OpenRemote Devices ####Binary Switch At left the ImVC that stores the received on/off value. Do note that the ImVCs must all have different addresses. At right is the sensor, which must always be of type:custom

UDP - ZWay_2cmnd

UDP - ZWay_2sens

####Temperature Sensor Similar command and sensor for the Fibaro Universal Sensor - Temperature gauge, that is referred further down this recipe.

UDP - ZWay_13_5cmnd

UDP - ZWay_13_5sens


#Z-Way (Raspberry Pi) ##The Sending part This part deals with the configuration settings on the Raspberry Pi, where you have to do some editing in files. Using Putty make a terminal connection. You can copy and paste (only touch right mouse button) the following instructions. The remainder of the instruction assumes you have set your working directory to:

cd /opt/z-way-server

###Bind actions to events Modern Z-Wave devices have the ability to report their stus changes to the Z-Wave controller that creates an even in return. The Z-Way stack can bind user defined actions to these events. In this case the action results in a UDP message being sent.

CAUTION: unsolicited status updates will only work if the Z-Wave controller is properly notified. This notification is done through the basic association mechanism. Most often association group 3 is used for that. With the RaZberry Expert tool you can check that the primary controller (node 1, RaZberry) is in that association group. In case of failure consult the documentation of the failing device first. automation/storage/UDPORSock.js

sudo nano automation/storage/UDPORSock.js

Below are some examples of functions bound to an event. They can be re-used. Adapt values between [] for your specific device. Please note that in the SwitchBinary example we have taken the opportunity to translate the outcome false|true into on|off, what is preferred at the receiving end. Other javascript operators (eg setting numbers of decimals) may be used as appropriate.

    var sock = new sockets.udp();
    sock.connect("IP_Of_RaspberryPi", 9091); //Use IP number of your OpenRemote Controller

    this.bindFunc1 = function (zwayName) {
	    if (zwayName != "zway")
		    return; // you want to bind to default zway instance

	    var devices = global.ZWave[zwayName].zway.devices;
 
 
    //from here insert your devices

    // Zwave>Me Binary Switch
	    devices[2].SwitchBinary.data.level.bind(function () {
		    var status = (this.value) ? "on" : "off";
		    sock.send("ZWay_2," + status);
	    });

    // Fibaro Universal Sensor-Temperature
	    devices[13].instances[5].SensorMultilevel.data[1].val.bind(function () {
		    var status = this.value;
		    sock.send("ZWay_13_5_1," + status);
	    });

    // Vision Door/window sensor
	    devices[30].SensorBinary.data[1].level.bind(function () {
		    var status = (this.value) ? "on" : "off";
		    sock.send("ZWay_30_0_1," + status);
	    });

    // End of your devices
    };

    // process all active bindings
    if (global.ZWave) {
      global.ZWave().forEach(this.bindFunc1);
    }

    // and listen for future ones
    global.controller.on("ZWave.register", this.bindFunc1);

For other types of devices the primary source of reference is the Z-Way Developer Documentation. If you are naughty you may peek in automation/modules/OpenRemoteHelpers/index.js. That is not recommended practice though!

###Activate UDPSender In principle the UDPORSock.js could be executed from the main.js file. The preferred and easiest way to it, is the RaZberry Home Automation engine. Therefore goto menu -Preferences-Modules-Scripting. Choose CustomUserCodeLoader. Make sure you have activated the following modules in the Home automation preferences.

UDP - HALoadJS

UDP - SelectedModules

##Watchdog on UDPListener (Extension of Code)

UDP - SwitchCount

Below is an extended version of the UDPListener rule given above. In order to get this to work you have to create one In memory Virtual Switch and one In memory Virtual Status for the counter.

package org.openremote.controller.protocol.preserve;
import java.util.*;
import org.openremote.controller.protocol.Event;
global org.openremote.controller.statuscache.CommandFacade execute;

rule "UDPListener9091"
when
  Event(source=="RaZ-UDP-Status-9091", $v: value!="")
then
  java.util.regex.Pattern regexPattern = java.util.regex.Pattern.compile("\\(?(ZWay.*),([\\d\\.+|on|off]+)\\)?");
  java.util.regex.Matcher matcher = regexPattern.matcher($v.toString());
  if (matcher.find()) {
    execute.command(matcher.group(1), matcher.group(2));
    execute.command("UDP9091On");                  //Added this
    execute.command("UDP9091countdown",100);       //Added this
  }
end

//Added following two rules
rule "UDP9091SourceFailed"
    timer (int: 2s)
when
    Event( source == "UDP9091countdownStatus", value == "0")
then
    execute.command("UDP9091Off");
end

rule "UDP9091CountDown"
    timer (int: 10s)
when
    Event( source == "UDP9091countdownStatus", $TimeLeft : value > 0 )
then
    Integer iTl = Integer.parseInt($TimeLeft.toString()) ;
    iTl = iTl - 1 ;
    execute.command("UDP9091countdown",iTl);
end

UDP - Capture

The Dashboard on the right displays the Status of two Raspberry Pi devices that are sending UDP messages. The red icon represents the Pi where ZWay-server has been stopped for a while. The numbers below the icons represent the watchdog timers.

##Assessment Be aware that UDP is not the most reliable protocol. There is no correction mechanism for missing data. So do not apply this recipe in mission critical applications. Some places are more susceptible for such errors.

##Troubleshooting If a device no longer sends status updates, there may be something wrong in its configuration. Check if the offending device still has the proper association with the controller. See Razberry forum for Testing UDP connection

##Usefull links