-
Notifications
You must be signed in to change notification settings - Fork 0
/
flows_PL.json
1 lines (1 loc) · 69.2 KB
/
flows_PL.json
1
[{"id":"dfca7471.a1e698","type":"tab","label":"cooja collection"},{"id":"2ccc54b4.8ffd1c","type":"subflow","name":"param_config","info":"","in":[{"x":100,"y":100,"wires":[{"id":"50a21a9b.7d5be4"}]}],"out":[{"x":880,"y":80,"wires":[{"id":"f429ba8b.5d3d78","port":0}]}]},{"id":"fdcac4bc.f79df8","type":"subflow","name":"final_action","info":"","in":[{"x":80,"y":140,"wires":[{"id":"f0ef6ddd.cf56b"},{"id":"61d0acce.1e9dd4"}]}],"out":[]},{"id":"127ce787.bea268","type":"subflow","name":"cooja_setup","info":"","in":[{"x":60,"y":100,"wires":[{"id":"9e612998.e30bb8"}]}],"out":[{"x":840,"y":360,"wires":[{"id":"73270f62.9fd6e","port":0}]}]},{"id":"dded60f6.fe4b2","type":"subflow","name":"Measurement","info":"","in":[{"x":120,"y":100,"wires":[{"id":"51e340b4.ab5e6"}]}],"out":[{"x":940,"y":240,"wires":[{"id":"92613d00.8377c","port":0}]},{"x":860,"y":580,"wires":[{"id":"ad178a6d.922778","port":0},{"id":"1a479fcb.74ed1","port":0}]},{"x":940,"y":280,"wires":[{"id":"f0329892.498c48","port":0}]}]},{"id":"422359ef.8e2e38","type":"function","z":"dfca7471.a1e698","name":"Experiment Setup","func":"\n// Resource controller identifier\ncontext.global.RC_ID = 1;\n\n// Calculate ID to X-Y coordinates\nfunction ID_to_cord(ID, testbed)\n{ var cord = {};\n // IDLab wilab 1 office testbed floor 11\n // ┌─────────────────────────────────────────────────────────────────────┐\n // │ 13 14 15 16 17 18 19 │\n // │ 36 │\n // │ 35 1 2 3 4 5 6 │\n // │ 34 38 39 20 │\n // │ 33 40 37 │\n // │ 32 41 21 │\n // │ 31 12 11 10 9 8 7 │\n // │ 30 28 27 26 25 24 23 22 │\n // │ 29 │\n // └─────────────────────────────────────────────────────────────────────┘\n if(testbed === \"wilab1_11\")\n {\n \tswitch(ID)\n \t{\n \t // Source/Sink nodes\n \t\tcase 1: cord = {X: 9.5, Y: 8.0}; break;\t\t\tcase 21: cord = {X: 38.7, Y: 15.0}; break;\n \t\tcase 2: cord = {X: 14.3, Y: 8.0}; break;\t\t\tcase 22: cord = {X: 40.0, Y: 22.5}; break;\n \t\tcase 3: cord = {X: 19.1, Y: 8.0}; break;\t\t\tcase 23: cord = {X: 34.0, Y: 23.0}; break;\n \t\tcase 4: cord = {X: 23.9, Y: 8.0}; break;\t\t\tcase 24: cord = {X: 28.0, Y: 23.0}; break;\n \t\tcase 5: cord = {X: 28.7, Y: 8.0}; break;\t\t\tcase 25: cord = {X: 24.5, Y: 23.0}; break;\n \t\tcase 6: cord = {X: 33.5, Y: 8.0}; break;\t\t\tcase 26: cord = {X: 18.0, Y: 23.0}; break;\n \t\tcase 7: cord = {X: 33.5, Y: 19.2}; break;\t\t\tcase 27: cord = {X: 14.5, Y: 23.0}; break;\n \t\tcase 8: cord = {X: 28.7, Y: 19.2}; break;\t\t\tcase 28: cord = {X: 8.7, Y: 23.0}; break;\n \t\tcase 9: cord = {X: 23.9, Y: 19.2}; break;\t\t\tcase 29: cord = {X: 3.5, Y: 24.5}; break;\n \t\tcase 10: cord = {X: 19.1, Y: 19.2}; break;\t\t\tcase 30: cord = {X: 3.0, Y: 21.8}; break;\n \t\tcase 11: cord = {X: 14.3, Y: 19.2}; break;\t\t\tcase 31: cord = {X: 3.0, Y: 19.3}; break;\n \t\tcase 12: cord = {X: 9.5, Y: 19.2}; break;\t\t\tcase 32: cord = {X: 3.0, Y: 16.8}; break;\n \t\tcase 13: cord = {X: 3.5, Y: 2.0}; break;\t\t\tcase 33: cord = {X: 3.0, Y: 14.2}; break;\n \t\tcase 14: cord = {X: 8.7, Y: 3.5}; break;\t\t\tcase 34: cord = {X: 3.0, Y: 11.5}; break;\n \t\tcase 15: cord = {X: 14.5, Y: 3.5}; break;\t\t\tcase 35: cord = {X: 3.0, Y: 7.5}; break;\n \t\tcase 16: cord = {X: 18.0, Y: 3.5}; break;\t\t\tcase 36: cord = {X: 3.0, Y: 5.0}; break;\n \t\tcase 17: cord = {X: 24.5, Y: 3.5}; break;\t\t\tcase 37: cord = {X: 10.7, Y: 13.0}; break;\n \t\tcase 18: cord = {X: 28.0, Y: 3.5}; break;\t\t\tcase 38: cord = {X: 12.6, Y: 12.6}; break;\n \t\tcase 19: cord = {X: 40.0, Y: 3.5}; break;\t\t\tcase 39: cord = {X: 25.0, Y: 10.5}; break;\n \t\tcase 20: cord = {X: 40.0, Y: 10.7}; break;\t\t\tcase 40: cord = {X: 7.3, Y: 13.5}; break;\n \t\t case 41: cord = {X: 19.5, Y: 16.0}; break;\n \t\t// Disturber nodes\n \t\tcase 70: cord = {X: 31.5, Y: 18.0}; break;\t\t\tcase 71: cord = {X: 6.6, Y: 8.8}; break;\n \t}\n\t return cord;\n }\n // IDLab wilab 2 clean room 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 else if(testbed === \"wilab2\")\n {\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\t return cord;\n }\n}\n\nvar testbed = \"wilab2\";\nvar sink_ID = [ 1 ];\nvar source_ID = [ 2, 11 ];\n\n//var sink_ID = [ 27 ];\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, 28, 29, 30, 31, 35, 36, 37, 38, 39, 40, 41, 46, 47, 48, 49, 50 ];\n\n//var sink_ID = [ 40 ];\n//var source_ID = [ 14, 16, 3, 5, 34, 37, 20, 31, 10, 28, 24, 22 ];\n//var source_ID = [ 14, 16, 3, 5, 34, 37, 20, 31, 10, 28, 24, 22, 13, 18, 19, 35, 2, 4, 32, 21, 11, 8, 29, 26, 23, 41 ];\n//var source_ID = [ 14, 16, 3, 5, 34, 37, 20, 31, 10, 28, 24, 22, 13, 18, 19, 35, 2, 4, 32, 21, 11, 8, 29, 26, 23, 41, 15, 17, 36, 1, 6, 39, 33, 12, 9, 7, 30, 27, 25 ];\n\nvar disturber_ID = [ ];\n//var disturber_ID = [ 70, 71 ];\n\n// Cooja simulation parameters\nvar cooja = {};\ncooja.title = \"single-hop_WSN\";\n//cooja.randomseed = \"123456\";\n\n// Radio medium configuration\n// Multi-path Ray-tracing radio medium (MRM)\nvar MRM = {};\nMRM.name = \"MRM\";\nMRM.snr_threshold = 6;\nMRM.bg_noise_mean = -100;\nMRM.bg_noise_var = 1;\nMRM.rx_sensitivity = -100;\nMRM.rt_max_rays = 8;\nMRM.rt_max_refractions = 5;\nMRM.rt_max_reflections = 5;\nMRM.rt_max_diffractions = 0;\nMRM.rt_refrac_coefficient = -3;\nMRM.rt_reflec_coefficient = -5;\nMRM.rt_diffr_coefficient = -10;\nMRM.obstacle_attenuation = -3;\nvar obstacles =[[0,\t0,\t3,\t270],\t\n [3,\t0,\t418,\t3],\t\n [418,\t3,\t3,\t270],\t\n [0,\t270,\t418,\t3],\t\n [3,\t40,\t60,\t1.5],\t\n [3,\t67.5,\t45,\t1.5],\t\n [3,\t92.5,\t45,\t1.5],\t\n [3,\t120,\t45,\t1.5],\t\n [3,\t146,\t45,\t1.5],\t\n [3,\t172,\t45,\t1.5],\t\n [3,\t198,\t45,\t1.5],\t\n [3,\t225,\t60,\t1.5],\t\n [48,\t41.5,\t1.5,\t184],\t\n [63,\t3,\t1.5,\t70],\t\n [159,\t3,\t1.5,\t70],\t\n [255,\t3,\t1.5,\t70],\t\n [303.5,\t3,\t2.5,\t70],\t\n [350,\t3,\t2.5,\t70],\t\n [63,\t73,\t289.5,\t1.5],\t\n [351,\t74.5,\t1.5,\t195.5],\t\n [352.5,\t112.5,\t66,\t1.5],\t\n [352.5,\t174.2,\t66,\t1.5],\t\n [63,\t200,\t1.5,\t70],\t\n [159,\t200,\t1.5,\t70],\t\n [255,\t200,\t1.5,\t70],\t\n [63,\t198.5,\t288,\t1.5],\t\n [63,\t91.5,\t48,\t1.5],\t\n [64.5,\t133.75,\t46.5,\t1.5],\t\n [63,\t176,\t48,\t1.5],\t\n [63,\t93,\t1.5,\t83],\t\n [111,\t91.5,\t46,\t3],\t\n [175,\t91.5,\t134.5,\t3],\t\n [111,\t94.5,\t3,\t80],\t\n [136.5,\t94.5,\t3,\t80],\t\n [154,\t94.5,\t3,\t36],\t\n [157,\t104.5,\t18,\t3],\t\n [175,\t94.5,\t3,\t36],\t\n [139.5,\t130.5,\t65,\t3],\t\n [237.5,\t148.5,\t69,\t3],\t\n [258.5,\t125.5,\t22,\t3],\t\n [283.5,\t115.5,\t23,\t3],\t\n [255.5,\t125.5,\t3,\t23],\t\n [280.5,\t94.5,\t3,\t54],\t\n [289.5,\t151.5,\t3,\t23],\t\n [208,\t110.5,\t26.5,\t3],\t\n [164,\t133.5,\t3,\t41],\t\n [204.75,\t94.5,\t3,\t80],\t\n [234.75,\t94.5,\t3,\t80],\t\n [306.5,\t94.5,\t3,\t80],\t\n [111,\t174.5,\t198.5,\t3]];\nMRM.obstacles = obstacles;\n\n// Unit Disk Graph Radio Medium (UDGM)\nvar UDGM = {};\nUDGM.name = \"UDGM\";\nUDGM.transmitting_range = \"80.0\";\nUDGM.interference_range = \"120.0\";\nUDGM.success_ratio_tx = \"1.0\";\nUDGM.success_ratio_rx = \"0.8\";\n\ncooja.radiomedium = UDGM;\n\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 = \"non_gui\";\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], testbed)});\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], testbed)});\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], testbed)});\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":[["a3a7e623.89f348"]]},{"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\nTODO\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 Retx_max : 46644\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 Retx_max = 0; // Maximum retransmissions\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.Retx_max, type: UINT_T, len: 1, value : Retx_max }\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":"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\nvar UINT_T = 0;\nvar INT_T = 1;\n\n// Parameters Under Test\nvar PUT = \n[\n {\n GROUPs: [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\n { uid: UID.phy_txPower, type: INT_T, len: 1, values : [-4, -2, 0, 2, 4] }, // 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 : [-95, -80, -65 ] }, // 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 : [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\nmsg = {};\nmsg.PUT = PUT;\nmsg.topic = \"start_experiment\";\nmsg.port = context.global.pts_mux_port;\n\nreturn msg;","outputs":1,"noerr":0,"x":210,"y":480,"wires":[["4f1aaae7.4d46c4"]]},{"id":"b4478f18.78109","type":"comment","z":"dfca7471.a1e698","name":"Planning","info":"","x":420,"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 activate_app : 25440,\n message_size : 57215,\n receiver : 57217,\n source_IDs : 57218\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 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.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.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\n//var intr_period = 40000; // Interference period in usec\n//var intr_dutyCycle = 0; // 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":"68178fe7.d46a3","type":"subflow:2ccc54b4.8ffd1c","z":"dfca7471.a1e698","name":"","x":880,"y":240,"wires":[["f588c087.1ce03"]]},{"id":"d562d571.3d70b8","type":"link in","z":"dfca7471.a1e698","name":"experiment_setup","links":["cad5031f.ce83b","b2f800fd.70b48"],"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":"f588c087.1ce03","type":"link out","z":"dfca7471.a1e698","name":"reasoning","links":["5d7a5c2e.85f964"],"x":1015,"y":240,"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","feccecfd.d7035"],"x":295,"y":440,"wires":[["4f1aaae7.4d46c4"]]},{"id":"1c66ecc.ac53013","type":"UPI_exec","z":"dfca7471.a1e698","name":"PUT Exec","host":"127.0.0.1","port":"6200","timeout":"3000","retry":"3","reload_MAC":true,"x":600,"y":480,"wires":[["faab04f2.bf0c68"]]},{"id":"b24094be.c4a1a8","type":"debug","z":"dfca7471.a1e698","name":"stderr","active":true,"console":"false","complete":"true","x":950,"y":540,"wires":[]},{"id":"9fc48c1b.ed7ca","type":"link in","z":"dfca7471.a1e698","name":"stderr","links":["85cadc9a.9c5be"],"x":835,"y":540,"wires":[["b24094be.c4a1a8"]]},{"id":"85cadc9a.9c5be","type":"link out","z":"dfca7471.a1e698","name":"LHD_stderr","links":["9fc48c1b.ed7ca"],"x":555,"y":540,"wires":[]},{"id":"840ee49d.5fb4e8","type":"link out","z":"dfca7471.a1e698","name":"collection","links":["5f39396e.667518"],"x":915,"y":440,"wires":[]},{"id":"8b109a79.481828","type":"comment","z":"dfca7471.a1e698","name":"Collection","info":"","x":760,"y":440,"wires":[]},{"id":"4f1aaae7.4d46c4","type":"exhaustive-search","z":"dfca7471.a1e698","name":"exhaustive","x":430,"y":480,"wires":[["1c66ecc.ac53013"],["85cadc9a.9c5be"]]},{"id":"9c9fa26b.04b55","type":"subflow:fdcac4bc.f79df8","z":"dfca7471.a1e698","name":"","x":170,"y":700,"wires":[]},{"id":"4c30e975.2e9c28","type":"comment","z":"dfca7471.a1e698","name":"Experiment Action","info":"","x":130,"y":640,"wires":[]},{"id":"40ed1bb4.063f74","type":"link in","z":"dfca7471.a1e698","name":"final_action","links":["8720d9a7.95f998"],"x":55,"y":700,"wires":[["9c9fa26b.04b55"]]},{"id":"8720d9a7.95f998","type":"link out","z":"dfca7471.a1e698","name":"final_action","links":["40ed1bb4.063f74"],"x":1055,"y":520,"wires":[]},{"id":"17ee11a5.e3ebbe","type":"function","z":"fdcac4bc.f79df8","name":"PL_calc","func":"\n// Retrieve base name of a path\nfunction baseName(path)\n{\n\tvar base = path.substring(path.lastIndexOf('/') + 1); \n\tif(base.lastIndexOf(\".\") != -1) \n\t\tbase = base.substring(0, base.lastIndexOf(\".\"));\n\treturn base;\n}\n\t\n// Group of nodes global variable\nvar GROUPs = context.global.GROUPs;\n\n// Receiver node location\nreceiver_loc = GROUPs.sink[0].loc;\n\n// Construct a dataset of pathloss vs distance parameters\nvar data = [];\nfor(var i = 0; i < msg.payload.length; i++)\n{\n var filename = msg.payload[i].filename;\n var base_filename = baseName(filename);\n var sender_ID = parseInt(base_filename.substring(base_filename.indexOf(\"samplesValues\") + 13));\n var sender_loc = [];\n \n // Search for location from a given sender ID\n for(var j = 0; j < GROUPs.source.length; j++)\n {\n if(sender_ID === GROUPs.source[j].ID)\n {\n sender_loc = GROUPs.source[j].loc;\n break;\n }\n }\n \n // Distance between sender and receiver\n var dist = Math.sqrt(Math.pow((sender_loc.X-receiver_loc.X), 2) + Math.pow(((sender_loc.Y-receiver_loc.Y)), 2));\n\n // 10*log(distance between source and sink)\n x = 10*Math.log10(dist);\n\n // Path loss between sender and receiver\n var dataset = msg.payload[i].payload.split('\\n').filter(String);\n \n // Construct path loss array\n var PL_array = [];\n for(var j = 0; j < dataset.length; j++)\n {\n var tx_power = dataset[j].split('\\t');\n PL_array.push(parseFloat(tx_power[0]) - parseFloat(tx_power[1]));\n }\n \n // Calculate average path loss\n var PL = PL_array.reduce(function (a, b) { return a + b;}) / PL_array.length;\n \n // push distance vs path loss into data array\n data.push([x, PL]);\n}\n\n// Apply linear regression to estimate Path loss coefficient (n) and Reference path loss (PL0) at a distance of 1m \nvar len = data.length;\nvar sum = [0, 0, 0, 0, 0];\nfor (var i = 0; i < data.length; i++)\n{\n var x = data[i][0];\n var PL = data[i][1];\n \n sum[0] += x;\n sum[1] += PL;\n sum[2] += x * x;\n sum[3] += x * PL;\n sum[4] += PL * PL;\n}\nvar n = (len * sum[3] - sum[0] * sum[1]) / (len * sum[2] - sum[0] * sum[0]);\nvar PL0 = (sum[1] / len) - (n * sum[0]) / len;\n\nmsg.PL0 = PL0;\nmsg.n = n;\n\nreturn msg;","outputs":1,"noerr":0,"x":540,"y":80,"wires":[["84e0360.0422ec8"]]},{"id":"ea1e1ed0.7e382","type":"function","z":"dfca7471.a1e698","name":"Check","func":"\nvar PUT = context.global.PUT;\nvar PUT_count = 1;\nfor(var i = 0; i < PUT.control_hdr.length; i++)\n PUT_count = PUT_count * PUT.control_hdr[i].values.length;\n\nif(msg.sample_Idx == PUT_count - 1)\n{\n return [null, msg];\n}\nelse\n{\n msg.sample_Idx = msg.sample_Idx + 1;\n return [msg, null];\n}","outputs":"2","noerr":0,"x":950,"y":480,"wires":[["feccecfd.d7035"],["8720d9a7.95f998"]]},{"id":"feccecfd.d7035","type":"link out","z":"dfca7471.a1e698","name":"reasoning","links":["5f39396e.667518"],"x":1055,"y":440,"wires":[]},{"id":"3fae389e.c323f8","type":"inject","z":"dfca7471.a1e698","name":"Start experiment","topic":"start_experiment","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"x":140,"y":80,"wires":[["b2f800fd.70b48"]]},{"id":"b2f800fd.70b48","type":"link out","z":"dfca7471.a1e698","name":"experiment_setup","links":["d562d571.3d70b8"],"x":275,"y":80,"wires":[]},{"id":"f0329892.498c48","type":"link in","z":"dded60f6.fe4b2","name":"stderr","links":["43cc822c.82fbcc","a2b3269.3a6c7d8","8a4e1528.8c50e8","270d0a6.4c3a4f6"],"x":755,"y":280,"wires":[[]]},{"id":"a2b3269.3a6c7d8","type":"link out","z":"dded60f6.fe4b2","name":"stderr","links":["f0329892.498c48"],"x":695,"y":280,"wires":[]},{"id":"79f83d3c.390f34","type":"link in","z":"dded60f6.fe4b2","name":"delay_in","links":["f89722c9.aadb"],"x":115,"y":440,"wires":[["d4fd4a29.d5d178"]]},{"id":"f89722c9.aadb","type":"link out","z":"dded60f6.fe4b2","name":"delay_in","links":["79f83d3c.390f34"],"x":695,"y":320,"wires":[]},{"id":"c54fe750.68e4e8","type":"comment","z":"dded60f6.fe4b2","name":"Reset statistic variables","info":"","x":280,"y":240,"wires":[]},{"id":"21e17692.776c3a","type":"function","z":"dded60f6.fe4b2","name":"Retrv","func":"\n// Control opcode enumeration\nvar UID =\n{\n RXSTATS : 57216\n};\n\n// Default application parameters\nvar GROUPs = context.global.GROUPs;\nvar sink_ptsFile = GROUPs.sink[0].ptsFile;\n\n// Retrieve PUT global variable\nvar PUT = context.global.PUT;\n\n// pts device file paths\nvar ptsFiles = [];\nfor(var i = 0; i < PUT.GROUPs.length; i++)\n{\n var GROUP = PUT.GROUPs[i];\n for(var j = 0; j < GROUP.length; j++)\n\t ptsFiles.push(GROUP[j].ptsFile);\n}\n\nvar parameters = [];\nfor(var i = 0; i < ptsFiles.length; i++)\n{\n var ptsFile = ptsFiles[i];\n \n // RxStats parameters on sink nodes\n var sender_ID;\n \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 \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 } // Rx packet statistics\n ]\n };\n \n parameters.push(rx_parameter);\n}\n\nmsg.payload = parameters;\nmsg.port = context.global.pts_mux_port;\n\nreturn msg;\n","outputs":1,"noerr":0,"x":230,"y":600,"wires":[["b68f24f0.44d588"]]},{"id":"1df8c220.01c80e","type":"comment","z":"dded60f6.fe4b2","name":"Retrieve statistic variables","info":"","x":290,"y":560,"wires":[]},{"id":"314b2c18.e4e4d4","type":"link out","z":"dded60f6.fe4b2","name":"delay_out","links":["7bc280eb.f6658"],"x":555,"y":420,"wires":[]},{"id":"7bc280eb.f6658","type":"link in","z":"dded60f6.fe4b2","name":"delay_out","links":["314b2c18.e4e4d4"],"x":115,"y":600,"wires":[["21e17692.776c3a"]]},{"id":"43cc822c.82fbcc","type":"link out","z":"dded60f6.fe4b2","name":"stderr","links":["f0329892.498c48"],"x":695,"y":660,"wires":[]},{"id":"5d1750e2.972af","type":"link in","z":"dded60f6.fe4b2","name":"reset_in","links":["582a2686.b74f18"],"x":115,"y":280,"wires":[["e7351bea.18b378"]]},{"id":"582a2686.b74f18","type":"link out","z":"dded60f6.fe4b2","name":"reset_in","links":["5d1750e2.972af"],"x":375,"y":140,"wires":[]},{"id":"51e340b4.ab5e6","type":"function","z":"dded60f6.fe4b2","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":[["66729a4d.8cedb4"],["8a4e1528.8c50e8"],["582a2686.b74f18"]]},{"id":"8a4e1528.8c50e8","type":"link out","z":"dded60f6.fe4b2","name":"stderr","links":["f0329892.498c48"],"x":375,"y":100,"wires":[]},{"id":"cda5d311.c2639","type":"comment","z":"dded60f6.fe4b2","name":"Wait before collecting results","info":"","x":300,"y":400,"wires":[]},{"id":"719da2db.f3248c","type":"function","z":"dded60f6.fe4b2","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":[["faa129d4.208fe8"],["a2b3269.3a6c7d8"],["f89722c9.aadb"]]},{"id":"faa129d4.208fe8","type":"link out","z":"dded60f6.fe4b2","name":"redo_experiment","links":["48119838.49d9c8"],"x":695,"y":240,"wires":[]},{"id":"66729a4d.8cedb4","type":"link out","z":"dded60f6.fe4b2","name":"redo_experiment","links":["48119838.49d9c8"],"x":375,"y":60,"wires":[]},{"id":"48119838.49d9c8","type":"link in","z":"dded60f6.fe4b2","name":"redo_experiment","links":["faa129d4.208fe8","66729a4d.8cedb4","7ac2473a.8f4d98"],"x":755,"y":240,"wires":[["92613d00.8377c"]]},{"id":"7ac2473a.8f4d98","type":"link out","z":"dded60f6.fe4b2","name":"redo_experiment","links":["48119838.49d9c8"],"x":695,"y":540,"wires":[]},{"id":"832dbb63.0b2e98","type":"comment","z":"dded60f6.fe4b2","name":"redo experiment","info":"","x":1060,"y":240,"wires":[]},{"id":"cb05747d.7d7de8","type":"comment","z":"dded60f6.fe4b2","name":"error message","info":"","x":1050,"y":280,"wires":[]},{"id":"894f327b.7f942","type":"comment","z":"dded60f6.fe4b2","name":"experiment passed","info":"","x":990,"y":580,"wires":[]},{"id":"ac277442.9e8778","type":"UPI_exec","z":"dded60f6.fe4b2","name":"Reset Exec","host":"127.0.0.1","port":"6200","timeout":"20000","retry":"3","reload_MAC":false,"x":390,"y":280,"wires":[["719da2db.f3248c"]]},{"id":"b68f24f0.44d588","type":"UPI_exec","z":"dded60f6.fe4b2","name":"Retrv Exec","host":"127.0.0.1","port":"6200","timeout":"20000","retry":"3","reload_MAC":false,"x":390,"y":600,"wires":[["ec72fc80.719e1"]]},{"id":"e7351bea.18b378","type":"function","z":"dded60f6.fe4b2","name":"Reset","func":"\n// Control opcode enumeration\nvar UID =\n{\n RXSTATS : 57216\n};\n\n// Default application parameters\nvar GROUPs = context.global.GROUPs;\nvar sink_ptsFile = GROUPs.sink[0].ptsFile;\n\n// Retrieve PUT global variable\nvar PUT = context.global.PUT;\n\n// pts device file paths\nvar ptsFiles = [];\nfor(var i = 0; i < PUT.GROUPs.length; i++)\n{\n var GROUP = PUT.GROUPs[i];\n for(var j = 0; j < GROUP.length; j++)\n\t ptsFiles.push(GROUP[j].ptsFile);\n}\n\n// Integer to hexadicimal string convertor\nvar int2hex = context.global.int2hex;\n\nvar parameters = [];\nfor(var i = 0; i < ptsFiles.length; i++)\n{\n var ptsFile = ptsFiles[i];\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 \n parameters.push(rx_parameter);\n}\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":[["ac277442.9e8778"]]},{"id":"79c9cb07.643a44","type":"debug","z":"dded60f6.fe4b2","name":"Msrmt_stdout","active":true,"console":"false","complete":"true","x":920,"y":620,"wires":[]},{"id":"faab04f2.bf0c68","type":"subflow:dded60f6.fe4b2","z":"dfca7471.a1e698","name":"","x":780,"y":480,"wires":[["840ee49d.5fb4e8"],["ea1e1ed0.7e382"],["b24094be.c4a1a8"]]},{"id":"84e0360.0422ec8","type":"debug","z":"fdcac4bc.f79df8","name":"Action_stdout","active":true,"console":"false","complete":"true","x":720,"y":140,"wires":[]},{"id":"ec72fc80.719e1","type":"function","z":"dded60f6.fe4b2","name":"Retrv_perf","func":"\nvar error_msg = msg.error_msg;\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, null, null, {payload: error_msg}];\n}\nelse\n{\n // Control opcode enumeration\n var UID =\n {\n RXSTATS : 57216\n };\n \n // Default application parameters\n var GROUPs = context.global.GROUPs;\n \n // Retreive global PUT variable\n var PUT = context.global.PUT;\n \n // Retreive PUT parameters\n var PUT_params = context.global.PUT_params;\n \n // sample index\n var sample_Idx = context.global.sample_Idx;\n \n var payload = msg.payload;\n var RSSI_list = {};\n for(var i = 0; i < payload.length; i++)\n {\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 uid = response.control_hdr[0].uid;\n var sender_ID = response.control_hdr[0].type;\n \n // RxStat message\n if(uid === UID.RXSTATS)\n {\n var value = Buffer.from(response.control_hdr[0].value, 'hex');\n \n var rssi_sum = value.readInt16LE(0);\n var lqi_sum = value.readUInt16LE(2);\n var packet_recvd = value.readUInt16LE(4);\n var packet_lost = value.readUInt16LE(6);\n var seq_nr = value.readUInt16LE(8);\n \n // Calculate performance objectives\n if(packet_recvd > 0)\n RSSI_list[sender_ID] = parseFloat(rssi_sum/packet_recvd);\n else\n RSSI_list[sender_ID] = -120.0;\n }\n }\n }\n\n var rxstats = [];\n \n for(var ptsFile in PUT_params)\n {\n var sender_ID = -1;\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 sender_ID = GROUPs.source[j].ID;\n break;\n }\n }\n \n // MOSBO file path\n var filename = \"/tmp/samplesValues\" + sender_ID + \".txt\";\n \n // Dataset string = PUT parameters + performance objectives\n var dataset_str = PUT_params[ptsFile].join('\\t') + \"\\t\" + RSSI_list[sender_ID];\n \n rxstats.push({filename: filename, payload: dataset_str});\n }\n\n msg.payload = rxstats;\n msg.sample_Idx = sample_Idx;\n delete msg.error_msg;\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","outputs":"4","noerr":0,"x":570,"y":600,"wires":[["7ac2473a.8f4d98"],["ad178a6d.922778"],["1a479fcb.74ed1"],["43cc822c.82fbcc"]]},{"id":"ad178a6d.922778","type":"Mfile_out","z":"dded60f6.fe4b2","name":"1st data","appendNewline":true,"overwriteFile":"true","x":740,"y":580,"wires":[["79c9cb07.643a44"]]},{"id":"1a479fcb.74ed1","type":"Mfile_out","z":"dded60f6.fe4b2","name":"cont data","appendNewline":true,"overwriteFile":"false","x":740,"y":620,"wires":[["79c9cb07.643a44"]]},{"id":"a3a7e623.89f348","type":"subflow:127ce787.bea268","z":"dfca7471.a1e698","name":"","x":410,"y":240,"wires":[["d490cced.0bfc","f995d8d8.0d4328","9264f556.824c38"]]},{"id":"f0ef6ddd.cf56b","type":"function","z":"fdcac4bc.f79df8","name":"format_files","func":"\nvar filenames = [];\nfor(var i = 0; i < msg.payload.length; i++)\n{\n filenames.push(msg.payload[i].filename);\n}\nmsg.filenames = filenames;\n\nreturn msg;","outputs":1,"noerr":0,"x":210,"y":80,"wires":[["6546290b.f988b8"]]},{"id":"6546290b.f988b8","type":"Mfile_in","z":"fdcac4bc.f79df8","name":"dataset","format":"utf8","x":380,"y":80,"wires":[["17ee11a5.e3ebbe"]]},{"id":"270d0a6.4c3a4f6","type":"link out","z":"dded60f6.fe4b2","name":"stderr","links":["f0329892.498c48"],"x":555,"y":460,"wires":[]},{"id":"387d2fe3.7eab3","type":"debug","z":"127ce787.bea268","name":"cooja_stderr","active":true,"console":"false","complete":"true","x":890,"y":440,"wires":[]},{"id":"5d810004.b5332","type":"function","z":"127ce787.bea268","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":[["e4c59c5f.fba01"],["ebffd747.aeaf58"],["35184772.9fef18"]]},{"id":"ae91d514.4d1e68","type":"comment","z":"127ce787.bea268","name":"Retrieve pts devices","info":"","x":130,"y":360,"wires":[]},{"id":"9e612998.e30bb8","type":"function","z":"127ce787.bea268","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\n// Simulation configuration\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: \"events\", children: \n [\n {name: \"logoutput\", text: \"40000\"}\n ]}\n ]}\n];\n\n// Simulation array\nvar sim_array = simconf[0].children;\n\n// Multi-path Ray-tracing radio medium (MRM)\nif(cooja.radiomedium.name === \"MRM\")\n{\n sim_array.push({name: \"radiomedium\", text: \"org.contikios.mrm.MRM\", children: \n [\n {name: \"snr_threshold\", attrs: {value: cooja.radiomedium.snr_threshold}},\n {name: \"bg_noise_mean\", attrs: {value: cooja.radiomedium.bg_noise_mean}},\n {name: \"bg_noise_var\", attrs: {value: cooja.radiomedium.bg_noise_var}},\n {name: \"rx_sensitivity\", attrs: {value: cooja.radiomedium.rx_sensitivity}},\n {name: \"rt_max_rays\", attrs: {value: cooja.radiomedium.rt_max_rays}},\n {name: \"rt_max_refractions\", attrs: {value: cooja.radiomedium.rt_max_refractions}},\n {name: \"rt_max_reflections\", attrs: {value: cooja.radiomedium.rt_max_reflections}},\n {name: \"rt_max_diffractions\", attrs: {value: cooja.radiomedium.rt_max_diffractions}},\n {name: \"rt_refrac_coefficient\", attrs: {value: cooja.radiomedium.rt_refrac_coefficient}},\n {name: \"rt_reflec_coefficient\", attrs: {value: cooja.radiomedium.rt_reflec_coefficient}},\n {name: \"rt_diffr_coefficient\", attrs: {value: cooja.radiomedium.rt_diffr_coefficient}},\n {name: \"obstacle_attenuation\", attrs: {value: cooja.radiomedium.obstacle_attenuation}},\n {name: \"obstacles\"}\n ]});\n \n if(typeof(cooja.radiomedium.obstacles) !== \"undefined\")\n {\n // Obstacles object\n var radiomedium_array = sim_array[sim_array.length-1].children;\n var obstacles_obj = radiomedium_array[radiomedium_array.length-1];\n \n // Obstacles array\n obstacles_obj.children = [];\n var obstacles_array = obstacles_obj.children;\n for(var i = 0; i < cooja.radiomedium.obstacles.length; i++)\n {\n var obstacle_str = (cooja.radiomedium.obstacles[i][0]/10.0).toFixed(3);\n for(var j = 1; j < cooja.radiomedium.obstacles[i].length; j++)\n obstacle_str = obstacle_str + \";\" + (cooja.radiomedium.obstacles[i][j]/10.0).toFixed(3);\n \n obstacles_array.push({name: \"obst\", text: obstacle_str});\n }\n \n }\n}\n// Unit Disk Graph Radio Medium (UDGM)\nelse if(cooja.radiomedium.name === \"UDGM\")\n{\n sim_array.push({name: \"radiomedium\", text: \"org.contikios.cooja.radiomediums.UDGM\", children: \n [\n {name: \"transmitting_range\", text: cooja.radiomedium.transmitting_range},\n {name: \"interference_range\", text: cooja.radiomedium.interference_range},\n {name: \"success_ratio_tx\", text: cooja.radiomedium.success_ratio_tx},\n {name: \"success_ratio_rx\", text: cooja.radiomedium.success_ratio_rx}\n ]});\n}\n\n// Create mote configuration\nvar GROUPs = context.global.GROUPs;\n\nvar firm_path_rel = cooja.motetype.firm_path_rel;\nvar firm_path_CONTIKI = \"[CONTIKI_DIR]/\" + firm_path_rel;\nvar platform = extName(firm_path_rel);\n\n// Add mote configuration to simulation configuration\n// Solution Under Test (SUT) motetype configuration\nif(GROUPs.sink.length > 0 || GROUPs.source.length > 0)\n{\n sim_array.push({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}\n// Disturber motetype configuration\nif(GROUPs.disturber.length > 0)\n{\n sim_array.push({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}\n\nfor(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_array.push({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 }\n }\n // Disturber nodes mote configuration\n else if(g === \"disturber\")\n {\n for(var n in GROUPs[g])\n {\n sim_array.push({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 }\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 CONTIKI_DIR = cooja.motetype.CONTIKI_DIR;\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":[["c3736171.43571"]]},{"id":"e914bff9.6664e","type":"comment","z":"127ce787.bea268","name":"Create cooja simulation file","info":"","x":150,"y":60,"wires":[]},{"id":"ebffd747.aeaf58","type":"exec","z":"127ce787.bea268","command":"pts_mux -g","addpay":true,"append":"","useSpawn":true,"timer":"","name":"start pts_mux","x":520,"y":400,"wires":[["73270f62.9fd6e"],["a0366943.224638"],[]]},{"id":"73270f62.9fd6e","type":"function","z":"127ce787.bea268","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 simulation has started\"}];\n}","outputs":"2","noerr":0,"x":710,"y":380,"wires":[[],["387d2fe3.7eab3"]]},{"id":"261468ba.81f6f8","type":"link in","z":"127ce787.bea268","name":"pts_devices","links":["e4c59c5f.fba01"],"x":575,"y":340,"wires":[["73270f62.9fd6e"]]},{"id":"e4c59c5f.fba01","type":"link out","z":"127ce787.bea268","name":"pts_devices","links":["261468ba.81f6f8"],"x":455,"y":340,"wires":[]},{"id":"60c6aa38.93fe44","type":"tcpClient","z":"127ce787.bea268","name":"pts devices","host":"127.0.0.1","port":"6100","timeout":"10000","client_disconnects":false,"x":190,"y":400,"wires":[["5d810004.b5332"],["752076c8.95df68"]]},{"id":"c3736171.43571","type":"js2xml","z":"127ce787.bea268","name":"","x":390,"y":100,"wires":[["7656c998.198a08"]]},{"id":"2235c975.3a4066","type":"cooja","z":"127ce787.bea268","name":"cooja","restart_cooja":true,"debug":true,"x":310,"y":240,"wires":[["98ccdd99.5c631"],["7d2f7d4c.265404"]]},{"id":"7d2f7d4c.265404","type":"link out","z":"127ce787.bea268","name":"stderr","links":["f2273a1e.3bd858"],"x":415,"y":260,"wires":[]},{"id":"591c5e00.646904","type":"link in","z":"127ce787.bea268","name":"from_cooja","links":["e68e630d.476a6"],"x":55,"y":400,"wires":[["60c6aa38.93fe44"]]},{"id":"f2273a1e.3bd858","type":"link in","z":"127ce787.bea268","name":"stderr","links":["7d2f7d4c.265404","752076c8.95df68","35184772.9fef18","a0366943.224638"],"x":755,"y":440,"wires":[["387d2fe3.7eab3"]]},{"id":"c585b5ad.730828","type":"comment","z":"127ce787.bea268","name":"(Re)Start cooja simulator","info":"","x":150,"y":200,"wires":[]},{"id":"b2921235.68452","type":"link in","z":"127ce787.bea268","name":"to_cooja","links":["5f4bfad8.bb69f4"],"x":55,"y":240,"wires":[["83f62c60.2241"]]},{"id":"5f4bfad8.bb69f4","type":"link out","z":"127ce787.bea268","name":"to_cooja","links":["b2921235.68452"],"x":655,"y":100,"wires":[]},{"id":"e68e630d.476a6","type":"link out","z":"127ce787.bea268","name":"from_cooja","links":["591c5e00.646904"],"x":555,"y":220,"wires":[]},{"id":"dbd1bab2.8ce1c8","type":"comment","z":"127ce787.bea268","name":"Start pts multiplexer","info":"","x":530,"y":300,"wires":[]},{"id":"83f62c60.2241","type":"function","z":"127ce787.bea268","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":[["2235c975.3a4066"]]},{"id":"7656c998.198a08","type":"Mfile_out","z":"127ce787.bea268","name":"cooja csc","appendNewline":true,"overwriteFile":"true","x":540,"y":100,"wires":[["5f4bfad8.bb69f4"]]},{"id":"752076c8.95df68","type":"link out","z":"127ce787.bea268","name":"stderr","links":["f2273a1e.3bd858"],"x":315,"y":460,"wires":[]},{"id":"35184772.9fef18","type":"link out","z":"127ce787.bea268","name":"stderr","links":["f2273a1e.3bd858"],"x":455,"y":460,"wires":[]},{"id":"a0366943.224638","type":"link out","z":"127ce787.bea268","name":"stderr","links":["f2273a1e.3bd858"],"x":655,"y":440,"wires":[]},{"id":"98ccdd99.5c631","type":"function","z":"127ce787.bea268","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":[["e68e630d.476a6"]]},{"id":"50a21a9b.7d5be4","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":[["55965aab.879cd4"]]},{"id":"fb8089bb.c13018","type":"debug","z":"2ccc54b4.8ffd1c","name":"default_stderr","active":true,"console":"false","complete":"true","x":800,"y":120,"wires":[]},{"id":"c771e5c7.9f3a08","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":[["f429ba8b.5d3d78"],["fb8089bb.c13018"]]},{"id":"55965aab.879cd4","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":[["c771e5c7.9f3a08"]]},{"id":"f429ba8b.5d3d78","type":"delay","z":"2ccc54b4.8ffd1c","name":"delay","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":770,"y":80,"wires":[[]]},{"id":"d4fd4a29.d5d178","type":"function","z":"dded60f6.fe4b2","name":"20 packet delay","func":"\n// packet count to be sent\nvar packet_count = 20;\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":[["e91bb3f9.37df6"]]},{"id":"e91bb3f9.37df6","type":"tcpClient","z":"dded60f6.fe4b2","name":"simTimer","host":"127.0.0.1","port":"7700","timeout":"300000","client_disconnects":false,"x":440,"y":440,"wires":[["314b2c18.e4e4d4"],["270d0a6.4c3a4f6"]]},{"id":"92613d00.8377c","type":"delay","z":"dded60f6.fe4b2","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":"61d0acce.1e9dd4","type":"function","z":"fdcac4bc.f79df8","name":"cooja_pid","func":"\nreturn {payload: context.global.cooja_pid};","outputs":1,"noerr":0,"x":200,"y":200,"wires":[["50982a44.8b65a4"]]},{"id":"50982a44.8b65a4","type":"exec","z":"fdcac4bc.f79df8","command":"killall -s 9 pts_mux ; kill -s 9","addpay":true,"append":"","useSpawn":"","timer":"","name":"Stop APPs","x":370,"y":200,"wires":[["22bb7061.a6959"],[],[]]},{"id":"22bb7061.a6959","type":"function","z":"fdcac4bc.f79df8","name":"message","func":"\nreturn {payload: \"Cooja simulation has finished\"};","outputs":1,"noerr":0,"x":540,"y":200,"wires":[["84e0360.0422ec8"]]},{"id":"8ebe13e3.7722d","type":"comment","z":"fdcac4bc.f79df8","name":"Path Loss calculation","info":"","x":240,"y":40,"wires":[]},{"id":"b120ed89.067ff","type":"comment","z":"fdcac4bc.f79df8","name":"Stop cooja simulation","info":"","x":240,"y":160,"wires":[]}]