[HowTo] Send status updates as UDP messages

Tips, Tricks and Scripts to enhance your home automation and workaround known device bugs, limitations and incompatibilities
pz1
Posts: 2053
Joined: 08 Apr 2012 13:44

Re: [HowTo] Send status updates as UDP messages

Post by pz1 »

pofs wrote:
pz1 wrote:I still do not understand why my UDP code has to start before Z-Wave is started
Because you have only a subscription for future zwave binding creation. But if your code starts after zwave binding, bindFunc1 is never called.
I had to manually rebuild my system to RaspberryPi2 with UZB1. I am running into an old problem with the recipe (See first post) again I think.

The essence is that the zwave bindings executed in by my file UDPORSock.js shoud be executed before the Z-Wave bindings were executed. Therefore the module that loads that code should be specified as first module, well before the Zwave bindings. That worked fine in the past.

It seems now that the order in which modules are started are no longer determined by the order in which they appear in the list. In my logs I see the bindings script is consistently started some 3 seconds after the start of the Z-wave bindings.

How can I force a different order, so the bindings will work as before?
User avatar
PoltoS
Posts: 7565
Joined: 26 Jan 2011 19:36

Re: [HowTo] Send status updates as UDP messages

Post by PoltoS »

You can not force it. The only correct way to do it is to register in your module a hook on "zway.register" event and then do all the bindings.
pz1
Posts: 2053
Joined: 08 Apr 2012 13:44

Re: [HowTo] Send status updates as UDP messages

Post by pz1 »

PoltoS wrote:You can not force it.
So you disagree here with pofs, who insisted on putting the modules in order, And as a matter of fact that made it work for me. But as it seems flaky with this latest release, I should use some other method apparantly?
The only correct way to do it is to register in your module a hook on "zway.register" event and then do all the bindings.
So ZWave.register that I use in the last line does no longer work, and should be replaced with zway.register? The ZWave.register did work with the latest 2.0.1-rc. I am surprised that it does not work anymore in 2.02-rc1

update 2015-07-28: Just changed it to zway.register. Unfortunately that does not make it work.

My code stripped down to serve one device only

Code: Select all

	var sock = new sockets.udp();
	sock.connect("myIP", myPort);

	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
		devices[199].SwitchBinary.data.level.bind(function () {
			var status = (this.value) ? "on" : "off";
			sock.send("ZWay_2," + status);
		});
		//Last device before this comment
	};
	global.controller.on("ZWave.register", this.bindFunc1);
User avatar
PoltoS
Posts: 7565
Joined: 26 Jan 2011 19:36

Re: [HowTo] Send status updates as UDP messages

Post by PoltoS »

> this.controller.emit("ZWave.register", this.config.name);
Excuse, it is ZWave.register
pz1
Posts: 2053
Joined: 08 Apr 2012 13:44

Re: [HowTo] Send status updates as UDP messages

Post by pz1 »

PoltoS wrote:> this.controller.emit("ZWave.register", this.config.name);
Excuse, it is ZWave.register
But still I have no clue why this does not work. I now have the JS script file installed on two machines. On one it does work most of the time. On the other most of the time it does not work.

Code: Select all

       var sock = new sockets.udp();
       sock.connect("myIP", myPort);
       sock.send("Socket quadras started");

       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
          devices[199].SwitchBinary.data.level.bind(function () {
             var status = (this.value) ? "on" : "off";
             sock.send("ZWay_2," + status);
          });
          //Last device before this comment
       };
       global.controller.on("ZWave.register", this.bindFunc1);
The code seems to have properly started. The first message "Socket quadras started" does arrive at the OpenRemote server, but then it stops. It seems the bindings are not properly made.

Code: Select all

[2015-08-09 14:04:03.303] [I] [core] Executing script:   /*** CustomUserCodeLoader ZAutomation module **************************************** ...
[2015-08-09 14:04:03.308] [I] [core] Instantiating module 1 from class CustomUserCodeLoader
[2015-08-09 14:04:03.309] [I] [core] --- Starting module Load custom JavaScript file
[2015-08-09 14:04:03.337] [I] [core] Executing script: var sock = new sockets.udp(); ...
[2015-08-09 14:04:03.339] [I] [core] Socket 9091 started
In both cases I tested that the UDP socket connection with the OpenRemote server did exist with linux command:

Code: Select all

ss -u -a

State      Recv-Q Send-Q      Local Address:Port          Peer Address:Port
ESTAB      0      0           192.168.yyy.xxx:40125       192.168.yyy.xxx:9192
pz1
Posts: 2053
Joined: 08 Apr 2012 13:44

Re: [HowTo] Send status updates as UDP messages

Post by pz1 »

I got one step further in debugging this:
As said in the previous post, after a Z-Way restart or a reboot it is very uncertain if the UDP sender gets started:

I just noticed that if I deactivate/reactivate the Z-Wave module, the bindings do work. I'll see if I can repeat this. Strange, don't understand how this can "randomly" happen.
pz1
Posts: 2053
Joined: 08 Apr 2012 13:44

Re: [HowTo] Send status updates as UDP messages

Post by pz1 »

pz1 wrote:I just noticed that if I deactivate/reactivate the Z-Wave module, the bindings do work. I'll see if I can repeat this. Strange, don't understand how this can "randomly" happen.
Unfortunately the deactivate/activate did not lead to further solid results.

In conclusion these UDP status updates still are highly unreliable . Not because UDP is unreliable, but because the methos to create bindings is unreliable. (The JS code does send a "socket started message" that is received by OpenRemote (see previous post))
pofs
Posts: 688
Joined: 25 Mar 2011 19:03

Re: [HowTo] Send status updates as UDP messages

Post by pofs »

I believe I've already explained it nearly half a year ago (and there's even a link in this thread), but still :)

The one and only correct way of subscribing is:

Code: Select all

// process all active bindings
if (global.ZWave) {
  global.ZWave().forEach(this.bindFunc1);
}
// and listen for future ones
global.controller.on("ZWave.register", this.bindFunc1);
pz1
Posts: 2053
Joined: 08 Apr 2012 13:44

Re: [HowTo] Send status updates as UDP messages

Post by pz1 »

pofs wrote:I believe I've already explained it nearly half a year ago (and there's even a link in this thread), but still :)
  1. I am aware of that! But for several reasons I had to individually specify bindings of devices. Your simple loop that auto creates bindings on the fly would not work for me, since I directly send the value to a named existing OpenRemote sensor. Above that I do not want to send all available statuses there.
  2. As a matter of fact my code does work, but does not always instantiates the bindings. That also depends somewhat on the ZWay release. With v2.1.1 my RaZberry RPi-B+ rig starts most of the time, my UZB1 RPi-2 hardly ever starts. Under v2.0.2-rc1 both worked right away, or after one or two Z-Way restarts, or reboots.

    Based on previous discussions I came to beleive there is something tricky in the relation of Z-Wave being started and the start of my UDP code. Even though I have specified my js code well before the Zwave binding, the log showed at times that it had started after the ZWave bindings. According to PoltoS that would not matter though.
My present full UDP Status send code

Code: Select all

var sock = new sockets.udp();
sock.connect("192.168.1.33", 9091);
sock.send("Socket quadras started");

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
	devices[4].SwitchBinary.data.level.bind(function () {
		var status = (this.value) ? "on" : "off";
		sock.send("ZWay_2," + status);
	});

	devices[7].SwitchBinary.data.level.bind(function () {
		var status = (this.value) ? "on" : "off";
		sock.send("ZWay_3," + status);
	});

	devices[27].SwitchBinary.data.level.bind(function () {
		var status = (this.value) ? "on" : "off";
		sock.send("ZWay_6," + status);
	});

	devices[26].SwitchBinary.data.level.bind(function () {
		var status = (this.value) ? "on" : "off";
		sock.send("ZWay_7," + status);
	});

	devices[6].SwitchBinary.data.level.bind(function () {
		var status = (this.value) ? "on" : "off";
		sock.send("ZWay_21," + status);
	});

	devices[28].SwitchBinary.data.level.bind(function () {
		var status = (this.value) ? "on" : "off";
		sock.send("ZWay_26," + status);
	});

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

	devices[31].instances[1].SensorBinary.data[1].level.bind(function () {
		var status = (this.value) ? "on" : "off";
		sock.send("ZWay_15_1_1," + status);
	});

	devices[31].instances[2].SensorBinary.data[1].level.bind(function () {
		var status = (this.value) ? "on" : "off";
		sock.send("ZWay_15_2_1," + status);
	});

	devices[31].instances[3].SensorMultilevel.data[1].val.bind(function () {
		var status = this.value;
		sock.send("ZWay_15_3_1," + status);
	});

	devices[31].instances[4].SensorMultilevel.data[1].val.bind(function () {
		var status = this.value;
		sock.send("ZWay_15_4_1," + status);
	});

	devices[31].instances[5].SensorMultilevel.data[1].val.bind(function () {
		var status = this.value;
		sock.send("ZWay_15_5_1," + status);
	});

	devices[31].instances[6].SensorMultilevel.data[1].val.bind(function () {
		var status = this.value;
		sock.send("ZWay_15_6_1," + status);
	});

	devices[6].instances[0].Meter.data[2].val.bind(function () {
		var status = this.value;
		sock.send("ZWay_21_0_2," + status);
	});

	//Last device before this comment
};
global.controller.on("ZWave.register", this.bindFunc1);
Thank you for your attention
Pieter
pofs
Posts: 688
Joined: 25 Mar 2011 19:03

Re: [HowTo] Send status updates as UDP messages

Post by pofs »

pz1, you still don't iterate existing bindings in your code. No wonder it doesn't work correctly when zway is created before your code.
Post Reply