-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflows_DYN.json
More file actions
1 lines (1 loc) · 76.6 KB
/
Copy pathflows_DYN.json
File metadata and controls
1 lines (1 loc) · 76.6 KB
1
[{"id":"dfca7471.a1e698","type":"tab","label":"single-hop_WSN"},{"id":"9e87c9ce.0ab558","type":"subflow","name":"final_action","info":"","in":[{"x":160,"y":160,"wires":[{"id":"6f4a8bda.c013e4"},{"id":"3972ce6c.855b12"}]}],"out":[]},{"id":"7823bf3e.a929f","type":"subflow","name":"Measurement","info":"","in":[{"x":120,"y":100,"wires":[{"id":"2b087b64.ee4304"}]}],"out":[{"x":940,"y":240,"wires":[{"id":"ed0ef637.615ba8","port":0}]},{"x":980,"y":600,"wires":[{"id":"8e46b0fc.31eca","port":0}]},{"x":940,"y":280,"wires":[{"id":"c26cb2.cecd835","port":0}]}]},{"id":"2ccc54b4.8ffd1c","type":"subflow","name":"param_config","info":"","in":[{"x":100,"y":100,"wires":[{"id":"50dac24a.d1c73c"}]}],"out":[{"x":880,"y":80,"wires":[{"id":"a357dbef.56af58","port":0}]}]},{"id":"6ecf21cd.62a7b","type":"subflow","name":"portable_setup","info":"","in":[{"x":80,"y":160,"wires":[{"id":"f5b98115.f66d9"}]}],"out":[{"x":860,"y":80,"wires":[{"id":"94b02590.76a6e8","port":0}]}]},{"id":"cdf9b642.28c878","type":"subflow","name":"wilab2_setup","info":"","in":[{"x":240,"y":60,"wires":[]}],"out":[{"x":400,"y":60,"wires":[]}]},{"id":"4bd24dc8.2d0bd4","type":"subflow","name":"cooja_setup","info":"","in":[{"x":60,"y":100,"wires":[{"id":"c314ba76.aa4f48"}]}],"out":[{"x":840,"y":360,"wires":[{"id":"e3550a12.b34508","port":0}]}]},{"id":"f439654.2d2c198","type":"subflow","name":"CV_parser","info":"","in":[{"x":120,"y":100,"wires":[{"id":"90728140.743ce"}]}],"out":[]},{"id":"1e47311c.96e34f","type":"debug","z":"9e87c9ce.0ab558","name":"action_stdout","active":true,"console":"false","complete":"true","x":510,"y":160,"wires":[]},{"id":"422359ef.8e2e38","type":"function","z":"dfca7471.a1e698","name":"Experiment Setup","func":"// Get coordinates of IMEC w-ilab.t sensor nodes\nfunction ID_to_cord(ID)\n{ var cord = {};\n\tswitch(ID)\n\t{\n\t\tcase 1: cord = {X: 6.0, Y: 2.0}; break;\tcase 22: cord = {X: 6.0, Y: 9.2 }; break;\tcase 43: cord = {X: 6.0, Y: 16.4}; break;\n\t\tcase 2: cord = {X: 12.0, Y: 2.0}; break;\tcase 23: cord = {X: 12.0, Y: 9.2 }; break;\tcase 44: cord = {X: 12.0, Y: 16.4}; break;\n\t\tcase 3: cord = {X: 18.0, Y: 2.0}; break;\tcase 24: cord = {X: 18.0, Y: 9.2 }; break;\tcase 45: cord = {X: 18.0, Y: 16.4}; break;\n\t\tcase 4: cord = {X: 24.0, Y: 2.0}; break;\tcase 25: cord = {X: 24.0, Y: 9.2 }; break;\tcase 46: cord = {X: 24.0, Y: 16.4}; break;\n\t\tcase 5: cord = {X: 30.0, Y: 2.0}; break;\tcase 26: cord = {X: 30.0, Y: 9.2 }; break;\tcase 47: cord = {X: 30.0, Y: 16.4}; break;\n\t\tcase 6: cord = {X: 36.0, Y: 2.0}; break;\tcase 27: cord = {X: 36.0, Y: 9.2 }; break;\tcase 48: cord = {X: 36.0, Y: 16.4}; break;\n\t\tcase 7: cord = {X: 42.0, Y: 2.0}; break;\tcase 28: cord = {X: 42.0, Y: 9.2 }; break;\tcase 49: cord = {X: 42.0, Y: 16.4}; break;\n\t\tcase 8: cord = {X: 48.0, Y: 2.0}; break;\tcase 29: cord = {X: 48.0, Y: 9.2 }; break;\tcase 50: cord = {X: 48.0, Y: 16.4}; break;\n\t\tcase 9: cord = {X: 54.0, Y: 2.0}; break;\tcase 30: cord = {X: 54.0, Y: 9.2 }; break;\tcase 51: cord = {X: 54.0, Y: 16.4}; break;\n\t\tcase 10: cord = {X: 60.0, Y: 2.0}; break;\tcase 31: cord = {X: 60.0, Y: 9.2 }; break;\tcase 52: cord = {X: 60.0, Y: 16.4}; break;\n\t\tcase 11: cord = {X: 6.0, Y: 5.6}; break;\tcase 33: cord = {X: 6.0, Y: 12.8}; break;\n\t\tcase 12: cord = {X: 12.0, Y: 5.6}; break;\tcase 34: cord = {X: 12.0, Y: 12.8}; break;\tcase 53: cord = {X: 12.0, Y: 20.0}; break;\n\t\tcase 13: cord = {X: 18.0, Y: 5.6}; break;\tcase 35: cord = {X: 18.0, Y: 12.8}; break;\tcase 54: cord = {X: 18.0, Y: 20.0}; break;\n\t\tcase 14: cord = {X: 24.0, Y: 5.6}; break;\tcase 36: cord = {X: 24.0, Y: 12.8}; break;\n\t\tcase 15: cord = {X: 30.0, Y: 5.4}; break;\tcase 37: cord = {X: 30.0, Y: 12.8}; break;\tcase 55: cord = {X: 30.0, Y: 20.0}; break;\n\t\tcase 16: cord = {X: 36.0, Y: 5.5}; break;\tcase 38: cord = {X: 36.0, Y: 12.8}; break;\tcase 56: cord = {X: 36.0, Y: 20.0}; break;\n\t\tcase 17: cord = {X: 42.0, Y: 5.5}; break;\tcase 39: cord = {X: 42.0, Y: 12.8}; break;\tcase 57: cord = {X: 42.0, Y: 20.0}; break;\n\t\tcase 18: cord = {X: 48.0, Y: 5.5}; break;\tcase 40: cord = {X: 48.0, Y: 12.8}; break;\tcase 58: cord = {X: 48.0, Y: 20.0}; break;\n\t\tcase 19: cord = {X: 54.0, Y: 5.5}; break;\tcase 41: cord = {X: 54.0, Y: 12.8}; break;\tcase 59: cord = {X: 54.0, Y: 20.0}; break;\n\t\tcase 20: cord = {X: 60.0, Y: 5.5}; break;\tcase 42: cord = {X: 60.0, Y: 12.8}; break;\tcase 60: cord = {X: 60.0, Y: 20.0}; break;\n\t}\n\treturn cord;\n}\n// IMEC w-ilab.t Testbed\n// ┌─────────────────────────────────────────────────────────────────────┐\n// │ 1 2 3 4 5 6 7 8 9 10 │\n// │ 11 12 13 14 15 16 17 18 19 20 │\n// │ 22 23 24 25 26 27 28 29 30 31 │\n// │ 33 34 35 36 37 38 39 40 41 42 │\n// │ 43 44 45 46 47 48 49 50 51 52 │\n// │ 53 54 55 56 57 58 59 60 │\n// └─────────────────────────────────────────────────────────────────────┘\n\nvar sink_ID = [ 1 ];\nvar source_ID = [ 2 ];\n//var source_ID = [ 4, 6, 8, 23, 25, 29, 31, 46, 48, 50 ];\n//var source_ID = [ 4, 6, 8, 13, 15, 17, 19, 23, 25, 29, 31, 35, 37, 39, 41, 46, 48, 50 ];\n//var source_ID = [ 4, 5, 6, 7, 8, 13, 14, 15, 16, 17, 18, 19, 23, 24, 25, 26, 29, 30, 31, 28, 35, 36, 37, 38, 39, 40, 41, 46, 47, 48, 49, 50 ];\nvar disturber_ID = [ ];\n//var disturber_ID = [ 56 ];\n\n// Cooja simulation parameters\nvar cooja = {};\ncooja.title = \"single-hop_WSN\";\n//cooja.randomseed = \"123456\";\ncooja.radiomedium = {};\ncooja.radiomedium.transmitting_range = \"50.0\";\ncooja.radiomedium.interference_range = \"100.0\";\ncooja.radiomedium.success_ratio_tx = \"1.0\";\ncooja.radiomedium.success_ratio_rx = \"0.8\";\ncooja.motetype = {};\ncooja.motetype.CONTIKI_DIR = \"/home/mmehari/contiki\";\ncooja.motetype.firm_path_rel = \"examples/rime/single-hop_WSN.rm090\";\n\n// Cooja contiki parameters\ncooja.contiki_log = \"COOJA.contikilog\";\ncooja.contiki_done_str = \"taiscmac nullrdc, channel check rate\";\n\nmsg.cooja = cooja;\n\n// choose simulation mode [non_gui/gui]\nmsg.simulation_mode = \"gui\";\n\n\n// ******* Do not change beyond this line ******* //\n// nodes used in the experiment\nvar GROUPs = {};\n// Sink node group definition\nGROUPs.sink = [];\nGROUPs.sink.push({ID: sink_ID[0], loc: ID_to_cord(sink_ID[0])});\n// Source nodes group definition\nGROUPs.source = [];\nfor(var i=0; i<source_ID.length; i++)\n{\n GROUPs.source.push({ID: source_ID[i], loc: ID_to_cord(source_ID[i])});\n}\n// Disturber nodes group definition\nGROUPs.disturber = [];\nfor(var i=0; i<disturber_ID.length; i++)\n{\n GROUPs.disturber.push({ID: disturber_ID[i], loc: ID_to_cord(disturber_ID[i])});\n}\n\n// Make nodes and ids global\ncontext.global.GROUPs = GROUPs;\n\n// Convert integer to hexadecimal of given size\ncontext.global.int2hex = function (integer, size)\n{\n\t// Is the passed value an integer\n\tif(Number.isInteger(integer) === true)\n\t{\n\t\tvar buf = Buffer.allocUnsafe(4);\n\t\t// 8 bit integer\n\t\tif(size == 1)\n\t\t{\n\t\t\tvar uint8 = new Uint8Array([integer]);\n\t\t\tbuf.writeUInt8(uint8[0], 0);\n\t\t}\n\t\t// 16 bit integer\n\t\telse if(size == 2)\n\t\t{\n\t\t\tvar uint16 = new Uint16Array([integer]);\n\t\t\tbuf.writeUInt16LE(uint16[0], 0);\n\t\t}\n\t\t// Else, use 32 bit integer\n\t\telse\n\t\t{\n\t\t\tsize = 4;\n\t\t\tvar uint32 = new Uint32Array([integer]);\n\t\t\tbuf.writeUInt32LE(uint32[0], 0);\n\t\t}\n\t\treturn buf.toString('hex', 0, size);\n\t}\n\telse\n\t{\n\t\tconsole.error(\"int2hex: \" + integer + \" is not an integer\");\n\t}\n};\n\nreturn msg;\n","outputs":1,"noerr":0,"x":190,"y":240,"wires":[["f7a2f887.5fd728"]]},{"id":"feca1dc3.2391e","type":"comment","z":"dfca7471.a1e698","name":"Experiment Setup + Initialization","info":"In this part of the experiment, initial configuraton and setting up of the experiment is conducted.\n\nAt the end of this phase, the experimentation setup will be in a known state with all default parameters configured.","x":170,"y":160,"wires":[]},{"id":"cc8c849.715ac78","type":"comment","z":"dfca7471.a1e698","name":"Initial parameter settings","info":"","x":650,"y":160,"wires":[]},{"id":"f995d8d8.0d4328","type":"function","z":"dfca7471.a1e698","name":"Radio Parameters","func":"\n// Group of nodes global variable\nvar GROUPs = context.global.GROUPs;\n\n// Radio UIDs\nvar UID =\n{\n phy_channel : 14751,\n phy_txPower : 28244,\n cca_threshold : 6819,\n cycleTime : 43299,\n ccaRxCountMax : 26072,\n ccaTxCountMax : 5735\n};\n\n// Variable types\nvar UINT_T = 0;\nvar INT_T = 1;\n\n// Configurable parameters\nvar phy_channel = 27; // zigbee channel\nvar phy_txPower = 5; // transmission power in dBm\nvar cca_threshold = -80; // CCA threshold in dBm\nvar cycleTime = 131072; // contikiMAC cycle time usec\nvar ccaRxCountMax = 2; // Rx CCA max Count\nvar ccaTxCountMax = 6; // Tx CCA max Count\n\n// Default radio parameters\nvar radio_parameters = \n[\n // Set parameters on sink and source nodes\n {\n GROUPs: [GROUPs.sink, GROUPs.source],\n control_hdr:\n [ \n { uid: UID.phy_channel, type: UINT_T, len: 1, value : phy_channel },\n { uid: UID.phy_txPower, type: INT_T, len: 1, value : phy_txPower },\n { uid: UID.cca_threshold, type: INT_T, len: 1, value : cca_threshold },\n { uid: UID.cycleTime, type: UINT_T, len: 4, value : cycleTime },\n { uid: UID.ccaRxCountMax, type: UINT_T, len: 1, value : ccaRxCountMax },\n { uid: UID.ccaTxCountMax, type: UINT_T, len: 1, value : ccaTxCountMax }\n ]\n }\n];\n\n// ******* Do not change beyond this line ******* //\nvar msg = {};\nmsg.parameters = radio_parameters;\nmsg.topic = \"radio_configuration\";\n\nreturn msg;","outputs":1,"noerr":0,"x":630,"y":240,"wires":[["68178fe7.d46a3"]]},{"id":"ceb87228.3f744","type":"comment","z":"dfca7471.a1e698","name":"Experiment Action","info":"","x":130,"y":640,"wires":[]},{"id":"57500133.1a477","type":"comment","z":"dfca7471.a1e698","name":"Intelligent experimentation","info":"","x":150,"y":380,"wires":[]},{"id":"658babd1.b88c94","type":"function","z":"dfca7471.a1e698","name":"Parameters Under Test","func":"\n// Group of nodes global variable\nvar GROUPs = context.global.GROUPs;\n\n// PUT UIDs\nvar UID =\n{\n phy_txPower : 28244,\n cycleTime : 43299,\n cca_threshold : 6819,\n ccaRxCountMax : 26072,\n ccaTxCountMax : 5735,\n Retx_max : 46644\n \n \n};\n\nvar UINT_T = 0;\nvar INT_T = 1;\n\n// Parameters Under Test\nvar PUT = \n[\n {\n GROUPs: [GROUPs.sink, GROUPs.source],\n opcode: 1,\n control_hdr:\n [\n { uid: UID.phy_txPower, type: INT_T, len: 1, values : [-18, -7, -4, -2, 0, 1, 2, 3, 5] }\n// { uid: UID.cca_threshold, type: INT_T, len: 1, values : [-50, -55, -60, -65, -70, -75, -80, -85, -90, -95, -100, -105, -110 ] }\n// { uid: UID.ccaTxCountMax, type: UINT_T, len: 1, values : [2, 3, 4, 5, 6, 7, 8] }\n \n// { uid: UID.phy_txPower, type: INT_T, len: 1, values : [0, 1, 2, 3] }, // transmission power in dBm\n// { uid: UID.cycleTime, type: UINT_T, len: 4, values : [32768, 65536, 98304, 131072] }, // ContikiMAC cycleTime in usec\n// { uid: UID.cca_threshold, type: INT_T, len: 1, values : [-90, -85, -80, -75, -70] }, // Clear Channel Assesment threshold\n// { uid: UID.ccaRxCountMax, type: UINT_T, len: 1, values : [2, 3, 4, 5] }, // ContikiMAC Rx CCA count\n// { uid: UID.ccaTxCountMax, type: UINT_T, len: 1, values : [3, 4, 5, 6, 7] }, // ContikiMAC Tx CCA count\n// { uid: UID.Retx_max, type: UINT_T, len: 1, values : [0, 1, 2, 3, 4] } // Retransmission count\n ]\n }\n];\n\n// Save PUT as a global variable\ncontext.global.PUT = PUT[0];\n\n// Global sample index\ncontext.global.sample_Idx = 0;\n\ncontext.global.reptd_expr_count = 0;\ncontext.global.reptd_expr_max = 1;\n\nmsg = {};\nmsg.PUT = PUT;\nmsg.topic = \"start_experiment\";\n//msg.topic = \"restart_experiment\";\n//msg.sample_Idx = context.global.sample_Idx;\n//msg.payload = [0, 32768, -90, 1, 8, 3];\nmsg.port = context.global.pts_mux_port;\nreturn msg;","outputs":1,"noerr":0,"x":210,"y":480,"wires":[["dc2897d8.b779c8"]]},{"id":"628d5c69.bb29a4","type":"subflow:7823bf3e.a929f","z":"dfca7471.a1e698","name":"","x":780,"y":480,"wires":[["620458e1.f98428"],["a82291be.4a432"],["a0f16bee.b00f58"]]},{"id":"e08b2ee5.d7ded","type":"subflow:9e87c9ce.0ab558","z":"dfca7471.a1e698","name":"","x":170,"y":700,"wires":[]},{"id":"b4478f18.78109","type":"comment","z":"dfca7471.a1e698","name":"Planning","info":"","x":420,"y":440,"wires":[]},{"id":"74da1545.132bcc","type":"comment","z":"dfca7471.a1e698","name":"Reasoning","info":"","x":960,"y":440,"wires":[]},{"id":"adc47910.160cc8","type":"comment","z":"dfca7471.a1e698","name":"Execution","info":"","x":600,"y":440,"wires":[]},{"id":"d490cced.0bfc","type":"function","z":"dfca7471.a1e698","name":"Application Parameters","func":"\n// Group of nodes global variable\nvar GROUPs = context.global.GROUPs;\n\n// Application UIDs\nvar UID = \n{\n send_interval : 19367,\n message_size : 57215,\n Retx_max : 46644,\n receiver : 57217,\n source_IDs : 57218,\n activate_app : 25440\n};\n\n// Variable types\nvar UINT_T = 0;\nvar INT_T = 1;\n\n// Configurable parameters\nvar send_interval = 128; // sending interval in ticks [128 ticks === 1 sec]\nvar message_size = 100; // message size\nvar Retx_max = 4; // maximum retransmission\nvar sink_ID = GROUPs.sink[0].ID; // Receiver ID\nvar source_IDs = []; // source IDs\nfor(var i = 0; i < GROUPs.source.length; i++)\n source_IDs.push(GROUPs.source[i].ID);\n\n// Make sending interval a global parameter\ncontext.global.send_interval = send_interval;\n\n// Default application parameters\nvar app_parameters = \n[\n // Set parameters on sink nodes\n {\n GROUPs: [GROUPs.sink],\n control_hdr:\n [\n { uid: UID.Retx_max, type: UINT_T, len: 1, value : Retx_max },\n { uid: UID.receiver, type: UINT_T, len: 2, value : sink_ID },\n { uid: UID.source_IDs, type: UINT_T, len: 2, value : source_IDs },\n { uid: UID.activate_app, type: UINT_T, len: 1, value : 1 }\n ]\n },\n // Set parameters on source nodes\n {\n GROUPs: [GROUPs.source],\n control_hdr:\n [\n { uid: UID.send_interval, type: UINT_T, len: 4, value : send_interval},\n { uid: UID.message_size, type: UINT_T, len: 1, value : message_size },\n { uid: UID.Retx_max, type: UINT_T, len: 1, value : Retx_max },\n { uid: UID.receiver, type: UINT_T, len: 2, value : sink_ID },\n { uid: UID.activate_app, type: UINT_T, len: 1, value : 1 }\n ]\n }\n];\n\nvar msg = {};\nmsg.parameters = app_parameters;\nmsg.topic = \"app_configuration\";\n\nreturn msg;","outputs":1,"noerr":0,"x":650,"y":200,"wires":[["68178fe7.d46a3"]]},{"id":"9264f556.824c38","type":"function","z":"dfca7471.a1e698","name":"Custom Parameters","func":"\n// Group of nodes global variable\nvar GROUPs = context.global.GROUPs;\n\n// Custom UIDs\nvar UID = \n{\n// intr_period : 45200,\n// intr_dutyCycle : 45201\n};\n\n// Variable types\nvar UINT_T = 0;\nvar INT_T = 1;\n\n// configurable parameters\nvar intr_period = 40000; // Interference period in usec\nvar intr_dutyCycle = 5; // Interference duty cycle percentage\n\n// Custom parameters\nvar custom_parameters = \n[\n // Set parameters on disturber nodes\n/* {\n GROUPs: [GROUPs.disturber],\n control_hdr:\n [\n { uid: UID.intr_period, type: UINT_T, len: 4, value : intr_period },\n { uid: UID.intr_dutyCycle, type: UINT_T, len: 1, value : intr_dutyCycle }\n ]\n }*/\n];\n\nvar msg = {};\nmsg.parameters = custom_parameters;\nmsg.topic = \"custom_configuration\";\n\nreturn msg;","outputs":1,"noerr":0,"x":640,"y":280,"wires":[["68178fe7.d46a3"]]},{"id":"50dac24a.d1c73c","type":"function","z":"2ccc54b4.8ffd1c","name":"combine_param","func":"\n// Convert integer to hexadecimal of given size\nvar int2hex = context.global.int2hex;\n\n// Update parameters to default state\nvar parameters = msg.parameters;\nvar payload = [];\nfor(var i = 0; i < parameters.length; i++)\n{\n var groups = parameters[i].GROUPs;\n var control_hdr_orig = parameters[i].control_hdr;\n \n // Update control header values\n var control_hdr = [];\n for(var j = 0; j < control_hdr_orig.length; j++)\n {\n var uid = control_hdr_orig[j].uid;\n var type = control_hdr_orig[j].type;\n var len_orig = control_hdr_orig[j].len;\n var value_orig = control_hdr_orig[j].value;\n\n // value is a number\n if(typeof(value_orig) == \"number\")\n {\n var value = int2hex(value_orig, len_orig);\n \tvar len = len_orig;\n }\n // value is a string\n else if(typeof(value_orig) == \"string\")\n {\n var value = \"\";\n for(var k = 0; k < value_orig.length; k++)\n \t value = value + value_orig.charCodeAt(k);\n var len = value_orig.length;\n }\n // value is an array or an object\n else if(typeof(value_orig) == \"object\")\n {\n var value = \"\";\n for(var k in value_orig)\n \t value = value + int2hex(value_orig[k], len_orig);\n \tvar len = len_orig * Object.keys(value_orig).length;\n }\n \n control_hdr.push({uid: uid, type: type, len: len, value : value});\n }\n\n // Update group of nodes\n for(var j = 0; j < groups.length; j++)\n {\n var nodes = groups[j];\n \tvar node_count = Object.keys(nodes).length;\n \tfor(var k = 0; k < node_count; k++)\n \t{\n \t var ptsFile = nodes[k].ptsFile;\n \t \n \t payload.push({ptsFile : ptsFile, opcode : 1, control_hdr : control_hdr});\n \t}\n }\n}\n\nif(msg.topic == \"app_configuration\")\n{\n context.app_configuration = payload;\n}\nelse if(msg.topic == \"radio_configuration\")\n{\n context.radio_configuration = payload;\n}\nelse if(msg.topic == \"custom_configuration\")\n{\n context.custom_configuration = payload;\n}\n\nif(typeof(context.app_configuration) !== \"undefined\" && typeof(context.radio_configuration) !== \"undefined\" && typeof(context.custom_configuration) !== \"undefined\")\n{\n var configurations = context.radio_configuration.concat(context.app_configuration.concat(context.custom_configuration));\n\n // Bind identical ptsFile request configurations\n for(var i = 0; i < configurations.length; i++)\n {\n // Search remaining configurations having similar ptsFiles and similar opcodes\n for(var j = i+1; j < configurations.length; j++)\n {\n if((configurations[i].ptsFile == configurations[j].ptsFile) && (configurations[i].opcode == configurations[j].opcode))\n {\n configurations[i].control_hdr = configurations[i].control_hdr.concat(configurations[j].control_hdr);\n configurations.splice(j,1);\n j--;\n }\n }\n }\n\n msg = {};\n msg.payload = configurations;\n msg.topic = \"start_experiment\";\n msg.port = context.global.pts_mux_port;\n\n // Reset context parameters for next round\n delete context.app_configuration;\n delete context.radio_configuration;\n delete context.custom_configuration;\n\n return msg;\n}\n\n","outputs":1,"noerr":0,"x":240,"y":100,"wires":[["93a77663.cb66d8"]]},{"id":"c26cb2.cecd835","type":"link in","z":"7823bf3e.a929f","name":"stderr","links":["f59ec35d.47189","f800d3dc.43e82","25922f09.f9abb","27fe6cb0.8612a4"],"x":755,"y":280,"wires":[[]]},{"id":"f800d3dc.43e82","type":"link out","z":"7823bf3e.a929f","name":"stderr","links":["c26cb2.cecd835"],"x":695,"y":280,"wires":[]},{"id":"68178fe7.d46a3","type":"subflow:2ccc54b4.8ffd1c","z":"dfca7471.a1e698","name":"","x":880,"y":240,"wires":[["f588c087.1ce03"]]},{"id":"94b02590.76a6e8","type":"function","z":"6ecf21cd.62a7b","name":"pts to nodeID","func":"\nif(msg.payload == \"pts_mux has STARTED\")\n{\n context.pts_mux = msg.payload;\n}\nelse if(msg.topic == \"start_experiment\")\n{\n context.ptsFiles = msg.payload;\n}\n\nif(typeof context.pts_mux !== 'undefined' && typeof context.ptsFiles !== 'undefined')\n//if(typeof context.ptsFiles !== 'undefined')\n{\n var ptsFiles = context.ptsFiles.split(',');\n var GROUPs = context.global.GROUPs;\n \n // Make sure the number of assingned nodes and configured pts devices are the same\n var pts_count = ptsFiles.length;\n var sink_count = GROUPs.sink.length;\n var source_count = GROUPs.source.length;\n if(pts_count != sink_count + source_count)\n {\n msg.payload = \"Assigned and configured node count does not match\";\n return [null, msg];\n }\n \n // Match sink nodes to pts devices\n for(var i = 0; i < sink_count; i++)\n {\n GROUPs.sink[i].ptsFile = ptsFiles[i];\n }\n // Match source nodes to pts devices\n for(var j = 0; j < source_count; i++,j++)\n {\n GROUPs.source[j].ptsFile = ptsFiles[i];\n }\n \n context.global.GROUPs = GROUPs;\n delete context.ptsFiles;\n delete context.pts_mux;\n \n return [msg, null];\n}","outputs":"2","noerr":0,"x":730,"y":120,"wires":[[],["d5c88003.8daf"]]},{"id":"e26f582e.9ac338","type":"function","z":"6ecf21cd.62a7b","name":"check","func":"\nvar msg1 = {};\nvar msg2 = {};\n\n// Empty payload => cooja is not started\nif(msg.payload === \"\")\n{\n msg.payload = \"ERROR: portable setup is not started\";\n return [null, msg];\n}\nelse\n{\n var ptyFiles = msg.payload.split('\\n').filter(function(e){return e;});\n msg.payload = ptyFiles.join(',');\n\n return [msg, null];\n}","outputs":"2","noerr":0,"x":370,"y":140,"wires":[["dd6f7ee5.8634f","74c3d1e8.63136"],["770eaf66.6b45a"]]},{"id":"dd6f7ee5.8634f","type":"link out","z":"6ecf21cd.62a7b","name":"pts_devices","links":["6a4938a5.f39438"],"x":475,"y":80,"wires":[]},{"id":"6a4938a5.f39438","type":"link in","z":"6ecf21cd.62a7b","name":"pts_devices","links":["dd6f7ee5.8634f"],"x":595,"y":80,"wires":[["94b02590.76a6e8"]]},{"id":"7735c2ce.08c65c","type":"link in","z":"6ecf21cd.62a7b","name":"stderr","links":["6e78f16.4c9bb1","770eaf66.6b45a","a09afe78.daf87","4f963f9.bb5c3c","16e6c4cf.ce4b4b"],"x":775,"y":160,"wires":[["d5c88003.8daf"]]},{"id":"770eaf66.6b45a","type":"link out","z":"6ecf21cd.62a7b","name":"stderr","links":["7735c2ce.08c65c"],"x":475,"y":200,"wires":[]},{"id":"6f320d.93050df4","type":"comment","z":"6ecf21cd.62a7b","name":"Is experimentation started?","info":"","x":250,"y":100,"wires":[]},{"id":"6e78f16.4c9bb1","type":"link out","z":"6ecf21cd.62a7b","name":"stderr","links":["7735c2ce.08c65c"],"x":335,"y":200,"wires":[]},{"id":"f5b98115.f66d9","type":"exec","z":"6ecf21cd.62a7b","command":"motelist -c | cut -d, -f2","addpay":false,"append":"","useSpawn":false,"timer":"","name":"pts devices","x":210,"y":160,"wires":[["e26f582e.9ac338"],["6e78f16.4c9bb1"],[]]},{"id":"74c3d1e8.63136","type":"exec","z":"6ecf21cd.62a7b","command":"pts_mux -g","addpay":true,"append":"","useSpawn":true,"timer":"","name":"start pts_mux","x":540,"y":140,"wires":[["94b02590.76a6e8"],["16e6c4cf.ce4b4b"],[]]},{"id":"d5c88003.8daf","type":"debug","z":"6ecf21cd.62a7b","name":"portable_stderr","active":true,"console":"false","complete":"true","x":920,"y":160,"wires":[]},{"id":"25232dfe.1d5632","type":"debug","z":"2ccc54b4.8ffd1c","name":"default_stderr","active":true,"console":"false","complete":"true","x":800,"y":140,"wires":[]},{"id":"dd3393f9.97be","type":"link in","z":"7823bf3e.a929f","name":"delay_in","links":["b2332f43.08231"],"x":115,"y":440,"wires":[["614f3a7b.531ea4"]]},{"id":"b2332f43.08231","type":"link out","z":"7823bf3e.a929f","name":"delay_in","links":["dd3393f9.97be"],"x":695,"y":320,"wires":[]},{"id":"354cb8d0.974f78","type":"comment","z":"7823bf3e.a929f","name":"Reset statistic variables","info":"","x":280,"y":240,"wires":[]},{"id":"b7383a3f.5f47d8","type":"function","z":"7823bf3e.a929f","name":"Retrv","func":"\n// Control opcode enumeration\nvar UID =\n{\n TXSTATS : 57219,\n RXSTATS : 57216,\n ENERGESTSTATS : 57220\n};\n\n// Default application parameters\nvar GROUPs = context.global.GROUPs;\nvar sink_ptsFile = GROUPs.sink[0].ptsFile;\nvar source_ptsFiles = [];\nfor(var i = 0; i < GROUPs.source.length; i++)\n source_ptsFiles.push(GROUPs.source[i].ptsFile);\n\nvar parameters = [];\nfor(var i = 0; i < source_ptsFiles.length; i++)\n{\n var ptsFile = source_ptsFiles[i];\n\n // Retrieve txStats parameters on source nodes\n var tx_parameter =\n {\n ptsFile: ptsFile,\n opcode: 0,\n control_hdr:\n [\n { uid: UID.TXSTATS, type: 0xFF, len: 6 }\n ]\n };\n parameters.push(tx_parameter);\n \n // Retrieve rxStats parameters on sink nodes\n var sender_ID;\n // Search for sender ID from the given pts device file path\n for(var j = 0; j < GROUPs.source.length; j++)\n {\n if(ptsFile == GROUPs.source[j].ptsFile)\n {\n // senser ID is sent through the type attribute of control_hdr structure\n sender_ID = GROUPs.source[j].ID;\n break;\n }\n }\n var rx_parameter =\n {\n ptsFile: sink_ptsFile,\n opcode: 0,\n control_hdr:\n [\n { uid: UID.RXSTATS, type: sender_ID, len: 10 }\n ]\n };\n parameters.push(rx_parameter);\n \n // Retrieve energest parameters on source nodes\n var energest_parameter =\n {\n ptsFile: ptsFile,\n opcode: 0,\n control_hdr:\n [\n { uid: UID.ENERGESTSTATS, type: 0xFF, len: 16 }\n ]\n };\n parameters.push(energest_parameter);\n}\n \n// Retrieve energest parameters on sink node\nvar energest_parameter =\n{\n ptsFile: sink_ptsFile,\n opcode: 0,\n control_hdr:\n [\n { uid: UID.ENERGESTSTATS, type: 0xFF, len: 16 }\n ]\n};\nparameters.push(energest_parameter);\n\nmsg.payload = parameters;\nmsg.port = context.global.pts_mux_port;\n\nreturn msg;\n\n","outputs":1,"noerr":0,"x":230,"y":600,"wires":[["655a6ecf.d0d2a"]]},{"id":"bfa8825a.f8078","type":"comment","z":"7823bf3e.a929f","name":"Retrieve statistic variables","info":"","x":290,"y":560,"wires":[]},{"id":"7c74086a.613078","type":"link out","z":"7823bf3e.a929f","name":"delay_out","links":["b2935017.a41c"],"x":555,"y":420,"wires":[]},{"id":"b2935017.a41c","type":"link in","z":"7823bf3e.a929f","name":"delay_out","links":["7c74086a.613078"],"x":115,"y":600,"wires":[["b7383a3f.5f47d8"]]},{"id":"f59ec35d.47189","type":"link out","z":"7823bf3e.a929f","name":"stderr","links":["c26cb2.cecd835"],"x":695,"y":660,"wires":[]},{"id":"647c15b2.de598c","type":"link in","z":"7823bf3e.a929f","name":"reset_in","links":["59f98fab.12ff"],"x":115,"y":280,"wires":[["bc25892c.d242e8"]]},{"id":"59f98fab.12ff","type":"link out","z":"7823bf3e.a929f","name":"reset_in","links":["647c15b2.de598c"],"x":375,"y":140,"wires":[]},{"id":"2b087b64.ee4304","type":"function","z":"7823bf3e.a929f","name":"PUT check","func":"\n// PUT execution request/response payload and error\nvar payload = msg.payload;\nvar error_msg = msg.error_msg;\n\n// Iterate through all request/response parameters and\n// 1. retrieve PUT parameter values\n// 2. verify that values are successfully executed [\"00\"]\nvar PUT_params = {};\nfor(var i = 0; i < payload.length; i++)\n{\n var request = payload[i].request;\n var response = payload[i].response;\n \n var resp_control_hdr = response.control_hdr;\n for(var j = 0; j < resp_control_hdr.length; j++)\n {\n // Is a parameter executed successfully?\n if(resp_control_hdr[j].value === \"00\")\n {\n\t\t\tresp_control_hdr.splice(j, 1);\n\t\t\tj--;\n }\n }\n \n // Display errors\n if(resp_control_hdr.length !== 0)\n {\n error_msg.push({request: request, response: response});\n }\n else\n {\n var ptsFile = request.ptsFile;\n var req_control_hdr = request.control_hdr;\n \n PUT_params[ptsFile] = [];\n for(var j = 0; j < req_control_hdr.length; j++)\n {\n var uid = req_control_hdr[j].uid;\n // Do not include active radio program reloading parameter\n// if(uid !== 28170)\n\t\t\t// Dirty modification and to be removed after a fix\n\t\t\t// Don't consider strobeTime parameter (32120)\n if(uid !== 28170 && uid !== 32120)\n {\n var type = req_control_hdr[j].type;\n var len = req_control_hdr[j].len;\n var value;\n \n // UINT_T\n if(type === 0)\n value = Buffer.from(req_control_hdr[j].value, 'hex').readUIntLE(0, len);\n // INT_T\n else if(type === 1)\n value = Buffer.from(req_control_hdr[j].value, 'hex').readIntLE(0, len);\n \n PUT_params[ptsFile].push(value);\n }\n }\n }\n}\n\n// delete PUT execution request/response payload\ndelete msg.payload;\n \n// Do we have an error message\nif(error_msg.length !== 0)\n{\n msg.sample_Idx = context.global.sample_Idx;\n return [msg, {payload: error_msg}, null];\n}\n// Experiment execution has passed\nelse\n{\n // Save PUT parameters for later use\n context.global.PUT_params = PUT_params;\n\t\n return [null, null, msg];\n}","outputs":"3","noerr":0,"x":250,"y":100,"wires":[["7ad86a1e.c42ba4"],["25922f09.f9abb"],["59f98fab.12ff"]]},{"id":"25922f09.f9abb","type":"link out","z":"7823bf3e.a929f","name":"stderr","links":["c26cb2.cecd835"],"x":375,"y":100,"wires":[]},{"id":"15bb44f4.c909db","type":"comment","z":"7823bf3e.a929f","name":"Wait before collecting results","info":"","x":300,"y":400,"wires":[]},{"id":"f6036096.b398","type":"function","z":"7823bf3e.a929f","name":"reset check","func":"\n// PUT execution request/response payload and error\nvar payload = msg.payload;\nvar error_msg = msg.error_msg;\n\n// Iterate through all request/response parameters and verify that values are successfully executed [\"00\"]\nfor(var i = 0; i < payload.length; i++)\n{\n var request = payload[i].request;\n var response = payload[i].response;\n \n var control_hdr = response.control_hdr;\n \n for(var j = 0; j < control_hdr.length; j++)\n {\n // Is a parameter executed successfully?\n if(control_hdr[j].value === \"00\")\n {\n\t\t\tcontrol_hdr.splice(j, 1);\n\t\t\tj--;\n }\n }\n \n // Display errors\n if(control_hdr.length !== 0)\n error_msg.push({request: request, response: response});\n}\n\n// delete PUT execution request/response payload\ndelete msg.payload;\n \n// Do we have an error message\nif(error_msg.length !== 0)\n{\n msg.sample_Idx = context.global.sample_Idx;\n return [msg, {payload: error_msg}, null];\n}\n// Experiment execution has passed\nelse\n{\n return [null, null, msg];\n}","outputs":"3","noerr":0,"x":570,"y":280,"wires":[["66498699.415548"],["f800d3dc.43e82"],["b2332f43.08231"]]},{"id":"66498699.415548","type":"link out","z":"7823bf3e.a929f","name":"redo_experiment","links":["e33aa464.db8818"],"x":695,"y":240,"wires":[]},{"id":"7ad86a1e.c42ba4","type":"link out","z":"7823bf3e.a929f","name":"redo_experiment","links":["e33aa464.db8818"],"x":375,"y":60,"wires":[]},{"id":"e33aa464.db8818","type":"link in","z":"7823bf3e.a929f","name":"redo_experiment","links":["66498699.415548","7ad86a1e.c42ba4","25413c89.512fa4"],"x":755,"y":240,"wires":[["ed0ef637.615ba8"]]},{"id":"25413c89.512fa4","type":"link out","z":"7823bf3e.a929f","name":"redo_experiment","links":["e33aa464.db8818"],"x":695,"y":540,"wires":[]},{"id":"277f5f2a.bf33d","type":"comment","z":"7823bf3e.a929f","name":"redo experiment","info":"","x":1060,"y":240,"wires":[]},{"id":"33f7b98c.723016","type":"comment","z":"7823bf3e.a929f","name":"error message","info":"","x":1050,"y":280,"wires":[]},{"id":"16591027.57894","type":"comment","z":"7823bf3e.a929f","name":"experiment passed","info":"","x":1110,"y":600,"wires":[]},{"id":"af8c03e1.2882f","type":"function","z":"2ccc54b4.8ffd1c","name":"default check","func":"\n// PUT execution request/response payload\nvar payload = msg.payload;\nvar error_msg = msg.error_msg;\n\n// Iterate through all request/response parameters and verify that values are successfully executed [\"00\"]\nfor(var i = 0; i < payload.length; i++)\n{\n var request = payload[i].request;\n var response = payload[i].response;\n \n var control_hdr = response.control_hdr;\n for(var j = 0; j < control_hdr.length; j++)\n {\n // Are parameters executed successfully?\n if(control_hdr[j].value === \"00\")\n {\n\t\t\tcontrol_hdr.splice(j, 1);\n\t\t\tj--;\n }\n }\n \n // Display errors\n if(control_hdr.length !== 0)\n error_msg.push({request: request, response: response});\n}\n\n// delete PUT execution request/response payload\ndelete msg.payload;\n \n// Do we have an error message\nif(error_msg.length !== 0)\n return [null, {payload: error_msg}];\n// Experiment execution has passed\nelse\n return [msg, null];","outputs":"2","noerr":0,"x":610,"y":100,"wires":[["a357dbef.56af58"],["25232dfe.1d5632"]]},{"id":"d562d571.3d70b8","type":"link in","z":"dfca7471.a1e698","name":"experiment_setup","links":["cad5031f.ce83b","78729d33.d2d714"],"x":55,"y":240,"wires":[["422359ef.8e2e38"]]},{"id":"5d7a5c2e.85f964","type":"link in","z":"dfca7471.a1e698","name":"PUT","links":["72a6250f.461e0c","f588c087.1ce03"],"x":55,"y":480,"wires":[["658babd1.b88c94"]]},{"id":"67232339.a0ba8c","type":"link in","z":"dfca7471.a1e698","name":"action","links":["d3e95180.f9e2b","1aa0e54a.3fa1db","cf320c23.2bd3d","9c93a6b7.ba11f8","570f448.32383bc"],"x":55,"y":700,"wires":[["e08b2ee5.d7ded"]]},{"id":"f588c087.1ce03","type":"link out","z":"dfca7471.a1e698","name":"reasoning","links":["5d7a5c2e.85f964"],"x":1015,"y":240,"wires":[]},{"id":"570f448.32383bc","type":"link out","z":"dfca7471.a1e698","name":"reasoning","links":["67232339.a0ba8c"],"x":1115,"y":480,"wires":[]},{"id":"5f39396e.667518","type":"link in","z":"dfca7471.a1e698","name":"planning","links":["cf45859f.5ab428","f15a1d2b.73394","cffaf00b.9bed6","ed15d9e.4ac6828","b1e465c3.f8bfc8","84f4b1eb.de37d","d4b35c63.7c04d","c84ff049.b212a","840ee49d.5fb4e8","39a0e98a.cf8746","b2f400ee.b1541","53283c8b.9f6924","78701514.aa6d2c","58cd477f.734778","620458e1.f98428","b699e30.3d6f72","1b935ea9.7984e1"],"x":295,"y":440,"wires":[["dc2897d8.b779c8"]]},{"id":"1c66ecc.ac53013","type":"UPI_exec","z":"dfca7471.a1e698","name":"PUT Exec","host":"127.0.0.1","port":"6200","timeout":"10000","retry":"3","reload_MAC":true,"x":600,"y":480,"wires":[["628d5c69.bb29a4"]]},{"id":"93a77663.cb66d8","type":"UPI_exec","z":"2ccc54b4.8ffd1c","name":"Default Exec","host":"127.0.0.1","port":"6200","timeout":"10000","retry":"3","reload_MAC":true,"x":430,"y":100,"wires":[["af8c03e1.2882f"]]},{"id":"82ebe0aa.f1317","type":"UPI_exec","z":"7823bf3e.a929f","name":"Reset Exec","host":"127.0.0.1","port":"6200","timeout":"10000","retry":"3","reload_MAC":false,"x":390,"y":280,"wires":[["f6036096.b398"]]},{"id":"655a6ecf.d0d2a","type":"UPI_exec","z":"7823bf3e.a929f","name":"Retrv Exec","host":"127.0.0.1","port":"6200","timeout":"10000","retry":"3","reload_MAC":false,"x":390,"y":600,"wires":[["25bd72f4.2afabe"]]},{"id":"25bd72f4.2afabe","type":"function","z":"7823bf3e.a929f","name":"centr_output","func":"\n// Function to calculate the current consumption (mA) of CC2520 radio chip for different Transmit power settings\nfunction TXdBm2mA(TXdBm)\n{\n if(TXdBm == -18) return 10.2; else if(TXdBm == -7) return 15.3;\n else if(TXdBm == -4) return 18.4; else if(TXdBm == -2) return 22.1;\n else if(TXdBm === 0) return 25.8; else if(TXdBm === 1) return 26.7;\n else if(TXdBm === 2) return 27.9; else if(TXdBm === 3) return 29.5;\n else if(TXdBm === 5) return 33.6; else return 33.6;\n \n}\n\n// Function to generate sampleSet header string\nfunction gen_sampleSet_hdr_str()\n{\n // Retreive global PUT variable\n var PUT = context.global.PUT;\n\n var PUT_ctrl_hdr = PUT.control_hdr;\n var lower_bound = \"\";\n var upper_bound = \"\";\n var steps = \"\";\n for (var key in PUT_ctrl_hdr)\n {\n \t// Sort values in ascending order\n \tvar values = PUT_ctrl_hdr[key].values.sort(function(a, b){return a - b;});\n \n \t// Calculate step width\n\t\tvar step = 0;\n\t\tif(values.length == 1)\n\t\t{\n\t\t\tstep = values[0];\n\t\t}\n\t\telse if(values.length > 1)\n\t\t{\n\t\t\tvar array_sum = values.reduce(function (a, b) {return a + b;}, 0);\n\t\t\tstep = 2*(array_sum - values.length * values[0]) / ( values.length * (values.length - 1) );\n\t\t}\n \n \tlower_bound = lower_bound + values[0] + \",\";\n \tupper_bound = upper_bound + values[values.length - 1] + \",\";\n \tsteps = steps + step + \",\";\n }\n lower_bound = lower_bound.slice(0, -1);\n upper_bound = upper_bound.slice(0, -1);\n steps = steps.slice(0, -1);\n \n return \"[ \" + lower_bound + \" ; \" + upper_bound + \" ; \" + steps + \" ]\";\n}\n\n// Function to calculate average of an array\nfunction AVG(data)\n{\n\tif(data.length === 0)\n\t\treturn 0;\n\telse\n\t return (data.reduce(function (a,b) { return a+b; }) / data.length);\n}\n\n// Relative [population] standard deviation calculation of an array\nfunction STD_rel(data)\n{\n\t// Calculate average\n\tvar avg = AVG(data);\n \t\n\tif(avg === 0)\n\t\treturn 0;\n\telse\n \t// Calculate relative standard daviation\n\t\treturn Math.sqrt(AVG(data.map(function (val) { return Math.pow(val-avg, 2); }))) / avg;\n}\n\n// Median calculation of an array\nfunction MEDIAN(data)\n{\n // Sort data in ascending order\n var sorted_data = data.slice(0).sort( function(a,b) {return a - b;} );\n \n // Calculate the half point\n var half = Math.floor(sorted_data.length/2);\n \n // If data length is odd, return the middle value\n if (sorted_data.length % 2)\n return sorted_data[half];\n // If data length is even, return the average of the middle two values\n else\n return (sorted_data[half-1] + sorted_data[half]) / 2.0;\n}\n\n// Median Absolute Deviation calculation\nfunction MAD (data)\n{\n var median = MEDIAN(data);\n var absoluteDeviation = data.map(function (val)\n {\n return Math.abs(val - median);\n });\n \n return MEDIAN(absoluteDeviation);\n}\n\n// Calculate data outliers using Iglewicz and Hoaglin method.\n// values with a Z-score > 3.5 are considered potential outliers\nfunction indexOfOutliers (data)\n{\n\tvar dataMedian = MEDIAN(data);\n\tvar dataMAD = MAD(data);\n\n\treturn data.reduce(function (res, val, i)\n\t{\n\t\tif (Math.abs((0.6745 * (val - dataMedian)) / dataMAD) > 3.5)\n\t\t\tres.push(i);\n\t\treturn res;\n\t}, []);\n}\n\n// Retreive PUT parameters\nvar PUT_params = context.global.PUT_params;\nvar sampleSet_array = PUT_params[Object.keys(PUT_params)[0]];\n\n// Retrieve error message\nvar error_msg = msg.error_msg;\n\n// Do we have an error message\nif(error_msg.length !== 0)\n{\n msg = {};\n msg.sample_Idx = context.global.sample_Idx;\n msg.payload = sampleSet_array;\n return [msg, null, null, {payload: error_msg}];\n}\nelse\n{\n // Control opcode enumeration\n var UID =\n {\n TXSTATS : 57219,\n RXSTATS : 57216,\n ENERGESTSTATS : 57220\n };\n \n var GROUPs = context.global.GROUPs;\n var sink_ptsFile = GROUPs.sink[0].ptsFile;\n \n // Sample index\n var sample_Idx = context.global.sample_Idx;\n \n var payload = msg.payload;\n var LAT_array = [];\n var PER_array = [];\n var Energy_sink = 0;\n var Energy_source = 0;\n for(var i = 0; i < payload.length; i++)\n {\n var ptsFile = payload[i].request.ptsFile;\n var response = payload[i].response;\n var num_param = response.num_param;\n \n // We expect one message\n if(num_param === 1)\n {\n var control_hdr = response.control_hdr[0];\n var uid = control_hdr.uid;\n \n // TxStat message\n if(uid === UID.TXSTATS)\n {\n var value = Buffer.from(control_hdr.value, 'hex');\n \n var latency_sum = value.readUInt32LE(0);\n var latency_count = value.readUInt16LE(4);\n\n // Calculate performance objectives\n LAT_array.push(parseFloat(latency_sum / (1000*latency_count)));\n }\n // RxStat message\n else if(uid === UID.RXSTATS)\n {\n var value = Buffer.from(control_hdr.value, 'hex');\n \n var packet_recvd = value.readUInt16LE(4);\n var packet_lost = value.readUInt16LE(6);\n \n // Calculate performance objectives\n if(packet_recvd > 0)\n PER_array.push(parseFloat(100 * packet_lost/(packet_lost + packet_recvd)));\n else\n PER_array.push(100.0);\n }\n // Energest message\n else if(uid === UID.ENERGESTSTATS)\n {\n var value = Buffer.from(control_hdr.value, 'hex');\n \n var Tx_mA = TXdBm2mA(sampleSet_array[0]);\n var TX_energy = (value.readUInt32LE(0)/1000000) * Tx_mA * 3;\n var LST_energy = (value.readUInt32LE(4)/1000000) * 22.3 * 3;\n var IDLE_energy = (value.readUInt32LE(8)/1000000) * 1.6 * 3;\n var SLEEP_energy = (value.readUInt32LE(12)/1000000) * 0.175 * 3;\n \n // Sink node\n if(ptsFile === sink_ptsFile)\n Energy_sink += TX_energy + LST_energy + IDLE_energy + SLEEP_energy;\n // source nodes\n else\n Energy_source += TX_energy + LST_energy + IDLE_energy + SLEEP_energy;\n }\n }\n }\n // Calculate average [Lateny and PER] values\n var LAT_avg = AVG(LAT_array);\n var PER_avg = AVG(PER_array);\n \n // Make sure all objectives are numbers\n if(isNaN(LAT_avg) || isNaN(PER_avg) || isNaN(Energy_sink) || isNaN(Energy_source))\n {\n msg = {};\n msg.sample_Idx = sample_Idx;\n msg.payload = sampleSet_array;\n error_msg = \"At least one objective value is NaN. LAT_avg=\" + LAT_avg + \" PER_avg=\" + PER_avg + \" Energy_sink=\" + Energy_sink + \" Energy_source=\" + Energy_source;\n return [msg, null, null, {payload: error_msg}];\n }\n else\n {\n // Create empty performance objective arrays\n if(typeof(context.LAT_avg_array) === \"undefined\" || typeof(context.PER_avg_array) === \"undefined\" || typeof(context.Energy_sink_array) === \"undefined\" || typeof(context.Energy_source_array) === \"undefined\")\n {\n context.LAT_avg_array = [];\n context.PER_avg_array = [];\n context.Energy_sink_array = [];\n context.Energy_source_array = [];\n }\n \n // Populate performance objective arrays\n context.LAT_avg_array.push(LAT_avg);\n context.PER_avg_array.push(PER_avg);\n context.Energy_sink_array.push(Energy_sink);\n context.Energy_source_array.push(Energy_source);\n \n // Repeated experiment counter and maximum value\n var reptd_expr_count = context.global.reptd_expr_count;\n var reptd_expr_max = context.global.reptd_expr_max;\n \n // Check if experiment counter reached the maximum\n if(reptd_expr_count == reptd_expr_max - 1)\n {\n // Remove outliers from latency data\n var outlier_Idx = indexOfOutliers(context.LAT_avg_array);\n for(var i = outlier_Idx.length - 1; i >= 0; i--)\n {\n context.LAT_avg_array.splice(outlier_Idx[i], 1);\n context.PER_avg_array.splice(outlier_Idx[i], 1);\n context.Energy_sink_array.splice(outlier_Idx[i], 1);\n context.Energy_source_array.splice(outlier_Idx[i], 1);\n }\n // Remove outliers from PER data\n outlier_Idx = indexOfOutliers(context.PER_avg_array);\n for(var i = outlier_Idx.length - 1; i >= 0; i--)\n {\n context.LAT_avg_array.splice(outlier_Idx[i], 1);\n context.PER_avg_array.splice(outlier_Idx[i], 1);\n context.Energy_sink_array.splice(outlier_Idx[i], 1);\n context.Energy_source_array.splice(outlier_Idx[i], 1);\n }\n // Remove outliers from energy sink data\n outlier_Idx = indexOfOutliers(context.Energy_sink_array);\n for(var i = outlier_Idx.length - 1; i >= 0; i--)\n {\n context.LAT_avg_array.splice(outlier_Idx[i], 1);\n context.PER_avg_array.splice(outlier_Idx[i], 1);\n context.Energy_sink_array.splice(outlier_Idx[i], 1);\n context.Energy_source_array.splice(outlier_Idx[i], 1);\n }\n // Remove outliers from energy source data\n outlier_Idx = indexOfOutliers(context.Energy_source_array);\n for(var i = outlier_Idx.length - 1; i >= 0; i--)\n {\n context.LAT_avg_array.splice(outlier_Idx[i], 1);\n context.PER_avg_array.splice(outlier_Idx[i], 1);\n context.Energy_sink_array.splice(outlier_Idx[i], 1);\n context.Energy_source_array.splice(outlier_Idx[i], 1);\n }\n \n // Calculate average of performance objective arrays\n var LAT_avg_avg = AVG(context.LAT_avg_array);\n var PER_avg_avg = AVG(context.PER_avg_array);\n var Energy_sink_avg = AVG(context.Energy_sink_array);\n var Energy_source_avg = AVG(context.Energy_source_array);\n var Energy_total_avg = Energy_sink_avg + Energy_source_avg;\n \n // Calculate standard deviation of performance objective arrays\n var LAT_avg_std = STD_rel(context.LAT_avg_array);\n var PER_avg_std = STD_rel(context.PER_avg_array);\n var Energy_sink_std = STD_rel(context.Energy_sink_array);\n var Energy_source_std = STD_rel(context.Energy_source_array);\n \n // Performance objective arrays length\n var dataLen = context.LAT_avg_array.length + \"/\" + reptd_expr_max;\n \n // Formulate objective string\n var obj_str = LAT_avg_avg + \"\\t\" + PER_avg_avg + \"\\t\" + Energy_total_avg + \"\\t\" + Energy_sink_avg + \"\\t\" + Energy_source_avg + \"\\t\" + LAT_avg_std + \"\\t\" + PER_avg_std + \"\\t\" + Energy_sink_std + \"\\t\" + Energy_source_std + \"\\t\" + dataLen;\n \n var sampleSet_str = \"\";\n // First message includes sampleSet header\n if(sample_Idx === 0)\n sampleSet_str = sampleSet_str + gen_sampleSet_hdr_str() + \"\\n\";\n // Add PUT parameters\n sampleSet_str = sampleSet_str + sampleSet_array.join('\\t');\n // Add performance objectives\n sampleSet_str = sampleSet_str + \"\\t\" + obj_str;\n \n // MOSBO file path and sampleSet string\n msg.payload = [{filename: \"/home/mmehari/SUMO/single-hop_WSN/samplesValues.txt\", payload: sampleSet_str}];\n msg.sample_Idx = sample_Idx;\n delete msg.error_msg;\n \n // Reset performance objective arrays\n context.LAT_avg_array = [];\n context.PER_avg_array = [];\n context.Energy_sink_array = [];\n context.Energy_source_array = [];\n \n // Reset repeated experiment counter\n context.global.reptd_expr_count = 0;\n \n // Update sample index\n context.global.sample_Idx = sample_Idx + 1;\n \n if(sample_Idx === 0)\n return [null, msg, null, null];\n else\n return [null, null, msg, null];\n }\n else\n {\n // Increase repeated experiment counter\n reptd_expr_count = reptd_expr_count + 1;\n context.global.reptd_expr_count = reptd_expr_count;\n \n // Restart current experiment\n msg = {};\n msg.sample_Idx = sample_Idx;\n msg.payload = sampleSet_array;\n return [msg, null, null, {payload: \"reptd_expr_count = \" + reptd_expr_count + \"/\" + reptd_expr_max}];\n }\n }\n}\n","outputs":"4","noerr":0,"x":570,"y":600,"wires":[["25413c89.512fa4"],["98509978.45f6b8"],["c1e616dc.c824d8"],["f59ec35d.47189"]]},{"id":"8b109a79.481828","type":"comment","z":"dfca7471.a1e698","name":"Collection","info":"","x":760,"y":440,"wires":[]},{"id":"bc25892c.d242e8","type":"function","z":"7823bf3e.a929f","name":"Reset","func":"\n// Control opcode enumeration\nvar UID =\n{\n TXSTATS : 57219,\n RXSTATS : 57216,\n ENERGESTSTATS : 57220\n};\n\n// Default application parameters\nvar GROUPs = context.global.GROUPs;\nvar sink_ptsFile = GROUPs.sink[0].ptsFile;\nvar source_ptsFiles = [];\nfor(var i = 0; i < GROUPs.source.length; i++)\n source_ptsFiles.push(GROUPs.source[i].ptsFile);\n\n// Integer to hexadicimal string convertor\nvar int2hex = context.global.int2hex;\n\nvar parameters = [];\nfor(var i = 0; i < source_ptsFiles.length; i++)\n{\n var ptsFile = source_ptsFiles[i];\n\n // Reset TxStat parameters\n var latency_sum_hex = int2hex(0, 4);\n var latency_count_hex = int2hex(0, 2);\n \n var txstats_value = latency_sum_hex + latency_count_hex;\n var txstats_len = txstats_value.length / 2;\n var tx_parameter = \n {\n ptsFile: ptsFile,\n opcode: 1,\n control_hdr:\n [\n { uid: UID.TXSTATS, type: 0xFF, len: txstats_len, value: txstats_value }\n ]\n };\n parameters.push(tx_parameter);\n\n // Reset RxStat parameters \n var sender_ID;\n var rxstats_value = \"\";\n // Search for sender ID from the given pts device file path\n for(var j = 0; j < GROUPs.source.length; j++)\n {\n if(ptsFile == GROUPs.source[j].ptsFile)\n {\n // senser ID is sent through the type attribute of control_hdr structure\n sender_ID = GROUPs.source[j].ID;\n \n var rssi_sum_hex = int2hex(0, 2);\n var lqi_sum_hex = int2hex(0, 2);\n var packet_recvd_hex = int2hex(0, 2);\n var packet_lost_hex = int2hex(0, 2);\n\n rxstats_value = rssi_sum_hex + lqi_sum_hex + packet_recvd_hex + packet_lost_hex;\n break;\n }\n }\n var rxstats_len = rxstats_value.length / 2;\n var rx_parameter = \n {\n ptsFile: sink_ptsFile,\n opcode: 1,\n control_hdr:\n [\n { uid: UID.RXSTATS, type: sender_ID, len: rxstats_len, value: rxstats_value }\n ]\n };\n parameters.push(rx_parameter);\n \n // Reset energest parameters on source nodes\n var energest_parameter =\n {\n ptsFile: ptsFile,\n opcode: 1,\n control_hdr:\n [\n { uid: UID.ENERGESTSTATS, type: 0xFF, len: 1, value: \"FF\" }\n ]\n };\n parameters.push(energest_parameter);\n}\n\n// Reset energest parameters on sink node\nvar energest_parameter =\n{\n ptsFile: sink_ptsFile,\n opcode: 1,\n control_hdr:\n [\n { uid: UID.ENERGESTSTATS, type: 0xFF, len: 1, value: \"FF\" }\n ]\n};\nparameters.push(energest_parameter);\n\n\n\n// ******* Do not change beyond this line ******* //\nmsg.payload = parameters;\nmsg.port = context.global.pts_mux_port;\n\nreturn msg;\n\n","outputs":1,"noerr":0,"x":230,"y":280,"wires":[["82ebe0aa.f1317"]]},{"id":"98509978.45f6b8","type":"Mfile_out","z":"7823bf3e.a929f","name":"header","appendNewline":true,"overwriteFile":"true","x":740,"y":580,"wires":[["8e46b0fc.31eca"]]},{"id":"c1e616dc.c824d8","type":"Mfile_out","z":"7823bf3e.a929f","name":"dataset","appendNewline":true,"overwriteFile":"false","x":740,"y":620,"wires":[["8e46b0fc.31eca"]]},{"id":"f7a2f887.5fd728","type":"subflow:4bd24dc8.2d0bd4","z":"dfca7471.a1e698","name":"","x":410,"y":240,"wires":[["d490cced.0bfc","f995d8d8.0d4328","9264f556.824c38"]]},{"id":"f04a5251.eb484","type":"inject","z":"dfca7471.a1e698","name":"Start experiment","topic":"start_experiment","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":140,"y":80,"wires":[["78729d33.d2d714"]]},{"id":"78729d33.d2d714","type":"link out","z":"dfca7471.a1e698","name":"experiment_setup","links":["d562d571.3d70b8"],"x":275,"y":80,"wires":[]},{"id":"614f3a7b.531ea4","type":"function","z":"7823bf3e.a929f","name":"5 packet delay","func":"\n// packet count to be sent\nvar packet_count = 5;\n\n// Sending interval in usec\nvar send_interval_ticks = context.global.send_interval; \nvar send_interval_usec = send_interval_ticks * 1000000 / 128;\n\n// Wait until [packet_count] packets are sent\nvar delay_usec = packet_count * send_interval_usec + 10000;\n\nmsg.payload = delay_usec.toString() + \"\\n\";\n\n// If simTimer port exists as a global variable\nif(typeof(context.global.simTimer_port) !== \"undefined\")\n msg.port = context.global.simTimer_port;\n\nreturn msg;","outputs":1,"noerr":0,"x":260,"y":440,"wires":[["85e538ae.291218"]]},{"id":"85e538ae.291218","type":"tcpClient","z":"7823bf3e.a929f","name":"simTimer","host":"127.0.0.1","port":"7700","timeout":"60000","client_disconnects":false,"x":440,"y":440,"wires":[["7c74086a.613078"],["27fe6cb0.8612a4"]]},{"id":"a82291be.4a432","type":"model-creation","z":"dfca7471.a1e698","outCol_Idx":"7,8,9","max_iter":"500","cv_folds":"10","cv_iter":"20","cv_std_thold":"0.01","cv_std_width":"5","name":"SUMO-model","x":980,"y":480,"wires":[["1b935ea9.7984e1","46b9cd8.c881534"],["570f448.32383bc"],["eedfe88b.bb6c28"]]},{"id":"8e46b0fc.31eca","type":"split","z":"7823bf3e.a929f","name":"","splt":"\\n","x":890,"y":600,"wires":[[]]},{"id":"27fe6cb0.8612a4","type":"link out","z":"7823bf3e.a929f","name":"stderr","links":["c26cb2.cecd835"],"x":555,"y":460,"wires":[]},{"id":"683e0903.c018b8","type":"debug","z":"4bd24dc8.2d0bd4","name":"cooja_stderr","active":true,"console":"false","complete":"true","x":890,"y":440,"wires":[]},{"id":"a357dbef.56af58","type":"delay","z":"2ccc54b4.8ffd1c","name":"delay","pauseType":"delay","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":770,"y":80,"wires":[[]]},{"id":"fdf7d5a4.e13a78","type":"file","z":"f439654.2d2c198","name":"data","filename":"/home/mmehari/GRAPH/cv_score.log","appendNewline":true,"createDir":true,"overwriteFile":"false","x":410,"y":120,"wires":[]},{"id":"a3e3d1fe.f25b1","type":"file","z":"f439654.2d2c198","name":"hdr","filename":"/home/mmehari/GRAPH/cv_score.log","appendNewline":true,"createDir":true,"overwriteFile":"true","x":410,"y":80,"wires":[]},{"id":"90728140.743ce","type":"function","z":"f439654.2d2c198","name":"CV_parser","func":"\nif(typeof(msg.sample_Idx) !== \"undefined\")\n{\n // First message\n if(msg.sample_Idx == 1)\n {\n msg.payload = \"H:CV_score#ITER||score1,score2,score3\\nH:CV_std#ITER||std1,std2,std3\\n\";\n context.iter = 0;\n return [msg, null];\n }\n else if(typeof(msg.cv_score) !== \"undefined\")\n {\n context.iter = context.iter + 1;\n \n msg.payload = \"D:CV_score\\t\" + context.iter + \"\\t\" + msg.cv_score.join(\"\\t\");\n if(typeof(msg.cv_std) !== \"undefined\")\n {\n msg.payload = msg.payload + \"\\nD:CV_std\\t\" + context.iter + \"\\t\" + msg.cv_std.join(\"\\t\");\n }\n return [null, msg];\n }\n}","outputs":"2","noerr":0,"x":250,"y":100,"wires":[["a3e3d1fe.f25b1"],["fdf7d5a4.e13a78"]]},{"id":"620458e1.f98428","type":"link out","z":"dfca7471.a1e698","name":"collection","links":["5f39396e.667518","5f4a2077.c42f2"],"x":915,"y":400,"wires":[]},{"id":"6f4a8bda.c013e4","type":"function","z":"9e87c9ce.0ab558","name":"email notification","func":"\nmsg.payload = \"Experiment has ended\";\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":160,"wires":[["1e47311c.96e34f"]]},{"id":"ed0ef637.615ba8","type":"delay","z":"7823bf3e.a929f","name":"delay","pauseType":"delay","timeout":"100","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":850,"y":240,"wires":[[]]},{"id":"1b935ea9.7984e1","type":"link out","z":"dfca7471.a1e698","name":"reasoning","links":["5f39396e.667518","5f4a2077.c42f2"],"x":1115,"y":400,"wires":[]},{"id":"16e6c4cf.ce4b4b","type":"link out","z":"6ecf21cd.62a7b","name":"stderr","links":["7735c2ce.08c65c"],"x":675,"y":160,"wires":[]},{"id":"3972ce6c.855b12","type":"exec","z":"9e87c9ce.0ab558","command":"killall java ; killall pts_mux","addpay":false,"append":"","useSpawn":"","timer":"","name":"Stop APPs","x":310,"y":220,"wires":[[],["1e47311c.96e34f"],[]]},{"id":"dc2897d8.b779c8","type":"exhaustive-search","z":"dfca7471.a1e698","name":"exhaustive","x":430,"y":480,"wires":[["1c66ecc.ac53013"],["dddd50c4.346e9"]]},{"id":"ea0f4f43.ffddb","type":"function","z":"4bd24dc8.2d0bd4","name":"check","func":"\nvar msg1 = {};\nvar msg2 = {};\n\n// Empty payload => cooja is not started\nif(msg.payload === \"\")\n{\n msg.payload = \"ERROR: cooja simulation is not started\";\n return [null, null, msg];\n}\nelse\n{\n var ptyFiles_IDs = msg.payload.split('\\n').filter(function(e){return e;});\n var ptyFiles = [];\n for(var i = 0; i < ptyFiles_IDs.length; i++)\n ptyFiles.push(ptyFiles_IDs[i].split('\\t')[1]);\n\n return [{payload: ptyFiles_IDs}, {payload: ptyFiles.join(',')}, null];\n}","outputs":"3","noerr":0,"x":350,"y":400,"wires":[["e9b80322.b22b8"],["4220b151.1374b"],["84ed04d3.ccb498"]]},{"id":"9641f49a.6c5638","type":"comment","z":"4bd24dc8.2d0bd4","name":"Retrieve pts devices","info":"","x":130,"y":360,"wires":[]},{"id":"c314ba76.aa4f48","type":"function","z":"4bd24dc8.2d0bd4","name":"cooja csc template","func":"// Retrieve extention name of a path\nfunction extName(path)\n{\n return path.substring(path.lastIndexOf('.') + 1); \n}\n\n// Retrieve base name of a path\nfunction baseName(path)\n{\n var base = path.substring(path.lastIndexOf('/') + 1); \n if(base.lastIndexOf(\".\") != -1) \n base = base.substring(0, base.lastIndexOf(\".\"));\n return base;\n}\n\n// Retrieve directory name of a path\nfunction dirName(path)\n{\n var dir = \"\";\n if(path.lastIndexOf('/') != -1)\n dir = path.substring(0, path.lastIndexOf('/'));\n else\n dir = path;\n return dir;\n}\n\nvar cooja = msg.cooja;\nvar title = (typeof(cooja.title) !== \"undefined\") ? cooja.title : \"node-red_cooja_example\";\nvar randomseed = (typeof(cooja.randomseed) !== \"undefined\") ? cooja.randomseed : \"generated\";\n\nvar transmitting_range = cooja.radiomedium.transmitting_range;\nvar interference_range = cooja.radiomedium.interference_range;\nvar success_ratio_tx = cooja.radiomedium.success_ratio_tx;\nvar success_ratio_rx = cooja.radiomedium.success_ratio_rx;\n\nvar CONTIKI_DIR = cooja.motetype.CONTIKI_DIR;\nvar firm_path_rel = cooja.motetype.firm_path_rel;\n\nvar firm_path_CONTIKI = \"[CONTIKI_DIR]/\" + firm_path_rel;\nvar platform = extName(firm_path_rel);\n\nvar simconf = \n[\n {name: \"simulation\", children:\n [\n {name: \"title\", text: title},\n// {name: \"speedlimit\", text: \"1.0\"},\n {name: \"randomseed\", text: randomseed},\n {name: \"motedelay_us\", text: \"1000000\"},\n {name: \"radiomedium\", text: \"org.contikios.cooja.radiomediums.UDGM\", children: \n [\n {name: \"transmitting_range\", text: transmitting_range},\n {name: \"interference_range\", text: interference_range},\n {name: \"success_ratio_tx\", text: success_ratio_tx},\n {name: \"success_ratio_rx\", text: success_ratio_rx}\n ]},\n {name: \"events\", children: \n [\n {name: \"logoutput\", text: \"40000\"}\n ]},\n ]}\n];\n\n// Create mote configuration\nvar GROUPs = context.global.GROUPs;\n\n// Add mote configuration to simulation configuration\nfor(var i in simconf)\n{\n // Search the last object within simulation object\n if(simconf[i].name == 'simulation')\n {\n var sim_obj = simconf[i].children;\n var key = Object.keys(sim_obj)[Object.keys(sim_obj).length-1] + 1;\n \n // Solution Under Test (SUT) motetype configuration\n if(GROUPs.sink.length > 0 || GROUPs.source.length > 0)\n {\n sim_obj[key] = {name: \"motetype\", text: \"org.contikios.cooja.mspmote.\" + platform.toUpperCase() + \"MoteType\", children:\n [\n {name: \"identifier\", text: platform + \"1\"},\n {name: \"description\", text: platform + \" Mote Type #\" + platform},\n {name: \"firmware\", text: firm_path_CONTIKI, attrs: {EXPORT: \"copy\"}},\n [\n {name: \"moteinterface\", text: \"org.contikios.cooja.interfaces.Position\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.interfaces.RimeAddress\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.interfaces.IPAddress\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.interfaces.Mote2MoteRelations\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.interfaces.MoteAttributes\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.mspmote.interfaces.MspClock\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.mspmote.interfaces.MspMoteID\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.mspmote.interfaces.MspButton\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.mspmote.interfaces.CC2520Radio\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.mspmote.interfaces.UsciA1Serial\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.mspmote.interfaces.MspLED\"},\n {name: \"moteinterface\", text: \"org.contikios.cooja.mspmote.interfaces.MspDebugOutput\"}\n ]\n ]};\n key++;\n }\n // Disturber motetype configuration\n if(GROUPs.disturber.length > 0)\n {\n sim_obj[key] = {name: \"motetype\", text: \"org.contikios.cooja.motes.DisturberMoteType\", children:\n [\n {name: \"identifier\", text: \"apptype1\"},\n {name: \"description\", text: \"Disturber Mote Type #apptype1\"}\n ]};\n key++;\n }\n \n for(var g in GROUPs)\n {\n // Sink and Source nodes mote configuration\n if(g === \"sink\" || g === \"source\")\n {\n for(var n in GROUPs[g])\n {\n sim_obj[key] = {name: \"mote\", children:\n [\n {name: \"breakpoints\"},\n {name: \"interface_config\", text: \"org.contikios.cooja.interfaces.Position\", children:\n [\n {name: \"x\", text: GROUPs[g][n].loc.X},\n {name: \"y\", text: GROUPs[g][n].loc.Y},\n {name: \"z\", text: \"0\"}\n ]},\n {name: \"interface_config\", text: \"org.contikios.cooja.mspmote.interfaces.MspClock\", children: [{name: \"deviation\", text: \"1.0\"}]},\n {name: \"interface_config\", text: \"org.contikios.cooja.mspmote.interfaces.MspMoteID\", children: [{name: \"id\", text: GROUPs[g][n].ID}]},\n {name: \"motetype_identifier\", text: platform + \"1\"}\n ]};\n key++;\n }\n }\n // Disturber nodes mote configuration\n else if(g === \"disturber\")\n {\n for(var n in GROUPs[g])\n {\n sim_obj[key] = {name: \"mote\", children:\n [\n {name: \"interface_config\", text: \"org.contikios.cooja.interfaces.Position\", children:\n [\n {name: \"x\", text: GROUPs[g][n].loc.X},\n {name: \"y\", text: GROUPs[g][n].loc.Y},\n {name: \"z\", text: \"0\"}\n ]},\n {name: \"interface_config\", text: \"org.contikios.cooja.motes.AbstractApplicationMoteType$SimpleMoteID\", children: [{name: \"id\", text: GROUPs[g][n].ID}]},\n {name: \"motetype_identifier\", text: \"apptype1\"}\n ]};\n key++;\n }\n }\n }\n }\n}\n\n// Plugin configuration section\n// Simulation Timer plugin configuration\nsimconf.push({name: \"plugin\", text: \"org.contikios.cooja.plugins.simTimer\"});\n\n// Serial2Pty plugin configuration\nsimconf.push({name: \"plugin\", text: \"de.fau.cooja.plugins.Serial2PtyPlugin\"});\n\n// Script Runner plugin configuration\nsimconf.push({name: \"plugin\", text: \"org.contikios.cooja.plugins.ScriptRunner\", children:\n[\n {name: \"plugin_config\", children: \n [\n {name: \"script\", text: \"\\/\\/ Nashorn compatibility module for using importPackage within java 8\\nload(\\\"nashorn:mozilla_compat.js\\\");\\n\\/\\/import Java Package to JavaScript\\nimportPackage(java.io);\\n\\/\\/ file writer object\\nvar logWriter = new FileWriter(\\\"\" + cooja.contiki_log + \"\\\");\\n\\/\\/ Wait very long\\nTIMEOUT(1000000000000);\\nwhile (true){\\n\\tlogWriter.write(time + \\\" \\\" + id + \\\" \\\" + msg + \\\"\\\\n\\\");\\n\\tlogWriter.flush();\\n\\tYIELD();\\n}\"},\n {name: \"active\", text: \"true\"}\n ]}]\n});\n\n// Extra configuration for gui simulation mode\nif(msg.simulation_mode === \"gui\")\n{\n // Event Listener plugin configuration\n simconf.push({name: \"plugin\", text: \"org.contikios.cooja.plugins.EventListener\"});\n \n // Power Tracker plugin configuration\n simconf.push({name: \"plugin\", text: \"PowerTracker\"});\n \n // Log listener plugin configuration\n simconf.push({name: \"plugin\", text: \"org.contikios.cooja.plugins.LogListener\"});\n \n // simulation control plugin configuration\n simconf.push({name: \"plugin\", text: \"org.contikios.cooja.plugins.SimControl\"});\n \n // Visualizer plugin configuration\n simconf.push({name: \"plugin\", text: \"org.contikios.cooja.plugins.Visualizer\", children:\n [\n {name: \"plugin_config\", children:\n [\n {name: \"skin\", text: \"org.contikios.cooja.plugins.skins.IDVisualizerSkin\"},\n {name: \"skin\", text: \"org.contikios.cooja.plugins.skins.GridVisualizerSkin\"},\n {name: \"skin\", text: \"org.contikios.cooja.plugins.skins.TrafficVisualizerSkin\"},\n {name: \"skin\", text: \"org.contikios.cooja.plugins.skins.UDGMVisualizerSkin\"},\n ]}\n ]});\n \n // Timeline plugin configuration\n var motecount = 0;\n var plugin_config = [];\n for(var g in GROUPs)\n {\n for(var n in GROUPs[g])\n {\n plugin_config.push({name: \"mote\", text: motecount});\n motecount++;\n }\n }\n plugin_config.push({name: \"showRadioRXTX\"});\n plugin_config.push({name: \"showRadioHW\"});\n simconf.push({name: \"plugin\", text: \"org.contikios.cooja.plugins.TimeLine\", children:\n [\n {name: \"plugin_config\", children: plugin_config}\n ]});\n}\n\nmsg.payload = {simconf: simconf};\n\nvar csc_path_rel = dirName(firm_path_rel) + \"/\" + baseName(firm_path_rel) + \".csc\";\nmsg.filename = CONTIKI_DIR + \"/\" + csc_path_rel;\n\ncooja.motetype.csc_path_rel = csc_path_rel;\n\nreturn msg;\n","outputs":1,"noerr":0,"x":210,"y":100,"wires":[["701e4c.2a85a1b4"]]},{"id":"5b6700a8.3c695","type":"comment","z":"4bd24dc8.2d0bd4","name":"Create cooja simulation file","info":"","x":150,"y":60,"wires":[]},{"id":"4220b151.1374b","type":"exec","z":"4bd24dc8.2d0bd4","command":"pts_mux -g","addpay":true,"append":"","useSpawn":true,"timer":"","name":"start pts_mux","x":520,"y":400,"wires":[["e3550a12.b34508"],["ce8649c5.d13bc8"],[]]},{"id":"e3550a12.b34508","type":"function","z":"4bd24dc8.2d0bd4","name":"pts to nodeID","func":"\nif(msg.payload.indexOf(\"pts_mux has STARTED on port \") !== -1)\n{\n context.pts_mux_port = msg.payload.substring(msg.payload.indexOf(\"pts_mux has STARTED on port \") + 28).trim();\n}\nelse\n{\n context.ptyFiles_IDs = msg.payload;\n}\n\nif(typeof context.pts_mux_port !== 'undefined' && typeof context.ptyFiles_IDs !== 'undefined')\n//if(typeof context.ptyFiles_IDs !== 'undefined')\n{\n var ptyFiles_IDs = context.ptyFiles_IDs;\n var GROUPs = context.global.GROUPs;\n \n // Make sure the number of assigned and configured pts devices are the same\n var pts_count = ptyFiles_IDs.length;\n var sink_count = GROUPs.sink.length;\n var source_count = GROUPs.source.length;\n var disturber_count = GROUPs.disturber.length;\n if(pts_count != sink_count + source_count + disturber_count)\n {\n msg.error = \"Assigned and configured nodes count does not match\";\n delete msg.payload;\n return [null, msg];\n }\n\n // Match [sink,source,disturber] nodes to pts devices\n\touter_loop:\n for(var i = 0; i < ptyFiles_IDs.length; i++)\n {\n var moteID = parseInt(ptyFiles_IDs[i].split('\\t')[0]);\n var ptyFile = ptyFiles_IDs[i].split('\\t')[1];\n\n // Search mote ID within sink nodes\n for(var j = 0; j < sink_count; j++)\n {\n if(GROUPs.sink[j].ID === moteID)\n {\n GROUPs.sink[j].ptsFile = ptyFile;\n continue outer_loop;\n }\n }\n // Search mote ID within source nodes\n for(var k = 0; k < source_count; k++)\n {\n if(GROUPs.source[k].ID === moteID)\n {\n GROUPs.source[k].ptsFile = ptyFile;\n continue outer_loop;\n }\n }\n // Search mote ID within disturber nodes\n for(var l = 0; l < disturber_count; l++)\n {\n if(GROUPs.disturber[l].ID === moteID)\n {\n GROUPs.disturber[l].ptsFile = ptyFile;\n continue outer_loop;\n }\n }\n \n msg.error = \"simulated ptsFile = \" + ptyFile + \" is not part of configured nodes\";\n delete msg.payload;\n return [null, msg];\n }\n \n context.global.GROUPs = GROUPs;\n context.global.pts_mux_port = context.pts_mux_port;\n \n delete context.ptyFiles_IDs;\n delete context.pts_mux_port;\n \n return [{topic: \"start_experiment\"}, {payload: \"Cooja simulator has started\"}];\n}","outputs":"2","noerr":0,"x":710,"y":380,"wires":[[],["683e0903.c018b8"]]},{"id":"37f03d5a.ec2dc2","type":"link in","z":"4bd24dc8.2d0bd4","name":"pts_devices","links":["e9b80322.b22b8"],"x":575,"y":340,"wires":[["e3550a12.b34508"]]},{"id":"e9b80322.b22b8","type":"link out","z":"4bd24dc8.2d0bd4","name":"pts_devices","links":["37f03d5a.ec2dc2"],"x":455,"y":340,"wires":[]},{"id":"3307eaff.8d10d6","type":"tcpClient","z":"4bd24dc8.2d0bd4","name":"pts devices","host":"127.0.0.1","port":"6100","timeout":"10000","client_disconnects":false,"x":190,"y":400,"wires":[["ea0f4f43.ffddb"],["d5a244a4.7ee268"]]},{"id":"701e4c.2a85a1b4","type":"js2xml","z":"4bd24dc8.2d0bd4","name":"","x":390,"y":100,"wires":[["ea67c347.9950b"]]},{"id":"6a323cce.b14594","type":"cooja","z":"4bd24dc8.2d0bd4","name":"cooja","restart_cooja":true,"x":310,"y":240,"wires":[["ce790507.05f1c8"],["3beabc60.86dd94"]]},{"id":"3beabc60.86dd94","type":"link out","z":"4bd24dc8.2d0bd4","name":"stderr","links":["c0727233.4d40f"],"x":415,"y":260,"wires":[]},{"id":"15a3a881.1badf7","type":"link in","z":"4bd24dc8.2d0bd4","name":"from_cooja","links":["fbbeb559.ce72d8"],"x":55,"y":400,"wires":[["3307eaff.8d10d6"]]},{"id":"c0727233.4d40f","type":"link in","z":"4bd24dc8.2d0bd4","name":"stderr","links":["3beabc60.86dd94","d5a244a4.7ee268","84ed04d3.ccb498","ce8649c5.d13bc8"],"x":755,"y":440,"wires":[["683e0903.c018b8"]]},{"id":"3408f6f3.99303a","type":"comment","z":"4bd24dc8.2d0bd4","name":"(Re)Start cooja simulator","info":"","x":150,"y":200,"wires":[]},{"id":"7ae3c412.e11b8c","type":"link in","z":"4bd24dc8.2d0bd4","name":"to_cooja","links":["decf84d6.e65118"],"x":55,"y":240,"wires":[["66f23b81.26d074"]]},{"id":"decf84d6.e65118","type":"link out","z":"4bd24dc8.2d0bd4","name":"to_cooja","links":["7ae3c412.e11b8c"],"x":655,"y":100,"wires":[]},{"id":"fbbeb559.ce72d8","type":"link out","z":"4bd24dc8.2d0bd4","name":"from_cooja","links":["15a3a881.1badf7"],"x":555,"y":220,"wires":[]},{"id":"2124b214.9faf6e","type":"comment","z":"4bd24dc8.2d0bd4","name":"Start pts multiplexer","info":"","x":530,"y":300,"wires":[]},{"id":"66f23b81.26d074","type":"function","z":"4bd24dc8.2d0bd4","name":"format","func":"\nvar cooja = msg.payload[0].cooja;\nvar topic = msg.payload[0].topic;\nvar simulation_mode = msg.payload[0].simulation_mode;\nvar contiki_log = msg.payload[0].cooja.contiki_log;\nvar contiki_done_str = msg.payload[0].cooja.contiki_done_str;\n\n// Sink and source nodes array\nvar GROUPs = context.global.GROUPs;\nvar node_IDs = [];\nfor(var i=0; i<GROUPs.sink.length; i++)\n node_IDs.push( GROUPs.sink[i].ID);\nfor(var i=0; i<GROUPs.source.length; i++)\n node_IDs.push( GROUPs.source[i].ID);\n\nreturn {CONTIKI_DIR: cooja.motetype.CONTIKI_DIR, csc_path_rel: cooja.motetype.csc_path_rel, simulation_mode: simulation_mode, contiki_log: contiki_log, contiki_done_str: contiki_done_str, node_IDs: node_IDs, topic: topic};\n","outputs":1,"noerr":0,"x":170,"y":240,"wires":[["6a323cce.b14594"]]},{"id":"ea67c347.9950b","type":"Mfile_out","z":"4bd24dc8.2d0bd4","name":"cooja csc","appendNewline":true,"overwriteFile":"true","x":540,"y":100,"wires":[["decf84d6.e65118"]]},{"id":"d5a244a4.7ee268","type":"link out","z":"4bd24dc8.2d0bd4","name":"stderr","links":["c0727233.4d40f"],"x":315,"y":460,"wires":[]},{"id":"84ed04d3.ccb498","type":"link out","z":"4bd24dc8.2d0bd4","name":"stderr","links":["c0727233.4d40f"],"x":455,"y":460,"wires":[]},{"id":"ce8649c5.d13bc8","type":"link out","z":"4bd24dc8.2d0bd4","name":"stderr","links":["c0727233.4d40f"],"x":655,"y":440,"wires":[]},{"id":"ce790507.05f1c8","type":"function","z":"4bd24dc8.2d0bd4","name":"parser","func":"\nvar filePath = msg.CONTIKI_DIR + \"/\" + msg.csc_path_rel;\n\n// Make cooja pid a global variable\nif(typeof(msg.cooja_pid) !== \"undefined\")\n{\n context.global.cooja_pid = msg.cooja_pid;\n delete msg.cooja_pid;\n}\n\n// Make simTimer port a global variable\nif(typeof(msg.simTimer_port) !== \"undefined\")\n{\n context.global.simTimer_port = msg.simTimer_port;\n delete msg.simTimer_port;\n}\n\n// Rename serial2pty_port to port\nif(typeof(msg.serial2pty_port) !== \"undefined\")\n{\n msg.port = msg.serial2pty_port;\n delete msg.serial2pty_port;\n}\n\ndelete msg.CONTIKI_DIR;\ndelete msg.csc_path_rel;\ndelete msg.simulation_mode;\ndelete msg.contiki_log;\ndelete msg.node_IDs;\n\nmsg.payload = \"\";\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":220,"wires":[["fbbeb559.ce72d8"]]},{"id":"dddd50c4.346e9","type":"link out","z":"dfca7471.a1e698","name":"planning_error","links":["5f4a2077.c42f2"],"x":555,"y":540,"wires":[]},{"id":"a0f16bee.b00f58","type":"link out","z":"dfca7471.a1e698","name":"collection_error","links":["5f4a2077.c42f2"],"x":915,"y":540,"wires":[]},{"id":"5f4a2077.c42f2","type":"link in","z":"dfca7471.a1e698","name":"stderr","links":["1b935ea9.7984e1","a0f16bee.b00f58","dddd50c4.346e9","620458e1.f98428"],"x":1035,"y":540,"wires":[["eedfe88b.bb6c28"]]},{"id":"eedfe88b.bb6c28","type":"debug","z":"dfca7471.a1e698","name":"stderr","active":true,"console":"false","complete":"true","x":1150,"y":540,"wires":[]},{"id":"46b9cd8.c881534","type":"subflow:f439654.2d2c198","z":"dfca7471.a1e698","name":"","x":1170,"y":400,"wires":[]}]