Node red multi-line status

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

it here, multi line in status.
image

Hi @datdp, is this post relavent to this old thread? If not, could you please delete it?

Thanks.

image
@TotallyInformation I thinks this post relavent to this thread

Hi @datdp,
Thanks for developing this node and sharing with us!!
It is certainly related for sure. But perhaps it is better if you "announce" a new node in a new discussion, that is 100% dedicated to your node. Instead of responding to a very old discussion.
I'm pretty sure that there will be a discussion. For example: do you show scrollbars for large messages, to avoid filling up the entire flow editor, and so on...
But I´m pretty sure that I am going to use it a lot :wink:
Bart

2 Likes

Looks useful BUT on a dark Node-Red background - you can't see the information. I thought it was bust until I looked very carefully.

1 Like

The JASON version of this is GREAT - but if I uwe an inject node injecting a string (tell me if I'm missing something) - along the lines of "hello\nthere" - thats what I get out - not 2 lines with "hello" on the first line and "there" on the second line... all without the quotes of course

The inject node will interpret that as exactly what you type it won't use the \ as an escape character/ (Internally it will be hello\\nthere - (ie it will auto escape the \ to be \) - so yes you need to use json inject.

Or indeed use a function node - that handles the backslash N correctly to get multiline out - as I just realised... thanks DCJay.

2 Likes