1900 lines
55 KiB
JSON
1900 lines
55 KiB
JSON
[
|
|
{
|
|
"id": "67eddebaafa49d22",
|
|
"type": "tab",
|
|
"label": "Flow 1",
|
|
"disabled": false,
|
|
"info": "",
|
|
"env": []
|
|
},
|
|
{
|
|
"id": "1ac5238bc8e86a32",
|
|
"type": "mqtt in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "MQTT IN (aquamonn/data)",
|
|
"topic": "aquamonn/data",
|
|
"qos": "0",
|
|
"datatype": "json",
|
|
"broker": "bfc3b3d0112912d7",
|
|
"nl": false,
|
|
"rap": false,
|
|
"inputs": 0,
|
|
"x": 210,
|
|
"y": 240,
|
|
"wires": [
|
|
[
|
|
"fae8f9eddf47b0e8"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "fae8f9eddf47b0e8",
|
|
"type": "json",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Parse JSON",
|
|
"property": "payload",
|
|
"action": "obj",
|
|
"pretty": false,
|
|
"x": 410,
|
|
"y": 240,
|
|
"wires": [
|
|
[
|
|
"eb5c53304dede5d8",
|
|
"fde1f8e9948ff9b3",
|
|
"257786bc47f4472f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "bf9607cb418cb77c",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Cek Amonia ",
|
|
"func": "// Ambil nilai amonia dari flow context\nlet amonia = Number(flow.get(\"amonia\")) || 0;\nlet maksimum = Number(flow.get(\"p_maks\")) || 2.0;\nlet auto = String(flow.get(\"auto\") || \"false\").toLowerCase();\nlet statusManual = Number(flow.get(\"relay_manual\")) || 0;\n\n// Logika kontrol pompa\nlet relayState = 0;\n\nif (auto === \"true\") {\n if (amonia > maksimum) {\n relayState = 1;\n node.warn(\"🚨 AMONIA BERLEBIH! Pompa ON\");\n } else {\n relayState = 0;\n node.log(\"✅ Amonia normal, Pompa OFF\");\n }\n} else {\n relayState = statusManual;\n node.log(\"👆 Mode manual, Pompa = \" + (relayState ? \"ON\" : \"OFF\"));\n}\n\n// Simpan ke flow context\nflow.set(\"relay\", relayState);\n\n// Kirim ke ESP32 (topic khusus pompa)\nmsg.payload = {\n pompa_auto_mode: (auto === \"true\"),\n batas_amonia: maksimum,\n pompa_command: relayState ? \"ON\" : \"OFF\"\n};\nmsg.topic = \"aquamonn/relay\";\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": "",
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 730,
|
|
"y": 320,
|
|
"wires": [
|
|
[
|
|
"4209516a2282ed2f",
|
|
"94b36373e7c0a702"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "fde1f8e9948ff9b3",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "pH",
|
|
"func": "msg.payload = msg.payload.pH || null;\nmsg.topic = \"pH\";\n\nflow.set(\"pH\", msg.payload);\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 550,
|
|
"y": 240,
|
|
"wires": [
|
|
[
|
|
"614f7212ee1c0723",
|
|
"c172fef7c3246031",
|
|
"227e27214ab882c2"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "eb5c53304dede5d8",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Amonia",
|
|
"func": "msg.payload = msg.payload.amonia || null;\nmsg.topic = \"amonia_total\";\n\nflow.set(\"amonia\", msg.payload);\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 560,
|
|
"y": 280,
|
|
"wires": [
|
|
[
|
|
"9a2cd222e4412337",
|
|
"bf9607cb418cb77c",
|
|
"c172fef7c3246031",
|
|
"227e27214ab882c2",
|
|
"6e76986120cce23f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "257786bc47f4472f",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Suhu",
|
|
"func": "// Contoh jika suhu ada di dalam msg.payload.suhu\nmsg.payload = msg.payload.suhu || null;\nmsg.topic = \"Suhu\";\n\nflow.set(\"suhu\", msg.payload);\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 550,
|
|
"y": 200,
|
|
"wires": [
|
|
[
|
|
"e74efbe9e10e5303",
|
|
"c172fef7c3246031",
|
|
"227e27214ab882c2"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "e220cd1c7b384424",
|
|
"type": "change",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "p_maks",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 1080,
|
|
"y": 1260,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "4209516a2282ed2f",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Status relay",
|
|
"func": "// Ambil status relay dari flow context\nlet relayState = Number(flow.get(\"relay\")) || 0;\n\n// Ubah jadi ON / OFF\nif (relayState === 1) {\n msg.payload = \"ON\";\n} else if (relayState === 0) {\n msg.payload = \"OFF\";\n} else {\n msg.payload = \"unknown\";\n}\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 890,
|
|
"y": 360,
|
|
"wires": [
|
|
[
|
|
"0e6815c586945467"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "2c8f752891c86ff2",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"url": "/set-pmaks",
|
|
"method": "post",
|
|
"upload": true,
|
|
"swaggerDoc": "",
|
|
"x": 280,
|
|
"y": 1260,
|
|
"wires": [
|
|
[
|
|
"07f1dfec2ed7e826"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "07f1dfec2ed7e826",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "set parameter maks",
|
|
"func": "var nilaiBaru = parseFloat(msg.payload.maks);\n\nif (!isNaN(nilaiBaru) && nilaiBaru >= 0.1 && nilaiBaru <= 100.0) {\n flow.set(\"p_maks\", nilaiBaru);\n msg.payload = nilaiBaru;\n} else {\n node.warn(\"Nilai di luar rentang yang diperbolehkan (0.1 - 100.0)\");\n return null;\n}\n\nreturn msg;\n\n",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 580,
|
|
"y": 1260,
|
|
"wires": [
|
|
[
|
|
"4ca05874370f0321",
|
|
"3bf3670a4281b696"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "3ecd2803f9f68396",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"url": "/get-data",
|
|
"method": "get",
|
|
"upload": false,
|
|
"swaggerDoc": "",
|
|
"x": 270,
|
|
"y": 1140,
|
|
"wires": [
|
|
[
|
|
"9ba31890b8a451cf"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "09ce34fa2cc121bc",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "http out",
|
|
"statusCode": "",
|
|
"headers": {},
|
|
"x": 680,
|
|
"y": 1140,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "9ba31890b8a451cf",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "nr ke flutter",
|
|
"func": "msg.payload = {\n suhu: flow.get(\"suhu\"),\n ph: flow.get(\"pH\"),\n amonia: flow.get(\"amonia\"),\n relay: flow.get(\"relay\"),\n turbidity: flow.get(\"turbidity\"),\n distance: flow.get(\"distance\"),\n tinggi_air: flow.get(\"tinggi_air\")\n};\nreturn msg;\n",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 490,
|
|
"y": 1140,
|
|
"wires": [
|
|
[
|
|
"09ce34fa2cc121bc",
|
|
"4b9ee9fd3c7deca6"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "1ebae4590b28a2c9",
|
|
"type": "debug",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "debug 1",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "payload",
|
|
"targetType": "msg",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 1420,
|
|
"y": 340,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "44a0a9781ec82884",
|
|
"type": "mqtt in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "MQTT IN (aquamonn/kekeruhan)",
|
|
"topic": "aquamonn/kekeruhan",
|
|
"qos": "0",
|
|
"datatype": "json",
|
|
"broker": "bfc3b3d0112912d7",
|
|
"nl": false,
|
|
"rap": false,
|
|
"inputs": 0,
|
|
"x": 190,
|
|
"y": 760,
|
|
"wires": [
|
|
[
|
|
"6122fc5ebc06e71e"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "6122fc5ebc06e71e",
|
|
"type": "json",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Parse JSON",
|
|
"property": "payload",
|
|
"action": "obj",
|
|
"pretty": false,
|
|
"x": 410,
|
|
"y": 760,
|
|
"wires": [
|
|
[
|
|
"5f4a8e3e12915b58",
|
|
"66d2f5c55fcf730f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "5f4a8e3e12915b58",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "turbidity",
|
|
"func": "msg.payload = msg.payload.turbidity || null;\nmsg.topic = \"turbidity\";\n\nflow.set(\"turbidity\",msg.payload);\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 580,
|
|
"y": 740,
|
|
"wires": [
|
|
[
|
|
"c172fef7c3246031",
|
|
"227e27214ab882c2",
|
|
"75d4ebf392abdea1",
|
|
"6e76986120cce23f",
|
|
"8980aa1777ac9774"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "66d2f5c55fcf730f",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "distance",
|
|
"func": "msg.payload = msg.payload.distance || null;\nmsg.topic = \"distance\";\n\nflow.set(\"distance\", msg.payload);\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 580,
|
|
"y": 800,
|
|
"wires": [
|
|
[
|
|
"227e27214ab882c2",
|
|
"341937785cc480d3"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "4ca05874370f0321",
|
|
"type": "ui_numeric",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"label": "P_mak kadar Amonia",
|
|
"tooltip": "",
|
|
"group": "4cdf3e91604f4b5c",
|
|
"order": 1,
|
|
"width": 0,
|
|
"height": 0,
|
|
"wrap": false,
|
|
"passthru": false,
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"format": "{{value}}",
|
|
"min": "00.00",
|
|
"max": "100.00",
|
|
"step": "00.10",
|
|
"className": "",
|
|
"x": 860,
|
|
"y": 1260,
|
|
"wires": [
|
|
[
|
|
"e220cd1c7b384424"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "0e6815c586945467",
|
|
"type": "ui_text",
|
|
"z": "67eddebaafa49d22",
|
|
"group": "cda931dc01569f7c",
|
|
"order": 4,
|
|
"width": 12,
|
|
"height": 1,
|
|
"name": "Status Relay",
|
|
"label": "Relay",
|
|
"format": "{{msg.payload}}",
|
|
"layout": "col-center",
|
|
"className": "",
|
|
"style": false,
|
|
"font": "",
|
|
"fontSize": "",
|
|
"color": "#000000",
|
|
"x": 1090,
|
|
"y": 360,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "e74efbe9e10e5303",
|
|
"type": "ui_gauge",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Suhu",
|
|
"group": "cda931dc01569f7c",
|
|
"order": 3,
|
|
"width": 4,
|
|
"height": 3,
|
|
"gtype": "wave",
|
|
"title": "Suhu",
|
|
"label": "°C",
|
|
"format": "{{msg.payload}}",
|
|
"min": "0",
|
|
"max": "100",
|
|
"colors": [
|
|
"#00b500",
|
|
"#e6e600",
|
|
"#ca3838"
|
|
],
|
|
"seg1": "",
|
|
"seg2": "",
|
|
"diff": false,
|
|
"className": "",
|
|
"x": 690,
|
|
"y": 200,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "614f7212ee1c0723",
|
|
"type": "ui_gauge",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "pH",
|
|
"group": "cda931dc01569f7c",
|
|
"order": 1,
|
|
"width": 4,
|
|
"height": 3,
|
|
"gtype": "wave",
|
|
"title": "pH",
|
|
"label": "",
|
|
"format": "{{msg.payload}}",
|
|
"min": "0",
|
|
"max": "14",
|
|
"colors": [
|
|
"#00b500",
|
|
"#e6e600",
|
|
"#ca3838"
|
|
],
|
|
"seg1": "",
|
|
"seg2": "",
|
|
"diff": false,
|
|
"className": "",
|
|
"x": 710,
|
|
"y": 240,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "9a2cd222e4412337",
|
|
"type": "ui_gauge",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Amonia",
|
|
"group": "cda931dc01569f7c",
|
|
"order": 2,
|
|
"width": 4,
|
|
"height": 3,
|
|
"gtype": "wave",
|
|
"title": "amonia",
|
|
"label": "mg/L",
|
|
"format": "{{msg.payload}}",
|
|
"min": "0",
|
|
"max": "100",
|
|
"colors": [
|
|
"#00b500",
|
|
"#e6e600",
|
|
"#ca3838"
|
|
],
|
|
"seg1": "",
|
|
"seg2": "",
|
|
"diff": false,
|
|
"className": "",
|
|
"x": 720,
|
|
"y": 280,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "c172fef7c3246031",
|
|
"type": "ui_chart",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"group": "cda931dc01569f7c",
|
|
"order": 5,
|
|
"width": 0,
|
|
"height": 0,
|
|
"label": "diagram",
|
|
"chartType": "line",
|
|
"legend": "false",
|
|
"xformat": "dd HH:mm",
|
|
"interpolate": "linear",
|
|
"nodata": "",
|
|
"dot": false,
|
|
"ymin": "0",
|
|
"ymax": "200",
|
|
"removeOlder": "1",
|
|
"removeOlderPoints": "",
|
|
"removeOlderUnit": "86400",
|
|
"cutout": 0,
|
|
"useOneColor": false,
|
|
"useUTC": false,
|
|
"colors": [
|
|
"#1f77b4",
|
|
"#aec7e8",
|
|
"#ff7f0e",
|
|
"#2ca02c",
|
|
"#98df8a",
|
|
"#d62728",
|
|
"#ff9896",
|
|
"#9467bd",
|
|
"#c5b0d5"
|
|
],
|
|
"outputs": 1,
|
|
"useDifferentColor": false,
|
|
"className": "",
|
|
"x": 860,
|
|
"y": 220,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "4b9ee9fd3c7deca6",
|
|
"type": "debug",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "debug 3",
|
|
"active": false,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 680,
|
|
"y": 1080,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "fd77a2e5286229bb",
|
|
"type": "mqtt out",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "MQTT OUT (aquamonn/relay1)",
|
|
"topic": "aquamonn/relay1",
|
|
"qos": "0",
|
|
"retain": "false",
|
|
"respTopic": "",
|
|
"contentType": "",
|
|
"userProps": "",
|
|
"correl": "",
|
|
"expiry": "",
|
|
"broker": "bfc3b3d0112912d7",
|
|
"x": 1490,
|
|
"y": 780,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "c09a60dd099d0aa8",
|
|
"type": "rbe",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"func": "rbei",
|
|
"gap": "",
|
|
"start": "",
|
|
"inout": "out",
|
|
"septopics": false,
|
|
"property": "payload",
|
|
"topi": "topic",
|
|
"x": 1230,
|
|
"y": 780,
|
|
"wires": [
|
|
[
|
|
"fd77a2e5286229bb"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "69a7497e51fb0f5b",
|
|
"type": "change",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "batas_kekeruhan",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 1130,
|
|
"y": 1320,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "9bbc432f4cd9c29d",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"url": "/set-batas_kekeruhan",
|
|
"method": "post",
|
|
"upload": true,
|
|
"skipBodyParsing": false,
|
|
"swaggerDoc": "",
|
|
"x": 320,
|
|
"y": 1320,
|
|
"wires": [
|
|
[
|
|
"b01e86bb965a9cbf"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b01e86bb965a9cbf",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "set parameter maks kekeruhan ",
|
|
"func": "var nilaiBaru = parseFloat(msg.payload.max_kekeruhan);\n\nif (!isNaN(nilaiBaru) && nilaiBaru >= 0.1 && nilaiBaru <= 500.0) {\n\n flow.set(\"batas_kekeruhan\", nilaiBaru);\n\n node.warn(\"✅ Batas kekeruhan diset: \" + nilaiBaru);\n\n msg.payload = nilaiBaru;\n\n} else {\n node.warn(\"Nilai di luar rentang yang diperbolehkan (0.1 - 400.0)\");\n return null;\n}\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 590,
|
|
"y": 1320,
|
|
"wires": [
|
|
[
|
|
"841b1f1ac2853ebf",
|
|
"adcdbc88d26c1e33"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "841b1f1ac2853ebf",
|
|
"type": "ui_numeric",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"label": "Parameter Maksimal kekeruhan",
|
|
"tooltip": "",
|
|
"group": "4cdf3e91604f4b5c",
|
|
"order": 1,
|
|
"width": 0,
|
|
"height": 0,
|
|
"wrap": false,
|
|
"passthru": false,
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"format": "{{value}}",
|
|
"min": "00.00",
|
|
"max": "500.00",
|
|
"step": "01.00",
|
|
"className": "",
|
|
"x": 870,
|
|
"y": 1320,
|
|
"wires": [
|
|
[
|
|
"69a7497e51fb0f5b"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "629d8859cb8bfd1a",
|
|
"type": "change",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "batas_distance",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 1350,
|
|
"y": 1380,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "76a3866ccc228ded",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"url": "/set-batas_distance",
|
|
"method": "post",
|
|
"upload": true,
|
|
"skipBodyParsing": false,
|
|
"swaggerDoc": "",
|
|
"x": 310,
|
|
"y": 1380,
|
|
"wires": [
|
|
[
|
|
"e46ab0cc98b35111"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "e46ab0cc98b35111",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "set parameter min jarak",
|
|
"func": "var value1 = Number(msg.payload.min_jarak);\n\nif (isNaN(value1)) {\n node.error(\"Nilai min_jarak tidak valid\");\n return null;\n}\n\nflow.set(\"batas_distance\", value1);\n\nnode.warn(\"✅ Batas distance diset: \" + value1);\n\nmsg.payload = value1;\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 590,
|
|
"y": 1380,
|
|
"wires": [
|
|
[
|
|
"cf869f06daa73226",
|
|
"cc4d36240559c7d4"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "cf869f06daa73226",
|
|
"type": "ui_numeric",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"label": "batas tinggi air",
|
|
"tooltip": "",
|
|
"group": "4cdf3e91604f4b5c",
|
|
"order": 1,
|
|
"width": 0,
|
|
"height": 0,
|
|
"wrap": false,
|
|
"passthru": false,
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"format": "{{value}}",
|
|
"min": "0",
|
|
"max": "100",
|
|
"step": "1",
|
|
"className": "",
|
|
"x": 840,
|
|
"y": 1380,
|
|
"wires": [
|
|
[
|
|
"629d8859cb8bfd1a"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "1190c7b944689348",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"url": "/get_history",
|
|
"method": "get",
|
|
"upload": false,
|
|
"skipBodyParsing": false,
|
|
"swaggerDoc": "",
|
|
"x": 280,
|
|
"y": 1200,
|
|
"wires": [
|
|
[
|
|
"ea9a44a9b4ebfe17"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ea9a44a9b4ebfe17",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "query d history",
|
|
"func": "let tanggal = msg.req.query.date;\n\nif (tanggal) {\n msg.topic = `\n SELECT\n id,\n suhu,\n ph,\n amonia,\n turbidity AS kekeruhan,\n distance,\n tinggiAir,\n waktu AS time,\n lampu\n FROM data_sensor\n WHERE DATE(waktu)='${tanggal}'\n ORDER BY waktu DESC\n `;\n} else {\n msg.topic = `\n SELECT\n id,\n suhu,\n ph,\n amonia,\n turbidity AS kekeruhan,\n distance,\n tinggiAir,\n waktu AS time,\n lampu\n FROM data_sensor\n ORDER BY waktu DESC\n `;\n}\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 560,
|
|
"y": 1200,
|
|
"wires": [
|
|
[
|
|
"971ddbe10f49f29f"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "971ddbe10f49f29f",
|
|
"type": "mysql",
|
|
"z": "67eddebaafa49d22",
|
|
"mydb": "91b465b9fa2c994f",
|
|
"name": "",
|
|
"x": 730,
|
|
"y": 1200,
|
|
"wires": [
|
|
[
|
|
"ce7a5b6faf32d2cd"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ce7a5b6faf32d2cd",
|
|
"type": "json",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"property": "payload",
|
|
"action": "str",
|
|
"pretty": false,
|
|
"x": 870,
|
|
"y": 1200,
|
|
"wires": [
|
|
[
|
|
"2e9b3ea41f7235d5"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "2e9b3ea41f7235d5",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "http out",
|
|
"statusCode": "",
|
|
"headers": {},
|
|
"x": 1020,
|
|
"y": 1200,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "101cb65acc03c85e",
|
|
"type": "comment",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Dashboard Monitoring",
|
|
"info": "Dashboard Monitoring",
|
|
"x": 200,
|
|
"y": 200,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "a1",
|
|
"type": "inject",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Contoh Data",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"payload": "{\"sensor_id\":\"sensor01\", \"suhu\":30.5, \"waktu\":\"2025-06-01 12:00:00\"}",
|
|
"payloadType": "json",
|
|
"x": 770,
|
|
"y": 500,
|
|
"wires": [
|
|
[
|
|
"a2"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "227e27214ab882c2",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Data ",
|
|
"func": "// Fungsi untuk merubah ke angka dengan aman\nfunction toNum(val) {\n let n = parseFloat(val);\n return isNaN(n) ? 0 : n;\n}\n\n// Ambil data sensor\nlet suhu = toNum(msg.payload?.suhu || flow.get(\"suhu\"));\nlet ph = toNum(msg.payload?.ph || flow.get(\"pH\"));\nlet amonia = toNum(msg.payload?.amonia || flow.get(\"amonia\"));\nlet turbidity = toNum(msg.payload?.turbidity || flow.get(\"turbidity\"));\nlet distance = toNum(msg.payload?.distance || flow.get(\"distance\"));\nlet tinggiAir = toNum(msg.payload?.tinggiAir || flow.get(\"tinggi_air\"));\n\n// ================= STATUS LAMPU =================\nlet statusLampu = flow.get(\"lampu\");\n\n// Debug nilai asli\nnode.warn(\"Nilai lampu asli: \" + statusLampu);\n\n// Konversi status\nif (\n statusLampu == 1 ||\n statusLampu == \"1\" ||\n statusLampu == \"on\" ||\n statusLampu == \"ON\" ||\n statusLampu === true\n) {\n\n statusLampu = \"ON\";\n\n} else {\n\n statusLampu = \"OFF\";\n\n}\n\n// Payload\nmsg.payload = {\n suhu: suhu,\n ph: ph,\n amonia: amonia,\n turbidity: turbidity,\n distance: distance,\n tinggiAir: tinggiAir,\n lampu: statusLampu,\n waktu: new Date().toLocaleString()\n};\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 790,
|
|
"y": 460,
|
|
"wires": [
|
|
[
|
|
"a2"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "2ac289b311f822de",
|
|
"type": "delay",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"pauseType": "rate",
|
|
"timeout": "1",
|
|
"timeoutUnits": "minutes",
|
|
"rate": "1",
|
|
"nbRateUnits": "5",
|
|
"rateUnits": "second",
|
|
"randomFirst": "1",
|
|
"randomLast": "5",
|
|
"randomUnits": "seconds",
|
|
"drop": false,
|
|
"allowrate": false,
|
|
"outputs": 1,
|
|
"x": 1240,
|
|
"y": 460,
|
|
"wires": [
|
|
[
|
|
"a3"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "a3",
|
|
"type": "mysql",
|
|
"z": "67eddebaafa49d22",
|
|
"mydb": "91b465b9fa2c994f",
|
|
"name": "Simpan ke MySQL",
|
|
"x": 1450,
|
|
"y": 460,
|
|
"wires": [
|
|
[
|
|
"1ebae4590b28a2c9"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "a2",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Buat Query",
|
|
"func": "// Mengambil data langsung dari msg.payload\nvar data = msg.payload;\n\n// Query SQL\nmsg.topic = `\nINSERT INTO data_sensor \n(suhu, ph, amonia, turbidity, distance, tinggiAir, lampu, waktu) \nVALUES (?, ?, ?, ?, ?, ?, ?, NOW())\n`;\n\n// Parameter MySQL\nmsg.payload = [\n parseFloat(data.suhu),\n parseFloat(data.ph),\n parseFloat(data.amonia),\n parseFloat(data.turbidity),\n parseFloat(data.distance),\n parseFloat(data.tinggiAir),\n data.lampu\n];\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": "",
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 930,
|
|
"y": 460,
|
|
"wires": [
|
|
[
|
|
"41d6eb4fe0f07296",
|
|
"19c6ea6e7225cca3"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "41d6eb4fe0f07296",
|
|
"type": "debug",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "debug 4",
|
|
"active": false,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "false",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 1080,
|
|
"y": 500,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "19c6ea6e7225cca3",
|
|
"type": "rbe",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"func": "rbei",
|
|
"gap": "",
|
|
"start": "",
|
|
"inout": "out",
|
|
"septopics": true,
|
|
"property": "payload",
|
|
"topi": "topic",
|
|
"x": 1090,
|
|
"y": 460,
|
|
"wires": [
|
|
[
|
|
"2ac289b311f822de"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b870d39796f44547",
|
|
"type": "comment",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "penyimpanan ke database",
|
|
"info": "",
|
|
"x": 590,
|
|
"y": 460,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "5aa05bbf5c017cc6",
|
|
"type": "comment",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Pompa Otomasi (amonia, kekruhan dan Volume)",
|
|
"info": "",
|
|
"x": 880,
|
|
"y": 720,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "ad6bc97e3db948bf",
|
|
"type": "comment",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Dashboard Monitoring",
|
|
"info": "Dashboard Monitoring",
|
|
"x": 180,
|
|
"y": 720,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "05fd7be03f3d40f0",
|
|
"type": "firebase cloud messaging",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "FCM aplikasi",
|
|
"admin": "88242af294bbf4e8",
|
|
"kind": "notification",
|
|
"x": 1130,
|
|
"y": 620,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "bfd5c8e23790ad5d",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "token nfc",
|
|
"func": "msg.token = \"dleP_pdMRpqt1EPl_8sTw4:APA91bFBiOeFEKXOR-k9yN3M8mXMa44AWUVlZceYnjxgmp_l2Ewvww5xJt7SBwBH99ZqocWGIf6UDDrGRDsgW_RwnYhrnXMOXSEd6DjgEpQ99JZYYr1weuY\";\n\nmsg.payload = {\n title: \"Tes Aquamon\",\n body: \"Notifikasi dari Node-RED\"\n};\n\ndelete msg.topic;\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 960,
|
|
"y": 620,
|
|
"wires": [
|
|
[
|
|
"05fd7be03f3d40f0"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "8980aa1777ac9774",
|
|
"type": "debug",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "debug 6",
|
|
"active": true,
|
|
"tosidebar": true,
|
|
"console": false,
|
|
"tostatus": false,
|
|
"complete": "true",
|
|
"targetType": "full",
|
|
"statusVal": "",
|
|
"statusType": "auto",
|
|
"x": 980,
|
|
"y": 960,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "8ca55be705adf870",
|
|
"type": "inject",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"props": [
|
|
{
|
|
"p": "payload"
|
|
},
|
|
{
|
|
"p": "topic",
|
|
"vt": "str"
|
|
}
|
|
],
|
|
"repeat": "",
|
|
"crontab": "",
|
|
"once": false,
|
|
"onceDelay": 0.1,
|
|
"topic": "",
|
|
"payload": "test",
|
|
"payloadType": "str",
|
|
"x": 830,
|
|
"y": 620,
|
|
"wires": [
|
|
[
|
|
"bfd5c8e23790ad5d"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "94b36373e7c0a702",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Notif amonia",
|
|
"func": "let amonia = Number(flow.get(\"amonia\")) || 0;\nlet maksimum = Number(flow.get(\"p_maks\")) || 2.0;\n\nlet sudahKirim = flow.get(\"notif_amonia\") || false;\n\nif (amonia > maksimum) {\n\n if (!sudahKirim) {\n\n flow.set(\"notif_amonia\", true);\n\n msg.token = \"dleP_pdMRpqt1EPl_8sTw4:APA91bFBiOeFEKXOR-k9yN3M8mXMa44AWUVlZceYnjxgmp_l2Ewvww5xJt7SBwBH99ZqocWGIf6UDDrGRDsgW_RwnYhrnXMOXSEd6DjgEpQ99JZYYr1weuY\";\n\n msg.payload = {\n title: \"Peringatan Aquamon\",\n body: `Kadar amonia tinggi (${Math.floor(amonia*10) / 10} mg/L)`\n };\n\n return msg;\n }\n\n} else {\n\n flow.set(\"notif_amonia\", false);\n}\n\nreturn null;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 890,
|
|
"y": 400,
|
|
"wires": [
|
|
[
|
|
"05fd7be03f3d40f0"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "63389c6186af5749",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Notif kekeruhan",
|
|
"func": "let turbidity = Number(msg.turbidity || flow.get(\"turbidity\") || 0);\nlet batas = Number(flow.get(\"batas_kekeruhan\")) || 50;\n\nlet sudahKirim = flow.get(\"notif_kekeruhan\") || false;\n\nif (turbidity > batas) {\n\n if (!sudahKirim) {\n\n flow.set(\"notif_kekeruhan\", true);\n\n msg.token = \"dleP_pdMRpqt1EPl_8sTw4:APA91bFBiOeFEKXOR-k9yN3M8mXMa44AWUVlZceYnjxgmp_l2Ewvww5xJt7SBwBH99ZqocWGIf6UDDrGRDsgW_RwnYhrnXMOXSEd6DjgEpQ99JZYYr1weuY\";\n\n msg.payload = {\n title: \"Peringatan Aquamon\",\n body: `Kekeruhan tinggi (${Math.floor(turbidity*10) / 10} NTU)`\n };\n\n return msg;\n }\n\n} else {\n\n flow.set(\"notif_kekeruhan\", false);\n}\n\nreturn null;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 1280,
|
|
"y": 700,
|
|
"wires": [
|
|
[
|
|
"05fd7be03f3d40f0"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "6e76986120cce23f",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "kontrol kekeruhan, jarak, dan amoniak",
|
|
"func": "// =========================\n// Ambil Data Sensor\n// =========================\nlet turbidity = Number(msg.turbidity || flow.get(\"turbidity\") || 0);\nlet tinggiAir = Number(flow.get(\"tinggi_air\") || 0);\nlet amonia = Number(flow.get(\"amonia\") || 0);\n\n// =========================\n// Ambil Batas\n// =========================\nlet batasKekeruhan = Number(flow.get(\"batas_kekeruhan\")) || 0;\n\n// Tinggi air yang diinginkan (cm)\nlet batasTinggiAir = Number(flow.get(\"batas_distance\")) || 0;\n\n// Batas amonia\nlet batasAmonia = Number(flow.get(\"p_maks\")) || 0;\n\n// =========================\n// Status Pompa\n// =========================\nlet pompaMasuk = 0;\nlet pompaKeluar = 0;\n\n// =========================\n// PRIORITAS LEVEL AIR\n// =========================\n\n// Air kurang → isi air\nif (tinggiAir < batasTinggiAir) {\n\n pompaMasuk = 1;\n pompaKeluar = 0;\n\n node.warn(\"💧 AIR KURANG - Tinggi Air: \" + tinggiAir + \" cm\");\n\n}\n// Tinggi air sudah memenuhi → cek kualitas air\nelse {\n\n // Jika kekeruhan atau amonia melebihi batas\n if (turbidity > batasKekeruhan || amonia > batasAmonia) {\n\n pompaMasuk = 0;\n pompaKeluar = 1;\n\n if (turbidity > batasKekeruhan && amonia > batasAmonia) {\n node.warn(\"⚠️ AIR KERUH & AMONIA TINGGI - Ganti air\");\n }\n else if (turbidity > batasKekeruhan) {\n node.warn(\"⚠️ AIR KERUH - Ganti air\");\n }\n else {\n node.warn(\"🚨 AMONIA TINGGI - Ganti air\");\n }\n\n }\n else {\n\n pompaMasuk = 0;\n pompaKeluar = 0;\n\n node.warn(\"✅ Kondisi Normal\");\n }\n}\n\n// =========================\n// Simpan Status\n// =========================\nflow.set(\"pompa_masuk\", pompaMasuk);\nflow.set(\"pompa_keluar\", pompaKeluar);\n\n// =========================\n// Kirim ke ESP32\n// =========================\nmsg.payload = {\n pompa_masuk: pompaMasuk,\n pompa_keluar: pompaKeluar,\n turbidity: turbidity,\n tinggi_air: tinggiAir,\n amonia: amonia\n};\n\nmsg.topic = \"aquamonn/relay1\";\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 990,
|
|
"y": 780,
|
|
"wires": [
|
|
[
|
|
"c09a60dd099d0aa8",
|
|
"63389c6186af5749"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "get-status-in",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"url": "/get-status",
|
|
"method": "get",
|
|
"x": 2380,
|
|
"y": 1700,
|
|
"wires": [
|
|
[
|
|
"get-status-fn"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "get-status-fn",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"func": "const s = flow.get('device_status') || {};\nconst schedule = flow.get('schedule') || {};\n\nmsg.payload = {\n relay: s.relay ?? 0,\n pompa_mode: s.pompa_mode ?? 'MANUAL',\n\n batas_amonia: flow.get('p_maks') ?? 0.5,\n batas_turbidity: flow.get('batas_kekeruhan') ?? 0,\n batas_distance: flow.get('batas_distance') ?? 0,\n tinggi_aquarium: flow.get('tinggi_aquarium') ?? 0,\n\n lampu: s.lampu ?? 0,\n lampu_mode: s.lampu_mode ?? 'MANUAL',\n\n lampu_on_time: schedule.on_time ?? '06:00',\n lampu_off_time: schedule.off_time ?? '18:00',\n schedule_enabled: schedule.enabled ?? false\n};\n\nmsg.statusCode = 200;\nmsg.headers = {\n \"Content-Type\": \"application/json\"\n};\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": "",
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 2660,
|
|
"y": 1700,
|
|
"wires": [
|
|
[
|
|
"get-status-out"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "get-status-out",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"x": 2850,
|
|
"y": 1700,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "75d4ebf392abdea1",
|
|
"type": "ui_gauge",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "turbidity",
|
|
"group": "cda931dc01569f7c",
|
|
"order": 3,
|
|
"width": 4,
|
|
"height": 3,
|
|
"gtype": "wave",
|
|
"title": "turbidity",
|
|
"label": "NTU",
|
|
"format": "{{msg.payload}}",
|
|
"min": "0",
|
|
"max": "150",
|
|
"colors": [
|
|
"#00b500",
|
|
"#e6e600",
|
|
"#ca3838"
|
|
],
|
|
"seg1": "",
|
|
"seg2": "",
|
|
"diff": false,
|
|
"className": "",
|
|
"x": 600,
|
|
"y": 660,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "f482a0176d55f712",
|
|
"type": "ui_gauge",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "distance",
|
|
"group": "cda931dc01569f7c",
|
|
"order": 3,
|
|
"width": 4,
|
|
"height": 3,
|
|
"gtype": "wave",
|
|
"title": "tinggi air",
|
|
"label": "cm",
|
|
"format": "{{msg.payload}}",
|
|
"min": "0",
|
|
"max": "200",
|
|
"colors": [
|
|
"#00b500",
|
|
"#e6e600",
|
|
"#ca3838"
|
|
],
|
|
"seg1": "",
|
|
"seg2": "",
|
|
"diff": false,
|
|
"className": "",
|
|
"x": 960,
|
|
"y": 880,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "ff08ce828a8ab3cb",
|
|
"type": "ui_form",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Setting Jadwal",
|
|
"label": "⚙️ SETTING JADWAL",
|
|
"group": "a94dd1f096ac2c9b",
|
|
"order": 1,
|
|
"width": 6,
|
|
"height": 3,
|
|
"options": [
|
|
{
|
|
"label": "Jam NYALA (contoh: 06:00)",
|
|
"value": "on_time",
|
|
"type": "text",
|
|
"required": true,
|
|
"rows": null
|
|
},
|
|
{
|
|
"label": "Jam MATI (contoh: 18:00)",
|
|
"value": "off_time",
|
|
"type": "text",
|
|
"required": true,
|
|
"rows": null
|
|
}
|
|
],
|
|
"formValue": {
|
|
"on_time": "",
|
|
"off_time": ""
|
|
},
|
|
"payload": "",
|
|
"submit": "set jadwal",
|
|
"cancel": "",
|
|
"topic": "",
|
|
"topicType": "str",
|
|
"splitLayout": false,
|
|
"className": "",
|
|
"x": 2040,
|
|
"y": 380,
|
|
"wires": [
|
|
[
|
|
"7969fbc0ae2282a3",
|
|
"33fa2cfc4d307cc0"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "7969fbc0ae2282a3",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Proses & Kirim Jadwal",
|
|
"func": "var onParts = msg.payload.on_time.split(\":\");\nvar offParts = msg.payload.off_time.split(\":\");\n\nmsg.payload = {\n auto_mode: true,\n on_hour: parseInt(onParts[0]),\n on_minute: parseInt(onParts[1]),\n off_hour: parseInt(offParts[0]),\n off_minute: parseInt(offParts[1])\n};\n\nmsg.topic = \"aquamonn/schedule\";\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": "",
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 2240,
|
|
"y": 420,
|
|
"wires": [
|
|
[
|
|
"3482f4c78fef1932"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "3482f4c78fef1932",
|
|
"type": "mqtt out",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "MQTT OUT(aquamon/schedule)",
|
|
"topic": "aquamonn/schedule",
|
|
"qos": "1",
|
|
"retain": false,
|
|
"respTopic": "",
|
|
"contentType": "",
|
|
"userProps": "",
|
|
"correl": "",
|
|
"expiry": "",
|
|
"broker": "bfc3b3d0112912d7",
|
|
"x": 2490,
|
|
"y": 420,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "da019ce3e84bd30b",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "API Schedule",
|
|
"url": "/api-schedule",
|
|
"method": "post",
|
|
"upload": false,
|
|
"skipBodyParsing": false,
|
|
"swaggerDoc": "",
|
|
"x": 1670,
|
|
"y": 420,
|
|
"wires": [
|
|
[
|
|
"33fa2cfc4d307cc0"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "2320ac246a8bc22b",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"statusCode": "200",
|
|
"headers": {
|
|
"Content-Type": "application/json"
|
|
},
|
|
"x": 2040,
|
|
"y": 440,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "b33a6e46b2fca1f9",
|
|
"type": "mqtt out",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"topic": "aquamonn/lampu",
|
|
"qos": "1",
|
|
"retain": false,
|
|
"respTopic": "",
|
|
"contentType": "",
|
|
"userProps": "",
|
|
"correl": "",
|
|
"expiry": "",
|
|
"broker": "bfc3b3d0112912d7",
|
|
"x": 2330,
|
|
"y": 500,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "962bb23a21c18f87",
|
|
"type": "ui_text",
|
|
"z": "67eddebaafa49d22",
|
|
"group": "a94dd1f096ac2c9b",
|
|
"order": 4,
|
|
"width": 6,
|
|
"height": 1,
|
|
"name": "",
|
|
"label": "📊 STATUS",
|
|
"format": "{{msg.payload}}",
|
|
"layout": "row-center",
|
|
"x": 2270,
|
|
"y": 600,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "16a71d81f5f2d986",
|
|
"type": "mqtt in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"topic": "aquamonn/lampu_status",
|
|
"qos": 0,
|
|
"datatype": "json",
|
|
"broker": "bfc3b3d0112912d7",
|
|
"nl": false,
|
|
"rap": false,
|
|
"inputs": 0,
|
|
"x": 1870,
|
|
"y": 600,
|
|
"wires": [
|
|
[
|
|
"d8e36ec0aeedf2ce",
|
|
"d357f3c50b1b7cb1"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "d8e36ec0aeedf2ce",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Format Status",
|
|
"func": "\nlet s = msg.payload;\nlet schedule = flow.get(\"schedule\") || {};\nlet on_time = schedule.on_time || \"--:--\";\nlet off_time = schedule.off_time || \"--:--\";\n\n\nlet status = s.lampu_status || \"OFF\";\nlet mode = s.lampu_mode || flow.get(\"schedule\")?.enabled ? \"AUTO\" : \"MANUAL\";\nmsg.payload =\n `💡 Lampu: ${status} | Mode: ${mode} | Jadwal: ${on_time}-${off_time}`;\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": "",
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 2090,
|
|
"y": 600,
|
|
"wires": [
|
|
[
|
|
"962bb23a21c18f87"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "33fa2cfc4d307cc0",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Proses API",
|
|
"func": "// Data dari Flutter\nlet on_time = msg.payload.on_time;\nlet off_time = msg.payload.off_time;\nlet enabled = msg.payload.enabled;\n\n// Simpan sebagai setting terbaru\nflow.set(\"schedule\", {\n on_time: on_time,\n off_time: off_time,\n enabled: enabled\n});\n\n// Kirim ke node berikutnya\nmsg.payload = flow.get(\"schedule\")\n\nreturn msg;",
|
|
"outputs": 2,
|
|
"timeout": "",
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 1830,
|
|
"y": 420,
|
|
"wires": [
|
|
[
|
|
"ff08ce828a8ab3cb",
|
|
"7969fbc0ae2282a3",
|
|
"603e2c200cd94f96"
|
|
],
|
|
[
|
|
"2320ac246a8bc22b"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "1edff568b079766b",
|
|
"type": "ui_switch",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"label": "lampu manual",
|
|
"tooltip": "",
|
|
"group": "a94dd1f096ac2c9b",
|
|
"order": 0,
|
|
"width": 0,
|
|
"height": 0,
|
|
"passthru": true,
|
|
"decouple": "false",
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"style": "",
|
|
"onvalue": "1",
|
|
"onvalueType": "num",
|
|
"onicon": "",
|
|
"oncolor": "",
|
|
"offvalue": "0",
|
|
"offvalueType": "num",
|
|
"officon": "",
|
|
"offcolor": "",
|
|
"animate": false,
|
|
"className": "",
|
|
"x": 2120,
|
|
"y": 500,
|
|
"wires": [
|
|
[
|
|
"b33a6e46b2fca1f9"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "62119e99371b7e14",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "API lampu",
|
|
"url": "/api-lampu",
|
|
"method": "post",
|
|
"upload": false,
|
|
"skipBodyParsing": false,
|
|
"swaggerDoc": "",
|
|
"x": 1760,
|
|
"y": 500,
|
|
"wires": [
|
|
[
|
|
"abb6bbae9528a933"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b28dcbc36e97dcd9",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"statusCode": "200",
|
|
"headers": {
|
|
"Content-Type": "application/json"
|
|
},
|
|
"x": 2100,
|
|
"y": 540,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "abb6bbae9528a933",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Proses API",
|
|
"func": "var statusLampu = msg.payload.lampu;\n\n// Jika ON\nif (statusLampu === \"on\") {\n\n flow.set(\"lampu\", \"ON\");\n\n msg.payload = 1;\n return [msg, null];\n\n}\n\n// Jika OFF\nif (statusLampu === \"off\") {\n\n flow.set(\"lampu\", \"OFF\");\n\n msg.payload = 0;\n return [msg, null];\n\n}\n\n// Jika data salah\nmsg.statusCode = 400;\n\nmsg.payload = {\n status: \"error\",\n message: \"Gunakan on/off\"\n};\n\nreturn [null, msg];",
|
|
"outputs": 2,
|
|
"timeout": "",
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 1910,
|
|
"y": 500,
|
|
"wires": [
|
|
[
|
|
"1edff568b079766b",
|
|
"227e27214ab882c2",
|
|
"4a32c5a52275c9de"
|
|
],
|
|
[
|
|
"b28dcbc36e97dcd9"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "a8240d8621d21ee4",
|
|
"type": "comment",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Penjadwalan Lampu",
|
|
"info": "",
|
|
"x": 2030,
|
|
"y": 340,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "d357f3c50b1b7cb1",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Notif jadwal lampu",
|
|
"func": "let status = (msg.payload.lampu_status || \"OFF\").toUpperCase();\n\nlet terakhir = flow.get(\"status_lampu_terakhir\");\n\nif (terakhir === status) {\n return null;\n}\n\nflow.set(\"status_lampu_terakhir\", status);\n\nmsg.token = \"dleP_pdMRpqt1EPl_8sTw4:APA91bFBiOeFEKXOR-k9yN3M8mXMa44AWUVlZceYnjxgmp_l2Ewvww5xJt7SBwBH99ZqocWGIf6UDDrGRDsgW_RwnYhrnXMOXSEd6DjgEpQ99JZYYr1weuY\";\n\nmsg.payload = {\n title: \"Lampu Aquascape\",\n body: status === \"ON\"\n ? \"Lampu menyala\"\n : \"Lampu mati\"\n};\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 2090,
|
|
"y": 660,
|
|
"wires": [
|
|
[
|
|
"05fd7be03f3d40f0"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "d7fa5aa55c52ab42",
|
|
"type": "comment",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "Pompa otomasi (Kadar Amonia)",
|
|
"info": "",
|
|
"x": 990,
|
|
"y": 280,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "35242a5545433aad",
|
|
"type": "http in",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"url": "/set-tinggi_aquarium",
|
|
"method": "post",
|
|
"upload": true,
|
|
"skipBodyParsing": false,
|
|
"swaggerDoc": "",
|
|
"x": 310,
|
|
"y": 1440,
|
|
"wires": [
|
|
[
|
|
"b806c84ab5bb9fc9"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "b806c84ab5bb9fc9",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "tinggi_aquarium",
|
|
"func": "var nilaiBaru = parseFloat(msg.payload.tinggi_aquarium);\n\nif (!isNaN(nilaiBaru) && nilaiBaru >= 1 && nilaiBaru <= 100) {\n\n flow.set(\"tinggi_aquarium\", nilaiBaru);\n\n node.warn(\"✅ Tinggi aquarium diset: \" + nilaiBaru + \" cm\");\n\n msg.payload = nilaiBaru;\n\n} else {\n\n node.warn(\"Nilai di luar rentang yang diperbolehkan (1 - 100 cm)\");\n return null;\n}\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 580,
|
|
"y": 1440,
|
|
"wires": [
|
|
[
|
|
"bc9026e0f0619982",
|
|
"ea1b224a2531a2c3"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "bc9026e0f0619982",
|
|
"type": "ui_numeric",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"label": "kontrol tinggi aquarium ",
|
|
"tooltip": "",
|
|
"group": "4cdf3e91604f4b5c",
|
|
"order": 1,
|
|
"width": 0,
|
|
"height": 0,
|
|
"wrap": false,
|
|
"passthru": false,
|
|
"topic": "topic",
|
|
"topicType": "msg",
|
|
"format": "{{value}}",
|
|
"min": "00.00",
|
|
"max": "100.00",
|
|
"step": "01.00",
|
|
"className": "",
|
|
"x": 840,
|
|
"y": 1440,
|
|
"wires": [
|
|
[
|
|
"3c3148c4f01bb1e4"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "3c3148c4f01bb1e4",
|
|
"type": "change",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "",
|
|
"rules": [
|
|
{
|
|
"t": "set",
|
|
"p": "tinggi_aquarium",
|
|
"pt": "flow",
|
|
"to": "payload",
|
|
"tot": "msg"
|
|
}
|
|
],
|
|
"action": "",
|
|
"property": "",
|
|
"from": "",
|
|
"to": "",
|
|
"reg": false,
|
|
"x": 1130,
|
|
"y": 1440,
|
|
"wires": [
|
|
[]
|
|
]
|
|
},
|
|
{
|
|
"id": "341937785cc480d3",
|
|
"type": "function",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "tinggi air",
|
|
"func": "// Ambil tinggi aquarium\nlet H = Number(flow.get(\"tinggi_aquarium\") || 0);\n\n// Ambil distance\nlet distance = Number(flow.get(\"distance\") || 0);\n\n// Hitung tinggi air\nlet tinggiAir = H - distance;\n\n// Batasi hasil\ntinggiAir = Math.max(0, Math.min(H, tinggiAir));\n\n// Simpan ke flow\nflow.set(\"tinggi_air\", tinggiAir);\n\n// Debug\nnode.warn(\n \"Tinggi Aquarium: \" + H +\n \" cm | Distance: \" + distance +\n \" cm | Tinggi Air: \" + tinggiAir.toFixed(1) + \" cm\"\n);\n\n// Payload hanya tinggi_air\nmsg.payload = Number(tinggiAir.toFixed(1));\nmsg.topic = \"tinggi_air\";\n\nreturn msg;",
|
|
"outputs": 1,
|
|
"timeout": 0,
|
|
"noerr": 0,
|
|
"initialize": "",
|
|
"finalize": "",
|
|
"libs": [],
|
|
"x": 760,
|
|
"y": 820,
|
|
"wires": [
|
|
[
|
|
"f482a0176d55f712",
|
|
"6e76986120cce23f",
|
|
"227e27214ab882c2"
|
|
]
|
|
]
|
|
},
|
|
{
|
|
"id": "ea1b224a2531a2c3",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "http out",
|
|
"statusCode": "",
|
|
"headers": {},
|
|
"x": 1360,
|
|
"y": 1460,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "cc4d36240559c7d4",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "http out",
|
|
"statusCode": "",
|
|
"headers": {},
|
|
"x": 1560,
|
|
"y": 1340,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "adcdbc88d26c1e33",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "http out",
|
|
"statusCode": "",
|
|
"headers": {},
|
|
"x": 1380,
|
|
"y": 1280,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "3bf3670a4281b696",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "http out",
|
|
"statusCode": "",
|
|
"headers": {},
|
|
"x": 1300,
|
|
"y": 1200,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "603e2c200cd94f96",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "http out",
|
|
"statusCode": "",
|
|
"headers": {},
|
|
"x": 2320,
|
|
"y": 300,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "4a32c5a52275c9de",
|
|
"type": "http response",
|
|
"z": "67eddebaafa49d22",
|
|
"name": "http out",
|
|
"statusCode": "",
|
|
"headers": {},
|
|
"x": 2420,
|
|
"y": 560,
|
|
"wires": []
|
|
},
|
|
{
|
|
"id": "bfc3b3d0112912d7",
|
|
"type": "mqtt-broker",
|
|
"name": "",
|
|
"broker": "broker.emqx.io",
|
|
"port": "1883",
|
|
"clientid": "",
|
|
"autoConnect": true,
|
|
"usetls": false,
|
|
"protocolVersion": 4,
|
|
"keepalive": 60,
|
|
"cleansession": true,
|
|
"autoUnsubscribe": true,
|
|
"birthTopic": "",
|
|
"birthQos": "0",
|
|
"birthRetain": "false",
|
|
"birthPayload": "",
|
|
"birthMsg": {},
|
|
"closeTopic": "",
|
|
"closeQos": "0",
|
|
"closeRetain": "false",
|
|
"closePayload": "",
|
|
"closeMsg": {},
|
|
"willTopic": "",
|
|
"willQos": "0",
|
|
"willRetain": "false",
|
|
"willPayload": "",
|
|
"willMsg": {},
|
|
"userProps": "",
|
|
"sessionExpiry": ""
|
|
},
|
|
{
|
|
"id": "4cdf3e91604f4b5c",
|
|
"type": "ui_group",
|
|
"name": "Kontrol ",
|
|
"tab": "4423227bec07427f",
|
|
"order": 2,
|
|
"disp": true,
|
|
"width": "6",
|
|
"collapse": false,
|
|
"className": ""
|
|
},
|
|
{
|
|
"id": "cda931dc01569f7c",
|
|
"type": "ui_group",
|
|
"name": "Monitoring",
|
|
"tab": "4423227bec07427f",
|
|
"order": 1,
|
|
"disp": true,
|
|
"width": 12,
|
|
"collapse": false,
|
|
"className": ""
|
|
},
|
|
{
|
|
"id": "91b465b9fa2c994f",
|
|
"type": "MySQLdatabase",
|
|
"name": "",
|
|
"host": "localhost",
|
|
"port": "3306",
|
|
"db": "mydb",
|
|
"tz": "",
|
|
"charset": "UTF8"
|
|
},
|
|
{
|
|
"id": "88242af294bbf4e8",
|
|
"type": "firebase admin",
|
|
"name": "Aquamon"
|
|
},
|
|
{
|
|
"id": "a94dd1f096ac2c9b",
|
|
"type": "ui_group",
|
|
"name": "📅 Penjadwalan Lampu",
|
|
"tab": "4423227bec07427f",
|
|
"order": 3,
|
|
"width": 12,
|
|
"collapse": false
|
|
},
|
|
{
|
|
"id": "4423227bec07427f",
|
|
"type": "ui_tab",
|
|
"name": "Sistem Monitoring dan Kotroling Kualitas Air Pada Aquarium",
|
|
"icon": "dashboard",
|
|
"order": 1,
|
|
"disabled": false,
|
|
"hidden": false
|
|
},
|
|
{
|
|
"id": "a9716a8fd7ce5d5a",
|
|
"type": "global-config",
|
|
"env": [],
|
|
"modules": {
|
|
"node-red-dashboard": "3.6.6",
|
|
"node-red-node-mysql": "3.0.0",
|
|
"node-red-contrib-firebase-messaging": "0.4.2"
|
|
}
|
|
}
|
|
] |