This isn't really the "production" flow, just an attempt to make this presentable. The injection nodes are simulations of the messages received from the other hardware controller. If you click the Injection Node "SB-A" (simulating receipt of a message), the browser console indicates there is an issue around line 27 of index.js. I think that's at least part of the issue.
If you click a line in one of the tables, it should open an editable form. On save, it will send (uibuilder.send) the edited object to the debug node. In production, the json object would be sent to the the other controller. The other controller would process the update, and return the updated result to this Node Red. This returned result is what the injection node mentioned above is simulating.
I've been trying different things all day, but so far no joy. Any advice would be appreciated. My "production" version is behaving similarity, but I can attest that the other hardware device is sending and receiving the json messages as expected.
Edit: Improved the Flow. Issue may be related to data types
[
{
"id": "773898f99a74b037",
"type": "tab",
"label": "PLC Simulator",
"disabled": false,
"info": "",
"env": []
},
{
"id": "74c68d52933ac6d0",
"type": "inject",
"z": "773898f99a74b037",
"name": "PLC-A",
"props": [
{
"p": "plc_in",
"v": "{\"x\":1}",
"vt": "json"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "plc_in",
"x": 150,
"y": 320,
"wires": [
[
"2a41e072020d15db"
]
]
},
{
"id": "2a41e072020d15db",
"type": "uibuilder",
"z": "773898f99a74b037",
"name": "haConfig",
"topic": "",
"url": "haConfig",
"fwdInMessages": false,
"allowScripts": false,
"allowStyles": false,
"copyIndex": true,
"templateFolder": "blank",
"extTemplate": "",
"showfolder": false,
"useSecurity": false,
"sessionLength": 432000,
"tokenAutoExtend": false,
"reload": true,
"sourceFolder": "src",
"x": 540,
"y": 340,
"wires": [
[
"76d13b2ea2efec56",
"42846a895b17d58e"
],
[
"c0e0b076ef3de7e5",
"bc4f4c2422b1b7b3"
]
]
},
{
"id": "4fde8d8c6d5ecfc5",
"type": "inject",
"z": "773898f99a74b037",
"name": "SB-A",
"props": [
{
"p": "sbanks",
"v": "{\"id\":1,\"zone\":1,\"config\":1,\"sw-a\":0,\"sw-b\":0,\"sw-c\":0}",
"vt": "json"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "sbanks",
"x": 150,
"y": 180,
"wires": [
[
"d7e75187777ab46a"
]
]
},
{
"id": "c0e0b076ef3de7e5",
"type": "function",
"z": "773898f99a74b037",
"name": "get Global Data",
"func": "if (msg.uibuilderCtrl === \"ready for content\") {\n\n let newMsg = {}\n \n newMsg.scenes = global.get('tbSN_ex')\n newMsg.sbanks = global.get('tbSB_ex')\n \n newMsg.plc_in = {\"x\":997}\n newMsg._socketId = msg._socketId\n\n return newMsg\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 760,
"y": 440,
"wires": [
[
"2a41e072020d15db"
]
]
},
{
"id": "f2f69e79a7cb131e",
"type": "inject",
"z": "773898f99a74b037",
"name": "SN-B",
"props": [
{
"p": "scenes",
"v": "{\"id\":1,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":0,\"state\":1,\"bri\":15}",
"vt": "json"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "scenes",
"x": 150,
"y": 500,
"wires": [
[
"d15264bc8d4e844b"
]
]
},
{
"id": "f269242d834d9450",
"type": "inject",
"z": "773898f99a74b037",
"name": "SN-A",
"props": [
{
"p": "scenes",
"v": "{\"id\":1,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":0,\"state\":1,\"bri\":255}",
"vt": "json"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "scenes",
"x": 150,
"y": 460,
"wires": [
[
"d15264bc8d4e844b"
]
]
},
{
"id": "ef27294314e9b34c",
"type": "inject",
"z": "773898f99a74b037",
"name": "SB-B",
"props": [
{
"p": "sbanks",
"v": "{\"id\":1,\"zone\":1,\"config\":1,\"sw-a\":8,\"sw-b\":16,\"sw-c\":32}",
"vt": "json"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "sbanks",
"x": 150,
"y": 220,
"wires": [
[
"d7e75187777ab46a"
]
]
},
{
"id": "b12443af76aecf5b",
"type": "inject",
"z": "773898f99a74b037",
"name": "PLC-B",
"props": [
{
"p": "plc_in",
"v": "{\"x\":2}",
"vt": "json"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "plc_in",
"x": 150,
"y": 360,
"wires": [
[
"2a41e072020d15db"
]
]
},
{
"id": "d15264bc8d4e844b",
"type": "function",
"z": "773898f99a74b037",
"name": "set tbSN Global",
"func": "var tbSN_ex = global.get('tbSN_ex') || [];\n\nvar rID = msg.scenes.id;\nvar rData = msg.scenes\n\ntbSN_ex[rID] = rData;\n\nmsg.scenes = tbSN_ex;\nglobal.set('tbSN_ex',msg.scenes);\n\nnode.warn(msg)\n\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 340,
"y": 460,
"wires": [
[
"2a41e072020d15db",
"dc8a250d0b92de66"
]
]
},
{
"id": "d7e75187777ab46a",
"type": "function",
"z": "773898f99a74b037",
"name": "set tbSB Global",
"func": "var tbSB_ex = global.get('tbSB_ex') || [];\n\nvar rID = msg.sbanks['id'];\nvar rData = msg.sbanks\n\ntbSB_ex[rID] = rData;\n\nmsg.sbanks = tbSB_ex;\nglobal.set('tbSB_ex',msg.sbanks);\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 340,
"y": 220,
"wires": [
[
"2a41e072020d15db",
"cfe4e233376550f7"
]
]
},
{
"id": "334b9626184d7d2f",
"type": "function",
"z": "773898f99a74b037",
"name": "Init Global Data",
"func": "// var tbSB_ex = global.get('tbSB_ex') || [];\n// var tbSN_ex = global.get('tbSN_ex') || [];\n\n// msg.sbanks = [{\"id\":0,\"zone\":1,\"config\":1,\"sw-a\":0,\"sw-b\":0,\"sw-c\":0,\"layer\":1,\"state\":1},{\"id\":1,\"zone\":1,\"config\":2,\"sw-a\":16,\"sw-b\":0,\"sw-c\":0,\"layer\":1,\"state\":1}]\nglobal.set('tbSB_ex',msg.sbanks);\n\n// msg.scenes = [{\"id\":0,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":0,\"state\":0,\"bri\":0},{\"id\":1,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":0,\"state\":1,\"bri\":32},{\"id\":2,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":1,\"state\":0,\"bri\":0},{\"id\":3,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":1,\"state\":1,\"bri\":255},{\"id\":4,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":2,\"state\":0,\"bri\":0},{\"id\":5,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":2,\"state\":1,\"bri\":255},{\"id\":6,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":3,\"state\":0,\"bri\":0},{\"id\":7,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":3,\"state\":1,\"bri\":255},{\"id\":8,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":3,\"state\":2,\"bri\":64},{\"id\":9,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":2,\"state\":2,\"bri\":0}]\nglobal.set('tbSN_ex',msg.scenes);\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 380,
"y": 40,
"wires": [
[]
]
},
{
"id": "24edb6c2a8088861",
"type": "inject",
"z": "773898f99a74b037",
"name": "Initialize Global",
"props": [
{
"p": "sbanks",
"v": "[{\"id\":0,\"zone\":0,\"config\":0,\"sw-a\":0,\"sw-b\":0,\"sw-c\":0},{\"id\":1,\"zone\":1,\"config\":1,\"sw-a\":16,\"sw-b\":0,\"sw-c\":0},{\"id\":2,\"zone\":1,\"config\":2,\"sw-a\":18,\"sw-b\":0,\"sw-c\":0}]",
"vt": "json"
},
{
"p": "scenes",
"v": "[{\"id\":0,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":0,\"state\":0,\"bri\":0},{\"id\":1,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":0,\"state\":1,\"bri\":255},{\"id\":2,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":1,\"state\":0,\"bri\":0},{\"id\":3,\"zone\":1,\"layer\":1,\"type\":1,\"addr\":1,\"state\":1,\"bri\":255},{\"id\":4,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":2,\"state\":0,\"bri\":0},{\"id\":5,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":2,\"state\":1,\"bri\":255},{\"id\":6,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":3,\"state\":0,\"bri\":0},{\"id\":7,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":3,\"state\":1,\"bri\":255},{\"id\":8,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":3,\"state\":2,\"bri\":64},{\"id\":9,\"zone\":1,\"layer\":2,\"type\":1,\"addr\":2,\"state\":2,\"bri\":0}]",
"vt": "json"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 160,
"y": 40,
"wires": [
[
"334b9626184d7d2f"
]
]
},
{
"id": "76d13b2ea2efec56",
"type": "debug",
"z": "773898f99a74b037",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 710,
"y": 180,
"wires": []
},
{
"id": "bc4f4c2422b1b7b3",
"type": "debug",
"z": "773898f99a74b037",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 730,
"y": 480,
"wires": []
},
{
"id": "f023c1ac6c0ffb8e",
"type": "uibuilder",
"z": "773898f99a74b037",
"name": "simpUI",
"topic": "",
"url": "simpUI",
"fwdInMessages": false,
"allowScripts": false,
"allowStyles": false,
"copyIndex": true,
"templateFolder": "blank",
"extTemplate": "",
"showfolder": false,
"useSecurity": false,
"sessionLength": 432000,
"tokenAutoExtend": false,
"reload": false,
"sourceFolder": "src",
"x": 720,
"y": 40,
"wires": [
[],
[]
]
},
{
"id": "c1c09b47305fcc37",
"type": "delay",
"z": "773898f99a74b037",
"name": "Simulate PLC",
"pauseType": "delay",
"timeout": "2",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 1020,
"y": 240,
"wires": [
[
"f5d70e8d7b34610f"
]
]
},
{
"id": "0c08e60c2167e6a0",
"type": "link out",
"z": "773898f99a74b037",
"name": "simScenes",
"mode": "link",
"links": [
"0b561ac888045f28"
],
"x": 1375,
"y": 400,
"wires": []
},
{
"id": "f5d70e8d7b34610f",
"type": "switch",
"z": "773898f99a74b037",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "cfgSB",
"vt": "str"
},
{
"t": "eq",
"v": "cfgSN",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 1090,
"y": 320,
"wires": [
[
"ec57a858b905b980"
],
[
"b8909ecfb4b43f22"
]
]
},
{
"id": "93a7bd057735b52a",
"type": "link out",
"z": "773898f99a74b037",
"name": "simSBanks",
"mode": "link",
"links": [
"1badc681b25a2eec"
],
"x": 1375,
"y": 240,
"wires": []
},
{
"id": "0b561ac888045f28",
"type": "link in",
"z": "773898f99a74b037",
"name": "",
"links": [
"0c08e60c2167e6a0"
],
"x": 175,
"y": 420,
"wires": [
[
"d15264bc8d4e844b",
"6c1524772d0fd6f0"
]
]
},
{
"id": "1badc681b25a2eec",
"type": "link in",
"z": "773898f99a74b037",
"name": "",
"links": [
"93a7bd057735b52a"
],
"x": 175,
"y": 260,
"wires": [
[
"d7e75187777ab46a",
"7471422559690b51"
]
]
},
{
"id": "b84fc83364365663",
"type": "debug",
"z": "773898f99a74b037",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 1410,
"y": 320,
"wires": []
},
{
"id": "ec57a858b905b980",
"type": "change",
"z": "773898f99a74b037",
"name": "cfg SBanks",
"rules": [
{
"t": "move",
"p": "payload",
"pt": "msg",
"to": "sbanks",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1230,
"y": 280,
"wires": [
[
"93a7bd057735b52a",
"b84fc83364365663"
]
]
},
{
"id": "b8909ecfb4b43f22",
"type": "change",
"z": "773898f99a74b037",
"name": "cfg Scenes",
"rules": [
{
"t": "move",
"p": "payload",
"pt": "msg",
"to": "scenes",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1230,
"y": 360,
"wires": [
[
"0c08e60c2167e6a0",
"b84fc83364365663"
]
]
},
{
"id": "7471422559690b51",
"type": "debug",
"z": "773898f99a74b037",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 310,
"y": 260,
"wires": []
},
{
"id": "6c1524772d0fd6f0",
"type": "debug",
"z": "773898f99a74b037",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 310,
"y": 420,
"wires": []
},
{
"id": "42846a895b17d58e",
"type": "json",
"z": "773898f99a74b037",
"name": "",
"property": "payload",
"action": "",
"pretty": false,
"x": 710,
"y": 340,
"wires": [
[
"c1c09b47305fcc37"
]
]
},
{
"id": "dc8a250d0b92de66",
"type": "debug",
"z": "773898f99a74b037",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 530,
"y": 460,
"wires": []
},
{
"id": "cfe4e233376550f7",
"type": "debug",
"z": "773898f99a74b037",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 530,
"y": 220,
"wires": []
}
]
<!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">
<title>Node-RED UI Builder - Blank template</title>
<meta name="description" content="Node-RED UI Builder - Blank template">
<link rel="icon" href="./images/node-blue.ico">
<link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css" />
<link type="text/css" rel="stylesheet" href="./index.css" media="all">
</head>
<body>
<div id="app">
<b-card>Input: {{ plc_in }}</b-card>
<b-card-group>
<b-card bg-variant="light">
<b-form-group label="Select Zone">
<b-form-radio-group size="lg" buttons v-model="ftrZone">
<b-form-radio v-for="zone in zones" :value=zone :key="zone" inline>{{ zone }}</b-form-radio>
</b-form-radio-group>
</b-form-group>
<p>For Testing, Select Zone 1!</p>
</b-card>
<b-card bg-variant="light">
<p>Future Use</p>
</b-card>
</b-card-group>
<b-card bg-variant="light">
<b-tabs>
<b-tab lazy title="Switches">
<b-card bg-variant="default"
title="Switch Bank Edit">
<b-card-text>
<p>Add note</p>
<b-button variant="success" class="float-right mx-2" @click="saveSB">Save</b-button>
<b-btn varient="danger" class="float-right mx-2" @click="sbank = []">Reset</b-btn>
</b-card-text>
<!-- Switch Modify -->
<!-- requires sbank to be array, form (above) requires object -->
<b-table id = "tbSBedit"
striped hover small fixed outlined
thead-class="d-none"
:items="sbank"
caption="">
<template v-slot:cell()="cellData">
<b-form-input v-model="sbank[cellData.index][cellData.field.key]" type="number"></b-form-input>
</template>
</b-table>
<!-- Switch Table Header Only-->
<b-table id = "tbSBheader"
small fixed
tbody-class="d-none"
:items="ftrSBbyZN">
</b-table>
<!-- Switch Bank Table -->
<b-table id = "tbSBlist"
striped hover small fixed outlined
selectable select-mode="single"
thead-class="d-none"
:items="ftrSBbyZN"
@row-selected="selectSB">
</b-table>
</b-card>
</b-tab>
<b-tab v-for="tab in layers" :key="tab" lazy :title="`Layer `+tab">
<b-card bg-variant="default"
title="Scene Edit">
<b-card-text>
<p>Add note</p>
<b-button variant="success" class="float-right px-4 mx-2" @click="saveSN">Save</b-button>
<b-btn varient="danger" class="float-right px-4 mx-2" @click="scene = []">Reset</b-btn>
</b-card-text>
<!-- Scene Modify -->
<!-- requires scene to be array, form (above) requires object -->
<b-table id = "tbSNedit"
striped hover small fixed outlined
thead-class="d-none"
:items="scene"
caption="">
<template v-slot:cell()="cellData">
<b-form-input v-model="scene[cellData.index][cellData.field.key]" type="number"></b-form-input>
</template>
</b-table>
<!-- Scene Table Header Only-->
<b-table id = "tbSNheader"
small fixed
tbody-class="d-none"
:items="scenes">
</b-table>
<!-- Scene Table -->
<!-- First filter scene data by zone set in compute, then filter by later using b-table filter-->
<b-table id = "tbSNlist"
hover small fixed outlined
selectable select-mode="single"
thead-class="d-none"
:items="ftrSNbyZN"
:filter="tab" :filter-function="ftrSNLayer" sort-by="layer"
@row-selected="selectSN">
</b-table>
</b-card>
</b-tab>
<b-tab title="msg log">
<pre id="msg" class="syntax-highlight">Waiting for a message from Node-RED</pre>
</b-tab>
</b-tabs>
</b-card>
</div>
<script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
<script src="../uibuilder/vendor/vue/dist/vue.js"></script> <!-- dev version with component compiler -->
<script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script> <!-- Dev version -->
<script src="./uibuilderfe.min.js"></script>
<script src="./index.js"></script>
</body>
</html>
/* jshint browser: true, esversion: 6, asi: true */
/* globals uibuilder */
// @ts-nocheck
var app = new Vue({
el: '#app',
data: {
scenes: [{"id": 0,"zone": 0, "layer":0}], // init
sbanks: [{"id": 0,"zone": 0, "layer":0}], // init
plc_in: null, // init
ftrZone: [0],
scene: [], // needed so that table row will be editable on select
sbank: [], // needed so that table row will be editable on select
},
computed: {
zones: function () {
// compute unique zones
let izones = [0]; // leave 0 so there is always 0 zone available to select
let scenz = this.scenes; // ** this appears to sometimes be undefined **
console.info('czn', JSON.stringify(scenz))
// loop thru each scene to build array of zones
scenz.forEach(s => {
if (s != null) { izones.push(s.zone) }
})
// to-do: loop thru switch table
// create array of unique zone numbers
let uzones = [... new Set(izones)];
return uzones.sort();
},
layers: function () {
// compute unique layers in scene
let ilayers = [];
let scenz = this.scenes;
scenz.forEach(i => {
if (i != null) { ilayers.push(i.layer) }
});
let ulayers = [... new Set(ilayers)];
return ulayers;
},
ftrSNbyZN: function () {
//compute scenes, filtered by selected zone
let sbnk = this.sbanks; //even though this isn't necessary, without it the table doesnt react
let scenz = this.scenes;
let selectedSN = this.ftrZone;
fSNbyZN = scenz.filter(scene =>{
return scene.zone == selectedSN;
});
return fSNbyZN;
},
ftrSBbyZN: function () {
//compute sbanks, filtered by selected zone
let sbnk = this.sbanks;
let scenz = this.scenes; //even though this isn't necessary, without it the table doesnt react
let selectedSN = this.ftrZone;
fSBbyZN = sbnk.filter(bank =>{
return bank.zone == selectedSN;
});
return fSBbyZN;
},
},
methods: {
ftrSNLayer(row, filter) {
// filter scenes by layer for each table in layer tabs
// b-table filter takes 2 parameters, row and row filter. returns boolean
if (row.layer == filter) {
return true;
} else {
return false;
}
},
selectSN(selSN) {
// create new Object from selected scene to be edited
this.scene = [{...selSN[0]}];
},
saveSN(data) {
// save/send edited scene data
payload=JSON.stringify(this.scene[0])
uibuilder.send( {
'topic':'cfgSN',
'payload': payload
}
);
console.info('sent',payload) //debug!
},
selectSB(selSB) {
// create new Object from selected SBank to be edited
this.sbank = [{...selSB[0]}];
},
saveSB(data) {
// save/send edited SBank data
payload=JSON.stringify(this.sbank[0])
uibuilder.send( {
'topic':'cfgSB',
'payload': payload
}
);
},
},
})
/** Minimalist code for uibuilder and Node-RED */
// return formatted HTML version of JSON object
function syntaxHighlight(json) {
json = JSON.stringify(json, undefined, 4)
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
json = 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>'
})
return json
} // --- End of syntaxHighlight --- //
// run this function when the document is loaded
window.onload = function() {
// Start up uibuilder - see the docs for the optional parameters
uibuilder.start()
// Listen for incoming messages from Node-RED
uibuilder.onChange('msg', function(msg){
app.scenes=msg.scenes;
app.sbanks=msg.sbanks;
app.plc_in=msg.plc_in;
console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', msg)
// dump the msg as text to the "msg" html element
const eMsg = document.getElementById('msg')
eMsg.innerHTML = syntaxHighlight(msg)
})
}