Skip to content

Instantly share code, notes, and snippets.

@VACIndustries
Forked from WolfwithSword/bambu_bed_mesh_flow.json
Created January 27, 2023 02:08
Show Gist options
  • Save VACIndustries/46b705cd4511d1d8c116f1eb83a3298d to your computer and use it in GitHub Desktop.
Save VACIndustries/46b705cd4511d1d8c116f1eb83a3298d to your computer and use it in GitHub Desktop.
Node-RED Flow - BambuLab X1 MQTT Relay for Home Assistant MQTT Auto-Discovery
[
{
"id": "fbda6ab16491b918",
"type": "tab",
"label": "BambuLab MQTT",
"disabled": false,
"info": "",
"env": []
},
{
"id": "296274a0d2a6c675",
"type": "group",
"z": "fbda6ab16491b918",
"name": "Bambu MQTT Relay",
"style": {
"stroke": "#92d04f",
"label": true,
"color": "#92d04f"
},
"nodes": [
"b1c1923cb89b667b",
"7c5bb5efa50cfa5b",
"69b4c2a7d4558125",
"a365818fb4a53f52",
"1389ca15cce63bbb",
"9737da24b3e03e14",
"9b44ae9e961cc5e3",
"ec5cf3eb1b12c22b",
"1f20b9de36cc424b",
"7260cf57c3edbd49",
"7c6b4583707029ea",
"8d2a544a9c61d783",
"d5e7799961b2eb4f",
"ff09ef39735c8dd8",
"5610f1312e4c57f2",
"07ff86f3cd404e2d",
"3412b5c7efd1d41e",
"098967fde25793c1",
"2d01d38e6dd73736",
"9d95b756f4601713",
"5774338c2d9e049b",
"d10c56abbd6b7b47",
"1f0305e93eed961a",
"2a60f3818c07cead",
"bf872cba7b8d4a63",
"2f77cb6feca03746",
"afcea49d4f94f15c",
"69cba2483fe68056",
"17945f4d7962a94a",
"a0317478d3f43ecf",
"8171a948ce6a2ae7",
"83f6c2b5b869cd97",
"472a15482a731de8",
"86e9caa98fa51352",
"d7a406891ffe1ae5",
"3fb2679ab80855bb",
"955d6d328d2b5e22",
"41797ced12627146",
"2ce84ba9618b908d",
"b2881b8ed28a467c",
"96b92ea713edd221",
"f7de3b0a2a7c5661",
"8399cea217e486b9",
"f0bcc0434d35f8db",
"1db470110f18fab6",
"2a0268a55eadf72f",
"c93c3bb2cc88b9dc",
"d8d2dad22b354fdf",
"187393ac342955a5",
"e9f7f1de7feb3909",
"dce813c208a9da90",
"ab7f1b7beb3a2f80",
"080745c0307e0218",
"8a61805ce8145c12",
"eec5b5dc9281ea93",
"9d626d59541a6e6f",
"6a13ae7af77d563d",
"5c4b13a29c630b8c",
"b5232b827fbef671",
"4a696bec52ae5acb",
"962c0c56346e023a",
"db012956ddb6c2af",
"ad4f3f980f172128",
"ecf4cb43eed20ca0",
"b3ee63836831ea89",
"b5fb8a1a65b4686b",
"682e4da1ee0769d4",
"e98417ec17a23249",
"135e57a801b6e9bf",
"7f4faea318d59bed",
"9a2aaf740774a256",
"f844bda465c93ddd",
"e34f034bed456673",
"dba47578907a6d23",
"735003dd7602e7dc",
"c40efe7b1b254622",
"b34fe28bd6f1cf0b",
"883a607fd81a0e23",
"67aa1b3a6a0ac3d7",
"c868c39bb6549391",
"af54a0a5940dd334",
"ca1821a15d5fe203",
"6db1d3c86598f8a4",
"0c9c48807302abbe",
"7cbd22af688976aa",
"12d493bc4868cb6b",
"6526126078390137",
"f6805ea36226a930",
"c1bc72e5401a7523",
"97e117e5e3b6b2ac",
"dbd5442f44b5d5eb",
"574efe9bef59bfe8",
"dff0a7bcab99db34",
"17dc50ac469fdac7",
"51c3cfdad1576d27",
"2dcd252aec842a4b",
"0539d7216c7abb63",
"dae563cbc58f46bd",
"1105b8629aa017ee",
"73ce7dbb92cee565",
"4293665f8ddd9f37",
"2fe75ce36321f506",
"a1c7a965b0d664fe",
"3907f3b052894ad1",
"a4d29254d471acd7",
"1288bcdd3d2bc704",
"d20b02ea37dbdddf",
"8959434b99b38bdd",
"7ba7e522b0b73697"
],
"x": 14,
"y": 19,
"w": 2232,
"h": 1047
},
{
"id": "b1c1923cb89b667b",
"type": "mqtt in",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Bambu X1C {PRINTER_NAME}",
"topic": "device/{PRINTER_SERIAL}/report",
"qos": "2",
"datatype": "json",
"broker": "84f61d394ba2ab34",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 190,
"y": 280,
"wires": [
[
"69b4c2a7d4558125"
]
]
},
{
"id": "7c5bb5efa50cfa5b",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Inject Machine Details",
"func": "let machine_name = \"{PRINTER_NAME}\";\nlet machine_serial = \"{PRINTER_SERIAL}\";\nlet manufacturer = \"Bambu Labs\";\nlet model = \"X1 Carbon\"\nif(msg.payload.mc_print != undefined) {\n msg.payload.mc_print.machine_name = machine_name;\n msg.payload.mc_print.machine_serial = machine_serial;\n msg.payload.mc_print.manufacturer = manufacturer;\n if(msg.payload.mc_print.param.includes(\"[AMS]\")) {\n msg.payload.mc_print.model = \"AMS\";\n }\n else {\n msg.payload.mc_print.model = model;\n }\n}\n\nif (msg.payload.print != undefined) {\n msg.payload.print.machine_name = machine_name;\n msg.payload.print.machine_serial = machine_serial;\n msg.machine_serial = machine_serial;\n msg.payload.print.manufacturer = manufacturer;\n msg.payload.print.model = model;\n\n if (msg.payload.print.ams !== undefined) {\n for (var ams of msg.payload.print.ams.ams) {\n ams.printer_name = machine_name\n ams.printer_serial = machine_serial\n }\n }\n msg.payload.print.status = \"online\";\n msg.payload.print.reset_filter = \"\";\n msg.payload.print.pause_print = \"\";\n msg.payload.print.resume_print = \"\";\n msg.payload.print.stop_print = \"\";\n}\n\n\nif (msg.payload.info != undefined) {\n msg.printer_name = machine_name;\n msg.machine_serial = machine_serial;\n msg.manufacturer = manufacturer;\n msg.model = model;\n}\nnode.send(msg);\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 180,
"y": 320,
"wires": [
[
"dba47578907a6d23"
]
]
},
{
"id": "69b4c2a7d4558125",
"type": "json",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "payload.print",
"action": "obj",
"pretty": false,
"x": 370,
"y": 280,
"wires": [
[
"7c5bb5efa50cfa5b"
]
]
},
{
"id": "a365818fb4a53f52",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "hask",
"v": "info",
"vt": "str"
},
{
"t": "hask",
"v": "mc_print",
"vt": "str"
},
{
"t": "hask",
"v": "print",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 4,
"x": 610,
"y": 300,
"wires": [
[
"97e117e5e3b6b2ac"
],
[
"883a607fd81a0e23"
],
[
"8a61805ce8145c12"
],
[]
]
},
{
"id": "1389ca15cce63bbb",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Known Filament Translator",
"func": "// Bambu spools are not needed for translation if they have the rfid tags\n// but this can be used to overwrite them for HA displaying only\n// This only overwrites the tray_type and tray_sub_brands, if you want other fields overwritten you can add them\n// e.g. tray_diameter, tray_weight, temps etc\n\nvar PolyLite_PLA = {\n \"tray_info_idx\": \"GFL00\", \n \"tray_type\": \"PLA\",\n \"tray_sub_brands\": \"PolyLite PLA\"\n}\n\nvar PolyTerra_PLA = {\n \"tray_info_idx\": \"GFL01\",\n \"tray_type\": \"PLA\",\n \"tray_sub_brands\": \"PolyTerra PLA\"\n}\n\nvar Bambu_ABS = {\n \"tray_info_idx\": \"GFB00\",\n \"tray_type\": \"ABS\"\n}\n\nvar Bambu_PACF = {\n \"tray_info_idx\": \"GFN03\",\n \"tray_type\": \"PA-CF\"\n}\n\nvar Bambu_PC = {\n \"tray_info_idx\": \"GFC00\",\n \"tray_type\": \"PC\"\n}\n\nvar Bambu_PLA_Basic = {\n \"tray_info_idx\": \"GFA00\",\n \"tray_type\": \"PLA\",\n \"tray_sub_brands\": \"PLA Basic\"\n}\nvar Bambu_PLA_Matte = {\n \"tray_info_idx\": \"GFA01\",\n \"tray_type\": \"PLA\",\n \"tray_sub_brands\": \"PLA Matte\"\n}\n\nvar Support_G = {\n \"tray_info_idx\": \"GFS01\",\n \"tray_type\": \"Support\",\n \"tray_sub_brands\": \"Support G\"\n}\n\nvar Support_W = {\n \"tray_info_idx\": \"GFS00\",\n \"tray_type\": \"Support\",\n \"tray_sub_brands\": \"Support W\"\n}\n\nvar Bambu_TPU_95A = {\n \"tray_info_idx\": \"GFU01\",\n \"tray_type\": \"TPU\",\n \"tray_sub_brands\": \"TPU 95A\"\n}\n\nvar Generic_ABS = {\n \"tray_info_idx\": \"GFB99\",\n \"tray_type\": \"ABS\",\n \"tray_sub_brands\": \"ABS\"\n}\n\nvar Generic_ASA = {\n \"tray_info_idx\": \"GFB98\",\n \"tray_type\": \"ASA\",\n \"tray_sub_brands\": \"ASA\"\n}\n\nvar Generic_PA = {\n \"tray_info_idx\": \"GFN99\",\n \"tray_type\": \"PA\",\n \"tray_sub_brands\": \"PA\"\n}\n\nvar Generic_PACF = {\n \"tray_info_idx\": \"GFN98\",\n \"tray_type\": \"PA-CF\",\n \"tray_sub_brands\": \"PA-CF\"\n}\n\nvar Generic_PC = {\n \"tray_info_idx\": \"GFC99\",\n \"tray_type\": \"PC\",\n \"tray_sub_brands\": \"PC\"\n} \n\nvar Generic_PETG = {\n \"tray_info_idx\": \"GFG99\",\n \"tray_type\": \"PETG\",\n \"tray_sub_brands\": \"PETG\"\n}\nvar Generic_PLA = {\n \"tray_info_idx\": \"GFL99\",\n \"tray_type\": \"PLA\",\n \"tray_sub_brands\": \"PLA\"\n}\nvar Generic_PLACF = {\n \"tray_info_idx\": \"GFL98\",\n \"tray_type\": \"PLA-CF\",\n \"tray_sub_brands\": \"PLA-CF\"\n}\nvar Generic_PVA = {\n \"tray_info_idx\": \"GFS99\",\n \"tray_type\": \"PVA\",\n \"tray_sub_brands\": \"PVA\"\n}\nvar Generic_TPU = {\n \"tray_info_idx\": \"GFU99\",\n \"tray_type\": \"TPU\",\n \"tray_sub_brands\": \"TPU\"\n}\n\nvar Bambu_PETCF = {\n \"tray_info_idx\": \"GFT00\",\n \"tray_type\": \"PET-CF\"\n}\n\nvar Bambu_PLA_Impact = {\n \"tray_info_idx\": \"GFA03\",\n \"tray_type\": \"PLA\",\n \"tray_sub_brands\": \"PLA Impact\"\n}\n\nvar Bambu_PLA_Metal = {\n \"tray_info_idx\": \"GFA02\",\n \"tray_type\": \"PLA\",\n \"tray_sub_brands\": \"PLA Metal\"\n}\n\nvar filament_library = {\n \"GFU99\": Generic_TPU,\n \"GFS99\": Generic_PVA,\n \"GFL98\": Generic_PLACF,\n \"GFL99\": Generic_PLA,\n \"GFG99\": Generic_PETG,\n \"GFC99\": Generic_PC,\n \"GFN98\": Generic_PACF,\n \"GFN99\": Generic_PA,\n \"GFB98\": Generic_ASA,\n \"GFB99\": Generic_ABS,\n \"GFU01\": Bambu_TPU_95A,\n \"GFS00\": Support_W,\n \"GFS01\": Support_G,\n \"GFA01\": Bambu_PLA_Matte,\n \"GFA00\": Bambu_PLA_Basic,\n \"GFC00\": Bambu_PC,\n \"GFN03\": Bambu_PACF,\n \"GFB00\": Bambu_ABS,\n \"GFL01\": PolyTerra_PLA,\n \"GFL00\": PolyLite_PLA\n}\n\nif (msg.payload.print.ams !== undefined) {\n for (var ams of msg.payload.print.ams.ams) {\n for (var tray of ams.tray) {\n if (tray.tray_info_idx !== undefined && tray.tray_info_idx !== \"\") {\n if(filament_library.hasOwnProperty(tray.tray_info_idx)) {\n var match = filament_library[tray.tray_info_idx];\n tray.tray_type = match.tray_type;\n tray.tray_sub_brands = match.tray_sub_brands;\n if (tray.tray_diameter == \"0.00\") {\n tray.tray_diameter = \"1.75\";\n }\n }\n }\n }\n }\n}\n\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 680,
"y": 360,
"wires": [
[
"9737da24b3e03e14"
]
]
},
{
"id": "9737da24b3e03e14",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Fan Speed Translator",
"func": "var percentages = {\n \"0\": 0,\n \"1\": 10,\n \"2\": 20,\n \"4\": 30,\n \"5\": 40,\n \"7\": 50,\n \"9\": 60,\n \"10\": 70,\n \"12\": 80,\n \"13\": 90,\n \"15\": 100\n}\n\n//msg.payload.print.big_fan1_speed_pct = percentages[msg.payload.print.big_fan1_speed]\n//msg.payload.print.big_fan2_speed_pct = percentages[msg.payload.print.big_fan2_speed]\n//msg.payload.print.heatbreak_fan_speed_pct = percentages[msg.payload.print.heatbreak_fan_speed]\n//msg.payload.print.cooling_fan_speed_pct = percentages[msg.payload.print.cooling_fan_speed]\n\n// Overwrite\nmsg.payload.print.big_fan1_speed = percentages[msg.payload.print.big_fan1_speed]\nmsg.payload.print.big_fan2_speed = percentages[msg.payload.print.big_fan2_speed]\nmsg.payload.print.heatbreak_fan_speed = percentages[msg.payload.print.heatbreak_fan_speed]\nmsg.payload.print.cooling_fan_speed = percentages[msg.payload.print.cooling_fan_speed]\n\n\nnode.send(msg)",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 660,
"y": 400,
"wires": [
[
"9b44ae9e961cc5e3"
]
]
},
{
"id": "9b44ae9e961cc5e3",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Set AMS Tray Statuses",
"func": "\nif (msg.payload.print.ams != undefined && msg.payload.print.ams.tray_now !== undefined) {\n for (var ams of msg.payload.print.ams.ams) {\n for (var tray of ams.tray) {\n if (tray.tray_type == undefined || tray.tray_type == \"\") {\n tray.tray_type = \"Empty\";\n tray.tray_color = \"#808080\";\n } \n else {\n tray.tray_color = \"#\" + tray.tray_color;\n }\n\n tray.in_use = false;\n\n var id = parseInt(tray.id);\n var used_id = parseInt(msg.payload.print.ams.tray_now);\n\n if (used_id == (id + 4* parseInt(ams.id))) {\n tray.in_use = true;\n }\n\n tray.ams_id = ams.id;\n }\n }\n}\nnode.send(msg);\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 670,
"y": 440,
"wires": [
[
"1f20b9de36cc424b"
]
]
},
{
"id": "ec5cf3eb1b12c22b",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Primary Organize",
"rules": [
{
"t": "move",
"p": "payload.print",
"pt": "msg",
"to": "payload.printer",
"tot": "msg"
},
{
"t": "delete",
"p": "payload.print",
"pt": "msg"
},
{
"t": "move",
"p": "payload.printer.ams",
"pt": "msg",
"to": "payload.ams",
"tot": "msg"
},
{
"t": "delete",
"p": "payload.printer.lights_report",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.printer.spd_lvl",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.printer.spd_mag",
"pt": "msg"
},
{
"t": "move",
"p": "payload.printer.xcam_status",
"pt": "msg",
"to": "payload.printer.xcam.status",
"tot": "msg"
},
{
"t": "set",
"p": "payload.printer.ams_count",
"pt": "msg",
"to": "$count(msg.payload.ams.ams)\t",
"tot": "jsonata"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 650,
"y": 600,
"wires": [
[
"8d2a544a9c61d783"
]
]
},
{
"id": "1f20b9de36cc424b",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Organize Lights",
"func": "var lights = {};\nif (msg.payload.print.lights_report !== undefined) {\n for (var element of msg.payload.print.lights_report) {\n lights[element.node] = element.mode;\n }\n}\nmsg.payload.print.lights = lights\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 640,
"y": 480,
"wires": [
[
"7260cf57c3edbd49"
]
]
},
{
"id": "7260cf57c3edbd49",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Stage Parser",
"func": "\nfunction parseAction(actionId) {\n if(actionId === undefined) {\n return \"\";\n }\n switch (actionId) {\n case -2:\n return \"Offline\";\n case -1:\n return \"Idle\";\n case 0:\n return \"Printing\";\n case 1:\n return \"Auto bed leveling\";\n case 2:\n return \"Heatbed preheating\";\n case 3:\n return \"Sweeping XY mech mode\";\n case 4:\n return \"Changing filament\";\n case 5:\n return \"M400 pause\";\n case 6:\n return \"Paused due to filament runout\";\n case 7:\n return \"Heating hotend\";\n case 8:\n return \"Calibrating extrusion\";\n case 9:\n return \"Scanning bed surface\";\n case 10:\n return \"Inspecting first layer\";\n case 11:\n return \"Identifying build plate type\";\n case 12:\n return \"Calibrating Micro Lidar\";\n case 13:\n return \"Homing toolhead\";\n case 14:\n return \"Cleaning nozzle tip\";\n case 15:\n return \"Checking extruder temperature\";\n case 16:\n return \"Printing was paused by the user\";\n case 17:\n return \"Pause of front cover falling\";\n case 18:\n return \"Calibrating the micro lidar\";\n case 19:\n return \"Calibrating extrusion flow\";\n case 20:\n return \"Paused due to nozzle temperature malfunction\";\n case 21:\n return \"Paused due to heat bed temperature malfunction\";\n default:\n return actionId.toString()\n }\n}\n\nvar current_action = parseAction(msg.payload.print.stg_cur);\n\nvar translated_stages = [];\nif(msg.payload.print.stg != undefined) {\n for (var stage of msg.payload.print.stg) {\n translated_stages.push(parseAction(stage))\n }\n}\n\n// Overwrite\nmsg.payload.print.stg_cur = current_action;\nmsg.payload.print.stg = translated_stages;\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 630,
"y": 520,
"wires": [
[
"a1c7a965b0d664fe"
]
]
},
{
"id": "7c6b4583707029ea",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Translate X1C Speed Profile",
"func": "var spd = {}\nspd.level = msg.payload.print.spd_lvl;\nspd.modifier = msg.payload.print.spd_mag;\n\nif (msg.payload.print !== undefined) {\n switch (msg.payload.print.spd_lvl) {\n case 1:\n spd.profile = \"Silent\";\n break;\n case 2:\n spd.profile = \"Standard\";\n break;\n case 3:\n spd.profile = \"Sport\";\n break;\n case 4:\n spd.profile = \"Ludicrous\";\n break;\n default:\n spd.profile = \"Undefined\";\n break;\n }\n}\n\nmsg.payload.print.speed = spd;\ndelete msg.payload.print.spd;\n\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 680,
"y": 560,
"wires": [
[
"ec5cf3eb1b12c22b"
]
]
},
{
"id": "8d2a544a9c61d783",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 610,
"y": 640,
"wires": [
[
"d5e7799961b2eb4f"
]
]
},
{
"id": "d5e7799961b2eb4f",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "printer",
"vt": "str"
},
{
"t": "eq",
"v": "ams",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 730,
"y": 640,
"wires": [
[
"db012956ddb6c2af"
],
[
"5610f1312e4c57f2"
]
]
},
{
"id": "ff09ef39735c8dd8",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "AMS Config",
"func": "let data = {};\nlet payload = {};\nlet device = {};\n\nvar printer_name = \"X1C_\";\nprinter_name = printer_name + msg.machine_name.match(/AMS_\\d+_(.*)/)[1];\n\n// Filter UoM from payload\nif (msg.topic == \"wifi_signal\")\n msg.payload = msg.payload.match(/^-?\\d+/)[0];\n\n// Inject config\nif (msg.topic.match(/temper/)) {\n msg.device_class = \"temperature\";\n}\nif (msg.topic.match(/temp/)) {\n msg.device_class = \"temperature\";\n}\nif (msg.topic == \"wifi_signal\") {\n msg.device_class = \"signal_strength\"\n msg.unit_of_measurement = \"dBm\";\n}\n\nif(msg.topic == \"humidity\") {\n msg.device_class = \"humidity\";\n msg.unit_of_measurement = \"%\";\n}\n\nif(msg.topic == \"HW_version\") {\n device.hw_version = msg.payload;\n}\nif(msg.topic == \"SW_version\") {\n device.sw_version = msg.payload;\n}\n\n\nfunction getFriendlyName(str) {\n var i, word = str.split('_');\n for (i = 0; i < word.length; i++) {\n word[i] = word[i].charAt(0).toUpperCase() + word[i].slice(1);\n }\n return word.join(' ');\n}\n\nlet base_topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic;\ndata.topic = base_topic + \"/config\";\npayload.name = getFriendlyName(msg.topic);\n\ndevice.identifiers = [];\ndevice.identifiers[0] = msg.machine_name;\n\nif (msg.topic == \"serial_number\") {\n device.identifiers[1] = msg.payload;\n}\n\ndevice.manufacturer = \"Bambu Labs\";\ndevice.model = \"AMS\";\ndevice.name = msg.machine_name;\ndevice.via_device = printer_name;\n\n\npayload.device = device;\npayload.unique_id = msg.machine_name + \"_\" + msg.topic;\npayload.object_id = payload.unique_id;\n\n//payload.force_update = true;\n\nif (!msg.topic.includes(\"tray\")){\n //payload.expire_after = 3600;\n}\nelse {\n payload.icon = \"mdi:printer-3d-nozzle\";\n}\n\nif(msg.topic.match(/serial/)) {\n payload.icon = \"mdi:barcode\";\n}\nif (msg.topic == \"printer_name\") {\n payload.icon = \"mdi:printer-3d\";\n}\nif (msg.device_class != undefined)\n payload.device_class = msg.device_class;\n\nif (msg.unit_of_measurement != undefined)\n payload.unit_of_measurement = msg.unit_of_measurement;\n\nif (payload.device_class == \"temperature\") {\n payload.unit_of_measurement = \"°C\";\n payload.temperature_unit = \"°C\";\n}\n\nif (!msg.topic.includes(\"tray\")) {\n payload.availability_topic = \"homeassistant/\" + \"sensor\" + \"/\" + printer_name + \"/\" + \"status\" + \"/state\";\n}\n\npayload.state_topic = base_topic + \"/state\";\npayload.json_attributes_topic = base_topic + \"/attr\";\ndata.payload = payload;\n\ndata.qos = 1;\ndata.retain = true;\nnode.send(data);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1210,
"y": 840,
"wires": [
[
"b3ee63836831ea89"
]
]
},
{
"id": "5610f1312e4c57f2",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Organize AMS",
"rules": [
{
"t": "move",
"p": "payload.ams",
"pt": "msg",
"to": "ams",
"tot": "msg"
},
{
"t": "delete",
"p": "payload",
"pt": "msg"
},
{
"t": "move",
"p": "ams",
"pt": "msg",
"to": "payload",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 640,
"y": 700,
"wires": [
[
"07ff86f3cd404e2d"
]
]
},
{
"id": "07ff86f3cd404e2d",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 610,
"y": 740,
"wires": [
[
"3412b5c7efd1d41e"
]
]
},
{
"id": "3412b5c7efd1d41e",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "ams",
"func": "msg.topic = \"AMS\";//_\" + msg.payload.id;\n\nmsg.machine_name = msg.topic + \"_\" + msg.payload.id + \"_\" + msg.payload.printer_name;\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 730,
"y": 740,
"wires": [
[
"afcea49d4f94f15c"
]
]
},
{
"id": "098967fde25793c1",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Set End Time Init",
"rules": [
{
"t": "set",
"p": "payload.gcode_end_time",
"pt": "msg",
"to": "",
"tot": "date"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1310,
"y": 340,
"wires": [
[
"2d01d38e6dd73736"
]
]
},
{
"id": "2d01d38e6dd73736",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Set EndTime",
"func": "if (msg.payload.gcode_start_time !== \"N/A\" && msg.payload.gcode_end_time !== undefined && msg.payload.gcode_end_time != \"N/A\") {\n var endTime = msg.payload.gcode_end_time + ((parseInt(msg.payload.mc_remaining_time) * 60) * 1000);\n endTime = Math.round(endTime / 60000) * 60000;\n var startSeconds = msg.payload.gcode_start_epoch.toString().slice(0,-5);\n endTime = endTime + parseInt(startSeconds);\n msg.payload.gcode_end_time = endTime;\n msg.payload.gcode_start_time = parseInt(msg.payload.gcode_start_time);\n node.send(msg);\n}\nelse if (msg.payload.gcode_end_time == \"N/A\" || msg.payload.gcode_start_Time == \"N/A\") {\n msg.payload.gcode_start_time = \"N/A\";\n msg.payload.gcode_end_time = \"N/A\";\n node.send(msg);\n}\n\nif(msg.payload.gcode_start_time == \"N/A\") {\n msg.payload.gcode_end_time = \"N/A\";\n}\nelse {\n node.send(msg);\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1290,
"y": 380,
"wires": [
[
"9d95b756f4601713"
]
]
},
{
"id": "9d95b756f4601713",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "payload.gcode_end_time",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "N/A",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 1430,
"y": 380,
"wires": [
[
"ad4f3f980f172128"
],
[
"af54a0a5940dd334"
]
]
},
{
"id": "5774338c2d9e049b",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "payload.gcode_start_time",
"propertyType": "msg",
"rules": [
{
"t": "neq",
"v": "N/A",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 1090,
"y": 300,
"wires": [
[
"098967fde25793c1"
],
[
"2d01d38e6dd73736"
]
]
},
{
"id": "d10c56abbd6b7b47",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Preserve Start Epoch",
"rules": [
{
"t": "set",
"p": "payload.gcode_start_epoch",
"pt": "msg",
"to": "payload.gcode_start_time",
"tot": "msg",
"dc": true
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1140,
"y": 260,
"wires": [
[
"8399cea217e486b9"
]
],
"info": "This is useful to keep as it will act as\r\na unique ID for each print"
},
{
"id": "1f0305e93eed961a",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "AMS State",
"func": "// Filter UoM from payload\nif (msg.topic == \"wifi_signal\")\n msg.payload = msg.payload.match(/^-?\\d+/)[0];\nif (msg.topic.match(/tray_\\d+/)) {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.type;\n}\n\nmsg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/state\";\n\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1210,
"y": 880,
"wires": [
[
"b3ee63836831ea89"
]
]
},
{
"id": "2a60f3818c07cead",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 690,
"y": 880,
"wires": [
[
"bf872cba7b8d4a63"
]
]
},
{
"id": "bf872cba7b8d4a63",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "neq",
"v": "tray",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 810,
"y": 880,
"wires": [
[
"735003dd7602e7dc"
],
[
"2f77cb6feca03746"
]
]
},
{
"id": "2f77cb6feca03746",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 610,
"y": 920,
"wires": [
[
"69cba2483fe68056"
]
]
},
{
"id": "afcea49d4f94f15c",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Change Humdiity Name",
"rules": [
{
"t": "move",
"p": "payload.humidity",
"pt": "msg",
"to": "payload.humidity_level",
"tot": "msg"
},
{
"t": "delete",
"p": "payload.humidity",
"pt": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 910,
"y": 740,
"wires": [
[
"ecf4cb43eed20ca0"
]
]
},
{
"id": "69cba2483fe68056",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "tray",
"func": "msg.topic = msg.topic + \"_\" + msg.payload.id;\nnode.send(msg);\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 730,
"y": 920,
"wires": [
[
"080745c0307e0218"
]
]
},
{
"id": "17945f4d7962a94a",
"type": "mqtt out",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Home Assistant",
"topic": "",
"qos": "",
"retain": "",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "489094618c340eef",
"x": 2140,
"y": 860,
"wires": []
},
{
"id": "a0317478d3f43ecf",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Set Status",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "online",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 930,
"y": 800,
"wires": [
[
"b5fb8a1a65b4686b"
]
]
},
{
"id": "8171a948ce6a2ae7",
"type": "comment",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "AMS",
"info": "AMS Split",
"x": 810,
"y": 700,
"wires": []
},
{
"id": "83f6c2b5b869cd97",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Remove Useless",
"rules": [
{
"t": "delete",
"p": "payload.command",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.force_upgrade",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.home_flag",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.hw_switch_state",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.lifecycle",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.online",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.ams_rfid_status",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.ams_status",
"pt": "msg"
},
{
"t": "delete",
"p": "payload.manufacturer",
"pt": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1310,
"y": 460,
"wires": [
[
"d7a406891ffe1ae5"
]
]
},
{
"id": "472a15482a731de8",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "X1C Config",
"func": "let data = {};\nlet payload = {};\nlet device = {};\n\nif(msg.payload == undefined && !msg.topic.includes(\"reset\")) {\n return;\n}\n\n// Filter UoM from payload\nif (msg.topic == \"wifi_signal\")\n msg.payload = msg.payload.match(/^-?\\d+/)[0];\n\n// Inject config\nif (msg.topic.match(/temperature/)) {\n msg.device_class = \"temperature\";\n}\nif (msg.topic == \"hms\") {\n msg.topic = \"HMS\";\n}\nif (msg.topic == \"wifi_signal\") {\n msg.device_class = \"signal_strength\"\n msg.unit_of_measurement = \"dBm\";\n}\n\nif (msg.topic.match(/(.*)fan(.*)/) && msg.topic !== \"fan_gear\") {\n msg.unit_of_measurement = \"%\";\n msg.icon = \"mdi:fan\"\n}\nif (msg.topic.match(/serial/)) {\n msg.icon = \"mdi:barcode\";\n}\nif (msg.topic == \"status\" || msg.topic == \"print_state\") {\n payload.icon = \"mdi:printer-3d\";\n}\nif(msg.topic == \"sdcard\") {\n msg.icon = \"mdi:sd\"\n}\nif (msg.topic == \"print_progress\") {\n msg.unit_of_measurement = \"%\";\n}\nif(msg.topic == \"print_remaining_time\") {\n msg.unit_of_measurement = \"min\";\n msg.device_class = \"duration\";\n}\nelse if (msg.topic.match(/time/)) {\n msg.icon = \"mdi:clock\";\n}\nif(msg.topic == \"speed\") {\n msg.icon = \"mdi:speedometer\"\n}\n\nif (msg.topic == \"SW_version\") {\n device.sw_version = msg.payload;\n}\nif (msg.topic == \"HW_version\") {\n device.hw_version = msg.payload;\n}\nif(msg.topic == \"pause_print\") {\n msg.icon = \"mdi:pause\";\n}\nif (msg.topic == \"resume_print\") {\n msg.icon = \"mdi:play\";\n}\nif (msg.topic == \"stop_print\") {\n msg.icon = \"mdi:cancel\";\n}\n\nfunction getFriendlyName(str) {\n var i, word = str.split('_');\n for (i = 0; i < word.length; i++) {\n word[i] = word[i].charAt(0).toUpperCase() + word[i].slice(1);\n }\n return word.join(' ');\n}\n\nlet type = \"sensor\";\nif(msg.topic == \"chamber_light\") {\n type = \"light\";\n} \n\nif(msg.topic == \"reset_filter\" || msg.topic == \"pause_print\" || msg.topic == \"resume_print\" || msg.topic == \"stop_print\") {\n type = \"button\";\n}\nif(msg.topic == \"speed\") {\n type = \"select\";\n}\n\nlet base_topic = \"homeassistant/\"+ type + \"/\" + msg.machine_name + \"/\" + msg.topic;\ndata.topic = base_topic + \"/config\";\npayload.name = getFriendlyName(msg.topic);\nif (msg.topic == \"HMS\") {\n payload.name = \"HMS Errors\";\n}\n\ndevice.identifiers = [];\ndevice.identifiers[0] = msg.machine_name;\nif (msg.topic == \"serial_number\") {\n device.identifiers[1] = msg.payload;\n}\ndevice.manufacturer = \"Bambu Labs\";\ndevice.model = msg.model;\ndevice.name = msg.machine_name;\n\nif( msg.icon != undefined) {\n payload.icon = msg.icon\n}\n\npayload.device = device;\npayload.unique_id = msg.machine_name + \"_\" + msg.topic;\npayload.object_id = payload.unique_id;\n\n//payload.force_update = true;\n//payload.expire_after = 3600;\n\n//if (msg.topic.match(/time/) || msg.topic.match(/epoch/)) {\n //payload.expire_after = 300;\n//}\n\nif (msg.device_class != undefined)\n payload.device_class = msg.device_class;\n\nif (msg.unit_of_measurement != undefined)\n payload.unit_of_measurement = msg.unit_of_measurement;\n\nif (payload.device_class == \"temperature\") {\n payload.unit_of_measurement = \"°C\";\n payload.temperature_unit = \"°C\";\n}\n\nif (msg.topic == \"machine_serial\") {\n return;\n}\npayload.state_topic = base_topic + \"/state\";\npayload.json_attributes_topic = base_topic + \"/attr\";\nif (type == \"light\") {\n payload.command_topic = base_topic + \"/set\";\n delete payload.json_attributes_topic;\n}\n\nif (type == \"button\" && msg.topic.includes(\"reset_filter\")) {\n delete payload.state_topic;\n delete payload.json_attributes_topic;\n payload.command_topic = \"homeassistant/\" + \"button\" + \"/\" + msg.machine_name + \"/\" + msg.topic;\n //payload.availability_topic = \"homeassistant/\" + \"sensor\" + \"/\" + msg.machine_name + \"/\" + \"status\" + \"/state\";\n}\nelse if (type == \"button\") {\n delete payload.state_topic;\n delete payload.json_attributes_topic;\n payload.command_topic = \"homeassistant/\" + \"button\" + \"/\" + msg.machine_name + \"/\" + msg.topic;\n if(msg.topic.includes(\"_print\")) {\n let available = \"\";\n if(msg.topic.includes(\"pause\")) {\n available = \"RUNNING\";\n }\n else if(msg.topic.includes(\"resume\")) {\n available = \"PAUSE\";\n }\n else if(msg.topic.includes(\"stop\")) {\n available = \"IS_RUNNING\"\n }\n else {\n return;\n }\n payload.availability = [];\n let a1 = {};\n a1.topic = \"homeassistant/\" + \"sensor\" + \"/\" + msg.machine_name + \"/\" + \"print_status\" + \"/state\";\n a1.payload_available = available;\n a1.payload_not_available = \"N/A\";\n delete payload.availability_topic;\n if(msg.topic.includes(\"stop\")) {\n a1.value_template = '{{ \"' + available + '\" if value == \"RUNNING\" or value == \"PAUSE\" else \"N/A\" }}'\n } else {\n a1.value_template = '{{ \"'+available+'\" if value == \"'+available+'\" else \"N/A\" }}'\n }\n payload.availability.push(a1);\n }\n}\nif(msg.topic == \"serial_number\" || msg.topic.includes(\"version\")) {\n payload.availability_topic = \"homeassistant/\" + \"sensor\" + \"/\" + msg.machine_name + \"/\" + \"status\" + \"/state\";\n}\n\nif (msg.topic == \"speed\") {\n payload.command_topic = \"homeassistant/\" + \"select\" + \"/\" + msg.machine_name + \"/\" + msg.topic + \"/set\";\n payload.state_topic = \"homeassistant/\" + \"select\" + \"/\" + msg.machine_name + \"/\" + msg.topic + \"/state\";\n payload.json_attributes_topic = \"homeassistant/\" + \"select\" + \"/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n payload.availability_topic = \"homeassistant/\" + \"sensor\" + \"/\" + msg.machine_name + \"/\" + \"status\" + \"/state\";\n payload.options = [\"Silent\", \"Standard\", \"Sport\", \"Ludicrous\"]; \n}\n\n\n\nif (msg.topic != \"status\" && msg.topic != \"print_status\"\n && msg.topic != \"resume_print\" && msg.topic != \"pause_print\" && msg.topic != \"stop_print\"\n && msg.topic != \"machine_name\" && msg.topic != \"machine_serial\") {\n payload.availability_topic = \"homeassistant/\" + \"sensor\" + \"/\" + msg.machine_name + \"/\" + \"status\" + \"/state\";\n\n}\n\ndata.payload = payload;\n\ndata.qos = 1;\ndata.retain = true;\n\nnode.send(data);\n\nif (msg.topic == \"speed\") {\n msg.topic = \"speed_info\";\n type = \"sensor\";\n payload.name = getFriendlyName(msg.topic);\n payload.unique_id = msg.machine_name + \"_\" + msg.topic;\n payload.object_id = payload.unique_id;\n delete payload.command_topic;\n delete payload.options;\n let base_topic = \"homeassistant/\" + \"sensor\" + \"/\" + msg.machine_name + \"/\" + msg.topic;\n payload.availability_topic = \"homeassistant/\" + \"sensor\" + \"/\" + msg.machine_name + \"/\" + \"status\" + \"/state\"; \n payload.state_topic = base_topic + \"/state\";\n payload.json_attributes_topic = base_topic + \"/attr\";\n\n data.topic = base_topic + \"/config\";\n data.payload = payload;\n\n data.qos = 1;\n data.retain = true;\n node.send(data);\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1690,
"y": 680,
"wires": [
[
"135e57a801b6e9bf"
]
]
},
{
"id": "86e9caa98fa51352",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "X1C State",
"func": "// Filter UoM from payload\n\nif (msg.payload == undefined) {\n return;\n}\nif (msg.topic == \"machine_serial\") {\n return;\n}\nif (msg.topic == \"reset_filter\" || msg.topic == \"resume_print\" || msg.topic == \"pause_print\") {\n return;\n}\nelse if (msg.topic == \"machine_name\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n let oldPayload = msg.payload;\n msg.payload = {\"Serial Number\": msg.machine_serial};\n node.send(msg);\n msg.payload = oldPayload;\n msg.topic = oldTopic;\n}\nelse if (msg.topic == \"wifi_signal\")\n msg.payload = msg.payload.match(/^-?\\d+/)[0];\nelse if (msg.topic == \"xcam\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.status;\n}\nelse if (msg.topic == \"upload\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.message;\n}\nelse if (msg.topic == \"upgrade_state\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.status;\n}\nelse if (msg.topic == \"stage\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n\n var current = msg.payload.current;\n var prev = {};\n var count = 0;\n for (var stg of msg.payload.prev) {\n prev[count.toString()] = stg;\n count += 1;\n }\n msg.payload = prev;\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = current;\n}\nelse if (msg.topic == \"ipcam\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.ipcam_dev;\n}\nelse if (msg.topic == \"subtask\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.name;\n}\nelse if (msg.topic == \"print\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.type;\n}\nelse if (msg.topic == \"bed_temperature\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.temperature;\n}\nelse if (msg.topic == \"nozzle_temperature\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.temperature;\n}\nelse if (msg.topic == \"chamber_temperature\") {\n msg.payload = msg.payload.temperature;\n}\nelse if (msg.topic == \"gcode\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = msg.payload.file;\n}\nelse if (msg.topic == \"hms\") {\n msg.topic = \"HMS\";\n var oldTopic = msg.topic;\n var numOfCodes = msg.payload == undefined ? 0 : msg.payload.length;\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n var links = {};\n for (var data of msg.payload) {\n links[data.code] = data.url;\n }\n msg.payload = links;\n node.send(msg);\n msg.topic = oldTopic;\n msg.payload = numOfCodes;\n}\nelse if (msg.topic == \"speed\") {\n var oldTopic = msg.topic;\n msg.topic = \"homeassistant/select/\" + msg.machine_name + \"/\" + msg.topic + \"/attr\";\n node.send(msg);\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + \"speed_info\" + \"/attr\";\n node.send(msg);\n msg.topic = \"speed\";\n msg.payload = msg.payload.profile;\n msg.topic = \"homeassistant/select/\" + msg.machine_name + \"/\" + \"speed\" + \"/state\";\n node.send(msg);\n msg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + \"speed_info\" + \"/state\";\n node.send(msg);\n return;\n}\nelse if (msg.topic == \"chamber_light\") {\n msg.payload = msg.payload.toUpperCase();\n msg.topic = \"homeassistant/light/\" + msg.machine_name + \"/\" + msg.topic + \"/state\";\n node.send(msg);\n return;\n}\n\nmsg.topic = \"homeassistant/sensor/\" + msg.machine_name + \"/\" + msg.topic + \"/state\";\n\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1690,
"y": 720,
"wires": [
[
"135e57a801b6e9bf"
]
]
},
{
"id": "d7a406891ffe1ae5",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Reorder Print Info",
"rules": [
{
"t": "move",
"p": "payload.gcode_file",
"pt": "msg",
"to": "payload.gcode.file",
"tot": "msg"
},
{
"t": "move",
"p": "payload.gcode_file_prepare_percent",
"pt": "msg",
"to": "payload.gcode.file_prepare_percent",
"tot": "msg"
},
{
"t": "move",
"p": "payload.gcode_start_time",
"pt": "msg",
"to": "payload.print_start_time",
"tot": "msg"
},
{
"t": "move",
"p": "payload.gcode_end_time",
"pt": "msg",
"to": "payload.print_end_time",
"tot": "msg"
},
{
"t": "move",
"p": "payload.gcode_state",
"pt": "msg",
"to": "payload.print_status",
"tot": "msg"
},
{
"t": "move",
"p": "payload.mc_percent",
"pt": "msg",
"to": "payload.print_progress",
"tot": "msg"
},
{
"t": "move",
"p": "payload.mc_print_error_code",
"pt": "msg",
"to": "payload.print.error_code",
"tot": "msg"
},
{
"t": "move",
"p": "payload.mc_print_stage",
"pt": "msg",
"to": "payload.print.stage",
"tot": "msg"
},
{
"t": "move",
"p": "payload.mc_print_sub_stage",
"pt": "msg",
"to": "payload.print.substage",
"tot": "msg"
},
{
"t": "move",
"p": "payload.print_error",
"pt": "msg",
"to": "payload.print.error",
"tot": "msg"
},
{
"t": "move",
"p": "payload.print_gcode_action",
"pt": "msg",
"to": "payload.print.gcode_action",
"tot": "msg"
},
{
"t": "move",
"p": "payload.print_real_action",
"pt": "msg",
"to": "payload.print.real_action",
"tot": "msg"
},
{
"t": "move",
"p": "payload.print_type",
"pt": "msg",
"to": "payload.print.type",
"tot": "msg"
},
{
"t": "move",
"p": "payload.profile_id",
"pt": "msg",
"to": "payload.print.profile_id",
"tot": "msg"
},
{
"t": "move",
"p": "payload.project_id",
"pt": "msg",
"to": "payload.print.project_id",
"tot": "msg"
},
{
"t": "move",
"p": "payload.sequence_id",
"pt": "msg",
"to": "payload.print.sequence_id",
"tot": "msg"
},
{
"t": "set",
"p": "payload.print.task",
"pt": "msg",
"to": "payload.subtask_name",
"tot": "msg"
},
{
"t": "move",
"p": "payload.mc_remaining_time",
"pt": "msg",
"to": "payload.print_remaining_time",
"tot": "msg"
},
{
"t": "move",
"p": "payload.gcode_start_epoch",
"pt": "msg",
"to": "payload.print_start_epoch",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1310,
"y": 500,
"wires": [
[
"3fb2679ab80855bb"
]
]
},
{
"id": "3fb2679ab80855bb",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Reorder Other",
"rules": [
{
"t": "move",
"p": "payload.stg_cur",
"pt": "msg",
"to": "payload.stage.current",
"tot": "msg"
},
{
"t": "move",
"p": "payload.stg",
"pt": "msg",
"to": "payload.stage.prev",
"tot": "msg"
},
{
"t": "move",
"p": "payload.subtask_id",
"pt": "msg",
"to": "payload.subtask.id",
"tot": "msg"
},
{
"t": "move",
"p": "payload.subtask_name",
"pt": "msg",
"to": "payload.subtask.name",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1300,
"y": 540,
"wires": [
[
"955d6d328d2b5e22"
]
]
},
{
"id": "955d6d328d2b5e22",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Reorder Temps and Fans",
"rules": [
{
"t": "move",
"p": "payload.bed_target_temper",
"pt": "msg",
"to": "payload.bed_temperature.target_temperature",
"tot": "msg"
},
{
"t": "move",
"p": "payload.bed_temper",
"pt": "msg",
"to": "payload.bed_temperature.temperature",
"tot": "msg"
},
{
"t": "move",
"p": "payload.nozzle_temper",
"pt": "msg",
"to": "payload.nozzle_temperature.temperature",
"tot": "msg"
},
{
"t": "move",
"p": "payload.nozzle_target_temper",
"pt": "msg",
"to": "payload.nozzle_temperature.target_temperature",
"tot": "msg"
},
{
"t": "move",
"p": "payload.big_fan1_speed",
"pt": "msg",
"to": "payload.fans.big_fan1",
"tot": "msg"
},
{
"t": "move",
"p": "payload.big_fan2_speed",
"pt": "msg",
"to": "payload.fans.big_fan2",
"tot": "msg"
},
{
"t": "move",
"p": "payload.heatbreak_fan_speed",
"pt": "msg",
"to": "payload.fans.heatbreak_fan",
"tot": "msg"
},
{
"t": "move",
"p": "payload.cooling_fan_speed",
"pt": "msg",
"to": "payload.fans.cooling_fan",
"tot": "msg"
},
{
"t": "move",
"p": "payload.chamber_temper",
"pt": "msg",
"to": "payload.chamber_temperature.temperature",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1330,
"y": 580,
"wires": [
[
"2ce84ba9618b908d"
]
]
},
{
"id": "41797ced12627146",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "lights",
"vt": "str"
},
{
"t": "eq",
"v": "fans",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 1390,
"y": 640,
"wires": [
[
"b2881b8ed28a467c"
],
[
"b2881b8ed28a467c"
],
[
"682e4da1ee0769d4"
]
]
},
{
"id": "2ce84ba9618b908d",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 1270,
"y": 620,
"wires": [
[
"41797ced12627146"
]
]
},
{
"id": "b2881b8ed28a467c",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 1530,
"y": 620,
"wires": [
[
"682e4da1ee0769d4"
]
]
},
{
"id": "96b92ea713edd221",
"type": "comment",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "X1C",
"info": "",
"x": 1090,
"y": 340,
"wires": []
},
{
"id": "f7de3b0a2a7c5661",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "x1c",
"func": "msg.topic = \"X1C\";//_\" + msg.payload.id;\n\nmsg.machine_name = msg.topic + \"_\" + msg.payload.machine_name;\nmsg.model = \"X1 Carbon\";\nmsg.payload.fans = {};\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1090,
"y": 220,
"wires": [
[
"d10c56abbd6b7b47"
]
]
},
{
"id": "8399cea217e486b9",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Fix Start Date",
"func": "if ( msg.payload.gcode_state == \"IDLE\" ||\n msg.payload.gcode_start_time == \"0\" || msg.payload.gcode_start_time == \"N/A\") {\n msg.payload.gcode_start_time = \"N/A\";\n msg.payload.gcode_end_time = \"N/A\";\n}\nelse {\n msg.payload.gcode_start_time = msg.payload.gcode_start_time + \"000\";\n}\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1340,
"y": 260,
"wires": [
[
"5774338c2d9e049b"
]
]
},
{
"id": "f0bcc0434d35f8db",
"type": "mqtt in",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "HomeAssistant In",
"topic": "homeassistant/light/X1C_{PRINTER_NAME}/chamber_light/set",
"qos": "2",
"datatype": "utf8",
"broker": "489094618c340eef",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 140,
"y": 460,
"wires": [
[
"2a0268a55eadf72f"
]
]
},
{
"id": "1db470110f18fab6",
"type": "mqtt out",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "bambu-mqtt-out {PRINTER_NAME}",
"topic": "device/{PRINTER_SERIAL}/request",
"qos": "1",
"retain": "false",
"respTopic": "",
"contentType": "",
"userProps": "",
"correl": "",
"expiry": "",
"broker": "84f61d394ba2ab34",
"x": 370,
"y": 880,
"wires": []
},
{
"id": "2a0268a55eadf72f",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Toggle Chamber Light",
"func": "var on = { \"system\": { \"sequence_id\": \"2003\", \"command\": \"ledctrl\", \"led_node\": \"chamber_light\", \"led_mode\": \"on\", \"led_on_time\": 500, \"led_off_time\": 500, \"loop_times\": 0, \"interval_time\": 0 }, \"user_id\": \"123456789\" }\nvar off = { \"system\": { \"sequence_id\": \"2003\", \"command\": \"ledctrl\", \"led_node\": \"chamber_light\", \"led_mode\": \"off\", \"led_on_time\": 500, \"led_off_time\": 500, \"loop_times\": 0, \"interval_time\": 0 }, \"user_id\": \"123456789\" }\n\nif(msg.payload == \"ON\") {\n node.send({\"payload\": on});\n}\nelse if (msg.payload == \"OFF\") {\n node.send({ \"payload\": off });\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 180,
"y": 500,
"wires": [
[
"e34f034bed456673"
]
]
},
{
"id": "c93c3bb2cc88b9dc",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Set Speed Profile",
"func": "var template = { \n \"print\": {\n \"sequence_id\": \"2004\", \n \"command\": \"print_speed\",\n \"param\": \"2\" \n },\n \"user_id\": \"1234567890\"\n}\n\n// In case you want to send a string message\nif (msg.payload !== undefined) {\n switch (msg.payload) {\n case \"Silent\":\n template.print.param= \"1\";\n break;\n case \"Standard\":\n template.print.param = \"2\";\n break;\n case \"Sport\":\n template.print.param = \"3\";\n break;\n case \"Ludicrous\":\n template.print.param = \"4\";\n break;\n default:\n return;\n }\n}\nif (global.get(\"{PRINTER_NAME}_is_connected\", \"true\")) {\n node.send({ \"payload\": template });\n}\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 170,
"y": 580,
"wires": [
[
"e34f034bed456673"
]
]
},
{
"id": "d8d2dad22b354fdf",
"type": "mqtt in",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "HomeAssistant In",
"topic": "homeassistant/select/X1C_{PRINTER_NAME}/speed/set",
"qos": "2",
"datatype": "utf8",
"broker": "489094618c340eef",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 140,
"y": 540,
"wires": [
[
"c93c3bb2cc88b9dc"
]
]
},
{
"id": "187393ac342955a5",
"type": "status",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Connected Status {PRINTER_NAME}",
"scope": [
"b1c1923cb89b667b"
],
"x": 190,
"y": 200,
"wires": [
[
"e9f7f1de7feb3909"
]
]
},
{
"id": "e9f7f1de7feb3909",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Set Connection Global {PRINTER_NAME}",
"func": "\nif (msg.status !== undefined && msg.status.text.includes(\"status.connected\")) {\n global.set(\"{PRINTER_NAME}_is_connected\", \"true\");\n\n} else {\n global.set(\"{PRINTER_NAME}_is_connected\", \"false\");\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 250,
"y": 240,
"wires": [
[]
]
},
{
"id": "dce813c208a9da90",
"type": "inject",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Inject OFFLINE {PRINTER_NAME}",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
},
{
"p": "machine_name",
"v": "X1C_{PRINTER_NAME}",
"vt": "str"
},
{
"p": "machine_serisal",
"v": "{PRINTER_SERIAL}",
"vt": "str"
}
],
"repeat": "15",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "printer",
"payload": "{\"print_status\":\"OFFLINE\",\"status\":\"offline\",\"machine_name\":\"{PRINTER_NAME}\",\"machine_serial\":\"{PRINTER_SERIAL}\",\"reset_filter\":\"\"}",
"payloadType": "json",
"x": 210,
"y": 380,
"wires": [
[
"ab7f1b7beb3a2f80"
]
]
},
{
"id": "ab7f1b7beb3a2f80",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "{PRINTER_NAME}_is_connected",
"propertyType": "global",
"rules": [
{
"t": "eq",
"v": "false",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 210,
"y": 420,
"wires": [
[
"f844bda465c93ddd"
]
]
},
{
"id": "080745c0307e0218",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Change Attribute Names",
"rules": [
{
"t": "move",
"p": "payload.tray_type",
"pt": "msg",
"to": "payload.type",
"tot": "msg"
},
{
"t": "move",
"p": "payload.tray_color",
"pt": "msg",
"to": "payload.color",
"tot": "msg"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 910,
"y": 920,
"wires": [
[
"735003dd7602e7dc"
]
]
},
{
"id": "8a61805ce8145c12",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "payload.print.command",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "push_status",
"vt": "str"
},
{
"t": "eq",
"v": "gcode_line",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 750,
"y": 320,
"wires": [
[
"1389ca15cce63bbb"
],
[],
[]
]
},
{
"id": "eec5b5dc9281ea93",
"type": "comment",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Filters",
"info": "These switch statements act as filters.\n\nFirst one acts to split mc_print and print\nand others\n\nSecond is to only accept \"push_status\" commands.\nOtherwise \"gcode_line\" and others are sent.\n\n(Gcode line is, for example,\nchanging speed profile)",
"x": 870,
"y": 320,
"wires": []
},
{
"id": "9d626d59541a6e6f",
"type": "comment",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Change Name/Serial Details",
"info": "Change the printer name and serial\nin the following nodes\n\n\"Connected Status\" -> select proper MQTT in\n& Modify the function node after\n\n\"Inject Machine Details\" Function\n\n\"Inject OFFLINE\" Inject Node ->\n& the Switch immediately after\nfor the global-connected Status\n\nMQTT In and Out topics for printer\nand home-assistant's mqtt in(s)\n\n\"Set Speed Profile\" Function ->\nFor the global-connected Status\nsince for some reason \"Select\" type\ndoesn't like to be set unavailable\n\n",
"x": 180,
"y": 160,
"wires": []
},
{
"id": "6a13ae7af77d563d",
"type": "comment",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "(?) Timezone",
"info": "Timezone configuration may be needed\nif the readable-dates format\nis not in your current timezone.\n\nThis should be using the NR System timezone\nbut in case it doesn't, add it.\n\nI.E. After $moment(var)\nput .tz(your/timezone)\nthen keep the .format after\n\n$moment(msg.payload.gcode_start_time).format(\"MMMM D, yyyy [at] h:mm A\")\n->\n$moment(msg.payload.gcode_start_time).tz(YOUR_TIMEZOME).format(\"MMMM D, yyyy [at] h:mm A\")",
"x": 1190,
"y": 420,
"wires": []
},
{
"id": "5c4b13a29c630b8c",
"type": "comment",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "MC_Print",
"info": "",
"x": 600,
"y": 200,
"wires": []
},
{
"id": "b5232b827fbef671",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Get AMS Humidity",
"func": "if (msg.payload.mc_print != undefined && msg.payload.mc_print.command == \"push_info\") {\n if (msg.payload.mc_print.param != undefined && msg.payload.mc_print.param.startsWith(\"[AMS][TASK]\")) {\n if(msg.payload.mc_print.param.includes(\"humidity\")) {\n let param = msg.payload.mc_print.param;\n let amsId = param.match(/ams(\\d+) /)[1];\n let humidity = param.match(/humidity:(\\d+)%/)[1];\n\n msg.topic = \"AMS\";\n\n msg.machine_name = msg.topic + \"_\" + amsId + \"_\" + msg.payload.mc_print.machine_name;\n \n msg.payload = {\n \"humidity\": humidity\n }\n node.send(msg);\n }\n }\n}\n\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 830,
"y": 240,
"wires": [
[
"4a696bec52ae5acb"
]
]
},
{
"id": "4a696bec52ae5acb",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 870,
"y": 280,
"wires": [
[
"c40efe7b1b254622"
]
]
},
{
"id": "962c0c56346e023a",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "payload.mc_print.param",
"propertyType": "msg",
"rules": [
{
"t": "cont",
"v": "humidity",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 610,
"y": 240,
"wires": [
[
"b5232b827fbef671"
],
[]
]
},
{
"id": "db012956ddb6c2af",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1000,
"y": 640,
"wires": [
[
"f7de3b0a2a7c5661"
]
]
},
{
"id": "ad4f3f980f172128",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1540,
"y": 420,
"wires": [
[
"83f6c2b5b869cd97"
]
]
},
{
"id": "ecf4cb43eed20ca0",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 840,
"y": 840,
"wires": [
[
"ff09ef39735c8dd8",
"2a60f3818c07cead",
"a0317478d3f43ecf"
]
]
},
{
"id": "b3ee63836831ea89",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1360,
"y": 860,
"wires": [
[
"e98417ec17a23249"
]
]
},
{
"id": "b5fb8a1a65b4686b",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1000,
"y": 880,
"wires": [
[
"1f0305e93eed961a"
]
]
},
{
"id": "682e4da1ee0769d4",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1560,
"y": 680,
"wires": [
[
"472a15482a731de8",
"86e9caa98fa51352"
]
]
},
{
"id": "e98417ec17a23249",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1860,
"y": 860,
"wires": [
[
"67aa1b3a6a0ac3d7"
]
]
},
{
"id": "135e57a801b6e9bf",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1800,
"y": 720,
"wires": [
[
"e98417ec17a23249"
]
]
},
{
"id": "7f4faea318d59bed",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1420,
"y": 1040,
"wires": [
[
"b2881b8ed28a467c"
]
]
},
{
"id": "9a2aaf740774a256",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 540,
"y": 1040,
"wires": [
[
"7f4faea318d59bed"
]
]
},
{
"id": "f844bda465c93ddd",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 500,
"y": 420,
"wires": [
[
"9a2aaf740774a256"
]
]
},
{
"id": "e34f034bed456673",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 340,
"y": 580,
"wires": [
[
"2fe75ce36321f506"
]
]
},
{
"id": "dba47578907a6d23",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 460,
"y": 320,
"wires": [
[
"a365818fb4a53f52"
]
]
},
{
"id": "735003dd7602e7dc",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1080,
"y": 860,
"wires": [
[
"ff09ef39735c8dd8",
"1f0305e93eed961a"
]
]
},
{
"id": "c40efe7b1b254622",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1000,
"y": 560,
"wires": [
[
"b34fe28bd6f1cf0b"
]
]
},
{
"id": "b34fe28bd6f1cf0b",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1060,
"y": 560,
"wires": [
[
"735003dd7602e7dc"
]
]
},
{
"id": "883a607fd81a0e23",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 500,
"y": 260,
"wires": [
[
"962c0c56346e023a"
]
]
},
{
"id": "67aa1b3a6a0ac3d7",
"type": "rbe",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"func": "rbe",
"gap": "",
"start": "",
"inout": "out",
"septopics": true,
"property": "payload",
"topi": "topic",
"x": 1950,
"y": 860,
"wires": [
[
"c868c39bb6549391"
]
]
},
{
"id": "c868c39bb6549391",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "neq",
"v": "",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 2070,
"y": 900,
"wires": [
[
"17945f4d7962a94a"
]
]
},
{
"id": "af54a0a5940dd334",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Convert Timestamps",
"rules": [
{
"t": "set",
"p": "payload.gcode_start_time",
"pt": "msg",
"to": "$moment(msg.payload.gcode_start_time).format(\"MMMM D, yyyy [at] h:mm A\")",
"tot": "jsonata"
},
{
"t": "set",
"p": "payload.gcode_end_time",
"pt": "msg",
"to": "$moment(msg.payload.gcode_end_time).format(\"MMMM D, yyyy [at] h:mm A\")",
"tot": "jsonata"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 1380,
"y": 420,
"wires": [
[
"ad4f3f980f172128"
]
]
},
{
"id": "ca1821a15d5fe203",
"type": "comment",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Configure",
"info": "Configure the reset timer here for the filter\n\nThis will reset the filter on an interval\nsuch that when HA is restarted or\nwhen first importing, it should reset values\nproperly.",
"x": 200,
"y": 920,
"wires": []
},
{
"id": "6db1d3c86598f8a4",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1860,
"y": 1000,
"wires": [
[
"67aa1b3a6a0ac3d7"
]
]
},
{
"id": "0c9c48807302abbe",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 300,
"y": 1000,
"wires": [
[
"6526126078390137"
]
]
},
{
"id": "7cbd22af688976aa",
"type": "inject",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Reset Timer Interval",
"props": [
{
"p": "reset",
"v": "true",
"vt": "bool"
},
{
"p": "machine_name",
"v": "X1C_{PRINTER_NAME}",
"vt": "str"
},
{
"p": "model",
"v": "X1 Carbon",
"vt": "str"
}
],
"repeat": "300",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 160,
"y": 960,
"wires": [
[
"0c9c48807302abbe"
]
]
},
{
"id": "12d493bc4868cb6b",
"type": "mqtt in",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "HomeAssistant In",
"topic": "homeassistant/button/X1C_{PRINTER_NAME}/reset_filter",
"qos": "2",
"datatype": "utf8",
"broker": "489094618c340eef",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 180,
"y": 1000,
"wires": [
[
"0c9c48807302abbe"
]
]
},
{
"id": "6526126078390137",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Reset",
"rules": [
{
"t": "set",
"p": "reset",
"pt": "msg",
"to": "true",
"tot": "bool"
},
{
"t": "set",
"p": "topic",
"pt": "msg",
"to": "",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 390,
"y": 1000,
"wires": [
[
"6db1d3c86598f8a4"
]
]
},
{
"id": "f6805ea36226a930",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Get_Version Command",
"func": "var template = {\n \"info\": {\n \"sequence_id\": \"20004\",\n \"command\": \"get_version\"\n },\n \"user_id\": \"1234567890\"\n}\nif (global.get(\"{PRINTER_NAME}_is_connected\", \"true\")) {\n node.send({ \"payload\": template });\n}\n",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 210,
"y": 660,
"wires": [
[
"2fe75ce36321f506"
]
]
},
{
"id": "c1bc72e5401a7523",
"type": "inject",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Fetch Versions",
"props": [],
"repeat": "60",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 140,
"y": 620,
"wires": [
[
"f6805ea36226a930"
]
]
},
{
"id": "97e117e5e3b6b2ac",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "payload.info.command",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "get_version",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 790,
"y": 140,
"wires": [
[
"574efe9bef59bfe8"
],
[]
]
},
{
"id": "dbd5442f44b5d5eb",
"type": "comment",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Info",
"info": "",
"x": 790,
"y": 100,
"wires": []
},
{
"id": "574efe9bef59bfe8",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Parse Versions",
"func": "let data = {\n \"printer\": {}\n};\n\nif(msg.payload.info.module !== undefined) {\n for(var m of msg.payload.info.module) {\n\n if (m.name.includes(\"ams/\")) {\n let n = \"AMS\"+ m.name.replace(\"ams/\", \"\");\n data[n] = {};\n data[n].SW_version = m.sw_ver;\n data[n].serial_number = m.sn;\n data[n].HW_version = m.hw_ver;\n continue;\n }\n else {\n switch(m.name) {\n case \"ota\":\n data.printer.SW_version = m.sw_ver;\n break;\n case \"rv1126\":\n data.printer.serial_number = m.sn;\n data.printer.HW_version = m.hw_ver;\n break;\n }\n continue;\n }\n }\n}\nmsg.payload = data;\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 980,
"y": 60,
"wires": [
[
"dff0a7bcab99db34"
]
]
},
{
"id": "dff0a7bcab99db34",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 1010,
"y": 100,
"wires": [
[
"2dcd252aec842a4b"
]
]
},
{
"id": "17dc50ac469fdac7",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "ams",
"func": "let name = msg.topic.replace(\"AMS\", \"AMS_\");\nmsg.machine_name = name + \"_\" + msg.printer_name;\nmsg.topic = \"AMS\";\nmsg.model = \"AMS\";\nmsg.printer_serial = msg.machine_serial;\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1290,
"y": 80,
"wires": [
[
"0539d7216c7abb63"
]
]
},
{
"id": "51c3cfdad1576d27",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "x1c",
"func": "msg.topic = \"X1C\";//_\" + msg.payload.id;\n\nmsg.machine_name = msg.topic + \"_\" + msg.printer_name;\nmsg.model = \"X1 Carbon\";\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1290,
"y": 120,
"wires": [
[
"dae563cbc58f46bd"
]
]
},
{
"id": "2dcd252aec842a4b",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "cont",
"v": "AMS",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 1150,
"y": 100,
"wires": [
[
"17dc50ac469fdac7"
],
[
"51c3cfdad1576d27"
]
]
},
{
"id": "0539d7216c7abb63",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 1410,
"y": 80,
"wires": [
[
"73ce7dbb92cee565"
]
]
},
{
"id": "dae563cbc58f46bd",
"type": "split",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "",
"splt": "\\n",
"spltType": "str",
"arraySplt": 1,
"arraySpltType": "len",
"stream": false,
"addname": "topic",
"x": 1410,
"y": 120,
"wires": [
[
"1105b8629aa017ee"
]
]
},
{
"id": "1105b8629aa017ee",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1500,
"y": 200,
"wires": [
[
"682e4da1ee0769d4"
]
]
},
{
"id": "73ce7dbb92cee565",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 1440,
"y": 200,
"wires": [
[
"4293665f8ddd9f37"
]
]
},
{
"id": "4293665f8ddd9f37",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 900,
"y": 180,
"wires": [
[
"c40efe7b1b254622"
]
]
},
{
"id": "2fe75ce36321f506",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 480,
"y": 820,
"wires": [
[
"1db470110f18fab6"
]
]
},
{
"id": "a1c7a965b0d664fe",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Convert HMS Codes",
"func": "function DecimalHexTwosComplement(decimal) {\n var size = 8;\n var hexadecimal;\n if (decimal >= 0) {\n hexadecimal = decimal.toString(16);\n\n while ((hexadecimal.length % size) != 0) {\n hexadecimal = \"\" + 0 + hexadecimal;\n }\n\n return hexadecimal;\n } else {\n hexadecimal = Math.abs(decimal).toString(16);\n while ((hexadecimal.length % size) != 0) {\n hexadecimal = \"\" + 0 + hexadecimal;\n }\n\n var output = '';\n for (var i = 0; i < hexadecimal.length; i++) {\n output += (0x0F - parseInt(hexadecimal[i], 16)).toString(16);\n }\n\n output = (0x01 + parseInt(output, 16)).toString(16);\n return output;\n }\n}\n\nlet template = []\nfor (var hms_code of msg.payload.print.hms) {\n var attr = DecimalHexTwosComplement(hms_code.attr);\n var code = DecimalHexTwosComplement(hms_code.code);\n let full_code = (attr + code).replace(/(.{4})/g, \"$1_\");\n full_code = full_code.substring(0, full_code.length - 1);\n let url = \"https://wiki.bambulab.com/en/x1/troubleshooting/hmscode/\"+full_code;\n template.push({\"code\": \"HMS_\"+full_code, \"url\": url, \"description\":\"\"});\n}\nmsg.payload.print.hms = template;\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 820,
"y": 520,
"wires": [
[
"7c6b4583707029ea"
]
]
},
{
"id": "3907f3b052894ad1",
"type": "mqtt in",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "HomeAssistant In",
"topic": "homeassistant/button/X1C_{PRINTER_NAME}/pause_print",
"qos": "2",
"datatype": "utf8",
"broker": "489094618c340eef",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 140,
"y": 700,
"wires": [
[
"d20b02ea37dbdddf"
]
]
},
{
"id": "a4d29254d471acd7",
"type": "function",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "Pause/Resume/Stop",
"func": "var pause = { \"print\": { \"sequence_id\": \"2008\", \"command\": \"pause\" }, \"user_id\": \"123456789\" }\nvar resume = { \"print\": { \"sequence_id\": \"2009\", \"command\": \"resume\"}, \"user_id\": \"123456789\" }\nvar stop = { \"print\": { \"sequence_id\": \"2010\", \"command\": \"stop\" }, \"user_id\": \"123456789\" }\n\nif(msg.payload == \"PAUSE\") {\n node.send({\"payload\": pause});\n}\nelse if (msg.payload == \"RESUME\") {\n node.send({ \"payload\": resume });\n}\nelse if(msg.payload == \"STOP\") {\n node.send({\"payload\": stop})\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 200,
"y": 820,
"wires": [
[
"2fe75ce36321f506"
]
]
},
{
"id": "1288bcdd3d2bc704",
"type": "mqtt in",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "HomeAssistant In",
"topic": "homeassistant/button/X1C_{PRINTER_NAME}/resume_print",
"qos": "2",
"datatype": "utf8",
"broker": "489094618c340eef",
"nl": false,
"rap": true,
"rh": 0,
"inputs": 0,
"x": 140,
"y": 740,
"wires": [
[
"8959434b99b38bdd"
]
]
},
{
"id": "d20b02ea37dbdddf",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "pause",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "PAUSE",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 290,
"y": 700,
"wires": [
[
"7ba7e522b0b73697"
]
]
},
{
"id": "8959434b99b38bdd",
"type": "change",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"name": "resume",
"rules": [
{
"t": "set",
"p": "payload",
"pt": "msg",
"to": "RESUME",
"tot": "str"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 300,
"y": 740,
"wires": [
[
"7ba7e522b0b73697"
]
]
},
{
"id": "7ba7e522b0b73697",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "296274a0d2a6c675",
"x": 400,
"y": 760,
"wires": [
[
"a4d29254d471acd7"
]
]
},
{
"id": "84f61d394ba2ab34",
"type": "mqtt-broker",
"name": "Bambu X1C MQTT {PRINTER_NAME}",
"broker": "{PRINTER_IP}",
"port": "1883",
"clientid": "",
"autoConnect": true,
"usetls": false,
"protocolVersion": "4",
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willPayload": "",
"willMsg": {},
"userProps": "",
"sessionExpiry": ""
},
{
"id": "489094618c340eef",
"type": "mqtt-broker",
"name": "homeassistant",
"broker": "{HA_MQTT_BROKER_HOST}",
"port": "1883",
"clientid": "",
"autoConnect": true,
"usetls": false,
"protocolVersion": "4",
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willPayload": "",
"willMsg": {},
"userProps": "",
"sessionExpiry": ""
}
]
[
{
"id": "35189d41d7e64098",
"type": "trigger-state",
"z": "fbda6ab16491b918",
"name": "When Print Starts",
"server": "ed9339d3bdf92870",
"version": 2,
"exposeToHomeAssistant": false,
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
}
],
"entityid": "sensor.{HA_PRINTER_ENTITY_NAME}_print_status",
"entityidfiltertype": "exact",
"debugenabled": false,
"constraints": [
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "previous_state",
"propertyValue": "old_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "RUNNING"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "current_state",
"propertyValue": "new_state.state",
"comparatorType": "is",
"comparatorValueDatatype": "str",
"comparatorValue": "RUNNING"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "previous_state",
"propertyValue": "old_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "PAUSE"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "previous_state",
"propertyValue": "old_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "Unknown"
}
],
"inputs": 0,
"outputs": 2,
"customoutputs": [],
"outputinitially": false,
"state_type": "str",
"enableInput": false,
"x": 80,
"y": 1320,
"wires": [
[
"bab486630826f18f"
],
[]
]
},
{
"id": "b37e1ea07031ddb3",
"type": "trigger-state",
"z": "fbda6ab16491b918",
"name": "When Print Ends or Pause",
"server": "ed9339d3bdf92870",
"version": 2,
"exposeToHomeAssistant": false,
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
}
],
"entityid": "sensor.{HA_PRINTER_ENTITY_NAME}_print_status",
"entityidfiltertype": "exact",
"debugenabled": false,
"constraints": [
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "previous_state",
"propertyValue": "old_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "OFFLINE"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "current_state",
"propertyValue": "new_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "OFFLINE"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "current_state",
"propertyValue": "new_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "RUNNING"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "current_state",
"propertyValue": "new_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "IDLE"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "previous_state",
"propertyValue": "old_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": ""
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "previous_state",
"propertyValue": "old_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "FINISH"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "previous_state",
"propertyValue": "old_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "FAILED"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "current_state",
"propertyValue": "new_state.state",
"comparatorType": "is_not",
"comparatorValueDatatype": "str",
"comparatorValue": "PREPARE"
}
],
"inputs": 0,
"outputs": 2,
"customoutputs": [],
"outputinitially": false,
"state_type": "str",
"enableInput": false,
"x": 110,
"y": 1560,
"wires": [
[
"a59ef513683810a9"
],
[]
]
},
{
"id": "0a2561d5abf6ca94",
"type": "trigger-state",
"z": "fbda6ab16491b918",
"name": "When Print Resume",
"server": "ed9339d3bdf92870",
"version": 2,
"exposeToHomeAssistant": false,
"haConfig": [
{
"property": "name",
"value": ""
},
{
"property": "icon",
"value": ""
}
],
"entityid": "sensor.{HA_PRINTER_ENTITY_NAME}_print_status",
"entityidfiltertype": "exact",
"debugenabled": false,
"constraints": [
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "current_state",
"propertyValue": "new_state.state",
"comparatorType": "is",
"comparatorValueDatatype": "str",
"comparatorValue": "RUNNING"
},
{
"targetType": "this_entity",
"targetValue": "",
"propertyType": "previous_state",
"propertyValue": "old_state.state",
"comparatorType": "is",
"comparatorValueDatatype": "str",
"comparatorValue": "PAUSE"
}
],
"inputs": 0,
"outputs": 2,
"customoutputs": [],
"outputinitially": false,
"state_type": "str",
"enableInput": false,
"x": 90,
"y": 1680,
"wires": [
[
"fd7de145f90381e2"
],
[]
]
},
{
"id": "bab486630826f18f",
"type": "junction",
"z": "fbda6ab16491b918",
"x": 220,
"y": 1320,
"wires": [
[
"eb7b7d95a12bca81",
"9f785ff8ae78f4c8"
]
]
},
{
"id": "a8e16f2f7cd7ca58",
"type": "group",
"z": "fbda6ab16491b918",
"name": "HTTP/FTP Print Fetch",
"style": {
"stroke": "#ffC000",
"label": true,
"color": "#ffcf3f"
},
"nodes": [
"35843fe61649dbc3",
"78542490c91bf887",
"30dad989631cfaa5",
"c67bbd325b89adbf",
"f688049b33fb6a61",
"d7c2cab04b8a0f78",
"33500f62b336ae89",
"51b15b96b7068b55",
"016e9b0f33308095",
"629c07afdacaed2c",
"522957aac1e24443",
"eb7b7d95a12bca81",
"0b423508e8a3515b",
"b7cc932d483c7cde",
"755f49719d3dd4eb",
"4e223d03cf30c7bd",
"5beec15f7d35c6ec",
"890ab48c5cb98981",
"349fd8f789e58660",
"984eea7487453707",
"1d903d5f9c8a8aa2",
"c24b378aa0b3c889"
],
"x": 314,
"y": 1119,
"w": 772,
"h": 322
},
{
"id": "35843fe61649dbc3",
"type": "ftp in",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"ftp": "9c5b6af93d09c8b7",
"operation": "get",
"filename": "",
"localFilename": "/data/fetched/{PRINTER_NAME}/current_print.3mf",
"name": "Get Print File",
"x": 590,
"y": 1280,
"wires": [
[
"629c07afdacaed2c"
]
]
},
{
"id": "78542490c91bf887",
"type": "http in",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "GetPreviewImage ",
"url": "/get/media/{PRINTER_NAME}/preview.png",
"method": "get",
"upload": false,
"swaggerDoc": "",
"x": 430,
"y": 1160,
"wires": [
[
"c67bbd325b89adbf"
]
]
},
{
"id": "30dad989631cfaa5",
"type": "http response",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"statusCode": "",
"headers": {
"Cache-control": "no-cache"
},
"x": 1010,
"y": 1160,
"wires": []
},
{
"id": "c67bbd325b89adbf",
"type": "file in",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Check for existing image",
"filename": "/data/fetched/{PRINTER_NAME}/preview.png",
"filenameType": "str",
"format": "",
"chunk": false,
"sendError": false,
"encoding": "none",
"allProps": false,
"x": 670,
"y": 1160,
"wires": [
[
"522957aac1e24443"
]
]
},
{
"id": "f688049b33fb6a61",
"type": "file in",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Read 3mf",
"filename": "localFilename",
"filenameType": "msg",
"format": "",
"chunk": false,
"sendError": false,
"encoding": "none",
"allProps": false,
"x": 880,
"y": 1280,
"wires": [
[
"d7c2cab04b8a0f78"
]
]
},
{
"id": "d7c2cab04b8a0f78",
"type": "zip",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"mode": "decompress",
"filename": "",
"compressionlevel": 6,
"outasstring": false,
"x": 410,
"y": 1320,
"wires": [
[
"33500f62b336ae89",
"5beec15f7d35c6ec"
]
]
},
{
"id": "33500f62b336ae89",
"type": "function",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Extract Preview Image Buffer",
"func": "var image = null;\nif (msg.payload !== undefined && msg.payload.length > 0) {\n for (var file of msg.payload) {\n if (file.filename == \"Metadata/plate_1.png\") {\n image = file.payload;\n break;\n }\n }\n}\n\nif (image !== null) {\n msg.payload = image;\n if(msg.req !== undefined) {\n msg.statusCode = 200;\n }\n node.send(msg);\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 620,
"y": 1320,
"wires": [
[
"016e9b0f33308095"
]
]
},
{
"id": "51b15b96b7068b55",
"type": "file",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Write Image",
"filename": "/data/fetched/{PRINTER_NAME}/preview.png",
"filenameType": "str",
"appendNewline": false,
"createDir": true,
"overwriteFile": "true",
"encoding": "base64",
"x": 970,
"y": 1320,
"wires": [
[]
],
"info": "This is a backup approach which writes \r\nthe file locally into the NR instance.\r\n\r\n"
},
{
"id": "016e9b0f33308095",
"type": "base64",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"action": "",
"property": "payload",
"x": 820,
"y": 1320,
"wires": [
[
"51b15b96b7068b55"
]
]
},
{
"id": "629c07afdacaed2c",
"type": "delay",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"pauseType": "delay",
"timeout": "25",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 740,
"y": 1280,
"wires": [
[
"f688049b33fb6a61"
]
]
},
{
"id": "522957aac1e24443",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"property": "req",
"propertyType": "msg",
"rules": [
{
"t": "nnull"
}
],
"checkall": "true",
"repair": false,
"outputs": 1,
"x": 870,
"y": 1160,
"wires": [
[
"30dad989631cfaa5"
]
]
},
{
"id": "eb7b7d95a12bca81",
"type": "delay",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"pauseType": "delay",
"timeout": "1",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 400,
"y": 1220,
"wires": [
[
"b7cc932d483c7cde"
]
]
},
{
"id": "0b423508e8a3515b",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Current Task Filename",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_subtask",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "filename",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 860,
"y": 1220,
"wires": [
[
"755f49719d3dd4eb"
]
]
},
{
"id": "b7cc932d483c7cde",
"type": "ftp in",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"ftp": "9c5b6af93d09c8b7",
"operation": "list",
"filename": "",
"localFilename": "",
"name": "List Files",
"x": 540,
"y": 1220,
"wires": [
[
"4e223d03cf30c7bd"
]
]
},
{
"id": "755f49719d3dd4eb",
"type": "function",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Check Print File",
"func": "var found = false;\nfor (var obj of msg.payload) {\n if (msg.filename == obj.name) {\n msg.payload = {};\n msg.filename = \"/\" + msg.filename\n node.send(msg)\n found = true;\n break;\n }\n else if (msg.filename+\".gcode.3mf\" == obj.name) {\n msg.payload = {};\n msg.filename = \"/\" + msg.filename + \".gcode.3mf\"\n node.send(msg)\n found = true;\n break;\n }\n}\nif (!found) {\n msg.payload = {};\n msg.filename = \"/local_print.gcode.3mf\"\n node.send(msg)\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 420,
"y": 1280,
"wires": [
[
"35843fe61649dbc3"
]
]
},
{
"id": "4e223d03cf30c7bd",
"type": "delay",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"pauseType": "delay",
"timeout": "4",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 680,
"y": 1220,
"wires": [
[
"0b423508e8a3515b"
]
]
},
{
"id": "5beec15f7d35c6ec",
"type": "function",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Extract Print Data XML",
"func": "var f = null;\nif (msg.payload !== undefined && msg.payload.length > 0) {\n for (var file of msg.payload) {\n if (file.filename == \"Metadata/slice_info.config\") {\n f = file.payload;\n break;\n }\n }\n}\n\nif (f !== null) {\n msg.payload = f;\n if(msg.req !== undefined) {\n msg.statusCode = 200;\n }\n node.send(msg);\n}",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 600,
"y": 1360,
"wires": [
[
"890ab48c5cb98981"
]
]
},
{
"id": "890ab48c5cb98981",
"type": "base64",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"action": "",
"property": "payload",
"x": 820,
"y": 1360,
"wires": [
[
"349fd8f789e58660"
]
]
},
{
"id": "349fd8f789e58660",
"type": "file",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Write XML",
"filename": "/data/fetched/{PRINTER_NAME}/slicer_info.xml",
"filenameType": "str",
"appendNewline": false,
"createDir": true,
"overwriteFile": "true",
"encoding": "base64",
"x": 970,
"y": 1360,
"wires": [
[
"984eea7487453707"
]
],
"info": "This is a backup approach which writes \r\nthe file locally into the NR instance.\r\n\r\n"
},
{
"id": "984eea7487453707",
"type": "file in",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"filename": "filename",
"filenameType": "msg",
"format": "utf8",
"chunk": false,
"sendError": false,
"encoding": "none",
"allProps": false,
"x": 580,
"y": 1400,
"wires": [
[
"1d903d5f9c8a8aa2"
]
]
},
{
"id": "1d903d5f9c8a8aa2",
"type": "xml",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "",
"property": "payload",
"attr": "property",
"chr": "",
"x": 710,
"y": 1400,
"wires": [
[
"c24b378aa0b3c889"
]
]
},
{
"id": "c24b378aa0b3c889",
"type": "function",
"z": "fbda6ab16491b918",
"g": "a8e16f2f7cd7ca58",
"name": "Extract And Sum Weights",
"func": "var weight = 0.0;\nif (msg.payload !== undefined && msg.payload.config != undefined\n && msg.payload.config.plate != undefined) {\n let plates = msg.payload.config.plate;\n for (var plate of plates) {\n for (var p of plate.metadata) {\n if (p.property.key == \"weight\") {\n weight += parseFloat(p.property.value);\n }\n }\n }\n}\nmsg.payload = weight;\nmsg.topic = \"weight\";\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 890,
"y": 1400,
"wires": [
[
"9f2d2e2411d850db"
]
]
},
{
"id": "9c5b6af93d09c8b7",
"type": "ftp",
"host": "{PRINTER_IP}",
"port": "",
"secureOptions": "",
"user": "bblp",
"connTimeout": "",
"pasvTimeout": "",
"keepalive": ""
},
{
"id": "a3e765e96362759b",
"type": "group",
"z": "fbda6ab16491b918",
"name": "Postgres DB",
"style": {
"stroke": "#001f60",
"label": true,
"color": "#3f93cf"
},
"nodes": [
"c207be711ef10b6a",
"50ca810a9ab07205",
"ba7473069f371df8",
"8bf5c9135058acb6",
"db4a43d5d6631118",
"0a9e3064d68660c7",
"eee0dce21d4b91c2",
"bc135fef68caf1ed",
"dcf293279321a598",
"7ef27dfc5aaf648f",
"80fe10448625eade",
"417afcee7a04a0a2",
"7f6eec43ae3d2fa0",
"c0bd71c5f8c63191",
"fd7de145f90381e2",
"9f785ff8ae78f4c8",
"a59ef513683810a9",
"57ed2f101a692dae",
"b62ebcf18556c189",
"10eb08b1a1de7acb",
"061ba64419d1fe72",
"68f63aed66cbd5e3",
"6a4ba58e99355e4c",
"c5c99a5cfe9da632",
"1707d16455cba415",
"c07ce3f59a10aac7",
"9f2d2e2411d850db",
"7ede0a3eb2a13c94",
"c7c9f6fcbdd71a9f",
"6e251ea8ba446823",
"fa51361c222215dd",
"e733d198e61a5062",
"d46519a504a1341d"
],
"x": 274,
"y": 1519,
"w": 1112,
"h": 522
},
{
"id": "c207be711ef10b6a",
"type": "postgrestor",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Initialize",
"query": "CREATE TABLE IF NOT EXISTS prints (\n id SERIAL,\n start_epoch numeric PRIMARY KEY,\n printer varchar(25) NOT NULL,\n printer_serial varchar(20) NOT NULL,\n name varchar(75) NOT NULL,\n start_time timestamp DEFAULT (now() at time zone 'utc'),\n end_time timestamp,\n initial_kwh numeric DEFAULT 0.0,\n final_kwh numeric DEFAULT 0.0,\n kwh numeric GENERATED ALWAYS AS\n \t\t(\n case WHEN final_kwh = 0.0 THEN 0.0\n ELSE final_kwh - initial_kwh\n end\n ) STORED,\n status varchar(10),\n electric_rate numeric NOT NULL,\n electric_cost numeric GENERATED ALWAYS AS ( \n case WHEN final_kwh = 0.0 THEN 0.0\n ELSE ((electric_rate / 100) * (final_kwh - initial_kwh))\n end\n ) STORED,\n material_used numeric default 0.0,\n material_type varchar(10) default 'filament',\n material_price numeric default 0.0,\n material_cost numeric GENERATED ALWAYS AS (\n material_used * (material_price / 1000)\n ) STORED,\n material_description varchar(50)\n);",
"postgresDB": "79ce3199b8eeaa1c",
"output": true,
"outputs": 1,
"x": 480,
"y": 1560,
"wires": [
[
"57ed2f101a692dae"
]
]
},
{
"id": "50ca810a9ab07205",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Start Epoch",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 2,
"halt_if": "0",
"halt_if_type": "num",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_print_start_epoch",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.start_epoch",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1030,
"y": 1560,
"wires": [
[
"ba7473069f371df8"
],
[]
]
},
{
"id": "ba7473069f371df8",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Print Name",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_subtask",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.name",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1030,
"y": 1600,
"wires": [
[
"8bf5c9135058acb6"
]
]
},
{
"id": "8bf5c9135058acb6",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Energy Rate",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_ELECTRIC_RATE_COST}",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.electric_rate",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1030,
"y": 1640,
"wires": [
[
"db4a43d5d6631118"
]
]
},
{
"id": "db4a43d5d6631118",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Printer Serial",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_serial_number",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.printer_serial",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1030,
"y": 1680,
"wires": [
[
"0a9e3064d68660c7"
]
]
},
{
"id": "0a9e3064d68660c7",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Printer Name",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_machine_name",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.printer",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1190,
"y": 1680,
"wires": [
[
"eee0dce21d4b91c2"
]
]
},
{
"id": "eee0dce21d4b91c2",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Print Status",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_print_status",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.status",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1030,
"y": 1720,
"wires": [
[
"bc135fef68caf1ed"
]
]
},
{
"id": "bc135fef68caf1ed",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Initial Kwh",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_METER_PLUG_TOTAL_KWH}",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.initial_kwh",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1190,
"y": 1720,
"wires": [
[
"dcf293279321a598"
]
]
},
{
"id": "dcf293279321a598",
"type": "postgrestor",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Insert Initial",
"query": "INSERT INTO prints (\n start_epoch,\n printer,\n printer_serial,\n name,\n initial_kwh,\n status,\n electric_rate\n) VALUES (\n '{{msg.values.start_epoch}}',\n '{{msg.values.printer}}',\n '{{msg.values.printer_serial}}',\n '{{msg.values.name}}',\n '{{msg.values.initial_kwh}}',\n '{{msg.values.status}}',\n '{{msg.values.electric_rate}}'\n);",
"postgresDB": "79ce3199b8eeaa1c",
"output": true,
"outputs": 1,
"x": 1290,
"y": 1760,
"wires": [
[]
]
},
{
"id": "7ef27dfc5aaf648f",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Start Epoch",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 2,
"halt_if": "0",
"halt_if_type": "num",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_print_start_epoch",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.start_epoch",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 410,
"y": 1780,
"wires": [
[
"80fe10448625eade"
],
[]
]
},
{
"id": "80fe10448625eade",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Print Status",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_print_status",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.status",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 410,
"y": 1820,
"wires": [
[
"c5c99a5cfe9da632"
]
]
},
{
"id": "417afcee7a04a0a2",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Final Kwh",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_METER_PLUG_TOTAL_KWH}",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.final_kwh",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 400,
"y": 1860,
"wires": [
[
"7f6eec43ae3d2fa0"
]
]
},
{
"id": "7f6eec43ae3d2fa0",
"type": "postgrestor",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Insert Update",
"query": "UPDATE prints SET\n status = '{{msg.values.status}}',\n final_kwh = '{{msg.values.final_kwh}}',\n end_time = (now() at time zone 'utc')\nWHERE \n start_epoch = '{{msg.values.start_epoch}}';",
"postgresDB": "79ce3199b8eeaa1c",
"output": true,
"outputs": 1,
"x": 960,
"y": 1900,
"wires": [
[]
]
},
{
"id": "c0bd71c5f8c63191",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Print Name",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_subtask",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.name",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 410,
"y": 1740,
"wires": [
[
"7ef27dfc5aaf648f"
]
]
},
{
"id": "fd7de145f90381e2",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Printer Name",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_machine_name",
"state_type": "str",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "values.printer",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 410,
"y": 1700,
"wires": [
[
"c0bd71c5f8c63191"
]
]
},
{
"id": "9f785ff8ae78f4c8",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"x": 380,
"y": 1560,
"wires": [
[
"c207be711ef10b6a"
]
]
},
{
"id": "a59ef513683810a9",
"type": "junction",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"x": 300,
"y": 1620,
"wires": [
[
"fd7de145f90381e2",
"c7c9f6fcbdd71a9f"
]
]
},
{
"id": "57ed2f101a692dae",
"type": "delay",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "",
"pauseType": "delay",
"timeout": "3",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 620,
"y": 1560,
"wires": [
[
"50ca810a9ab07205"
]
]
},
{
"id": "b62ebcf18556c189",
"type": "postgrestor",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Insert Energy Table",
"query": "CREATE TABLE IF NOT EXISTS energy_reading (\n id SERIAL,\n printer varchar(25) PRIMARY KEY,\n read_time timestamp DEFAULT (now() at time zone 'utc'),\n kwh numeric NOT NULL,\n electric_rate numeric NOT NULL,\n electric_cost numeric GENERATED ALWAYS AS ( \n case WHEN kwh = 0.0 THEN 0.0\n ELSE ((electric_rate / 100) * (kwh))\n end\n ) STORED\n);\nCOMMIT;\n\nINSERT INTO energy_reading (printer, kwh, electric_rate, read_time) VALUES (\n '{{msg.payload.printer}}',\n '{{msg.payload.kwh}}',\n '{{msg.payload.electric_rate}}',\n (now() at time zone 'utc')\n)\nON CONFLICT ON CONSTRAINT energy_reading_pkey\nDO UPDATE \n SET kwh = '{{msg.payload.kwh}}',\n electric_rate = '{{msg.payload.electric_rate}}',\n read_time = (now() at time zone 'utc')\n WHERE energy_reading.printer = '{{msg.payload.printer}}'; \n;",
"postgresDB": "79ce3199b8eeaa1c",
"output": true,
"outputs": 1,
"x": 430,
"y": 2000,
"wires": [
[]
]
},
{
"id": "10eb08b1a1de7acb",
"type": "inject",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "",
"props": [
{
"p": "payload.printer",
"v": "{PRINTER_NAME}",
"vt": "str"
}
],
"repeat": "60",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 390,
"y": 1940,
"wires": [
[
"6a4ba58e99355e4c"
]
]
},
{
"id": "061ba64419d1fe72",
"type": "rbe",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "",
"func": "deadbandEq",
"gap": "0.001",
"start": "",
"inout": "in",
"septopics": false,
"property": "payload.kwh",
"topi": "topic",
"x": 640,
"y": 1940,
"wires": [
[
"68f63aed66cbd5e3"
]
]
},
{
"id": "68f63aed66cbd5e3",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Energy Rate",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_ELECTRIC_RATE_COST}",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "payload.electric_rate",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 810,
"y": 1940,
"wires": [
[
"b62ebcf18556c189"
]
]
},
{
"id": "6a4ba58e99355e4c",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Kwh",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_METER_PLUG_TOTAL_KWH}",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "payload.kwh",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 510,
"y": 1940,
"wires": [
[
"061ba64419d1fe72"
]
]
},
{
"id": "c5c99a5cfe9da632",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "RUN / PAUSE / OTHER",
"property": "values.status",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "RUNNING",
"vt": "str"
},
{
"t": "eq",
"v": "PAUSE",
"vt": "str"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 610,
"y": 1820,
"wires": [
[
"1707d16455cba415"
],
[
"1707d16455cba415"
],
[
"417afcee7a04a0a2"
]
]
},
{
"id": "1707d16455cba415",
"type": "postgrestor",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Insert Update",
"query": "UPDATE prints SET\n status = '{{msg.values.status}}'\nWHERE \n start_epoch = '{{msg.values.start_epoch}}';",
"postgresDB": "79ce3199b8eeaa1c",
"output": true,
"outputs": 1,
"x": 960,
"y": 1860,
"wires": [
[]
]
},
{
"id": "c07ce3f59a10aac7",
"type": "postgrestor",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Insert Update",
"query": "UPDATE prints SET\n material_used = '{{msg.payload}}'\nWHERE \n start_epoch = '{{msg.start_epoch}}';",
"postgresDB": "79ce3199b8eeaa1c",
"output": true,
"outputs": 1,
"x": 1280,
"y": 1600,
"wires": [
[]
]
},
{
"id": "9f2d2e2411d850db",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Start Epoch",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 2,
"halt_if": "0",
"halt_if_type": "num",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_print_start_epoch",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "start_epoch",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 1270,
"y": 1560,
"wires": [
[
"c07ce3f59a10aac7"
],
[]
]
},
{
"id": "7ede0a3eb2a13c94",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Progress %",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 1,
"halt_if": "",
"halt_if_type": "str",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_print_progress",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "progress",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
},
{
"property": "entity",
"propertyType": "msg",
"value": "",
"valueType": "entity"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 570,
"y": 1640,
"wires": [
[
"6e251ea8ba446823"
]
]
},
{
"id": "c7c9f6fcbdd71a9f",
"type": "switch",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "If Failed",
"property": "payload",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "FAILED",
"vt": "str"
},
{
"t": "eq",
"v": "FINISH",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 420,
"y": 1640,
"wires": [
[
"7ede0a3eb2a13c94"
],
[]
]
},
{
"id": "6e251ea8ba446823",
"type": "api-current-state",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Start Epoch",
"server": "ed9339d3bdf92870",
"version": 3,
"outputs": 2,
"halt_if": "0",
"halt_if_type": "num",
"halt_if_compare": "is_not",
"entity_id": "sensor.{HA_PRINTER_ENTITY_NAME}_print_start_epoch",
"state_type": "num",
"blockInputOverrides": false,
"outputProperties": [
{
"property": "start_epoch",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"for": "0",
"forType": "num",
"forUnits": "minutes",
"override_topic": false,
"state_location": "payload",
"override_payload": "msg",
"entity_location": "data",
"override_data": "msg",
"x": 730,
"y": 1640,
"wires": [
[
"e733d198e61a5062"
],
[]
]
},
{
"id": "fa51361c222215dd",
"type": "postgrestor",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Insert Update",
"query": "UPDATE prints SET\n material_used = '{{msg.payload}}' * ('{{msg.progress}}' / 100.0)\nWHERE \n start_epoch = '{{msg.start_epoch}}';",
"postgresDB": "79ce3199b8eeaa1c",
"output": true,
"outputs": 1,
"x": 800,
"y": 1720,
"wires": [
[]
]
},
{
"id": "e733d198e61a5062",
"type": "postgrestor",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Get Material Used",
"query": "SELECt material_used FROM prints\nWHERE \n start_epoch = '{{msg.start_epoch}}';",
"postgresDB": "79ce3199b8eeaa1c",
"output": true,
"outputs": 1,
"x": 630,
"y": 1680,
"wires": [
[
"d46519a504a1341d"
]
]
},
{
"id": "d46519a504a1341d",
"type": "function",
"z": "fbda6ab16491b918",
"g": "a3e765e96362759b",
"name": "Parse Amt",
"func": "msg.payload = parseFloat(msg.payload.rows[0].material_used);\n\nnode.send(msg);",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 610,
"y": 1720,
"wires": [
[
"fa51361c222215dd"
]
]
},
{
"id": "79ce3199b8eeaa1c",
"type": "postgresDB",
"name": "3DPrint DB (PG13)",
"host": "{POSTGRES_DB_HOST}",
"hostFieldType": "str",
"port": "{POSTGRES_DB_PORT}",
"portFieldType": "num",
"database": "{POSTGRES_DB_DBNAME}",
"databaseFieldType": "str",
"ssl": "false",
"sslFieldType": "bool",
"max": "10",
"maxFieldType": "num",
"min": "1",
"minFieldType": "num",
"idle": "1000",
"idleFieldType": "num",
"connectionTimeout": "10000",
"connectionTimeoutFieldType": "num",
"user": "{POSTGRES_DB_USER}",
"userFieldType": "str",
"password": "{POSTGRES_DB_PASSWORD}",
"passwordFieldType": "str"
},
{
"id": "ed9339d3bdf92870",
"type": "server",
"name": "Home Assistant",
"version": 5,
"addon": false,
"rejectUnauthorizedCerts": true,
"ha_boolean": "y|yes|true|on|home|open",
"connectionDelay": true,
"cacheJson": true,
"heartbeat": false,
"heartbeatInterval": "30",
"areaSelector": "friendlyName",
"deviceSelector": "friendlyName",
"entitySelector": "friendlyName",
"statusSeparator": ": ",
"statusYear": "hidden",
"statusMonth": "short",
"statusDay": "numeric",
"statusHourCycle": "default",
"statusTimeFormat": "h:m",
"enableGlobalContextStore": false
}
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment