Node red multi-line status

I have a fully updated Nod-Red – don’t know if that makes a difference but I’m not seeing that size option

So do I :sunglasses:
..and using this flow;

[{"id":"79ab3bbc.27c244","type":"inject","z":"31e18edc.98bdc2","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":160,"y":630,"wires":[["40c5e58c.eeefec"]]},{"id":"40c5e58c.eeefec","type":"function","z":"31e18edc.98bdc2","name":"","func":"msg.payload = \"this\\nis\\non\\nmultiple\\nlines\"\nnode.warn(msg.payload)\n\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":630,"wires":[[]]}]

I get;

print

I stand corrected Paul – your flow DOES work – I must’ve made a mistake..– however, this is not a solution, you have to expand EVERY time - not much use on a page with 50 nodes firing stuff out while debugging.. I don’t know why the Node Red guys are dead set against using the area below a function for inline multiline debugging.. you would not have to use it if you didn’t want it….and if we had html we could use a really small font..

The solution you have would be ok if you did not have to manually expand every time, and even better without the particularly cryptic node name above… do people really hold names like 6b65 ac79.68e354 in their heads?

Oh well, I guess I’ll keep looking for answers…

Pete

If you give the function node a name, such as 'Test node' you will get;

image

Well you can pin stuff open but in general I agree.

I use the Vivaldi browser which lets you combine tabs into a split view. Useful sometimes.

??? Not sure how that applies.

Node.warn statements send their output not only to the debug pane but also to the log.
A technique I have used when I have complex diagnostics to follow is to give the function node a name and use node.warn to output the diagnostics. Then in a terminal run
tail -f /var/log/syslog | grep "function name"
The result is that the diagnostics are output to the terminal window and can therefore be watched at leisure, scrolled back over easily, and so on. Debug nodes can also be set to send to the terminal in which case they will appear there too.

That sounds useful Colin - I'll give that a shot. Yes, my bad.. my function node had a horrible name because I didn't actually give it a name. I should know better. Node-Red is on a headless PI in my case and I'm working on my PC, so maybe WinSCP to the log wherever that is might be worth looking at if it saves having to interact with the output.

No, actually with a function node called "my thing" outputting "this\nthat\nother" I just looked at the log exactly as your suggestion.

Mar 10 10:11:36 raspberry-two Node-RED[388]: 10 Mar 10:11:36 - [warn] [function:my thing] t his

No sign of "that or "other"

pi@raspberry-two:~:10:13[130]> tail -f /var/log/syslog | grep "my thing"
Mar 10 10:11:36 raspberry-two Node-RED[388]: 10 Mar 10:11:36 - [warn] [function:my thing] this
Mar 10 10:14:26 raspberry-two Node-RED[388]: 10 Mar 10:14:26 - [warn] [function:my thing] this
Mar 10 10:14:46 raspberry-two Node-RED[388]: 10 Mar 10:14:46 - [warn] [function:my thing] this
Mar 10 10:14:47 raspberry-two Node-RED[388]: 10 Mar 10:14:47 - [warn] [function:my thing] this
Mar 10 10:14:48 raspberry-two Node-RED[388]: 10 Mar 10:14:48 - [warn] [function:my thing] this
Mar 10 10:14:51 raspberry-two Node-RED[388]: 10 Mar 10:14:51 - [warn] [function:my thing] this

I can see the whole message in the degug window - but only the first word in the log output.

and it isnt truncating as the phrase "this is it you know" comes out, nothing after the "\n" though.

The other lines are there, but they haven't got the function name in them Try
tail -f /var/log/syslog | grep -A 2 "function name"
That will show the next two lines too.

Alternatively you could just use
node-red-log
which will show all the node red messages.

Already figured I'm chasing the holy grail and am likely to be disappointed. Didn't you at some point do a Node-Red dashboard debug window - a long time ago? I'm looking for multi-line output from a function node - and without using the debug window... I'm chatting with Colin....see elsewhere in here

Better – but it ends up looking like 3 messages – an ENTER after the “[function:things]” would be wonderful and no date on successive lines?

Mar 10 10:44:48 raspberry-two Node-RED[388]: 10 Mar 10:44:48 - [warn] [function:things] this and

Mar 10 10:44:48 raspberry-two Node-RED[388]: that and

Mar 10 10:44:48 raspberry-two Node-RED[388]: more

Like this?

Mar 10 10:44:48 raspberry-two Node-RED[388]: 10 Mar 10:44:48 - [warn] [function:things]

this and

that and

more

Anyway I'm missing the point which was to avoid output to the debug window.. it sends to the log as well as the debug window... not sure if that's configurable...

Certainly an awk command could be written to massage the log output to the format you want, so then you can do
node-red-log | awk 'some clever awk stuff'
to give you exactly what you want.

Thtanks Colin - when I figure out how to do clever stuff with AWK I'll be sure to pass the result back :slight_smile:

I have done similar things with it a few times, but not often enough to produce the answer off the top of my head.

Good memory - yes I did and it is still on the flows site. I don't use it any more however, not because it doesn't work, but because - with uibuilder - I have a much easier and more efficient way to build a web page for something like that. In fact, if you look in the WIKI, you will see a method called "syntaxHighlight" in most of the examples - that produces formatted output for JSON and I can use it to show the incoming/outgoing messages on the example pages. Of course, you can use it for anything you like.

Urg, I think you would have to poll the log for that and it would be horribly inefficient I would think. OK for a one-off but not for ongoing.

If you want to take that route, I would create a sub-flow that outputs to a file and then send what you want to it.

But overall, I think the best approach is something like my original debug page that Pete mentions - that was produced before all the clever dashboards and ui's we have access to now but it does the job, just not as efficiently as you could now. It does, however, keep multiple entries on screen dynamically based on topic so that it is easy to show multiple outputs. It only keeps the last output for each topic though as that was what I wanted at the time. It would be easy enough to adapt though.

Maybe I should take some time out from uibuilder v2 and create a debug output example for uibuilder?

So, I have a quick and dirty example using uibuilder and the (current) default jQuery template. Not terribly pretty but hopefully you can see the basics:

index.js

/*global document,$,window,uibuilder */
/*
  Copyright (c) 2017 Julian Knight (Totally Information)

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/
'use strict'

function syntaxHighlight(json) {
    json = JSON.stringify(json, undefined, 4)
    json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
        var cls = 'number'
        if (/^"/.test(match)) {
            if (/:$/.test(match)) {
                cls = 'key'
            } else {
                cls = 'string'
            }
        } else if (/true|false/.test(match)) {
            cls = 'boolean'
        } else if (/null/.test(match)) {
            cls = 'null'
        }
        return '<span class="' + cls + '">' + match + '</span>'
    })
}

$( document ).ready(function() {
    // Keeping track of received topics
    var topics = {}

    // Turn on debugging for uibuilderfe (default is off)
    uibuilder.debug(true)

    uibuilder.onChange('msg', function(newVal){
        //console.info('indexjs:msg: property msg has changed! ', newVal)

        // keep track of inbound topics
        if ( (newVal.topic !=='') && (newVal.topic !== undefined) ) {
            var encodedTopic = encodeURIComponent(newVal.topic).replace(/\%/g,'')
            // Existing topic?
            if ( newVal.topic in topics ) {
                // update count
                topics[newVal.topic].count++
                // update display
                $('#t' + encodedTopic).html(syntaxHighlight(newVal))
            } else { // new topic
                // add to obj
                topics[newVal.topic] = {'count': 0, 'data': newVal}
                // add to list
                $('#topicList').append('<li><a href="#t' + encodedTopic + '">' + newVal.topic + '</a></li>')
                // add to display
                $('#debug').append('<a href="#t' + encodedTopic + '"></a><h2>' + newVal.topic + '</h2><pre id="t' + encodedTopic + '">' + syntaxHighlight(newVal) + '</pre>')
            }
        }

    })
}) // --- End of JQuery Ready --- //

// EOF

index.html

<!doctype html><html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes">
    <title>uibuilder - Debug (jQuery version)</title>
    <meta name="description" content="uibuilder - Debug (jQuery version)">
    <link rel="icon" href="./images/node-blue.ico">
    <link rel="stylesheet" href="./vendor/normalize.css/normalize.css">
    <link rel="stylesheet" href="./index.css">
</head>
<body>
    <div id="app">
        <div id="topicList"><ul></ul></div>
        <div id="debug"></div>
    </div>

    <script src="/uibuilder/socket.io/socket.io.js"></script>
    <script src="./vendor/jquery/dist/jquery.min.js"></script>
    <script src="./uibuilderfe.min.js"></script>
    <script src="./index.js"></script>
</body></html>

index.css

body {font-family: sans-serif;}
div, p, code { margin:0.3em; padding: 0.3em;}

pre .string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }

Example flow

[{"id":"df2a6744.0f2088","type":"uibuilder","z":"18cb249f.38bafb","name":"jDebug","topic":"","url":"jdebug","fwdInMessages":false,"allowScripts":false,"allowStyles":false,"debugFE":false,"copyIndex":true,"x":410,"y":760,"wires":[[],[]]},{"id":"889953a1.0152e","type":"inject","z":"18cb249f.38bafb","name":"","topic":"devices/01/ab/02","payload":"{\"Oregon\":{\"location\":\"Patio\",\"source\":\"RFX\",\"sensors\":\"TH\",\"type\":\"Sensor\",\"description\":\"Oregon Scientific Temperature/Humidity Sensor\"},\"TH1/0x7D01\":{\"location\":\"Patio\",\"source\":\"RFX\",\"sensors\":\"TH\",\"type\":\"Sensor\",\"description\":\"Oregon Scientific Temperature/Humidity Sensor\"},\"SRF/UNO1\":{\"location\":\"Loft\",\"source\":\"SRF\",\"sensors\":\"THPL\",\"type\":\"Sensor\",\"description\":\"Arduino with Temperature, Humidity, Pressure and Light Sensors\"},\"ARD/UNO1\":{\"location\":\"Loft\",\"source\":\"SER\",\"sensors\":\"THPL\",\"type\":\"Sensor\",\"description\":\"Arduino with Temperature, Humidity, Pressure and Light Sensors\"},\"ARD/NANO1\":{\"location\":\"Loft\",\"source\":\"SER\",\"sensors\":\"THL\",\"type\":\"Sensor\",\"description\":\"Arduino with Temperature, Humidity and Light Sensors\"},\"HOMEEASY_EU/0x000081C0\":{\"location\":\"Landing\",\"source\":\"RFX\",\"sensors\":\"M\",\"type\":\"PIR\",\"description\":\"Home Easy PIR\",\"AKA\":\"AC/0x0000A9F8\"},\"LIGHTWAVERF/0xF4C95B\":{\"location\":\"Cellar Head\",\"source\":\"RFX\",\"sensors\":\"M\",\"type\":\"Mag\",\"description\":\"Siemens Magnetic Door Sensor\",\"AKA\":\"Freezer\"},\"LIGHTWAVERF/0xF4C36F\":{\"location\":\"Front Hall\",\"source\":\"RFX\",\"sensors\":\"M\",\"type\":\"Mag\",\"description\":\"Siemens Magnetic Door Sensor\"},\"LIGHTWAVERF/0xF2D8D7\":{\"location\":\"Landing\",\"source\":\"RFX\",\"sensors\":\"S\",\"type\":\"Remote\",\"description\":\"Siemens White 4 Channel Remote Control\"},\"LIGHTWAVERF/0xF30F69\":{\"location\":\"Loft\",\"source\":\"RFX\",\"sensors\":\"S\",\"type\":\"Remote\",\"description\":\"Siemens White 4 Channel Remote Control\"},\"LIGHTWAVERF/0xF55E26\":{\"location\":\"Loft\",\"source\":\"RFX\",\"sensors\":\"S\",\"type\":\"Remote\",\"description\":\"Siemens Black 4 Channel Remote Control\"},\"HOMEEASY_EU/0x00024404\":{\"location\":\"Front Hall\",\"source\":\"RFX\",\"sensors\":\"S\",\"type\":\"Remote\",\"description\":\"Home Easy dual remote control\",\"AKA\":\"AC/0x000247C4\"},\"AC/0x00C77BAA\":{\"location\":\"Front Hall\",\"source\":\"RFX\",\"sensors\":\"S\",\"type\":\"Bell\",\"description\":\"Nexa Doorbell, not in use\"},\"SELECT_PLUS/0x005AE0\":{\"location\":\"Front Hall\",\"source\":\"RFX\",\"sensors\":\"S\",\"type\":\"Bell\",\"description\":\"1ByOne Doorbell\"},\"SP01\":{\"location\":\"Loft Main\",\"source\":\"LAN\",\"sensors\":\"ES\",\"type\":\"Sensor, Smart Switch\",\"description\":\"Edimax SP2101W Smartswitch with energy monitor\"},\"D1M01\":{\"location\":\"NA\",\"source\":\"LAN\",\"sensors\":\"\",\"type\":\"Sensor\",\"description\":\"Wemos D1-mini\"},\"D1M02\":{\"location\":\"Rear Hall\",\"source\":\"LAN\",\"sensors\":\"THL\",\"type\":\"Sensor\",\"ipAddress\":\"192.168.1.152\",\"description\":\"Wemos D1-mini with Temperature, Humidity and Light\"},\"D1M03\":{\"location\":\"NA\",\"source\":\"LAN\",\"sensors\":\"\",\"type\":\"Sensor\",\"description\":\"Wemos D1-mini\"},\"D1M04\":{\"location\":\"Landing\",\"source\":\"LAN\",\"sensors\":\"TH\",\"type\":\"Sensor\",\"ipAddress\":\"192.168.1.187\",\"description\":\"Wemos D1-mini with Temperature, Humidity\"},\"D1M05\":{\"location\":\"Living Room\",\"source\":\"LAN\",\"sensors\":\"THL\",\"type\":\"Sensor\",\"ipAddress\":\"192.168.1.188\",\"description\":\"Wemos D1-mini with Temperature, Humidity and Light\"},\"Sonoff_073412\":{\"location\":\"Loft Main\",\"source\":\"LAN\",\"sensors\":\"S\",\"type\":\"Smart Switch\",\"description\":\"Sonoff Wi-Fi smart switch\"},\"POW1\":{\"location\":\"Patio\",\"source\":\"LAN\",\"sensors\":\"ES\",\"type\":\"Sensor, Smart Switch\",\"ipAddress\":\"192.168.1.159\",\"mac\":\"5c:cf:7f:20:dc:4d\",\"description\":\"Sonoff POW Wi-Fi smart switch\"},\"Pi2NR-LIVE\":{\"location\":\"Loft Main\",\"source\":\"LAN\",\"type\":\"Node-RED on Pi2\",\"ipAddress\":\"192.168.1.167\",\"description\":\"Node-RED on Pi2\"},\"Pi3NR-LIVE\":{\"location\":\"Loft Main\",\"source\":\"LAN\",\"type\":\"Node-RED on Pi3\",\"ipAddress\":\"192.168.1.169\",\"description\":\"Node-RED on Pi3\"}}","payloadType":"json","repeat":"5","crontab":"","once":true,"onceDelay":0.1,"x":250,"y":680,"wires":[["8c7b3d33.6e8aa"]]},{"id":"9d9fe6c2.35d2e8","type":"link in","z":"18cb249f.38bafb","name":"jDebug","links":["8c7b3d33.6e8aa"],"x":260,"y":760,"wires":[["df2a6744.0f2088"]]},{"id":"8c7b3d33.6e8aa","type":"link out","z":"18cb249f.38bafb","name":"To-jDebug","links":["9d9fe6c2.35d2e8"],"x":440,"y":680,"wires":[]},{"id":"d6b034cb.7ef188","type":"inject","z":"18cb249f.38bafb","name":"","topic":"devices.switches","payload":"{\"SWITCH09\":{\"id\":\"SWITCH09\",\"status\":\"Off\",\"lastUpdate\":\"2019-01-13T23:00:08.720Z\",\"room\":\"Loft Main\"},\"SWITCH02\":{\"id\":\"SWITCH02\",\"status\":\"On\",\"lastUpdate\":\"2019-01-13T13:01:22.383Z\",\"room\":\"Rear Hall\"},\"SWITCH03\":{\"id\":\"SWITCH03\",\"status\":\"On\",\"lastUpdate\":\"2019-01-13T23:37:57.831Z\",\"room\":\"Front Hall\"},\"SWITCH04\":{\"id\":\"SWITCH04\",\"status\":\"On\",\"lastUpdate\":\"2019-01-13T13:01:22.386Z\",\"room\":\"Landing\"},\"SWITCH05\":{\"id\":\"SWITCH05\",\"status\":\"On\",\"lastUpdate\":\"2019-01-13T23:37:57.833Z\",\"room\":\"NA\"},\"SWITCH06\":{\"id\":\"SWITCH06\",\"status\":\"On\",\"lastUpdate\":\"2019-01-13T13:01:22.386Z\",\"room\":\"NA\"},\"SWITCH01\":{\"id\":\"SWITCH01\",\"status\":\"On\",\"lastUpdate\":\"2019-01-13T23:37:57.834Z\",\"room\":\"Living Room\"},\"SWITCH07\":{\"id\":\"SWITCH07\",\"status\":\"Off\",\"lastUpdate\":\"2019-01-13T13:01:22.387Z\",\"room\":\"NA\"},\"SWITCH08\":{\"id\":\"SWITCH08\",\"status\":\"Off\",\"lastUpdate\":\"2019-01-13T13:01:22.388Z\",\"room\":\"NA\"},\"SWITCH10\":{\"id\":\"SWITCH10\",\"status\":\"OFF\",\"lastUpdate\":\"2019-01-13T23:30:01.176Z\",\"room\":\"Patio\"},\"SWITCH11\":{\"id\":\"SWITCH11\",\"status\":\"Off\",\"lastUpdate\":\"2019-01-13T13:01:22.390Z\",\"room\":\"Loft Main\"}}","payloadType":"json","repeat":"6","crontab":"","once":true,"onceDelay":"0.4","x":250,"y":640,"wires":[["8c7b3d33.6e8aa"]]}]

UPDATE: If anyone is interested, I also have another example using VueJS which is a bit nicer.

I am interested.. can you post it

1 Like

Better late than never I guess!

I've now posted a flow that illustrates a message debug page using uibuilder and VueJS.

It is very simple but could easily be expanded.

https://flows.nodered.org/flow/2cefa818970963b7fb79a48929538e53