How use node-red-contrib-rfxcom 2.12.1 with RFXCom?

Good evening,

I need some help to get my RFXCom running with node-red-contrib-rfxcom 2.12.1
The RFXCom is connected via USB and when I consult dmesg it looks fine:

[1468387.729015] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialN                        umber=3
[1468387.729031] usb 1-1.4: Product: RFXtrx433
[1468387.729046] usb 1-1.4: Manufacturer: RFXCOM
[1468387.729059] usb 1-1.4: SerialNumber: A1XSS5RN
[1468387.738289] ftdi_sio 1-1.4:1.0: FTDI USB Serial Device converter detecte                        d
[1468387.738504] usb 1-1.4: Detected FT232R
[1468387.742810] usb 1-1.4: FTDI USB Serial Device converter now attached to                         ttyUSB0

The installation of node-red-contrib-rfxcom 2.12.1 was no problem, several nodes were added to my pallet and the example flow shows status OK "connected"

I made this testflow which must switch a lighting4 power outlet, but nothing receives in the debug message pane if I use the original remote control or the inject node.

[
    {
        "id": "2102b3c0f170f212",
        "type": "debug",
        "z": "4d7c33f038b29c9a",
        "name": "debug 8",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 960,
        "y": 660,
        "wires": []
    },
    {
        "id": "6f781a1204eb1e7a",
        "type": "inject",
        "z": "4d7c33f038b29c9a",
        "name": "",
        "props": [
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "PT2262/",
        "x": 780,
        "y": 760,
        "wires": [
            [
                "e800bf6fa9334f20"
            ]
        ]
    },
    {
        "id": "0e133b1eac984adb",
        "type": "rfx-PT2262-in",
        "z": "4d7c33f038b29c9a",
        "name": "",
        "port": "dc1031e4.23efd",
        "deviceList": "b89e4b235c49c0f7",
        "topicSource": "all",
        "topic": "PT2262/0913000E11A80F012970",
        "x": 780,
        "y": 660,
        "wires": [
            [
                "2102b3c0f170f212"
            ]
        ]
    },
    {
        "id": "e800bf6fa9334f20",
        "type": "rfx-PT2262-out",
        "z": "4d7c33f038b29c9a",
        "name": "",
        "port": "dc1031e4.23efd",
        "deviceList": "b89e4b235c49c0f7",
        "topicSource": "msg",
        "retransmit": "none",
        "retransmitInterval": 20,
        "topic": "",
        "x": 990,
        "y": 760,
        "wires": []
    },
    {
        "id": "dc1031e4.23efd",
        "type": "rfxtrx-port",
        "port": "/dev/ttyUSB0",
        "enableDebug": true,
        "rfyVenetianMode": "EU"
    },
    {
        "id": "b89e4b235c49c0f7",
        "type": "PT2262-device-list",
        "name": "Radiator",
        "devices": [
            {
                "device": [
                    "PT2262",
                    "radiator",
                    "Off"
                ],
                "payload": "0001 0001 1010 1000 0000 1101",
                "rawData": "0x11a80c",
                "pulseWidth": 292
            },
            {
                "device": [
                    "PT2262",
                    "radiator",
                    "On"
                ],
                "payload": "0001 0001 1010 1000 0000 1110",
                "rawData": "0x11a80d",
                "pulseWidth": 294
            }
        ]
    }
]

Have you turned on the correct protocols in your RFX device? Been a long time since I touched mine but I remember that I had to make sure that the protocols I was interested in were turned on because some of the protocols interfered with each other and would not work together.

Thank you,

Yes I did, I first had the RFXcom connected to my Windows pc and only activated in RFXmngr the protocols I'm using.

And did you check in the Windows app that you were getting data from your devices?

Yes, the switch is working well in Windows.
I don't know if it is possible but it would be nice if I could monitor the usbport or use commandline options for the RFXCom to check.

You should be able to use Minicom or similar to monitor the port but serial port access is generally exclusive so unless you are using a sharable port driver, you will probably have to close Node-RED to do so.

I must admit that I rarely give any thought to my RFX nodes as they generally just work But then, in my typical fashion, I brute-force everything out and then split the data into known and unknown device sources. You'd be amazed what you might find around the neighbourhood.

Data is all posted to MQTT.

1 Like

That's interesting, I thought I would use MQTT too. I'm trying to analyze your flow but I don't fully understand it yet. You use switches to filter known and unknown devices and then this data is available via MQTT? So that's the receiving end and I think there is much more after the link nodes :thinking:

I would first like to start simple by switching a power outlet from a dashboard
Can you post a simple example flow with the nodes I should use?

Can't blame you! I have to read it multiple times to remember what it does as well. :rofl:

Basically, it listens for inputs from all the different input nodes, standardises some of the input data

Then passes to a couple of separate function nodes that add metadata and split into known and unknown devices. The metadata and the split come from some reference data that I keep.

Here is the bigger of the 2 main functions:

/**
 * Outputs:
 *   1) Static & dynamic device info as single serialised JSON 
 *      to "known_devices/<device>" topic
 *   2) Unknown_devices output
 *   3) Any inputs that are controllers sent to the CONTROLERS/... topic
 */

/*
{
 "status":{"rssi":6},
 "topic":"LIGHTWAVERF/0xF30F69/16","payload":"On",
 "input":"rfx-lights"
}
*/

const storeName = 'file' // name of the context store to use

const updated = (new Date()).toISOString()

const payload = msg.payload
let topic = ''; let value = ''
let isNew = false

const topics = msg.topic.split('/')
const id = topics[1]
const chan = topics.length === 3 ? topics[2] : undefined

// Get the cached devices data
const devices = global.get('known_devices', storeName) || {}
const deviceids = global.get('deviceids', storeName) || {}
const controller_map = global.get('controller_map', storeName) || {}

// Lookup device ID WITHOUT channel # first
let deviceid = '433/' + id  //+ ( chan !== undefined ? '-' + chan : '' )
let name = ''
if ( deviceids[deviceid] ) {
    
    //node.warn('found without chan #')
    name = deviceids[deviceid].name
    
} else if ( deviceids[deviceid + ( chan !== undefined ? '-' + chan : '' )] ) {
    
    //node.warn('found with chan #')
    deviceid = deviceid + ( chan !== undefined ? '-' + chan : '' )
    name = deviceids[deviceid].name
    
} else {
    
    // ==== UNKNOWN DEVICE - output to port #2 and stop ==== //
    global.set(`unknown_devices["${deviceid}"]`, {'topic': msg.topic, 'payload': msg.payload})
    msg.topic = `unknown/${msg.topic}`
    return [null, msg]
    
}

let thisdev = devices[name]

//node.warn({deviceid, name, thisdev})

// ======== Update operational data to known_devices ======= //

{ // Status
    if ( ! thisdev.hasOwnProperty('status') ) thisdev.status = {}

    if ( msg.status ) {
        
        if (msg.status.rssi) thisdev.status.rssi = msg.status.rssi
        if (msg.status.battery) thisdev.status.battery = msg.status.battery
        
    }
    
    thisdev.status.updated = updated
    thisdev.status.updated_by = 'nrmain/Devices/rfx-in/fn'
}

if ( thisdev.sensors ) {
    thisdev.sensors.forEach( sensor => {
        switch (sensor) {
            case 'switch': {
                thisdev = inputSwitches(thisdev, msg)
                break
            }

            default: {
                thisdev = outputs(sensor, thisdev, msg)
                break
            }
        }
    })
}

// Save
global.set('known_devices', devices, storeName)

//return [msg, null]
return [{topic: `known_devices/${thisdev.name}`, payload: thisdev}, null]


/** If device has switches (input switches/buttons), process them - also update MQTT
 * NB: PIR & Mag sensors don't have buttons but are still treated as having a single switch
 * @param {Object} thisdev The known_devices object for the current dev
 * @param {Object} msg The incoming msg ojbect
 * @returns {Object} Updated thisdev
 */
function inputSwitches(thisdev, msg) {
    // How long should the switches prop be?
    // We are assuming this is only called for a device with switches
    let swlen = 1
    if (thisdev.controls) swlen = thisdev.controls

    // Make sure we have a switches prop
    if ( ! thisdev.switches ) thisdev.switches = {}
    { // And make it the right size (keys are integer strings)
        // If it is too small, make it bigger
        let currlen = Object.keys(thisdev.switches).length
        if ( currlen < swlen ) {
            if ( currlen === 0 ) currlen = 1
            for (let i = currlen; i <= swlen; ++i) {
                thisdev.switches[i] = {} // Fill with empty objects
            }
        }
        // if it is too big, make it smaller
        if ( currlen > swlen ) {
            for (let i = swlen; i <= currlen; --i) {
                delete thisdev.switches[i]
            }
        }
    }
    
    // Which switch do we need to update?
    let currSw = 1
    if ( thisdev.controls ) { // Dev has buttons
        // We know which button from the incoming device channel
        if ( chan !== undefined ) currSw = chan
    }
    
    // Update the correct switch
    const rightSw = thisdev.switches[currSw]
    rightSw.state   = ''
    rightSw.updated = updated
    
    let lowerPayload = msg.payload
    try { lowerPayload = msg.payload.toLowerCase() } catch (e) { }
    
    if ( lowerPayload === 'on' || lowerPayload === 1 || lowerPayload === '1' || lowerPayload === true ) {
        
        // Going on so calculate how long the switch was off
        if ( rightSw.last_off ) {
            // @ts-ignore
            rightSw.off_duration = updated - rightSw.last_off
        }
        
        rightSw.last_on = updated
        rightSw.state = 'On'
        
    } else if ( lowerPayload === 'off' || lowerPayload === 0 || lowerPayload === '0' || lowerPayload === false ) {
        
        // Going off so calculate how long the switch was on
        if ( rightSw.last_on ) {
            // @ts-ignore
            rightSw.on_duration = updated - rightSw.last_on
        }
        
        rightSw.last_off = updated
        rightSw.state = 'Off'
        
    } else {
        
        rightSw.state = msg.payload
        
    }
    
    // Send the switch output to MQTT
    node.send([null, null, {
        'topic': `CONTROLS/${thisdev.name}/${currSw}`,
        payload: msg.payload,
    }])
    node.send([null, null, {
        'topic': `CONTROLS/${thisdev.name}/${currSw}/updated_by`,
        payload: 'nrmain/Devices/rfx-in/fn',
    }])
    node.send([null, null, {
        'topic': `CONTROLS/${thisdev.name}/${currSw}/updated`,
        payload: updated,
    }])

    return thisdev
    
} // --- End of switches() --- //

/** Process sensors that aren't switches
 * @param {string} sensor - Name of the sensor being processed
 * @param {Object} thisdev The known_devices object for the current dev
 * @param {Object} msg The incoming msg ojbect
 * @returns {Object} Updated thisdev
 */
function outputs(sensor, thisdev, msg) {
    if ( ! thisdev.outputs ) thisdev.outputs = {}

    let payload = msg.payload
    
    if (payload.constructor === Object) {
        // payload is an object, look for an appropriate value
        if ( payload[sensor] ) {
            // is payload.<sensor> an object?
            if ( payload[sensor].constructor === Object ) {
                // does it have a `value` prop?
                if ( payload[sensor].value ) thisdev.outputs[sensor] = payload[sensor].value
                // if not, give up
            } else {
                // payload.<sensor> not an object, assume it is the value
                thisdev.outputs[sensor] = payload[sensor]
            }
            
        } else {
            // What else can we realistically look for?
            // give up
        }
        
    } else {
        /** translate on/off payload to 1/0 */
        if (sensor === 'movement') {
            let lowerPayload = payload
            try { lowerPayload = payload.toLowerCase() } catch (e) { }
            if ( lowerPayload === 'on' || payload === 1 || payload === '1' || payload === true ) {
                payload = 1
            } else {
                payload = 0
            }
        }

        // Assuming a simple value
        thisdev.outputs[sensor] = payload
    }
    
    return thisdev
}   // ---- End of outputs ---- //

// EOF

The topmost flow keeps the raw data data for reference. Not really needed but doesn't really cost anything.

image

Well yes, since I use some old lightwave remotes to switch things that might be on WiFi or Zigbee (Not using any of the old Lightwave smartplugs any more). But the reason for using MQTT is to decouple the inputs from the outputs.

So to switch an outlet on/off, I listen for the appropriate controller switch being pressed (though could equally be CRON+ or something else sending a signal instead of good old-fashioned user input) and output the appropriate message. Here is an example of the flow I'm currently using to control the light (a table lamp) in the front-hall:

Well, you can probably tell that I don't really do "simple"! :grinning:

The simplest flows I have that still use 433MHz are these:

Both of these are on my "Warnings" tab. They listen for the front-door bell or the mag sensor on the front door and send a message to the separate flow I have that formats and sends on the message to Telegraph so that I get it on my phone.


The important thing is to try to decouple everything. That way, you can more easily break the problem down into independent sections.

  1. Get some useful input - maybe from a control switch - send that to MQTT
  2. Set a flow to listen to the MQTT message from 1 and output to a smartplug
  3. If needed setup another flow to listen and send a message to your mobile or a web page or wherever.

So as you are setting up #2 for example, you can simply start by triggering a message from within Node-RED and then when you know that you can actually turn on/off the plug, you can then wire to an MQTT input.

Thank you Julian for all the effort and information you have provided here. I'm starting to understand your setup.
I thought I would start with the simple flow (like example 2) and publish an Off command with MQTT explorer, but that's where things go wrong.

flows (4).json (2.9 KB)

What is meant by the "Raw data"?

I'm afraid that I've never used that node, I don't have any of those devices. I think that it means you have to define the data property with hex data that the device expects to receive?

And that in itself might complicate the definition of the payload that is sent via MQTT and then eventually needs to be decoded/splitted up after the MQTT in node

All I know is that the bitstream itself, filled in as payload, is correct. If I send this under Windows I can switch the power outlet on/off (tested in Windows).

I see, I'll poke around some more, thank you both for your input.

It looks like you have a problem with your device list. The basic idea is that the node translates between the topic & payload specified in the first two columns of the device list, to the raw data and pulse width time shown in the second two columns.

PT2262-in nodes look up the raw data received from the RFXtrx, and if they find a match, output a message with the matching topic & payload.

PT2262-out nodes look up the topic & payload combination of the incoming message, and if they find a match, tell the RFXtrx to transmit using the matching raw data and pulse width. The error message you highlighted above is telling us that the device list did not contain an entry that matched the topic PT2262/8913003411A8BC012970/11A80C and payload Off.

Try editing your device list to look like this:

(Although I think you may have got the raw data values wrong, as they don't match the binary data you had in your original flow. I think it should be 0x11a80e for On and 0x11a80d for Off.)

Change your inject node as below, and hopefully it should work. Or at least get you closer to a working flow:

1 Like

Great help Max, I can switch on/off the device now :+1: but there is another thing, I don't see debug messages in the debug pane?

image

You need to change the pattern to be matched to the topic of the matching device list entries, i.e. PT2262/radiator.

The PT2262-in node looks up the incoming raw data in its device list, and if it finds a match converts it to the corresponding topic & payload. Then, if in only listen for addresses matching a pattern mode, it will check if the pattern matches the incoming topic, or a leading subset of the incoming topic. If it does, the message is output, otherwise it is dropped.

If the device list contains no match for the incoming raw data, pattern matching is skipped, and the output message contains no topic or payload, but instead the raw data (and pulse width)

Nice, I've changed the PT2262-in node but I still don't see my messages if I switch the device on/off, but I do receive messages from "Unknown" devices I guess?

The raw data in those messages doesn’t match any device list entries, so they don’t get replaced with topic & payloads. It may be your radiator is one of those PT2262-alikes that use the same modulation pattern but have a rolling code, that changes after each message, or two messages. I have a wireless doorbell like that

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.