Node Red integration

Hi

I’ve started playing with NodeRed in openHAB2.

I must say that I’m finding it fairly easy to navigate.

There is still lots to learn, like how to create timed loops for colour changing etc, but I’m really enjoying the experience.

Hey Gert,

I’m trying to help a chap who wants to mimic button events in his Velbus setup.

If you have the time and inclination, could you suggest a way that the Function Node can calculate the required checksum ?

(I’m really out of my depth)

Many thanks,

Stuart

Hm, I’m very sorry … not responding to your question for many months … :frowning:
I must have missed it …

For what it’s worth, here’s my checksum code in javascript:

 /**
 * Packs the byte so it is ready for sending. Packing involves adding a checksum and the frame delimiters.
 * Returns a raw representation of the packet.
 */
pack() {
	this.rawPacket[0] = (Packet.STX);
	this.rawPacket[this.size - 1] = (Packet.ETX); //order is important
	this.rawPacket[this.size - 2] = (this.checksum_Crc8());

	return this.rawPacket;
}

/// Calculates the 2's complement checksum of a specified buffer.
checksum_Crc8() {

	let crc = 0;

	for (let i = 0; i < this.rawPacket.length - 2; i++) {
		crc = (crc + (this.rawPacket[i] & 0xFF)) & 0xFF;
	}

	return (0x100 - crc);

}

FYI, I’m working on an update of my Node-Red implementation right now, including a TCP Gateway.
I hope to have an update ready soon :slight_smile:

Gert

2 Likes

Hi

No worries, I got something working.
It’s not as elegant as that, but as I don’t understand what I’m doing, I’m just happy that I’ve got something.

Excellent, I’m looking forward to seeing what you create.

Good luck,

Stuart

I’m happy to announce a major update for my Velbus - Node-red integration :wink:

I updated the npm package and should be ready to install/update from within the Node-Red Palette. Search for Velbus and push the install button.
More details here.

The most significant change is the TCP server connection.
The usability is a bit better because Velbus modules and channel names are automatically detected.
There’s a node to send commands to Velbus and one to listen to Velbus messages. So basically all Velbus interactions are possible. The Button node is still in place: it can send and receive push button commands and messages.

What’s next: creating some dedicated nodes like reading out temperature sensors. I’ll have an update ready within a few days.

Looking forward to your comments :wink:

2 Likes

Excellent :slight_smile:
Let’s hope I don’t loose too much of today by being distracted by your work :smile:

1 Like

I think I might be doing something wrong.

With the button node, the address drop down seems to be empty.

Do I need to perform a scan or something to populate it?

Did you deploy first? after I deployed the list is filled with my bus modules.

Thank you @GertSt :+1:

2 Likes

My mistake.

It seems that VelServ had hung.

Everything was seeing a connection to it, but no traffic was passing.
@jeroends Have you ever seen this behaviour?

I’ll go back to exploring now… Or do I mean, I’ll leave it for later and do some proper work???

The handful of modules in my test rig are discovered :slight_smile:

Strange, deploying first should not be required. I’ll check that out.
But the workaround to deploy first should do for now :wink:

In its virgin state without configured velbus-connector, no elements were shown. Now every new node is aware of the available populated addresses.

Stuart, velserv consists in fact of 2 programs in 1 (all for the same price :slight_smile: ). One part is the gateway, the real connection between velbus and a network socket. The other is a distribution part, more a software hub. What probably happend is an error in the gateway part (for ex bad connection in the usb, had in the past some errors with a bad usb cable, emc problems). The gatewaywill exit at this moment, but the hub will be alive and it will look like there’s a connection, but no data is going actually to velbus. It would be better or to kill the hub process when the gateway is gone or even better try to restart the gateway. The only problem with the last option is that the virtual device stille be alive but not accesible anymore, so the gateway has to now that the usb must be resetted, a new interface has to be created and needs to now the new name (for ex. the first time it will be ttyACM0, after an error the device could be ttyACM1 or 2 or …). When I had the problem in the past (years ago) I was trying to find a solution softwarewise, but when I found that it was in fact a hardware error I stopped the quest (because it wasn’t as easy as it looks at first sight).

1 Like

A new version is pushed, including a new Temperature node and a bugfix involving name requests.

2 Likes

Hi

A chap in Edinburgh has just been playing with your lovely work and we’ve noticed a tiny mistake in the const.js file

You’ve added lots of glass panels, but marked them as False for inputs.

This version works well now.

(I’ll look at the VMB4AN and other things I have here)

'use strict';

let constants = {


	moduleMetaData: [
		{type: 0x01, name: "VMB8PD", nrOfChannels: 8, hasInput: true, requestNameBinary: false},
		{type: 0x02, name: "VMB1RY", nrOfChannels: 1, hasInput: false, requestNameBinary: false},
		{type: 0x05, name: "VMB6IN", nrOfChannels: 6, hasInput: true, requestNameBinary: false},
		{type: 0x07, name: "VMB1DM", nrOfChannels: 1, hasInput: false, requestNameBinary: false},
		{type: 0x08, name: "VMB4RY", nrOfChannels: 4, hasInput: false, requestNameBinary: false},
		{type: 0x0A, name: "VMB8IR", nrOfChannels: 8, hasInput: true, requestNameBinary: false},
		{type: 0x0B, name: "VMB4PD", nrOfChannels: 8, hasInput: true, requestNameBinary: false},
		{type: 0x0F, name: "VMB1LED", nrOfChannels: 1, hasInput: false, requestNameBinary: false},
		{type: 0x10, name: "VMB4RYLD", nrOfChannels: 5, hasInput: false, requestNameBinary: false},
		{type: 0x11, name: "VMB4RYNO", nrOfChannels: 5, hasInput: false, requestNameBinary: false},
		{type: 0x12, name: "VMB4DC", nrOfChannels: 4, hasInput: false, requestNameBinary: false},
		{type: 0x14, name: "VMBDME", nrOfChannels: 1, hasInput: false, requestNameBinary: false},
		{type: 0x15, name: "VMBDMI", nrOfChannels: 1, hasInput: false, requestNameBinary: false},
		{type: 0x16, name: "VMB8PBU", nrOfChannels: 8, hasInput: true, requestNameBinary: false},
		{type: 0x17, name: "VMB6PBN", nrOfChannels: 6, hasInput: true, requestNameBinary: false},
		{type: 0x18, name: "VMB2PBN", nrOfChannels: 8, hasInput: true, requestNameBinary: false},
		{type: 0x1B, name: "VMB1RYNO", nrOfChannels: 5, hasInput: false, requestNameBinary: false},
		{type: 0x1D, name: "VMB2BLE", nrOfChannels: 2, hasInput: false, requestNameBinary: false},
		{type: 0x1E, name: "VMBGP1", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x1F, name: "VMBGP2", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x20, name: "VMBGP4", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x21, name: "VMBGPO", nrOfChannels: 33, hasInput: true, requestNameBinary: false},
		{type: 0x22, name: "VMB7IN", nrOfChannels: 8, hasInput: true, requestNameBinary: false},
		{type: 0x28, name: "VMBGPOD", nrOfChannels: 33, hasInput: true, requestNameBinary: false},
		{type: 0x29, name: "VMB1RYNOS", nrOfChannels: 5, hasInput: false, requestNameBinary: false},
		{type: 0x2A, name: "VMBPIRM", nrOfChannels: 7, hasInput: true, requestNameBinary: false},
		{type: 0x2B, name: "VMBPIRC", nrOfChannels: 7, hasInput: true, requestNameBinary: false},
		{type: 0x2C, name: "VMBPIRO", nrOfChannels: 7, hasInput: true, requestNameBinary: false},
		{type: 0x2D, name: "VMBGP4PIR", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x2E, name: "VMB1BLS", nrOfChannels: 1, hasInput: false, requestNameBinary: false},
		{type: 0x2F, name: "VMBDMIR", nrOfChannels: 1, hasInput: false, requestNameBinary: false},
		{type: 0x30, name: "VMBRFR8S", nrOfChannels: 8, hasInput: true, requestNameBinary: false}, //
		{type: 0x31, name: "VMBMETEO", nrOfChannels: 8, hasInput: true, requestNameBinary: false},
		{type: 0x32, name: "VMB4AN", nrOfChannels: 4, hasInput: true, requestNameBinary: false},
		{type: 0x33, name: "VMBVP01", nrOfChannels: 8, hasInput: true, requestNameBinary: false},
		{type: 0x34, name: "VMBEL1", nrOfChannels: 16, hasInput: true, requestNameBinary: true},
		{type: 0x35, name: "VMBEL2", nrOfChannels: 16, hasInput: true, requestNameBinary: true},
		{type: 0x36, name: "VMBEL4", nrOfChannels: 24, hasInput: true, requestNameBinary: true},
		{type: 0x37, name: "VMBELO", nrOfChannels: 24, hasInput: true, requestNameBinary: true},
		// {type: 0x39, name: "VMBSIG", nrOfChannels: 0, hasInput: false, requestNameBinary: false}, //signum
		{type: 0x3A, name: "VMBGP1_2", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x3B, name: "VMBGP2_2", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x3C, name: "VMBGP4_2", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x3D, name: "VMBGPOD_2", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x3E, name: "VMBGP4PIR_2", nrOfChannels: 9, hasInput: true, requestNameBinary: false},
		{type: 0x3F, name: "VMCM3", nrOfChannels: 0, hasInput: false, requestNameBinary: false},
		{type: 0x40, name: "VMBUSBIP", nrOfChannels: 0, hasInput: false, requestNameBinary: false},
	],


	//priority
	PRIO_HI: 0xF8,
	PRIO_LOW: 0xFB,

	// Velbus commands
	commands: {
		COMMAND_SWITCH_STATUS: 0x00,
		COMMAND_SWITCH_RELAY_OFF: 0x01,
		COMMAND_SWITCH_RELAY_ON: 0x02,
		COMMAND_START_RELAY_TIMER: 0x03,
		COMMAND_BLIND_OFF: 0x04,
		COMMAND_BLIND_UP: 0x05,
		COMMAND_BLIND_DOWN: 0x06,
		COMMAND_SET_DIMMER_VALUE: 0x07,
		COMMAND_START_DIMMER_TIMER: 0x08,
		COMMAND_BUS_OFF: 0x09,
		COMMAND_BUS_ACTIVE: 0x0A,
		COMMAND_RS232_BUFFER_FULL: 0x0B,
		COMMAND_RS232_BUFFER_EMPTY: 0x0C,
		COMMAND_START_BLINK_RELAY_TIMER: 0x0D,
		COMMAND_INTERFACE_STATUS_REQUEST: 0x0E,
		COMMAND_SLIDER_STATUS: 0x0F,
		COMMAND_FIRMWARE_UPDATE_REQUEST: 0x60,
		COMMAND_FIRMWARE_INFO: 0x61,
		COMMAND_ENTER_FIRMWARE_UPGRADE: 0x62,
		COMMAND_ABORT_FIRMWARE_UPGRADE: 0x63,
		COMMAND_EXIT_FIRMWARE_UPGRADE: 0x64,
		COMMAND_FIRMWARE_UPGRADE_STARTED: 0x65,
		COMMAND_WRITE_FIRMWARE_MEMORY: 0x66,
		COMMAND_FIRMWARE_MEMORY: 0x67,
		COMMAND_FIRMWARE_MEMORY_WRITE_CONFIRMED: 0x68,
		COMMAND_READ_FIRMWARE_MEMORY: 0x69,
		COMMAND_MODULE_SUBTYPE: 0xB0,
		COMMAND_SET_REALTIME_DATE: 0xB7,
		COMMAND_VARIABLE_DIMMER_STATUS: 0xB8,
		COMMAND_TEMPERATURE_SETTINGS_PART3: 0xC6,
		COMMAND_STATISTICS_REQUEST: 0xC7,
		COMMAND_STATISTICS: 0xC8,
		COMMAND_READ_MEMORY_BLOCK: 0xC9,
		COMMAND_WRITE_MEMORY_BLOCK: 0xCA,
		COMMAND_MEMORY_DUMP_REQUEST: 0xCB,
		COMMAND_MEMORY_BLOCK: 0xCC,
		COMMAND_LCD_LINE_TEXT_PART1: 0xCD,
		COMMAND_LCD_LINE_TEXT_PART2: 0xCE,
		COMMAND_LCD_LINE_TEXT_PART3: 0xCF,
		COMMAND_LCD_LINE_TEXT_REQUEST: 0xD0,
		COMMAND_ENABLE_TIMER_CHANNELS: 0xD1,
		COMMAND_RESET_BACKLIGHT: 0xD2,
		COMMAND_RESET_PUSHBUTTON_BACKLIGHT: 0xD3,
		COMMAND_SET_PUSHBUTTON_BACKLIGHT: 0xD4,
		COMMAND_BACKLIGHT_STATUS_REQUEST: 0xD5,
		COMMAND_BACKLIGHT: 0xD6,
		COMMAND_REAL_TIME_CLOCK_REQUEST: 0xD7,
		COMMAND_REAL_TIME_CLOCK: 0xD8,
		COMMAND_ERROR_COUNT_REQUEST: 0xD9,
		COMMAND_ERROR_COUNT: 0xDA,
		COMMAND_TEMPERATURE_SENSOR_COMFORT_MODE: 0xDB,
		COMMAND_TEMPERATURE_SENSOR_DAY_MODE: 0xDC,
		COMMAND_TEMPERATURE_SENSOR_NIGHT_MODE: 0xDD,
		COMMAND_TEMPERATURE_SENSOR_SAFE_MODE: 0xDE,
		COMMAND_TEMPERATURE_SENSOR_COOLING_MODE: 0xDF,
		COMMAND_TEMPERATURE_SENSOR_HEATING_MODE: 0xE0,
		COMMAND_TEMPERATURE_SENSOR_LOCK: 0xE1,
		COMMAND_TEMPERATURE_SENSOR_UNLOCK: 0xE2,
		COMMAND_SET_DEFAULT_SLEEP_TIMER: 0xE3,
		COMMAND_TEMPERATURE_SENSOR_SET_TEMPERATURE: 0xE4,
		COMMAND_TEMPERATURE_SENSOR_TEMPERATURE_REQUEST: 0xE5,
		COMMAND_TEMPERATURE_SENSOR_TEMPERATURE: 0xE6,
		COMMAND_TEMPERATURE_SENSOR_REQUEST_SETTINGS: 0xE7,
		COMMAND_TEMPERATURE_SENSOR_SETTINGS_PART1: 0xE8,
		COMMAND_TEMPERATURE_SENSOR_SETTINGS_PART2: 0xE9,
		COMMAND_TEMPERATURE_SENSOR_STATUS: 0xEA,
		COMMAND_IR_RECIEVER_STATUS: 0xEB,
		COMMAND_BLIND_SWITCH_STATUS: 0xEC,
		COMMAND_INPUT_SWITCH_STATUS: 0xED,
		COMMAND_DIMMER_STATUS: 0xEE,
		COMMAND_MODULE_NAME_REQUEST: 0xEF,
		COMMAND_MODULE_NAME_PART1: 0xF0,
		COMMAND_MODULE_NAME_PART2: 0xF1,
		COMMAND_MODULE_NAME_PART3: 0xF2,
		COMMAND_SET_BACKLIGHT: 0xF3,
		COMMAND_UPDATE_LED_STATUS: 0xF4,
		COMMAND_CLEAR_LED: 0xF5,
		COMMAND_SET_LED: 0xF6,
		COMMAND_SLOW_BLINKING_LED: 0xF7,
		COMMAND_FAST_BLINKING_LED: 0xF8,
		COMMAND_VERY_FAST_BLINKING_LED: 0xF9,
		COMMAND_MODULE_STATUS_REQUEST: 0xFA,
		COMMAND_RELAY_SWITCH_STATUS: 0xFB,
		COMMAND_WRITE_EEPROM_DATA: 0xFC,
		COMMAND_READ_EEPROM_DATA: 0xFD,
		COMMAND_EEPROM_DATA_STATUS: 0xFE,
		COMMAND_MODULE_TYPE: 0xFF,
	},




	getCommandKeyByValue(value) {
		return Object.keys(this.commands).find(key => this.commands[key] === value);
	},

	numberToHexString(value) {
		if (isNaN(value)) {
			return "NaN"
		} else {
			let hex = value.toString(16).toUpperCase();
			if (hex.length < 2) {
				hex = "0" + hex;
			}
			hex = "0x" + hex;
			return hex;
		}
	}

};


module.exports = Object.freeze(constants); // freeze prevents changes by users

We’d also like to ask you consider a small change to the Send Raw Bytes node.

Can you make it accept the DataByte from the payload, when it appears as a String?

Maybe even use the Topic as the Command?

That way one Send node can be used for multiple actions to a selected Module.

I see that you have JSON formats as an input option, but we’re not too sure how this is achieved.

I’ll try to learn :slight_smile:

Dynamic data bytes You can feed the data bytes with dynamic data by using JSON keys in the input node and Mustache syntax in the Data Bytes input:
E.g.:

  • To send the current day and time, use the command COMMAND_REAL_TIME_CLOCK and this string for the data bytes: {{day}} {{hour}} {{minute}}
  • The input message payload of type JSON should be: {"day":1,"hour":7,"minute":45}
    Of course you can make this date dynamic by using a Function node. See example in the Readme on Github

We did struggle for a few minutes to realise what we needed to do in order to switch different relay channels.

But with a simple spreadsheet formula we soon got there

For example

If A3 = 100

The formula =bin2hex(A3,2) returns 08 which addresses channel 3 of the relay :slight_smile: (as per the Velbus protocol)

In my Node-Red V1.0.3 setup with version 0.2.2 the modules are now listed double.
Do I need to clear its cache?

Thanks for letting me know. I’ll update soon in a next release!

Can you clarify on how you see this? Just a list of bytes, like so: 0x01 0xA2 ... ?
If a topic is given, then use that for the command?
I will also add a demo on how to use the JSON / mustache method, as this is quite powerful.
I’m thinking about a dedicated node for relays. Then I can add a nicer channer selector and you don’t need to convert from bits to hex yourself. But that’s lower priority.

1 Like

I also saw this issue and will tackle it in the near future.
But it has no further impact, so don’t bother for now :wink:

1 Like

I just released v0.2.3 with some fixes. Thanks MDAR and Ggaljoen to help me on this!

1 Like