Ok, this is the subflow
code:
(Well, the function
node in the subflow which is all that is in it anyway.)
// 2021 06 21
// Added extra line/s to send incoming message to another ouput
// when mis-match happens.
// 2020 12 24
// Added code to try and negate "node config not set" getting through. Line 96 and on.
//
// 2019 10 1 16:40
// Button_Press_scanner14b
//
// Added a line when configuring node with
// `SET_Device_ID`
//
// CHECK AROUND line 59 is commented out.
// Should NOT be setting 'online'
//
// Removed check if error is active if receiving ICSS == 5.
// Makes it easier to clear false alarms.
//
//
// Written now for SUBFLOW use.
// MUST have name injected to node with message.topic = "SET_Device_ID" and payload of devicename.
//
// Sends ERROR and ERROR_ACK messages to set icon if error happens.
// Holds colour of buttons to RED until ERROR_ACK button pressed.
//
// Node variables.
// Name of machine this button set applies.
// Tags needed:
// msg.device_ID (name of device)
// msg.state (state)
// msg.background (if machine state active)
var device = context.get('device')||0;
// new
// This locks the button colours if an alarm is received.
var block_change = context.get("BLOCK_CHANGE") ||0;
if (msg.topic == "SET_Device_ID")
{
node.warn("Setting node name");
node.warn(msg.payload);
context.set('device',msg.payload);
}
var msg2;
var msg3;
// Check if debug is enabled.
var debug = flow.get(device+'_Button_Debug') || false;
//node.warn("Debug set to " + debug);
// Background colour for button. Colour for OFF-LINE device status.
var backgroundcolour = context.get('background') || "brown";
// State This sets what is happening. See below.
var previous_state = context.get('state') || 0;
// State.
var ICSS = msg.state || 0;
//node.warn("Message state is " + ICSS);
// Used to signal machine shutting down.
var shutdown = context.get('shutdown') || 0;
// If machine is online or offline.
var online = context.get('online') || "Off-line"; // status of machine.
// Code for testing node.
//online = "On-line"; // Temporary line of code.
//node.warn("online state is " + online);
// I/C message variables.
var ICDID = msg.device_ID || 0;
//var ICDID = payload.DEVICE;
//node.warn("Device ID is " + ICDID);
// Set up stuff here.
// This may no longer be needed. Left in as precuation.
if (ICDID == "ALL")
{
ICDID = device;
if (debug === true)
{
node.warn("** Reset button colours **");
node.warn(msg.background);
}
previous_state = 4;
backgroundcolour = msg.background;
context.set("BLOCK_CHANGE",0);
block_change = 0;
}
if (ICDID != device)
{
// 2020 12 24 small addition here.
error_counter = context.get("error_counter") || 0;
error_counter = error_counter + 1;
context.set("error_counter",error_counter);
if (error_counter > 1)
{
node.warn("Node Configuration not set");
node.error("Node Configuration not set", msg)
// fa-eye-slash
return [null,null,null,msg];
}
}
// Main body here.
// Check device name.
if (ICDID == device)
{
context.set("error_counter",0); //2020 12 24
if (debug === true)
{
node.warn("*******************");
node.warn("** DEVICES MATCH **");
node.warn("Existing state is " + previous_state);
node.warn("Incoming state is " + ICSS);
node.warn("Line state is " + online);
node.warn("Shutdown is " + shutdown);
node.warn("Back ground colour is " + backgroundcolour);
node.warn("*******************");
}
// Check function name.
// Check things have changed.
if (previous_state !== ICSS)
{
// And they have.
// List of states:
// 0 - normal or command received and ok.
// 1 - command sent.
// 2 - command received.
// 3 - command error.
// 4 - device status changed.
// 5 - clear existing alarm. (Work needed)
// 6 - Shutdown command received.
//node.warn("Miss match detected");
// Check if ERROR is active.
if (ICSS == 5)
{
//
// if (previous_state == 3)
// {
// CLEAR ALARM button pressed.
context.set("BLOCK_CHANGE",0);
block_change = 0;
previous_state = 0;
//
//node.warn("Alarm clear signal received");
node.status({fill:"green",shape:"dot",text:"0"});
// This line was background:msg.background but failed.
// Changed to what it is now and all ok.
msg2 = {payload:"", background:"lime"};
msg3 = {payload:"ERROR_ACK",background:"lime"};
msg = null;
return [msg,msg2,msg3,null];
// }
}
if (block_change == 1)
{
//
// Don't allow any changes unless it is the "clear" signal.
//
return;
}
context.set('previous_state', ICSS); // save new state.
// previous_state = ICSS; // NEW PART 2019 12 24 Alamrs not clearing
// Check if state is 0.
if (ICSS === 0)
{
if(previous_state != 3)
{
// Button ready to be pressed.
node.warn("Command completed ok");
node.status({fill:"green",shape:"dot",text:"0"});
msg2 = { payload:"", background:msg.background};
msg3 = {payload:"ERROR_ACK",background:"lime"};
msg = null;
return [msg,msg2,msg3,null];
}
} else
if (ICSS == 1)
{
// Button is pressed. Command SENT.
// Need to check here if context 'online' is correct to allow button press.
node.warn("Button press phase 1");
if (online == "On-line")
{
node.status({fill:"grey",shape:"dot",text:"1"});
msg2 = { payload:"", background:"grey"};
if (debug === true)
{
node.warn("Button press detected");
node.warn("original message payload is " + msg);
}
}
return [msg,msg2];
} else
if (ICSS == 2)
{
// Command RECEIVED.
node.status({fill:"black",shape:"dot",text:"2"});
msg2 = { payload:"", background:"black"};
msg = null;
return [msg,msg2];
} else
if (ICSS == 3)
{
// Command ERROR.
node.status({fill:"red",shape:"dot",text:"3"});
msg2 = { payload:"", background:"red"};
msg = null;
context.set("BLOCK_CHANGE",1);
context.set('state',3);
//
// Third message to send to set icon
// md-error
msg3 = {payload:"ERROR"};
return [msg,msg2,msg3];
} else
if (ICSS == 4) ////////// MACHINE STATE CHANGED //////////////////
{
if(previous_state != 3)
{
if (debug === true)
{
// Update button colour.
node.warn("@@@@@@@@@@@@@@@@");
node.warn(device);
node.warn("Payload = " + msg.payload);
node.warn("Background colour -- " + msg.background);
node.warn("State changed");
}
context.set('background',msg.background);
// Indicate node changed.
node.status({fill:"yellow",shape:"dot",text:"4"});
msg2 = { payload:"", background:msg.background};
context.set('state', 0);
// Set online status.
if (msg.background == "lime")
{
//
if (shutdown == 0)
{
//node.warn("Online routine");
context.set('online',"On-line");
//backgroundcolour = "lime";
backgroundcolour = msg.background;
}
} else
//if (msg.background == "brown")
{
//
//node.warn("Offline routine");
context.set('online',"Off-line");
context.set('shutdown',0);
//backgroundcolour = "brown";
backgroundcolour = msg.background;
}
}
// 2021 06 21
//msg = null;
//return [msg,msg2];
return [null,msg2];
} else
if (ICSS == 6)
{
//
context.set('shutdown',1);
node.warn("********* Shutdown set to 1 *************");
context.set('online',"Off-line");
msg2 = { payload:"", background:"brown"};
// backgroundcolour = msg.background; // Dunno what this line is supposed to do.
//msg = null; // 2018-10-06 Added these two lines to fix problem of buttons not changing from BLACK.
//return [msg,msg2];
// 2021 06 21
return [null,msg2];
}
}
}
4
outputs.
Last one is (I hope) the original message sent in that causes/d the error.
I have tweaked the flow for better error handling - kinda.
(Don't ask)
Sorry it is spread out but that's how it is in the flow.
[{"id":"65d097c2.63a148","type":"subflow","name":"Button colour","info":"","category":"","in":[{"x":40,"y":80,"wires":[{"id":"b82d4d5a.5931d8"}]}],"out":[{"x":440,"y":60,"wires":[{"id":"b82d4d5a.5931d8","port":0}]},{"x":440,"y":110,"wires":[{"id":"b82d4d5a.5931d8","port":1}]},{"x":440,"y":160,"wires":[{"id":"b82d4d5a.5931d8","port":2}]},{"x":440,"y":210,"wires":[{"id":"b82d4d5a.5931d8","port":3}]}],"env":[],"color":"#DDAA99","outputLabels":["","background colour","text","Original message if mismatch"],"icon":"node-red-dashboard/ui_button.png","status":{"x":440,"y":270,"wires":[{"id":"bcf40ba9.50171","port":0}]}},{"id":"b82d4d5a.5931d8","type":"function","z":"65d097c2.63a148","name":"Button Colour 2020 12 24","func":"// 2021 06 21\n// Added extra line/s to send incoming message to another ouput\n// when mis-match happens.\n\n// 2020 12 24\n// Added code to try and negate \"node config not set\" getting through. Line 96 and on.\n//\n// 2019 10 1 16:40\n//\tButton_Press_scanner14b\n// \n// Added a line when configuring node with\n// `SET_Device_ID`\n//\n// CHECK AROUND line 59 is commented out.\n// Should NOT be setting 'online'\n//\n// Removed check if error is active if receiving ICSS == 5.\n// Makes it easier to clear false alarms.\n// \n//\n//\tWritten now for SUBFLOW use.\n//\tMUST have name injected to node with message.topic = \"SET_Device_ID\" and payload of devicename.\n//\n// Sends ERROR and ERROR_ACK messages to set icon if error happens.\n// Holds colour of buttons to RED until ERROR_ACK button pressed.\n//\n// Node variables.\n// Name of machine this button set applies.\n// Tags needed:\n//\tmsg.device_ID (name of device)\n//\tmsg.state (state)\n//\tmsg.background (if machine state active)\n\nvar device = context.get('device')||0;\n\n// new\n// This locks the button colours if an alarm is received.\nvar block_change = context.get(\"BLOCK_CHANGE\") ||0;\n\nif (msg.topic == \"SET_Device_ID\")\n{\n node.warn(\"Setting node name\");\n node.warn(msg.payload);\n context.set('device',msg.payload);\n}\n\n\nvar msg2;\nvar msg3;\n// Check if debug is enabled.\nvar debug = flow.get(device+'_Button_Debug') || false;\n//node.warn(\"Debug set to \" + debug);\n\n// Background colour for button. Colour for OFF-LINE device status.\nvar backgroundcolour = context.get('background') || \"brown\";\n\n// State This sets what is happening. See below.\nvar previous_state = context.get('state') || 0;\n// State.\nvar ICSS = msg.state || 0;\n//node.warn(\"Message state is \" + ICSS);\n\n//\tUsed to signal machine shutting down.\nvar shutdown = context.get('shutdown') || 0;\n\n// If machine is online or offline.\nvar online = context.get('online') || \"Off-line\"; // status of machine.\n\n// Code for testing node.\n//online = \"On-line\"; // Temporary line of code.\n\n//node.warn(\"online state is \" + online);\n\n// I/C message variables.\nvar ICDID = msg.device_ID || 0;\n//var ICDID = payload.DEVICE;\n//node.warn(\"Device ID is \" + ICDID);\n\n// Set up stuff here.\n// This may no longer be needed. Left in as precuation.\nif (ICDID == \"ALL\")\n{\n ICDID = device;\n if (debug === true)\n {\n node.warn(\"** Reset button colours **\");\n node.warn(msg.background);\n }\n previous_state = 4;\n backgroundcolour = msg.background;\n context.set(\"BLOCK_CHANGE\",0);\n block_change = 0;\n}\n\nif (ICDID != device)\n{\n // 2020 12 24 small addition here.\n error_counter = context.get(\"error_counter\") || 0;\n error_counter = error_counter + 1;\n context.set(\"error_counter\",error_counter);\n if (error_counter > 1)\n {\n node.warn(\"Node Configuration not set\");\n node.error(\"Node Configuration not set\", msg)\n // fa-eye-slash\n return [null,null,null,msg];\n }\n}\n\n// Main body here.\n// Check device name.\nif (ICDID == device)\n{\n context.set(\"error_counter\",0); //2020 12 24\n if (debug === true)\n {\n node.warn(\"*******************\");\n node.warn(\"** DEVICES MATCH **\");\n node.warn(\"Existing state is \" + previous_state);\n node.warn(\"Incoming state is \" + ICSS);\n node.warn(\"Line state is \" + online);\n node.warn(\"Shutdown is \" + shutdown);\n node.warn(\"Back ground colour is \" + backgroundcolour);\n node.warn(\"*******************\");\n }\n\n // Check function name.\n\n // Check things have changed.\n if (previous_state !== ICSS)\n {\n // And they have.\n // List of states:\n // 0 - normal or command received and ok.\n // 1 - command sent.\n // 2 - command received.\n // 3 - command error.\n // 4 - device status changed.\n // 5 - clear existing alarm. (Work needed)\n // 6 - Shutdown command received.\n \n //node.warn(\"Miss match detected\");\n \n // Check if ERROR is active.\n if (ICSS == 5)\n {\n //\n// if (previous_state == 3)\n// {\n // CLEAR ALARM button pressed.\n context.set(\"BLOCK_CHANGE\",0);\n block_change = 0;\n previous_state = 0;\n //\n //node.warn(\"Alarm clear signal received\");\n node.status({fill:\"green\",shape:\"dot\",text:\"0\"});\n // This line was background:msg.background but failed.\n // Changed to what it is now and all ok.\n msg2 = {payload:\"\", background:\"lime\"};\n msg3 = {payload:\"ERROR_ACK\",background:\"lime\"};\n msg = null;\n return [msg,msg2,msg3,null];\n\n// }\n }\n \n if (block_change == 1)\n {\n //\n // Don't allow any changes unless it is the \"clear\" signal.\n //\n return;\n }\n\n context.set('previous_state', ICSS); // save new state.\n// previous_state = ICSS; // NEW PART 2019 12 24 Alamrs not clearing\n // Check if state is 0.\n if (ICSS === 0)\n {\n if(previous_state != 3)\n {\n //\t\tButton ready to be pressed.\n node.warn(\"Command completed ok\");\n node.status({fill:\"green\",shape:\"dot\",text:\"0\"});\n msg2 = { payload:\"\", background:msg.background};\n msg3 = {payload:\"ERROR_ACK\",background:\"lime\"};\n msg = null;\n return [msg,msg2,msg3,null];\n }\n } else\n if (ICSS == 1)\n {\n //\t\tButton is pressed. Command SENT.\n // Need to check here if context 'online' is correct to allow button press.\n node.warn(\"Button press phase 1\");\n if (online == \"On-line\")\n {\n node.status({fill:\"grey\",shape:\"dot\",text:\"1\"});\n msg2 = { payload:\"\", background:\"grey\"};\n if (debug === true)\n {\n node.warn(\"Button press detected\");\n node.warn(\"original message payload is \" + msg);\n }\n }\n return [msg,msg2];\n } else\n if (ICSS == 2)\n {\n //\t\tCommand RECEIVED.\n node.status({fill:\"black\",shape:\"dot\",text:\"2\"});\n msg2 = { payload:\"\", background:\"black\"};\n msg = null;\n return [msg,msg2];\n } else\n if (ICSS == 3)\n {\n //\t\tCommand ERROR.\n node.status({fill:\"red\",shape:\"dot\",text:\"3\"});\n msg2 = { payload:\"\", background:\"red\"};\n msg = null;\n context.set(\"BLOCK_CHANGE\",1);\n context.set('state',3);\n //\n // Third message to send to set icon\n // md-error\n msg3 = {payload:\"ERROR\"};\n return [msg,msg2,msg3];\n } else\n if (ICSS == 4) ////////// MACHINE STATE CHANGED //////////////////\n {\n if(previous_state != 3)\n {\n if (debug === true)\n {\n //\t\tUpdate button colour.\n node.warn(\"@@@@@@@@@@@@@@@@\");\n node.warn(device);\n node.warn(\"Payload = \" + msg.payload);\n node.warn(\"Background colour -- \" + msg.background);\n node.warn(\"State changed\");\n }\n context.set('background',msg.background);\n // Indicate node changed.\n node.status({fill:\"yellow\",shape:\"dot\",text:\"4\"});\n msg2 = { payload:\"\", background:msg.background};\n context.set('state', 0);\n \n // Set online status.\n if (msg.background == \"lime\")\n {\n //\n if (shutdown == 0)\n {\n //node.warn(\"Online routine\");\n context.set('online',\"On-line\");\n //backgroundcolour = \"lime\";\n backgroundcolour = msg.background;\n }\n } else\n //if (msg.background == \"brown\")\n {\n //\n //node.warn(\"Offline routine\");\n context.set('online',\"Off-line\");\n context.set('shutdown',0);\n //backgroundcolour = \"brown\";\n backgroundcolour = msg.background;\n }\n }\n // 2021 06 21\n //msg = null;\n //return [msg,msg2];\n return [null,msg2];\n } else\n if (ICSS == 6)\n {\n //\n context.set('shutdown',1);\n\tnode.warn(\"********* Shutdown set to 1 *************\");\n context.set('online',\"Off-line\");\n msg2 = { payload:\"\", background:\"brown\"};\n// backgroundcolour = msg.background;\t\t//\tDunno what this line is supposed to do.\n\n //msg = null;\t\t\t//\t2018-10-06 Added these two lines to fix problem of buttons not changing from BLACK.\n //return [msg,msg2];\n // 2021 06 21\n return [null,msg2];\n\n }\n }\n}\n","outputs":4,"noerr":0,"initialize":"","finalize":"","x":233,"y":80,"wires":[[],[],[],[]]},{"id":"bcf40ba9.50171","type":"status","z":"65d097c2.63a148","name":"","scope":null,"x":200,"y":270,"wires":[[]]},{"id":"375244ec.75aa14","type":"change","z":"381d953d.4cf092","name":"Setup","rules":[{"t":"set","p":"topic","pt":"msg","to":"SET_Device_ID","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"MusicPi","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":300,"y":1100,"wires":[["feb4d263.02fe58"]]},{"id":"9e32cf4d.bbc72","type":"catch","z":"381d953d.4cf092","name":"","scope":["feb4d263.02fe58"],"uncaught":false,"x":300,"y":1230,"wires":[["375244ec.75aa14"]]},{"id":"feb4d263.02fe58","type":"subflow:65d097c2.63a148","z":"381d953d.4cf092","name":"MusicPi button","env":[],"x":270,"y":1280,"wires":[["867e0921.94d2a8"],["9588db20.26f1b8","9100c526.4451","e1b743f8.1c4dd","82103f30.02acc8","13c988e.0e33277","4356c4f2.db883c","6a78ce63.dc5c58","341fb28e.a12546"],["a03446cc.d6fe78"],["968babd4.413468"]]},{"id":"968babd4.413468","type":"flogger","z":"381d953d.4cf092","name":"MusicPi","logfile":"musicpi.db","inputchoice":"fullmsg","inputobject":"payload","inputobjectType":"msg","inputmoustache":"Recieved payload {{payload}} and topic {{topic}}","loglevel":"INFO","logconfig":"17a90a5d.f9e26e","sendpane":"","x":310,"y":2070,"wires":[[]]},{"id":"17a90a5d.f9e26e","type":"config-log","logname":"MusicPi","logdir":"/home/pi/.node-red/public/logs","stamp":"local","logstyle":"plain","logrotate":false,"logcompress":false,"logrotatecount":"5","logsize":"1000"}]
Now, oops, that is for MusicPi
(which isn't active) this is what the log file is I get for BedPi
after getting errors.
This is extract.
The file is BIG as are the other two for the other two machines which are active.
2021/06/22 19:39:28 ERROR [msg] {"_msgid":"c6c268ab.ee9688","_event":"node:95ecca0a.3e62d","error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":8}},"topic":"SET_Device_ID","_error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":7}},"settings":{"input":"2021-06-22T09:39:02.586Z","input_format":"","input_tz":"Australia/Sydney","output_format":"YYYY-MM-DD HH:mm:ss","output_locale":"en_AU","output_tz":"Australia/Sydney"},"time":"2021-06-22 19:39:02","payload":"BedPi"}
2021/06/22 19:39:29 ERROR [msg] {"_msgid":"c6c268ab.ee9688","_event":"node:95ecca0a.3e62d","error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":7}},"topic":"SET_Device_ID","_error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":6}},"settings":{"input":"2021-06-22T09:39:02.963Z","input_format":"","input_tz":"Australia/Sydney","output_format":"YYYY-MM-DD HH:mm:ss","output_locale":"en_AU","output_tz":"Australia/Sydney"},"time":"2021-06-22 19:39:02","payload":"BedPi"}
2021/06/22 19:39:30 ERROR [msg] {"_msgid":"c6c268ab.ee9688","_event":"node:95ecca0a.3e62d","error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":9}},"topic":"SET_Device_ID","_error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":8}},"settings":{"input":"2021-06-22T09:39:02.586Z","input_format":"","input_tz":"Australia/Sydney","output_format":"YYYY-MM-DD HH:mm:ss","output_locale":"en_AU","output_tz":"Australia/Sydney"},"time":"2021-06-22 19:39:02","payload":"BedPi"}
2021/06/22 19:39:31 ERROR [msg] {"_msgid":"c6c268ab.ee9688","_event":"node:95ecca0a.3e62d","error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":8}},"topic":"SET_Device_ID","_error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":7}},"settings":{"input":"2021-06-22T09:39:02.963Z","input_format":"","input_tz":"Australia/Sydney","output_format":"YYYY-MM-DD HH:mm:ss","output_locale":"en_AU","output_tz":"Australia/Sydney"},"time":"2021-06-22 19:39:02","payload":"BedPi"}
2021/06/22 19:39:32 ERROR [msg] {"_msgid":"c6c268ab.ee9688","_event":"node:95ecca0a.3e62d","error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":9}},"topic":"SET_Device_ID","_error":{"message":"Node Configuration not set","source":{"id":"493eaac7.a0d6ec","type":"function","name":"BedPi button","count":8}},"settings":{"input":"2021-06-22T09:39:02.963Z","input_format":"","input_tz":"Australia/Sydney","output_format":"YYYY-MM-DD HH:mm:ss","output_locale":"en_AU","output_tz":"Australia/Sydney"},"time":"2021-06-22 19:39:02","payload":"BedPi"}
But all that is is the message sent as an error message.
Mind having a butcher's hook and see if you can see what is going on?
Oh, this is what is usually sent into it.
{"payload":"<font color = \"lime\" i class=\"fa fa-bullseye fa-2x\"></i></font>","topic":"BedPi/On-line","device_ID":"BedPi","background":"lime","_msgid":"b4a4d542.e604b8"}
and
{"topic":"BedPi","device_ID":"BedPi","state":4,"background":"lime","_msgid":"b4a4d542.e604b8"}
Yes, I have to look a bit more at why I am sending two messages, but both comply with with the needs of the subflow/node and shouldn't create an error.
Not sure if both do comply, but the one which does is the one which is sent.
SORRY
Only one of the two messages go into the node/subflow.
When I click on the link
node/s (two go from a different tab
to this one. Clicking on both I got sent to the same part of the page. But I then noticed it wasn't going there.)