Velbus glass panel button

You have a point… all this info can be found in the docs.
But there are al lot of pages were you must find the correct info.

Can you point me to the correct page where I can find how I can make a (virtual) button in the habpanel that triggers a rule (or script)

and I’m still curious why in paperui, (velbus) buttons cannot fire an action (via rules in paperui), and thermostates can…

Sorry, I do not (yet?) use HABPanel or Velbus.
A virtual button would just be an Item that can be referenced and/or set in a Rule.Just create an Item with no linked channel to create a virtual button. I assume the Item would be a Switch?

What have you tried? This forum is geared more to help somebody resolve their issues and learn. It is not a Help Desk just providing solutions.

How to ask a good question / Help Us Help You - Tutorials & Examples - openHAB Community

It is no different in habpanel!!.
What you need is to create a virtual item first. And then link it in Habpanel.
Whatever you do with this item, could be as well as a trigger in a rule.

They can, and it´s pretty easy… But you need to understand how to create the item… This is where you seem to have gone stucked. Try searc for vitual items. As wel as channel triggers, (velbus button IS the channel trigger).

2 Likes

Most people read documentation before embarking on this journey.
First, study the concepts of OH.

The configuration Guide is a good next step.

Rules are described here.

Please read this information and return after you have tried to implement something. You could surprise yourself.

1 Like

I understand the confusion, especially if you’re thinking about ‘virtual items’.

You’d use the State of a virtual Item in a similar way to how you’d use a trigger Channel of a Velbus Thing

(Note the Title case usage there)

An Item and a trigger Channel are both something that can be used in the When section of a rule.
With the added bonus that Item States can also be queried during the Then section of a rule. (As you’ve done with your Sonos Volume)

For example

rule "example triggers and queries"

when
Item Virtual_Switch_Item changed
or
Channel 'velbus:VMBGP2:xxxxxxxx:XX:ch1' triggered LONG_PRESSED

then
Virtual_Switch_Item.sendCommand(OFF)

If ( Another_Item.state == ON ) {

New_Item.sendCommand(ON)
Another_Item.sendCommand(OFF)
}

else {
New_Item.sendCommand(OFF)
Something_Volume.sendCommand(0)
}

end

Or do you mean in the Experimental Rules Engine of PaperUI.

(The hint might be in the name)

That said, can you clarify what you mean by ‘Thermostats can’
Because the Velbus thermostat functionality is made up of Trigger Channels (that can’t be linked to Items) and normal (state based) channels that can be linked to Items and thus used in all the rules / logic solutions available to openHAB2.

I’m curious about the (Yet?) Regarding Velbus :wink:

I meant I may eventually use HABPanel.

:crying_cat_face:

I thought for a moment that I might have another convert :frowning:

Oh well, let’s hope I hit next year’s target :wink:

Happy new year Bruce :slight_smile:

Thank you.
Last year I was not using OpenHAB. That is a start.

Happy New Year to you too.

1 Like

Yes, I am (was) using the Experimental Rules Engine of PaperUI.
I thought you could make this rule:
when ‘velbus:vmb8pbu:bc2e9d45:28:input#CH1’ triggered PRESSED then do something…
But this is impossible with he Experimental Rules Engine of PaperUI, but now it works with a DSL rule, so me happy.

But there is no way so I can simulate a key-press in velbus so a scene (stored in velbus) is recalled. In my living room I have 6 velbus dimmers, and I hope that I must not to copy all the settings (values and dim times stored in my velbus modules) in the rules in openhab.

Hello

Happy new year to you.

I’m glad to hear that the DSL rules are working for you.

As far as sending “Button events” back into Velbus from openHAB2, that isn’t possible right now.
At least, not through the Velbus binding.

I have worked out how to send a mimicking packet from NodeRed using a TCP node.
If that is something you’d like to play with ?

I would assume that there is a way to send a TCP packet to VelServ using the TCP / UDP binding in openHAB2, but I haven’t got my head around that yet.

What I do know is that you may need to send just a “Button Pressed” packet, but ideally follow it with a “Button Released” packet (just for compliance with the protocol)

Or you may need to send a “Button Pressed” packet, followed by “Button Long Pressed” packet, later followed with a “Button Released” packet, depending on how you have setup your scenes in VelbusLink.,

I have tested the following with a button from a VMB8PBU, which was programmed in VelbusLink with a “Up/Down” action on a VMB2BLE motor controller.

Just issuing a “Button Pressed” packet was enough to start and stop the VMB2BLE.
What happens with other modules will be a matter for you to explore.

Here is what I did.

I opened VelbusLink logging and isolated the VMB8PBU packets by using the filter

packet.addr==$A0

Then I Pressed, Long Pressed and Released Button 7 of the VMB8PBU (I did it from within VelbusLink, using the Operate function)

Which gave me this

image

The first Button Status is the “Press”
Second Button Status is the “Long Press”
Third Button Status is the “Released”


You’ll note that H40 pops up in all three strings, at different places.

H40 is derived from Bin 01000000, which indicated that Button 7 is in play.
So equally, H01 would mean Button 1, from Bin 00000001


By highlighting the first Button Status and clicking on “USE”, followed by “Check Sum”

I was able to highlight and copy the “RAW packet”

This gave me these three HEX strings

Press       0F F8 A0 04 00 40 00 00 15 04
Long press  0F F8 A0 04 00 00 00 40 15 04
Release     0F F8 A0 04 00 00 40 00 15 04

By using an Inject Node and an OutGoing TCP node in NodeRed, I was able to trigger the VMB2BLE as if I were pressing button 7 on the VMB8PBU

The BIG issue I found (and it may be possible to bypass this step if you know more about NodeRed than I do) is that I couldn’t simply paste in the HEX string into the Inject node.
I had to convert the HEX packet into something that NodeRed would convert (correctly) back into exactly the same HEX string.

I used a Google Drive sheet to convert the HEX string from VelbusLink into a formatted TEXT string.

Something like this

I’ve put that spreadsheet in a ZIP file here in Open Document and Excel formats.

The flow I used in NodeRed is this, which you can simply import into your own NodeRed instance, assuming that you have VelServ running on the same machine, on port 6000

[
    {
        "id": "42f5ffcd.151f3",
        "type": "comment",
        "z": "cfdce1d.4428b2",
        "name": "8PBU button 8",
        "info": "Press       0F F8 A0 04 00 40 00 00 15 04\nLong press  0F F8 A0 04 00 00 00 40 15 04\nRelease     0F F8 A0 04 00 00 40 00 15 04",
        "x": 460,
        "y": 160,
        "wires": []
    },
    {
        "id": "a30a7b05.702d98",
        "type": "tcp out",
        "z": "cfdce1d.4428b2",
        "host": "127.0.0.1",
        "port": "6000",
        "beserver": "client",
        "base64": false,
        "end": true,
        "name": "Velserv OUT",
        "x": 840,
        "y": 240,
        "wires": []
    },
    {
        "id": "e2810117.a6b88",
        "type": "tcp in",
        "z": "cfdce1d.4428b2",
        "name": "",
        "server": "client",
        "host": "127.0.0.1",
        "port": "6000",
        "datamode": "stream",
        "datatype": "buffer",
        "newline": "",
        "topic": "",
        "base64": false,
        "x": 180,
        "y": 300,
        "wires": [
            [
                "47871c2b.681744"
            ]
        ]
    },
    {
        "id": "47871c2b.681744",
        "type": "debug",
        "z": "cfdce1d.4428b2",
        "name": "",
        "active": true,
        "tosidebar": false,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "x": 410,
        "y": 300,
        "wires": []
    },
    {
        "id": "1f59345f.b397cc",
        "type": "inject",
        "z": "cfdce1d.4428b2",
        "name": "Pressed",
        "topic": "",
        "payload": "[15,248,160,4,0,64,0,0,21,4]",
        "payloadType": "bin",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 595,
        "y": 200,
        "wires": [
            [
                "a30a7b05.702d98"
            ]
        ],
        "l": false
    },
    {
        "id": "8e7383d0.c541b",
        "type": "inject",
        "z": "cfdce1d.4428b2",
        "name": "Released",
        "topic": "",
        "payload": "[15,248,160,4,0,0,64,0,21,4]",
        "payloadType": "bin",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 595,
        "y": 240,
        "wires": [
            [
                "a30a7b05.702d98"
            ]
        ],
        "l": false
    }
]

Looking into this further, I discovered that it is possible to use a Function node to format the VelServ packet, and get triggered by different Payload content.

For example, I created a Function node that can output the 3 different button events, based on a payload containing matching text.
Which means that by using a couple of Delay nodes and Change nodes, you could automate the sending of the correct sequence of Button events to correctly match your requirements.

IE

  • Pressed
  • Long_Pressed
  • Released

You will just have to work out the correct sequence of Button Events to trigger your scene and release all modules (IE, Don’t Leave them waiting for a “Button Released” event)

Please note that I have added 2 variables to the Function node so that you can easily adapt it for your use.

  • address
  • button

These need to the the Decimal version of the HEX command you wish to send, whereas the rest of the string you see in the function is made up of HEX .

This might help you a little further

[
    {
        "id": "60e3ffbc.83dd9",
        "type": "function",
        "z": "cfdce1d.4428b2",
        "name": "Send Button Events to VelServ",
        "func": "var button = 64; // Decimal of Hex 40, which is button No 7 only (Different numbers are generated if multiple buttons are pressed). Note Dec 64 is derived from the Binary state 01000000 indicating  button 7\nvar address = 160; // Decimal of Hex A0\n\nvar incoming = String(msg.payload);\nvar buffer = \"\"\n\nif  (incoming == \"Pressed\" )  {\n// Format Pressed event\nbuffer = Buffer.from( [0x0F, 0xF8, address, 0x04, 0x00, button, 0x00, 0x00, 0x15, 0x04] );\nreturn {payload:buffer};\n\t}\n\nif  (incoming == \"Released\" )  {\n// Format Released event\nbuffer = Buffer.from( [0x0F, 0xF8, address, 0x04, 0x00, 0x00, button, 0x00, 0x15, 0x04] );\nreturn {payload:buffer};\n\t}\n\t\nif  (incoming == \"Long_Pressed\" )  {\n// Format Long_Pressed event\nbuffer = Buffer.from( [0x0F, 0xF8, address, 0x04, 0x00, 0x00, 0x00, button, 0x15, 0x04] );\nreturn {payload:buffer};\n\t}\t\n\t\n\treturn [msg];\n\n\n//    Press of Button 7         0F F8 A0 04 00 40 00 00 15 04\n//    Long press of Button 7    0F F8 A0 04 00 00 00 40 15 04\n//    Release of Button 7       0F F8 A0 04 00 00 40 00 15 04",
        "outputs": 1,
        "noerr": 0,
        "x": 630,
        "y": 400,
        "wires": [
            [
                "a30a7b05.702d98",
                "bad326f4.ddade8"
            ]
        ]
    },
    {
        "id": "a30a7b05.702d98",
        "type": "tcp out",
        "z": "cfdce1d.4428b2",
        "host": "127.0.0.1",
        "port": "6000",
        "beserver": "client",
        "base64": false,
        "end": true,
        "name": "Velserv OUT",
        "x": 970,
        "y": 220,
        "wires": []
    },
    {
        "id": "6ffad126.388b2",
        "type": "inject",
        "z": "cfdce1d.4428b2",
        "name": "",
        "topic": "",
        "payload": "Pressed",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 340,
        "y": 480,
        "wires": [
            [
                "60e3ffbc.83dd9",
                "d5348adc.aafe68"
            ]
        ]
    },
    {
        "id": "bad326f4.ddade8",
        "type": "debug",
        "z": "cfdce1d.4428b2",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "x": 990,
        "y": 420,
        "wires": []
    },
    {
        "id": "bc061d43.76115",
        "type": "inject",
        "z": "cfdce1d.4428b2",
        "name": "",
        "topic": "",
        "payload": "Long_Pressed",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 350,
        "y": 520,
        "wires": [
            [
                "60e3ffbc.83dd9",
                "d5348adc.aafe68"
            ]
        ]
    },
    {
        "id": "1a857fb7.e05dd",
        "type": "inject",
        "z": "cfdce1d.4428b2",
        "name": "",
        "topic": "",
        "payload": "Released",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 340,
        "y": 560,
        "wires": [
            [
                "60e3ffbc.83dd9",
                "d5348adc.aafe68"
            ]
        ]
    },
    {
        "id": "d5348adc.aafe68",
        "type": "debug",
        "z": "cfdce1d.4428b2",
        "name": "",
        "active": true,
        "tosidebar": false,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "x": 610,
        "y": 480,
        "wires": []
    },
    {
        "id": "42f5ffcd.151f3",
        "type": "comment",
        "z": "cfdce1d.4428b2",
        "name": "8PBU button 8",
        "info": "Press       0F F8 A0 04 00 40 00 00 15 04\nLong press  0F F8 A0 04 00 00 00 40 15 04\nRelease     0F F8 A0 04 00 00 40 00 15 04",
        "x": 460,
        "y": 160,
        "wires": []
    }
]

Information sources

This mentions using HEX as a donor for strings

Hi stuart, also a happy 2020 for you and family,
Thank you for your help.
I was thinking also to send IP commands to the velserv directly via the tcp/udp binding, but I gonna give node-red a try.
Is it correct you have openhab, velserv and node-red on the same raspberry pi?

Hello :slight_smile:

You can put the software on as many different machines as you like / want / need.

I guess it comes down to performance and speed, my personal opinion of SBCs is well documented on this forum.

In theory, yes, you can run all three on the same Pi.

There’s no reason why you couldn’t use the TCP binding and just send out the packets you need to.

In fact, there is a method of interacting with Velbus networks from openHAB2 that doesn’t use Cédric’s binding at all.

VelServer

Hi,
I have now velserv, openhab and node-red working :slight_smile:
I think there is a little error in your hex codes the 9th hex value is changing depending the adress, or something else (checksum ?).
I 'm now trying to send the press and release command with one press of a button, do you know the correct comand for the delay. (I’m using now “timeout(1000)”)
here you have my node-red export file:

[{"id":"ccfd159f.c0e418","type":"function","z":"d86de69f.3d1a48","name":"Send Button Events to VelServ","func":"var button3 = 4; // Decimal of Hex 40, which is button No 7 only (Different numbers are generated if multiple buttons are pressed). Note Dec 64 is derived from the Binary state 01000000 indicating  button 7\nvar address3 = 34; // Decimal of Hex A0\n\nvar incoming = String(msg.payload);\nvar buffer = \"\"\n\nif  (incoming == \"Pressed3\" )  {\n// Format Pressed event\nbuffer = Buffer.from( [0x0F, 0xF8, address3, 0x04, 0x00, button3, 0x00, 0x00, 0xCF, 0x04] );\n//Timeout(1000)\nbuffer = Buffer.from( [0x0F, 0xF8, address3, 0x04, 0x00, 0x00, button3, 0x00, 0xCF, 0x04] );\n\nreturn {payload:buffer};\n\t}\n\t\nreturn [msg];\n","outputs":1,"noerr":0,"x":650,"y":640,"wires":[["440b7389.4d954c","adf0b974.f17448"]]}]

Hello

Yes, the one before last byte is always a checksum and I’ll confess I completely forgot to account for that.

It’s probably best at this stage to see how VelbusLink creates the checksum, by using the steps I showed above.

As for sending a Pressed AND Released msg from the same function call, I suggest you have a read of this page on the NodeRed site, specifically the section marked “Multiple Messages”

https://nodered.org/docs/user-guide/writing-functions

I think what you’re doing currently is creating a buffer with the PRESSED string, then immediately over writing it with the RELEASED string.

One other observation.

In your function, you have Button as 4

Do you mean Button 4, or Button 3?

Hex 04 (or even Dec 04) when converted to Binary is 00000100, which repesents button 3

Buttons 8 7 6 5 4 3 2 1
Pressed? No No No No Yes No No No
As Binary 0 0 0 0 1 0 0 0
Binary Form 00001000
Hex Form 08

Velbus uses this form so that all 8 buttons can be presented in a single command.

For example, if you were to press buttons 1 and 4 at the same time, it would look like this

Buttons 8 7 6 5 4 3 2 1
Pressed? No No No No Yes No No Yes
As Binary 0 0 0 0 1 0 0 1
Binary Form 00001001
Hex Form 09

Assuming you mean button 4 and the Decimal base address of 34 converts to HEX 22

Your PRESSED packet might well look like this

0F F8 22 04 00 08 00 00 CB 04

Hi stuart, I have a working solution now, thank you very much for your help.

This is my design in nodered.

and this is the code for one button.

// v1rtueel controls button VMB8PB (adress 22 button 1)
if  (String(msg.payload) == "ON" )  {
    return {payload:Buffer.from( [0x0F, 0xF8, 0x21, 0x04, 0x00, 0x01, 0x00, 0x00, 0xD3, 0x04] )};
	}
if  (String(msg.payload) == "OFF" )  {
return {payload:Buffer.from( [0x0F, 0xF8, 0x21, 0x04, 0x00, 0x00, 0x01, 0x00, 0xD3, 0x04] )}
	}

return [msg];

in openhab I made virtual items and I use in habpanel this widget


When you push the button, the ON command is send and after a few ms OFF is send to velbus.
It is very nice that every scene can be programmed within velbus, and recalled directly from the habpanel. (with fade times, etc)
I still do not find a reason why stef coene didn’t programmed the item “simulate this button” (you can find this in velbuslink to test your actions)

i just have to find a way that all my monstable buttons are in selection button(i have put my buttons in a group), like I have with my sonos fav.

1 Like

I have problems with running the lastest binding of velbus (witch recognises vmb1ts) and velserv (dsm rules doesn’t work anymore till I shut down velserv).
But I need velserv for my nodered, any idea how to talk to the velbus (usb) via the velbus raw byte node ?
If that is not possible a try a second pi with velserv seperated from openhab

By any chance…

Are you using the Velbus NodeRed nodes?

I believe these are strictly a ‘direct connection’, unless the author has been able to add TCP support.


Update

After looking closer at your screen grab.

Why are you using the Serial Only Velbus node AND a TCP node to VelServ ???

Unless you have 2 Velbus USB connections, this will never work. (And you’d be sending the same instruction twice)

Because VelServ takes exclusive control of the Velleman / Velbus USB port.

Blockquote
Why are you using the Serial Only Velbus node AND a TCP node to VelServ ???

I’m not using both at the same time (I disable one when I use the other way), It was for testing because the velbus binding was giving problems via velserv. I think when the binding is working perfect with velserv all my problems will be solved !

1 Like

If anyone is interested, I have got a Function node working now that will start a timer for up to 63532 seconds on a Velbus Relay channel.

I assume it would be possible to adapt this for a dimmer?

All you should need to do is change the HEX address of the Module and the Channel number

I’m certain I’ll not win an award for this mess, but it is working.

If you’re curious, the JavaScript inside the NodeRed Function looks like this

var address = "74"; // Hex address of Relay
var channel = "04"; // Hex value of Channel No 3 of relay, derived from a bit array = 00100 (as in =bin2hex(00100) in a spreadsheet )





// 01 = OFF, 02 = ON, 03 = Timer start
var eop = "04";

var a = '0f', b = 'f8', c = address, d = '02', e = '02', f = channel, g = '00', h ="00", i = "00", y = 'ff';
var ndigits = 2, x, carry = 0, z, checksum = "";


var incoming = String(msg.payload);
var buffer = ""


var newMsg =  { payload:incoming };


if  (incoming == "ON" )  {
    
    command = "02"; // ON
    c = address;
    e = command;
    f = channel;
    
for (x = ndigits - 1; x >= 0; x--) {
  z = parseInt(a[x], 16) + parseInt(b[x], 16)+ parseInt(c[x], 16)+ parseInt(d[x], 16)+ parseInt(e[x], 16)+ parseInt(f[x], 16) + carry;
  carry = z >> 4;
  checksum = (z & 15).toString(16) + checksum;
}
 checksum = ((parseInt(y, 16) - parseInt(checksum, 16))+1).toString(16)
   
    

newMsg.payload = checksum;

    
    
    
    
    
// Format Pressed event
// buffer = Buffer.from( [0x0F,0xF8,0x74,0x05,0x03,0x04,0x00,0x00,0x05,0x74,0x04] );

buffer = Buffer.from(["0x"+a.toString(16),"0x"+b.toString(16),"0x"+c.toString(16),"0x"+d.toString(16),"0x"+e.toString(16),"0x"+f.toString(16),"0x"+checksum,0x04])
return [{payload:buffer},newMsg];


	}


if  (incoming == "OFF" )  {
    
 command = "01"; // OFF
    c = address;
    d = size;
    e = command;
    f = channel;
    

for (x = ndigits - 1; x >= 0; x--) {
  z = parseInt(a[x], 16) + parseInt(b[x], 16)+ parseInt(c[x], 16)+ parseInt(d[x], 16)+ parseInt(e[x], 16)+ parseInt(f[x], 16) + carry;
  carry = z >> 4;
  checksum = (z & 15).toString(16) + checksum;
}
 checksum = ((parseInt(y, 16) - parseInt(checksum, 16))+1).toString(16)
   
    

 newMsg.payload = checksum;



buffer = Buffer.from(["0x"+a.toString(16),"0x"+b.toString(16),"0x"+c.toString(16),"0x"+d.toString(16),"0x"+e.toString(16),"0x"+f.toString(16),"0x"+checksum,0x04])
return [{payload:buffer},newMsg];


	}
	
	
	// Timer value less than 255 seconds
if  (incoming >= 0 )   { if (incoming <=255) {
    
 command = "03"; // Start Timer
    c = address;
    d = "05"; // Size
    e = command;
    f = channel;
    i = incoming.toString(16) // Duration of timer in seconds
    


    checksum = parseInt(a, 16) + parseInt(b, 16)+ parseInt(c, 16)+ parseInt(d, 16)+ parseInt(e, 16)+ parseInt(f, 16)+ parseInt(g, 16)+ parseInt(h, 16)+ parseInt(i, 16);
    checksum = checksum.toString(16);
    checksum = (parseInt("FFFF",16) - parseInt(checksum,16));
    checksum = (parseInt(checksum,10)) + 257;
    checksum = checksum.toString(16);
    checksum = checksum.slice(-2);


 newMsg.payload = checksum;



buffer = Buffer.from(["0x"+a.toString(16),"0x"+b.toString(16),"0x"+c.toString(16),"0x"+d.toString(16),"0x"+e.toString(16),"0x"+f.toString(16),"0x"+g.toString(16),"0x"+h.toString(16),"0x"+i.toString(16),"0x"+checksum,0x04])
return [{payload:buffer},newMsg];


	}}
	
		// Timer value more than 255 seconds and less than 63535 seconds
if  (incoming >= 255 )   { if (incoming <=63535) {
    
 command = "03"; // Start Timer
    c = address;
    d = "05"; // Size
    e = command;
    f = channel;
    h = incoming - 255
    i = (incoming - h).toString(16) // Duration of timer in seconds
    


    checksum = parseInt(a, 16) + parseInt(b, 16)+ parseInt(c, 16)+ parseInt(d, 16)+ parseInt(e, 16)+ parseInt(f, 16)+ parseInt(g, 16)+ parseInt(h, 16)+ parseInt(i, 16);
    checksum = checksum.toString(16);
    checksum = (parseInt("FFFF",16) - parseInt(checksum,16));
    checksum = (parseInt(checksum,10)) + 257;
    checksum = checksum.toString(16);
    checksum = checksum.slice(-2);


 newMsg.payload = checksum;



buffer = Buffer.from(["0x"+a.toString(16),"0x"+b.toString(16),"0x"+c.toString(16),"0x"+d.toString(16),"0x"+e.toString(16),"0x"+f.toString(16),"0x"+g.toString(16),"0x"+h.toString(16),"0x"+i.toString(16),"0x"+checksum,0x04])
return [{payload:buffer},newMsg];


	}}
	
	if  (incoming >= 63535 )   {
	    newMsg.payload ="";
	    msg.payload ="";
	    return;
	}
	
return [msg,newMsg];

full flow example

[
    {
        "id": "29389d4b.a45f02",
        "type": "function",
        "z": "1233381f.cbcdb8",
        "name": "Set channel of Velbus Relay",
        "func": "var address = \"74\"; // Hex address of Relay\nvar channel = \"04\"; // Hex value of Channel No 3 of relay, derived from a bit array = 00100 (as in =bin2hex(00100) in a spreadsheet )\n\n\n\n\n\n// 01 = OFF, 02 = ON, 03 = Timer start\nvar eop = \"04\";\n\nvar a = '0f', b = 'f8', c = address, d = '02', e = '02', f = channel, g = '00', h =\"00\", i = \"00\", y = 'ff';\nvar ndigits = 2, x, carry = 0, z, checksum = \"\";\n\n\nvar incoming = String(msg.payload);\nvar buffer = \"\"\n\n\nvar newMsg =  { payload:incoming };\n\n\nif  (incoming == \"ON\" )  {\n    \n    command = \"02\"; // ON\n    c = address;\n    e = command;\n    f = channel;\n    \nfor (x = ndigits - 1; x >= 0; x--) {\n  z = parseInt(a[x], 16) + parseInt(b[x], 16)+ parseInt(c[x], 16)+ parseInt(d[x], 16)+ parseInt(e[x], 16)+ parseInt(f[x], 16) + carry;\n  carry = z >> 4;\n  checksum = (z & 15).toString(16) + checksum;\n}\n checksum = ((parseInt(y, 16) - parseInt(checksum, 16))+1).toString(16)\n   \n    \n\nnewMsg.payload = checksum;\n\n    \n    \n    \n    \n    \n// Format Pressed event\n// buffer = Buffer.from( [0x0F,0xF8,0x74,0x05,0x03,0x04,0x00,0x00,0x05,0x74,0x04] );\n\nbuffer = Buffer.from([\"0x\"+a.toString(16),\"0x\"+b.toString(16),\"0x\"+c.toString(16),\"0x\"+d.toString(16),\"0x\"+e.toString(16),\"0x\"+f.toString(16),\"0x\"+checksum,0x04])\nreturn [{payload:buffer},newMsg];\n\n\n\t}\n\n\nif  (incoming == \"OFF\" )  {\n    \n command = \"01\"; // OFF\n    c = address;\n    d = size;\n    e = command;\n    f = channel;\n    \n\nfor (x = ndigits - 1; x >= 0; x--) {\n  z = parseInt(a[x], 16) + parseInt(b[x], 16)+ parseInt(c[x], 16)+ parseInt(d[x], 16)+ parseInt(e[x], 16)+ parseInt(f[x], 16) + carry;\n  carry = z >> 4;\n  checksum = (z & 15).toString(16) + checksum;\n}\n checksum = ((parseInt(y, 16) - parseInt(checksum, 16))+1).toString(16)\n   \n    \n\n newMsg.payload = checksum;\n\n\n\nbuffer = Buffer.from([\"0x\"+a.toString(16),\"0x\"+b.toString(16),\"0x\"+c.toString(16),\"0x\"+d.toString(16),\"0x\"+e.toString(16),\"0x\"+f.toString(16),\"0x\"+checksum,0x04])\nreturn [{payload:buffer},newMsg];\n\n\n\t}\n\t\n\t\n\t// Timer value less than 255 seconds\nif  (incoming >= 0 )   { if (incoming <=255) {\n    \n command = \"03\"; // Start Timer\n    c = address;\n    d = \"05\"; // Size\n    e = command;\n    f = channel;\n    i = incoming.toString(16) // Duration of timer in seconds\n    \n\n\n    checksum = parseInt(a, 16) + parseInt(b, 16)+ parseInt(c, 16)+ parseInt(d, 16)+ parseInt(e, 16)+ parseInt(f, 16)+ parseInt(g, 16)+ parseInt(h, 16)+ parseInt(i, 16);\n    checksum = checksum.toString(16);\n    checksum = (parseInt(\"FFFF\",16) - parseInt(checksum,16));\n    checksum = (parseInt(checksum,10)) + 257;\n    checksum = checksum.toString(16);\n    checksum = checksum.slice(-2);\n\n\n newMsg.payload = checksum;\n\n\n\nbuffer = Buffer.from([\"0x\"+a.toString(16),\"0x\"+b.toString(16),\"0x\"+c.toString(16),\"0x\"+d.toString(16),\"0x\"+e.toString(16),\"0x\"+f.toString(16),\"0x\"+g.toString(16),\"0x\"+h.toString(16),\"0x\"+i.toString(16),\"0x\"+checksum,0x04])\nreturn [{payload:buffer},newMsg];\n\n\n\t}}\n\t\n\t\t// Timer value more than 255 seconds and less than 63535 seconds\nif  (incoming >= 255 )   { if (incoming <=63535) {\n    \n command = \"03\"; // Start Timer\n    c = address;\n    d = \"05\"; // Size\n    e = command;\n    f = channel;\n    h = incoming - 255\n    i = (incoming - h).toString(16) // Duration of timer in seconds\n    \n\n\n    checksum = parseInt(a, 16) + parseInt(b, 16)+ parseInt(c, 16)+ parseInt(d, 16)+ parseInt(e, 16)+ parseInt(f, 16)+ parseInt(g, 16)+ parseInt(h, 16)+ parseInt(i, 16);\n    checksum = checksum.toString(16);\n    checksum = (parseInt(\"FFFF\",16) - parseInt(checksum,16));\n    checksum = (parseInt(checksum,10)) + 257;\n    checksum = checksum.toString(16);\n    checksum = checksum.slice(-2);\n\n\n newMsg.payload = checksum;\n\n\n\nbuffer = Buffer.from([\"0x\"+a.toString(16),\"0x\"+b.toString(16),\"0x\"+c.toString(16),\"0x\"+d.toString(16),\"0x\"+e.toString(16),\"0x\"+f.toString(16),\"0x\"+g.toString(16),\"0x\"+h.toString(16),\"0x\"+i.toString(16),\"0x\"+checksum,0x04])\nreturn [{payload:buffer},newMsg];\n\n\n\t}}\n\t\n\tif  (incoming >= 63535 )   {\n\t    newMsg.payload =\"\";\n\t    msg.payload =\"\";\n\t    return;\n\t}\n\t\nreturn [msg,newMsg];",
        "outputs": 2,
        "noerr": 0,
        "x": 1680,
        "y": 140,
        "wires": [
            [
                "1a157d79.4959a3",
                "19e87fb3.6b71e"
            ],
            [
                "760977c6.8a7fd8"
            ]
        ],
        "outputLabels": [
            "Payload, Buffer value to TCP port",
            "Checksum in HEX"
        ]
    },
    {
        "id": "1a157d79.4959a3",
        "type": "debug",
        "z": "1233381f.cbcdb8",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "x": 1990,
        "y": 100,
        "wires": []
    },
    {
        "id": "760977c6.8a7fd8",
        "type": "debug",
        "z": "1233381f.cbcdb8",
        "name": "",
        "active": true,
        "tosidebar": false,
        "console": false,
        "tostatus": true,
        "complete": "payload",
        "targetType": "msg",
        "x": 1910,
        "y": 220,
        "wires": []
    },
    {
        "id": "8f1c0497.da7398",
        "type": "inject",
        "z": "1233381f.cbcdb8",
        "name": "",
        "topic": "",
        "payload": "ON",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 1350,
        "y": 100,
        "wires": [
            [
                "29389d4b.a45f02"
            ]
        ]
    },
    {
        "id": "66c78a16.50a5e4",
        "type": "inject",
        "z": "1233381f.cbcdb8",
        "name": "",
        "topic": "",
        "payload": "OFF",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 1350,
        "y": 140,
        "wires": [
            [
                "29389d4b.a45f02"
            ]
        ]
    },
    {
        "id": "c11edda3.df313",
        "type": "inject",
        "z": "1233381f.cbcdb8",
        "name": "Timer value in seconds",
        "topic": "",
        "payload": "73555",
        "payloadType": "str",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 1380,
        "y": 180,
        "wires": [
            [
                "29389d4b.a45f02"
            ]
        ]
    },
    {
        "id": "19e87fb3.6b71e",
        "type": "tcp out",
        "z": "1233381f.cbcdb8",
        "host": "127.0.0.1",
        "port": "6000",
        "beserver": "client",
        "base64": false,
        "end": true,
        "name": "Velserv OUT",
        "x": 2190,
        "y": 140,
        "wires": []
    }
]