[ { "id": "fbda6ab16491b918", "type": "tab", "label": "BambuLab MQTT", "disabled": false, "info": "", "env": [] }, { "id": "fcfd0963bc7576c4", "type": "group", "z": "a27dd7cd964a6e1b", "name": "Bambu MQTT Relay", "style": { "stroke": "#92d04f", "label": true, "color": "#92d04f" }, "nodes": [ "ab7c2bc10b47c931", "12b872cefe9de42e", "1ff9b85cf6e36738", "8f035d77f8352e6b", "a39389f7924b69b1", "6a2d0afad0f7fc57", "4846637e8a4c0f9a", "f81eab072017892b", "74e128025afaaac0", "593e9ce7645fefa7", "71c37b77b27f1701", "b3f6ed44cde0c39a", "5d5bc57f6ccb929d", "889fe14e334c7b20", "225fe522fab8285c", "44b5dc6266f2d622", "3fea6c3a156373af", "7c9405368b75f9e1", "3e9fb907fc0cba6c", "a1be809f7519ed52", "174ec6e8733cb7dc", "86c20b9b4555239e", "d316a805e5454849", "48cd24149d64d169", "bdfe47bb18079cc3", "12e81b2423b79623", "5c4b4106a9da7918", "de2d74ae7fd5d24a", "c55c4138ee2fe345", "b96b03312ac5f80a", "3cce1fec3ac201c1", "0de907aacdd72eea", "54ba62d007e76155", "b9abc78f6f09ac5e", "30e5928ce4474dbf", "9d70f17695f4d166", "dc794a17ae19ee86", "d5900ad9ddfd1a45", "3f13a0fbe21745e8", "71e4e4d96eaf302a", "e37b29c72679b1b6", "7b3c01d998e2a9e2", "de8ba0a76368f70b", "b97699c5ab43ed80", "d7762c21d6c94196", "5fccc254eb77178d", "e24b7aca0323c9a1", "24ce942f5f1cc5eb", "bfc0e47af4cf20f5", "52520381b2b4f1fc", "77386f627ee8cde0", "e49b789c2a5f750a", "421c6bbf8b29abdc", "aab98fef632614cb", "d9d01ad9e80dda45", "4c7e56cee7467f25", "c503110093646df7", "c6f3803a5509b659", "a3d3a260e24f28e9", "dd79f37c770aa8bb", "d098d053a70b6d22", "a63c869ab069888e", "21ace281999a586a", "b60469e0904761b8", "6792a3619aacc3e0", "4404817ff5db0efb", "3c1ae664fc1fb1fa", "1c48e44ec28ad0f4", "e36ac7cf9aa9101a", "9f38c50072a903a8", "fb05863a80f5b840", "f15c559de644bd3f", "2f76593988b6f27e", "fdac6c8317856b64", "8199f69596fc4ecf", "3eed6656fdca859a", "365db984c5044c7c", "b4a7a6745ee42b2c", "2edc0d55bceaf5b7", "537fdc4290f39c8a", "d9a209e4dddb94ea", "d259f6f66feaa948", "ceb452ddf1f3ddec", "c9a99804388c58e1", "16f8467b1205eaab", "72c7f1afa546716b", "cfb28eab0b1e1289", "67244af4560b9ac7", "d2b473ce35c62ab7", "8be309db56aaccb9", "2a46e71c6eacf403", "60c09089e40cef0b" ], "x": 14, "y": 159, "w": 2232, "h": 1007 }, { "id": "2a46e71c6eacf403", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1560, "y": 1060, "wires": [ [] ] }, { "id": "21ace281999a586a", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1000, "y": 740, "wires": [ [ "7b3c01d998e2a9e2" ] ] }, { "id": "b60469e0904761b8", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1540, "y": 520, "wires": [ [ "0de907aacdd72eea" ] ] }, { "id": "6792a3619aacc3e0", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 840, "y": 940, "wires": [ [ "889fe14e334c7b20", "48cd24149d64d169", "b96b03312ac5f80a" ] ] }, { "id": "4404817ff5db0efb", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1360, "y": 960, "wires": [ [ "e36ac7cf9aa9101a" ] ] }, { "id": "3c1ae664fc1fb1fa", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1000, "y": 980, "wires": [ [ "d316a805e5454849" ] ] }, { "id": "1c48e44ec28ad0f4", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1560, "y": 780, "wires": [ [ "54ba62d007e76155", "b9abc78f6f09ac5e" ] ] }, { "id": "e36ac7cf9aa9101a", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1860, "y": 960, "wires": [ [ "d9a209e4dddb94ea" ] ] }, { "id": "9f38c50072a903a8", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1791, "y": 814, "wires": [ [ "e36ac7cf9aa9101a" ] ] }, { "id": "fb05863a80f5b840", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1420, "y": 1140, "wires": [ [ "71e4e4d96eaf302a" ] ] }, { "id": "f15c559de644bd3f", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 500, "y": 1140, "wires": [ [ "fb05863a80f5b840" ] ] }, { "id": "2f76593988b6f27e", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 460, "y": 520, "wires": [ [ "f15c559de644bd3f" ] ] }, { "id": "fdac6c8317856b64", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 340, "y": 700, "wires": [ [ "d7762c21d6c94196" ] ] }, { "id": "8199f69596fc4ecf", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 460, "y": 420, "wires": [ [ "8f035d77f8352e6b" ] ] }, { "id": "3eed6656fdca859a", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 560, "y": 220, "wires": [ [ "d098d053a70b6d22" ] ] }, { "id": "365db984c5044c7c", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1080, "y": 960, "wires": [ [ "889fe14e334c7b20", "d316a805e5454849" ] ] }, { "id": "b4a7a6745ee42b2c", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 940, "y": 660, "wires": [ [ "2edc0d55bceaf5b7" ] ] }, { "id": "2edc0d55bceaf5b7", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1060, "y": 660, "wires": [ [ "365db984c5044c7c" ] ] }, { "id": "537fdc4290f39c8a", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 500, "y": 360, "wires": [ [ "3eed6656fdca859a" ] ] }, { "id": "16f8467b1205eaab", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 1860, "y": 1100, "wires": [ [ "d9a209e4dddb94ea" ] ] }, { "id": "72c7f1afa546716b", "type": "junction", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "x": 300, "y": 1100, "wires": [ [ "8be309db56aaccb9" ] ] }, { "id": "ab7c2bc10b47c931", "type": "mqtt in", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 380, "wires": [ [ "1ff9b85cf6e36738" ] ] }, { "id": "12b872cefe9de42e", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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.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}\n\n\n\nnode.send(msg);\n", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 180, "y": 420, "wires": [ [ "8199f69596fc4ecf" ] ] }, { "id": "1ff9b85cf6e36738", "type": "json", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "property": "payload.print", "action": "obj", "pretty": false, "x": 370, "y": 380, "wires": [ [ "12b872cefe9de42e" ] ] }, { "id": "8f035d77f8352e6b", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "hask", "v": "mc_print", "vt": "str" }, { "t": "hask", "v": "print", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 3, "x": 610, "y": 400, "wires": [ [ "537fdc4290f39c8a" ], [ "aab98fef632614cb" ], [] ] }, { "id": "a39389f7924b69b1", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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\": \"PC-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 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": 460, "wires": [ [ "6a2d0afad0f7fc57" ] ] }, { "id": "6a2d0afad0f7fc57", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 500, "wires": [ [ "4846637e8a4c0f9a" ] ] }, { "id": "4846637e8a4c0f9a", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 540, "wires": [ [ "74e128025afaaac0" ] ] }, { "id": "f81eab072017892b", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 700, "wires": [ [ "b3f6ed44cde0c39a" ] ] }, { "id": "74e128025afaaac0", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 580, "wires": [ [ "593e9ce7645fefa7" ] ] }, { "id": "593e9ce7645fefa7", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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\"; // idle or 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": 620, "wires": [ [ "71c37b77b27f1701" ] ] }, { "id": "71c37b77b27f1701", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 660, "wires": [ [ "f81eab072017892b" ] ] }, { "id": "b3f6ed44cde0c39a", "type": "split", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "topic", "x": 610, "y": 740, "wires": [ [ "5d5bc57f6ccb929d" ] ] }, { "id": "5d5bc57f6ccb929d", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 740, "wires": [ [ "21ace281999a586a" ], [ "225fe522fab8285c" ] ] }, { "id": "889fe14e334c7b20", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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\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;\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": 940, "wires": [ [ "4404817ff5db0efb" ] ] }, { "id": "225fe522fab8285c", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 800, "wires": [ [ "44b5dc6266f2d622" ] ] }, { "id": "44b5dc6266f2d622", "type": "split", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "topic", "x": 610, "y": 840, "wires": [ [ "3fea6c3a156373af" ] ] }, { "id": "3fea6c3a156373af", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 840, "wires": [ [ "5c4b4106a9da7918" ] ] }, { "id": "7c9405368b75f9e1", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "rules": [ { "t": "set", "p": "payload.gcode_end_time", "pt": "msg", "to": "", "tot": "date" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1360, "y": 440, "wires": [ [ "3e9fb907fc0cba6c" ] ] }, { "id": "3e9fb907fc0cba6c", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 480, "wires": [ [ "a1be809f7519ed52" ] ] }, { "id": "a1be809f7519ed52", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 480, "wires": [ [ "b60469e0904761b8" ], [ "a63c869ab069888e" ] ] }, { "id": "174ec6e8733cb7dc", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 400, "wires": [ [ "7c9405368b75f9e1" ], [ "3e9fb907fc0cba6c" ] ] }, { "id": "86c20b9b4555239e", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 360, "wires": [ [ "de8ba0a76368f70b" ] ], "info": "This is useful to keep as it will act as\r\na unique ID for each print" }, { "id": "d316a805e5454849", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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\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": 980, "wires": [ [ "4404817ff5db0efb" ] ] }, { "id": "48cd24149d64d169", "type": "split", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "topic", "x": 690, "y": 980, "wires": [ [ "bdfe47bb18079cc3" ] ] }, { "id": "bdfe47bb18079cc3", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "property": "topic", "propertyType": "msg", "rules": [ { "t": "neq", "v": "tray", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 810, "y": 980, "wires": [ [ "365db984c5044c7c" ], [ "12e81b2423b79623" ] ] }, { "id": "12e81b2423b79623", "type": "split", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "topic", "x": 610, "y": 1020, "wires": [ [ "de2d74ae7fd5d24a" ] ] }, { "id": "5c4b4106a9da7918", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 840, "wires": [ [ "6792a3619aacc3e0" ] ] }, { "id": "de2d74ae7fd5d24a", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "tray", "func": "msg.topic = msg.topic + \"_\" + msg.payload.id;\nnode.send(msg);\n", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 730, "y": 1020, "wires": [ [ "421c6bbf8b29abdc" ] ] }, { "id": "c55c4138ee2fe345", "type": "mqtt out", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Home Assistant", "topic": "", "qos": "", "retain": "", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "489094618c340eef", "x": 2140, "y": 960, "wires": [] }, { "id": "b96b03312ac5f80a", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Set Status", "rules": [ { "t": "set", "p": "payload", "pt": "msg", "to": "online", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 930, "y": 900, "wires": [ [ "3c1ae664fc1fb1fa" ] ] }, { "id": "3cce1fec3ac201c1", "type": "comment", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "AMS", "info": "AMS Split", "x": 810, "y": 800, "wires": [] }, { "id": "0de907aacdd72eea", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Remove Useless", "rules": [ { "t": "delete", "p": "payload.command", "pt": "msg" }, { "t": "delete", "p": "payload.force_upgrade", "pt": "msg" }, { "t": "delete", "p": "payload.hms", "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": 560, "wires": [ [ "30e5928ce4474dbf" ] ] }, { "id": "54ba62d007e76155", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "X1C Config", "func": "let data = {};\nlet payload = {};\nlet device = {};\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 == \"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\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\") {\n type = \"button\";\n}\n\nlet base_topic = \"homeassistant/\"+ type + \"/\" + msg.machine_name + \"/\" + msg.topic;\ndata.topic = base_topic + \"/config\";\npayload.name = getFriendlyName(msg.topic);\n\ndevice.identifiers = [];\ndevice.identifiers[0] = msg.machine_name;\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\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\") {\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}\n\nif (msg.topic == \"speed\") {\n payload.command_topic = \"homeassistant/\" + \"select\" + \"/\" + msg.machine_name + \"/\" + msg.topic + \"/set\";\n payload.availability_topic = \"homeassistant/\" + \"sensor\" + \"/\" + msg.machine_name + \"/\" + \"status\" + \"/state\";\n payload.options = [\"Silent\", \"Standard\", \"Sport\", \"Ludicrous\"];\n}\n\nif (msg.topic != \"status\" && msg.topic != \"print_status\"\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);", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1690, "y": 780, "wires": [ [ "9f38c50072a903a8" ] ] }, { "id": "b9abc78f6f09ac5e", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "X1C State", "func": "// Filter UoM from payload\n\nif (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 == \"speed\") {\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.profile;\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}\nelse if (msg.topic == \"reset_filter\") {\n return;\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": 820, "wires": [ [ "9f38c50072a903a8" ] ] }, { "id": "30e5928ce4474dbf", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 600, "wires": [ [ "9d70f17695f4d166" ] ] }, { "id": "9d70f17695f4d166", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 640, "wires": [ [ "dc794a17ae19ee86" ] ] }, { "id": "dc794a17ae19ee86", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 680, "wires": [ [ "3f13a0fbe21745e8" ] ] }, { "id": "d5900ad9ddfd1a45", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 720, "wires": [ [ "71e4e4d96eaf302a" ], [ "71e4e4d96eaf302a" ], [ "1c48e44ec28ad0f4" ] ] }, { "id": "3f13a0fbe21745e8", "type": "split", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "topic", "x": 1270, "y": 720, "wires": [ [ "d5900ad9ddfd1a45" ] ] }, { "id": "71e4e4d96eaf302a", "type": "split", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "topic", "x": 1530, "y": 720, "wires": [ [ "1c48e44ec28ad0f4" ] ] }, { "id": "e37b29c72679b1b6", "type": "comment", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "X1C", "info": "", "x": 1090, "y": 440, "wires": [] }, { "id": "7b3c01d998e2a9e2", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "x1c", "func": "msg.topic = \"X1C\";//_\" + msg.payload.id;\n\nmsg.machine_name = msg.topic + \"_\" + msg.payload.machine_name;\nmsg.model = \"X1 Carbon\";\nnode.send(msg);", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 1090, "y": 320, "wires": [ [ "86c20b9b4555239e" ] ] }, { "id": "de8ba0a76368f70b", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 360, "wires": [ [ "174ec6e8733cb7dc" ] ] }, { "id": "b97699c5ab43ed80", "type": "mqtt in", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 580, "wires": [ [ "5fccc254eb77178d" ] ] }, { "id": "d7762c21d6c94196", "type": "mqtt out", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "bambu-mqtt-out {PRINTER_NAME}", "topic": "device/{PRINTER_SERIAL}/request", "qos": "1", "retain": "false", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "84f61d394ba2ab34", "x": 290, "y": 740, "wires": [] }, { "id": "5fccc254eb77178d", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 620, "wires": [ [ "fdac6c8317856b64" ] ] }, { "id": "e24b7aca0323c9a1", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 700, "wires": [ [ "fdac6c8317856b64" ] ] }, { "id": "24ce942f5f1cc5eb", "type": "mqtt in", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 660, "wires": [ [ "e24b7aca0323c9a1" ] ] }, { "id": "bfc0e47af4cf20f5", "type": "status", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Connected Status {PRINTER_NAME}", "scope": [ "ab7c2bc10b47c931" ], "x": 190, "y": 300, "wires": [ [ "52520381b2b4f1fc" ] ] }, { "id": "52520381b2b4f1fc", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 340, "wires": [ [] ] }, { "id": "77386f627ee8cde0", "type": "inject", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Inject OFFLINE {PRINTER_NAME}", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" }, { "p": "machine_name", "v": "X1C_{PRINTER_NAME}", "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}\"}", "payloadType": "json", "x": 210, "y": 480, "wires": [ [ "e49b789c2a5f750a" ] ] }, { "id": "e49b789c2a5f750a", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "property": "{PRINTER_NAME}_is_connected", "propertyType": "global", "rules": [ { "t": "eq", "v": "false", "vt": "str" } ], "checkall": "true", "repair": false, "outputs": 1, "x": 210, "y": 520, "wires": [ [ "2f76593988b6f27e" ] ] }, { "id": "421c6bbf8b29abdc", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 1020, "wires": [ [ "365db984c5044c7c" ] ] }, { "id": "aab98fef632614cb", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "property": "payload.print.command", "propertyType": "msg", "rules": [ { "t": "eq", "v": "push_status", "vt": "str" } ], "checkall": "true", "repair": false, "outputs": 1, "x": 750, "y": 420, "wires": [ [ "a39389f7924b69b1" ] ] }, { "id": "d9d01ad9e80dda45", "type": "comment", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 420, "wires": [] }, { "id": "4c7e56cee7467f25", "type": "comment", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 260, "wires": [] }, { "id": "c503110093646df7", "type": "comment", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Change Timezone", "info": "Change to a valid timezone here", "x": 1750, "y": 440, "wires": [] }, { "id": "c6f3803a5509b659", "type": "comment", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "MC_Print", "info": "", "x": 540, "y": 200, "wires": [] }, { "id": "a3d3a260e24f28e9", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 870, "y": 220, "wires": [ [ "dd79f37c770aa8bb" ] ] }, { "id": "dd79f37c770aa8bb", "type": "split", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "splt": "\\n", "spltType": "str", "arraySplt": 1, "arraySpltType": "len", "stream": false, "addname": "topic", "x": 870, "y": 340, "wires": [ [ "b4a7a6745ee42b2c" ] ] }, { "id": "d098d053a70b6d22", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "property": "payload.mc_print.param", "propertyType": "msg", "rules": [ { "t": "cont", "v": "humidity", "vt": "str" }, { "t": "else" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 690, "y": 220, "wires": [ [ "a3d3a260e24f28e9" ], [] ] }, { "id": "a63c869ab069888e", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Timezone Configuration", "rules": [ { "t": "set", "p": "timezone", "pt": "msg", "to": "America/Halifax", "tot": "str" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1730, "y": 480, "wires": [ [ "ceb452ddf1f3ddec" ] ] }, { "id": "d9a209e4dddb94ea", "type": "rbe", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "func": "rbe", "gap": "", "start": "", "inout": "out", "septopics": true, "property": "payload", "topi": "topic", "x": 1950, "y": 960, "wires": [ [ "d259f6f66feaa948" ] ] }, { "id": "d259f6f66feaa948", "type": "switch", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "", "property": "topic", "propertyType": "msg", "rules": [ { "t": "neq", "v": "", "vt": "str" } ], "checkall": "true", "repair": false, "outputs": 1, "x": 2070, "y": 1000, "wires": [ [ "c55c4138ee2fe345" ] ] }, { "id": "ceb452ddf1f3ddec", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Convert Timestamps", "rules": [ { "t": "set", "p": "payload.gcode_start_time", "pt": "msg", "to": "$moment(msg.payload.gcode_start_time).tz(\"msg.timezone\").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).tz(\"msg.timezone\").format(\"MMMM D, yyyy [at] h:mm A\")", "tot": "jsonata" } ], "action": "", "property": "", "from": "", "to": "", "reg": false, "x": 1320, "y": 520, "wires": [ [ "b60469e0904761b8" ] ] }, { "id": "c9a99804388c58e1", "type": "comment", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 1020, "wires": [] }, { "id": "cfb28eab0b1e1289", "type": "inject", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 1060, "wires": [ [ "72c7f1afa546716b" ] ] }, { "id": "67244af4560b9ac7", "type": "function", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "Add Reset Switch", "func": "// So you can make an automation in HA to\n// reset the filter on startup\n\n\nnode.send(msg);", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 330, "y": 840, "wires": [ [] ] }, { "id": "d2b473ce35c62ab7", "type": "mqtt in", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 1100, "wires": [ [ "72c7f1afa546716b" ] ] }, { "id": "8be309db56aaccb9", "type": "change", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "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": 1100, "wires": [ [ "16f8467b1205eaab" ] ] }, { "id": "60c09089e40cef0b", "type": "debug", "z": "a27dd7cd964a6e1b", "g": "fcfd0963bc7576c4", "name": "debug 2", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "statusVal": "", "statusType": "auto", "x": 1320, "y": 240, "wires": [] }, { "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": "" } ]