Test reception of ASTM-1394 messages from serial port
This flow receive messages at the serial port, that use the standard ASTM-1394. It is just a testing tool to validate communication or capture the frames to a file in order to process them later.
It is a proof of concept to demonstrate use of Node-RED in the healthcare industry.
[{"id":"bb14d97d.325b68","type":"tab","label":"Serial ASTM","disabled":false,"info":""},{"id":"36ab0272.30094e","type":"serial in","z":"bb14d97d.325b68","name":"","serial":"8269401d.f3814","x":130,"y":160,"wires":[["c19bf630.72c698"]]},{"id":"80e8be74.e5135","type":"serial out","z":"bb14d97d.325b68","name":"","serial":"8269401d.f3814","x":610,"y":60,"wires":[]},{"id":"596915de.fc7c9c","type":"debug","z":"bb14d97d.325b68","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":590,"y":400,"wires":[]},{"id":"c19bf630.72c698","type":"function","z":"bb14d97d.325b68","name":"Analize char in","func":"// msg1 is the answer sent to serial port\n// msg2 interprets the received character for the log file\n// msg3 when ready is the complete frame to be analized.\n\nvar frame=global.get('frame') // Buffer for the current frame\nvar chksum=global.get('chksum'); // Check sum of frame\nvar calchksum=global.get('calchksum'); // Calculate checksum\nvar framechksum = global.get('framechksum'); // We store here the frame chcksum\nvar numchars = context.get('numchars');\nvar cks = context.get('cks');\nvar tracechars = global.get('tracechars');\n\nvar msg1 = {payload: [0]};\nvar msg2 = {payload:\"\"};\nvar msg3 = {payload:\"\"};\n\n\nif (calchksum !== false) {\n global.set('chksum', chksum + msg.payload[0]);\n tracechars.push(msg.payload[0]);\n global.set('tracechars',tracechars);\n if (global.get('chksum') > 255) {\n global.set('chksum', global.get('chksum') - 256);\n }\n} else {\n if (context.get('finished') === true) {\n if (numchars <= 2) {\n framechksum = framechksum + String.fromCharCode(msg.payload[0]);\n global.set('framechksum',framechksum);\n numchars++;\n context.set('numchars',numchars)\n if (numchars >= 2) {\n context.set('finished',false);\n }\n }\n }\n \n}\n\nswitch(msg.payload[0]) {\n case 2:\n global.set('chksum',false); // Check sum of frame\n global.set('calchksum',1); // Flag to Calculate checksum\n global.set('frame', \"\"); // Buffer for the current frame\n global.set('framechksum',\"\"); // We store here the frame chcksum\n context.set('numchars',0); // Number of characters of received frame checksum\n context.set('finished',false); // Has finished summing chksum\n context.set('cks',\"\"); // String version of calculated checksum\n msg1 = null;\n msg2.payload = \"<STX>\";\n msg3 = null;\n break;\n case 3:\n global.set('calchksum',false);\n context.set('finished',true);\n msg1 = null;\n msg2.payload = \"<ETX>\";\n frame = frame + msg.payload.toString();\n global.set('frame', frame);\n\n msg3 = null;\n break;\n case 4:\n msg1.payload = new Buffer([0x04]);\n msg2.payload = \"<EOT>\";\n msg3 = null;\n break;\n case 5:\n global.set(\"frame\",\"\");\n msg1.payload = new Buffer([0x06]);\n msg2.payload = \"<ENQ>\";\n msg3 = null;\n break;\n case 6:\n msg1 = null;\n msg2.payload = \"<ACK>\";\n msg3 = null;\n break;\n case 10:\n cks = chksum.toString(16).padStart(2, '0').toUpperCase();\n context.set('cks',cks);\n if (cks == framechksum) {\n msg1.payload = new Buffer([0x06]); // Checksum OK = ACK\n msg3.payload = frame + \"\\n\";\n } else {\n msg1.payload = new Buffer([0x15]); // Checksum not OK = NAK\n msg3.payload = null;\n }\n msg2.payload = \"<LF>\";\n break;\n case 13:\n msg1 = null;\n msg2.payload = \"<CR>\";\n frame = frame + msg.payload.toString();\n global.set('frame', frame);\n msg3 = null;\n break;\n case 21:\n msg1 = null;\n msg2.payload = \"<NAK>\";\n msg3 = null;\n break;\n case 23:\n msg1 = null;\n global.set('calchksum',false);\n context.set('finished',true);\n msg2.payload = \"<ETB>\";\n frame = frame + msg.payload.toString();\n global.set('frame', frame);\n msg3 = null;\n break;\n default:\n msg1 = null;\n msg2.payload = msg.payload.toString();\n frame = frame + msg.payload.toString();\n global.set('frame', frame);\n msg3 = null;\n}\nmsg2.topic = \"Rx: \";\nreturn [msg1,msg2,msg3];","outputs":3,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is deployed.\n\nglobal.set('frame', \"\"); // Buffer for the current frame\nglobal.set('chksum',false); // Check sum of frame\nglobal.set('calchksum',0); // Flag to Calculate checksum\nglobal.set('framechksum',\"\"); // We store here the frame chcksum\ncontext.set('numchars',0); // Number of characters of received frame checksum\ncontext.set('finished',false); // Has finished summing chksum\ncontext.set('cks',\"\"); // String version of calculated checksum\n// debug arrays\nglobal.set('tracechars',[]);\n","finalize":"","x":360,"y":160,"wires":[["668f6f5d.2b7ce","80e8be74.e5135"],["aa909449.3b1258","69746b1f.3e14e4"],["596915de.fc7c9c"]]},{"id":"95dfb24.554b05","type":"debug","z":"bb14d97d.325b68","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1236,"y":160,"wires":[]},{"id":"668f6f5d.2b7ce","type":"function","z":"bb14d97d.325b68","name":"Analize char out","func":"// msg1 es la respuesta del puerto serial\n// msg1 es la interpretación del character recibido para el log\nvar msg1 = {payload:[0]};\nswitch(msg.payload[0]) {\n case 0:\n msg1.payload = \"<NUL>\";\n break;\n case 1:\n msg1.payload = \"<SOH>\";\n break;\n case 2:\n msg1.payload = \"<STX>\";\n break;\n case 3:\n msg1.payload = \"<ETX>\";\n break;\n case 4:\n msg1.payload = \"<EOT>\";\n break;\n case 5:\n msg1.payload = \"<ENQ>\";\n break;\n case 6:\n msg1.payload = \"<ACK>\";\n break;\n case 7:\n msg1.payload = \"<BEL>\";\n break;\n case 8:\n msg1.payload = \"<BS>\";\n break;\n case 9:\n msg1.payload = \"<TAB>\";\n break;\n case 10:\n msg1.payload = \"<LF>\";\n break;\n case 13:\n msg1.payload = \"<CR>\";\n break;\n case 21:\n msg1.payload = \"<NAK>\";\n break;\n case 23:\n msg1.payload = \"<ETB>\";\n break;\n default:\n msg1.payload = msg.payload.toString();\n}\nmsg1.topic = 'Tx: ';\nreturn msg1;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":620,"y":120,"wires":[["aa909449.3b1258","69746b1f.3e14e4"]]},{"id":"ef197f01.a89f9","type":"flogger","z":"bb14d97d.325b68","name":"serialtst.log","logfile":"serialtst.log","inputchoice":"fullmsg","inputobject":"payload","inputobjectType":"msg","inputmoustache":"Recieved payload {{payload}} and topic {{topic}}","loglevel":"INFO","logconfig":"8c711f6a.8cc4","sendpane":false,"x":1056,"y":160,"wires":[["95dfb24.554b05"]]},{"id":"c2554a97.c3e728","type":"file","z":"bb14d97d.325b68","name":"","filename":"/tmp/tramas.txt","appendNewline":false,"createDir":false,"overwriteFile":"false","encoding":"none","x":1260,"y":220,"wires":[[]]},{"id":"4cb748c4.aa2038","type":"inject","z":"bb14d97d.325b68","name":"Capture frames to a file","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"control","payload":"toggle","payloadType":"str","x":640,"y":240,"wires":[["aa909449.3b1258"]]},{"id":"aa909449.3b1258","type":"gate","z":"bb14d97d.325b68","name":"","controlTopic":"control","defaultState":"closed","openCmd":"open","closeCmd":"close","toggleCmd":"toggle","defaultCmd":"default","persist":false,"x":850,"y":220,"wires":[["e05a99c.b468968"]]},{"id":"69746b1f.3e14e4","type":"function","z":"bb14d97d.325b68","name":"","func":"var trama=context.get('trama') || \"\";\nvar tmp=\"\";\ntmp = trama.concat(msg.payload);\ncontext.set('trama',tmp); \nif (msg.payload.includes(\"<LF>\") || msg.payload.includes(\"<ACK>\") || msg.payload.includes(\"<NAK>\") || msg.payload.includes(\"<ENQ>\") || msg.payload.includes(\"<EOT>\") ) {\n msg.payload = msg.topic.concat(tmp);\n context.set(\"trama\",\"\"); \n return msg; \n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","x":880,"y":160,"wires":[["ef197f01.a89f9"]]},{"id":"e05a99c.b468968","type":"function","z":"bb14d97d.325b68","name":"","func":"if (msg.payload.includes(\"<LF>\") || msg.payload.includes(\"<ACK>\") || msg.payload.includes(\"<NAK>\") || msg.payload.includes(\"<ENQ>\") || msg.payload.includes(\"<EOT>\") ) {\n msg.payload = msg.payload.concat(\"\\n\");\n}\nreturn msg; ","outputs":1,"noerr":0,"initialize":"","finalize":"","x":1060,"y":220,"wires":[["c2554a97.c3e728"]]},{"id":"8269401d.f3814","type":"serial-port","z":"","serialport":"/dev/ttyUSB0","serialbaud":"9600","databits":"8","parity":"none","stopbits":"1","waitfor":"","newline":"1","bin":"bin","out":"count","addchar":"","responsetimeout":"10000"},{"id":"8c711f6a.8cc4","type":"config-log","z":"","logname":"logserial","logdir":"/var/log","stamp":"local","logstyle":"plain","logrotate":false,"logcompress":false,"logrotatecount":"5","logsize":"1000","logtopic":false,"logsource":true}]