[{"data":1,"prerenderedAt":5100},["ShallowReactive",2],{"blog-\u002Fblog\u002F2026\u002F07\u002Fbuild-downtime-logger":3,"featureCatalog":4173,"changelog-titles":4565,"blog-all-for-related":5099},{"id":4,"title":5,"authors":6,"body":8,"cta":4150,"date":4154,"description":4155,"extension":4156,"features":4157,"image":4158,"lastUpdated":4157,"meta":4159,"navigation":2368,"path":4164,"release":4157,"seo":4165,"sitemap":4166,"stem":4167,"subtitle":4168,"tags":4169,"tldr":4171,"video":4157,"__hash__":4172},"blog\u002Fblog\u002F2026\u002F07\u002Fbuild-downtime-logger.md","Build a Machine Downtime Tracking Application",[7],"sumit-shinde",{"type":9,"value":10,"toc":4142},"minimark",[11,15,18,21,32,41,44,49,52,101,104,108,111,144,147,151,154,165,173,250,261,264,267,271,274,282,293,302,311,316,325,345,354,359,393,403,433,436,2175,2178,2181,2184,2188,2191,2205,2255,2262,2274,2282,2294,2304,2523,2526,2534,2574,2584,2593,2598,2607,3871,3874,3906,3915,3920,3959,3964,3967,3976,3979,3983,3986,3991,4071,4074,4082,4117,4122,4125,4132,4139],[12,13,14],"p",{},"Production lines in manufacturing and automotive facilities experience planned and unplanned downtime every day. Tracking when a machine stops, how long it stays down, and why it happened helps production and maintenance teams identify recurring issues and improve operations.",[12,16,17],{},"Many factories still record downtime on paper or in spreadsheets. Others rely on PLC alarms without keeping a centralized history that teams can review and analyze later.",[12,19,20],{},"In this tutorial, you'll build a machine downtime tracking application using FlowFuse. The application records machine stop and start events, calculates downtime duration, lets operators assign downtime reasons, and displays a live dashboard with unresolved events and key metrics. Following the steps below, you can have this application built and deployed in about 10-15 minutes.",[12,22,23,28],{},[24,25],"img",{"alt":26,"src":27},"Screenshot: completed dashboard with KPI cards and stoppages table","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fdowntime-logger.png",[29,30,31],"em",{},"The finished dashboard: KPI cards on top, unresolved stoppages below.",[12,33,34,35,40],{},"You can interact with the live demo here: ",[36,37,39],"a",{"href":38},"https:\u002F\u002Fcheerful-western-sandpiper-1404.flowfuse.cloud\u002Fdashboard\u002Fdowntime-events","Try the Machine Downtime Tracking Demo",".",[12,42,43],{},"By the end, you'll have a foundation you can extend into OEE, production reporting, maintenance dashboards, or MES integrations.",[45,46,48],"h2",{"id":47},"what-youll-need","What You'll Need",[12,50,51],{},"Before you start building, get these ready:",[53,54,55,63,69,91],"ul",{},[56,57,58,62],"li",{},[59,60,61],"strong",{},"A FlowFuse account."," Sign up for FlowFuse Cloud, or use a self-hosted instance.",[56,64,65,68],{},[59,66,67],{},"A FlowFuse instance up and running."," If you don't have one yet, create a new instance from your FlowFuse Platform.",[56,70,71,74,75,79,80,83,84,83,87,90],{},[59,72,73],{},"FlowFuse Dashboard installed."," This tutorial uses ",[76,77,78],"code",{},"@flowfuse\u002Fnode-red-dashboard"," nodes (",[76,81,82],{},"ui-button",", ",[76,85,86],{},"ui-table",[76,88,89],{},"ui-chart",") to build the operator interface. Install it from the Palette Manager if it isn't already in your instance.",[56,92,93,96,97,100],{},[59,94,95],{},"The Humanizer node installed."," This is what turns raw downtime into readable text like \"12 minutes.\" It comes from the ",[76,98,99],{},"node-red-contrib-moment"," package, install it from the Palette Manager.",[12,102,103],{},"You won't need a PLC or any real hardware for this tutorial. We'll simulate machine stop and start events with inject nodes, and the same flow logic applies later when you connect real signals.",[45,105,107],{"id":106},"how-the-application-works","How the Application Works",[12,109,110],{},"Before we build anything, let's first walk through what it should do and how the flow will look:",[112,113,114,120,126,132,138],"ol",{},[56,115,116,119],{},[59,117,118],{},"Machine stops."," A signal comes in and a new downtime record opens for that machine.",[56,121,122,125],{},[59,123,124],{},"Machine starts again."," The record closes on its own, and the duration gets calculated.",[56,127,128,131],{},[59,129,130],{},"Operator logs a reason."," From the dashboard, closing it manually too if it wasn't already.",[56,133,134,137],{},[59,135,136],{},"The table shows what's unresolved."," Anything open, or anything closed without a reason, stays visible with the clock still running next to it.",[56,139,140,143],{},[59,141,142],{},"The KPI cards keep score."," Machines down now, missing reasons, average downtime, and the most common reason.",[12,145,146],{},"Once you see these five pieces working together, the rest of the tutorial is just wiring them up.",[45,148,150],{"id":149},"setting-up-the-database-table","Setting Up the Database Table",[12,152,153],{},"Everything in this application reads from and writes to a single table, so that's where we start.",[155,156,157],"blockquote",{},[12,158,159,160,164],{},"Note: ",[36,161,163],{"href":162},"\u002Fdocs\u002Fuser\u002Fff-tables\u002F","FlowFuse Tables"," is currently in beta and available to Enterprise tier teams on FlowFuse Cloud, as well as Enterprise licensed self hosted teams running on Kubernetes. If you're on a different tier, you can follow along using any external database instead, Postgres, MySQL, or whatever you already have, with the standard database nodes from the palette. The SQL and flow logic in this tutorial will work the same either way.",[112,166,167,170],{},[56,168,169],{},"Add a Query node to your canvas. This lets you run SQL queries directly against your FlowFuse managed database.",[56,171,172],{},"Set its query to create the table:",[174,175,180],"pre",{"className":176,"code":177,"language":178,"meta":179,"style":179},"language-sql shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","CREATE TABLE IF NOT EXISTS downtime_events (\n    id SERIAL PRIMARY KEY,\n    machine_id TEXT NOT NULL,\n    status TEXT NOT NULL DEFAULT 'Open',\n    reason TEXT,\n    comments TEXT,\n    start_time TIMESTAMPTZ NOT NULL,\n    end_time TIMESTAMPTZ,\n    duration_seconds INTEGER,\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n","sql","",[76,181,182,190,196,202,208,214,220,226,232,238,244],{"__ignoreMap":179},[183,184,187],"span",{"class":185,"line":186},"line",1,[183,188,189],{},"CREATE TABLE IF NOT EXISTS downtime_events (\n",[183,191,193],{"class":185,"line":192},2,[183,194,195],{},"    id SERIAL PRIMARY KEY,\n",[183,197,199],{"class":185,"line":198},3,[183,200,201],{},"    machine_id TEXT NOT NULL,\n",[183,203,205],{"class":185,"line":204},4,[183,206,207],{},"    status TEXT NOT NULL DEFAULT 'Open',\n",[183,209,211],{"class":185,"line":210},5,[183,212,213],{},"    reason TEXT,\n",[183,215,217],{"class":185,"line":216},6,[183,218,219],{},"    comments TEXT,\n",[183,221,223],{"class":185,"line":222},7,[183,224,225],{},"    start_time TIMESTAMPTZ NOT NULL,\n",[183,227,229],{"class":185,"line":228},8,[183,230,231],{},"    end_time TIMESTAMPTZ,\n",[183,233,235],{"class":185,"line":234},9,[183,236,237],{},"    duration_seconds INTEGER,\n",[183,239,241],{"class":185,"line":240},10,[183,242,243],{},"    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n",[183,245,247],{"class":185,"line":246},11,[183,248,249],{},");\n",[112,251,252,255,258],{"start":198},[56,253,254],{},"Wire an inject node into the Query node. This is what triggers the query to run.",[56,256,257],{},"Add a debug node after the Query node. This lets you confirm the table was created successfully.",[56,259,260],{},"Click the inject node once, then check the debug sidebar. You should see a confirmation that the query ran.",[12,262,263],{},"Each row in this table represents one stoppage. Status tracks whether it's open or closed, reason and comments stay empty until an operator fills them in, and duration_seconds gets calculated the moment a stoppage closes.",[12,265,266],{},"With the table in place, the application has somewhere to write to. Next, we'll set up the event that opens a record the moment a machine stops.",[45,268,270],{"id":269},"capturing-stop-and-start-events","Capturing Stop and Start Events",[12,272,273],{},"With the table ready, the next step is getting machine events into it, using MQTT.",[12,275,276,277,281],{},"Note: this tutorial uses the FlowFuse ",[36,278,280],{"href":279},"\u002Fdocs\u002Fuser\u002Fteambroker\u002F","built in broker",", available to Pro and Enterprise tier teams on FlowFuse Cloud. If you're on a different tier, contact us to get access, or use your own broker with the standard MQTT nodes instead, they work the same way here.",[12,283,284,285,288,289,292],{},"The event names used here, ",[76,286,287],{},"downtime_started"," and ",[76,290,291],{},"downtime_ended",", are just an example. Your source may use different tags or a boolean instead of a string. What matters is the pattern, one signal opens a record and one closes it, so adjust to match your actual data.",[112,294,295],{},[56,296,297,298,301],{},"Add an ff-mqtt-in node to the canvas, name it \"Machine Events In\", and set the topic to ",[76,299,300],{},"factory\u002Fplant2\u002Fline1\u002F+\u002Fevents",", with QoS 0. Once you deploy this node, it will automatically pick up the connection and credentials for your team's broker, no config node needed.",[12,303,304,308],{},[24,305],{"alt":306,"src":307},"Screenshot: ff-mqtt-in node configuration panel with topic and QoS set","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fmachine-events.png",[29,309,310],{},"The Machine Events In node subscribed to the wildcard topic.",[112,312,313],{"start":192},[56,314,315],{},"Add a switch node checking payload.event, with two rules, downtime_started and downtime_ended.",[12,317,318,322],{},[24,319],{"alt":320,"src":321},"Screenshot: switch node with two rules routing on payload.event","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fswitch-to-route-events.png",[29,323,324],{},"Routing incoming events by type before they reach the database.",[112,326,327],{"start":198},[56,328,329,330,333,334,337,338,333,341,344],{},"For downtime_started, add a change node before the Query node with two rules: set ",[76,331,332],{},"queryParameters.machine_id"," to ",[76,335,336],{},"payload.machine_id"," (msg), and set ",[76,339,340],{},"queryParameters.timestamp",[76,342,343],{},"payload.timestamp"," (msg).",[12,346,347,351],{},[24,348],{"alt":349,"src":350},"Screenshot: change node rules mapping payload fields to queryParameters","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fprep-params.png",[29,352,353],{},"Both sides of each rule set to msg, this is the step most likely to get mistyped.",[112,355,356],{"start":204},[56,357,358],{},"Add the Query node itself:",[174,360,362],{"className":176,"code":361,"language":178,"meta":179,"style":179},"INSERT INTO downtime_events (machine_id, start_time)\nSELECT $machine_id, $timestamp\nWHERE NOT EXISTS (\n    SELECT 1 FROM downtime_events\n    WHERE machine_id = $machine_id AND status = 'Open'\n);\n",[76,363,364,369,374,379,384,389],{"__ignoreMap":179},[183,365,366],{"class":185,"line":186},[183,367,368],{},"INSERT INTO downtime_events (machine_id, start_time)\n",[183,370,371],{"class":185,"line":192},[183,372,373],{},"SELECT $machine_id, $timestamp\n",[183,375,376],{"class":185,"line":198},[183,377,378],{},"WHERE NOT EXISTS (\n",[183,380,381],{"class":185,"line":204},[183,382,383],{},"    SELECT 1 FROM downtime_events\n",[183,385,386],{"class":185,"line":210},[183,387,388],{},"    WHERE machine_id = $machine_id AND status = 'Open'\n",[183,390,391],{"class":185,"line":216},[183,392,249],{},[112,394,395],{"start":210},[56,396,397,398,288,400,402],{},"For downtime_ended, add the same kind of change node, ",[76,399,332],{},[76,401,340],{}," mapped the same way, then a separate Query node:",[174,404,406],{"className":176,"code":405,"language":178,"meta":179,"style":179},"UPDATE downtime_events\nSET status = 'Closed',\n    end_time = $timestamp,\n    duration_seconds = EXTRACT(EPOCH FROM ($timestamp::timestamptz - start_time))\nWHERE machine_id = $machine_id AND status = 'Open';\n",[76,407,408,413,418,423,428],{"__ignoreMap":179},[183,409,410],{"class":185,"line":186},[183,411,412],{},"UPDATE downtime_events\n",[183,414,415],{"class":185,"line":192},[183,416,417],{},"SET status = 'Closed',\n",[183,419,420],{"class":185,"line":198},[183,421,422],{},"    end_time = $timestamp,\n",[183,424,425],{"class":185,"line":204},[183,426,427],{},"    duration_seconds = EXTRACT(EPOCH FROM ($timestamp::timestamptz - start_time))\n",[183,429,430],{"class":185,"line":210},[183,431,432],{},"WHERE machine_id = $machine_id AND status = 'Open';\n",[12,434,435],{},"To test without hardware, import the following flow:",[437,438,440],"render-flow",{":height":439},"300",[174,441,445],{"className":442,"code":443,"language":444,"meta":179,"style":179},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[{\"id\":\"bfc643d98eb10bb6\",\"type\":\"group\",\"z\":\"454731c79b51b360\",\"style\":{\"stroke\":\"#b2b3bd\",\"stroke-opacity\":\"1\",\"fill\":\"#f2f3fb\",\"fill-opacity\":\"0.5\",\"label\":true,\"label-position\":\"nw\",\"color\":\"#32333b\"},\"nodes\":[\"4b50bf631b33bc25\",\"c5c148db3ebd75ec\",\"6e840436690af375\",\"94a7e426af3a534c\"],\"x\":214,\"y\":959,\"w\":752,\"h\":122},{\"id\":\"4b50bf631b33bc25\",\"type\":\"ff-mqtt-out\",\"z\":\"454731c79b51b360\",\"g\":\"bfc643d98eb10bb6\",\"name\":\"\",\"topic\":\"\",\"qos\":\"0\",\"retain\":\"false\",\"respTopic\":\"\",\"contentType\":\"\",\"userProps\":\"\",\"correl\":\"\",\"expiry\":\"\",\"lwt\":\"58936bbe1460d6be\",\"x\":870,\"y\":1020,\"wires\":[]},{\"id\":\"c5c148db3ebd75ec\",\"type\":\"inject\",\"z\":\"454731c79b51b360\",\"g\":\"bfc643d98eb10bb6\",\"name\":\"Simulate: Downtime Started\",\"props\":[{\"p\":\"payload.machine_id\",\"v\":\"Robot-01\",\"vt\":\"str\"},{\"p\":\"payload.event\",\"v\":\"downtime_started\",\"vt\":\"str\"}],\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"onceDelay\":0.1,\"topic\":\"\",\"x\":380,\"y\":1000,\"wires\":[[\"94a7e426af3a534c\"]]},{\"id\":\"6e840436690af375\",\"type\":\"inject\",\"z\":\"454731c79b51b360\",\"g\":\"bfc643d98eb10bb6\",\"name\":\"Simulate: Downtime Ended\",\"props\":[{\"p\":\"payload.machine_id\",\"v\":\"Robot-01\",\"vt\":\"str\"},{\"p\":\"payload.event\",\"v\":\"downtime_ended\",\"vt\":\"str\"}],\"repeat\":\"\",\"crontab\":\"\",\"once\":false,\"onceDelay\":0.1,\"topic\":\"\",\"x\":370,\"y\":1040,\"wires\":[[\"94a7e426af3a534c\"]]},{\"id\":\"94a7e426af3a534c\",\"type\":\"function\",\"z\":\"454731c79b51b360\",\"g\":\"bfc643d98eb10bb6\",\"name\":\"Build Event Payload\",\"func\":\"const p = msg.payload || {};\\n\\nconst machine_id = p.machine_id || \\\"unknown\\\";\\nconst event = p.event || \\\"unknown_event\\\";\\n\\nmsg.topic = `factory\u002Fplant2\u002Fline1\u002F${machine_id}\u002Fevents`;\\n\\nmsg.payload = {\\n    machine_id,\\n    event,\\n    timestamp: new Date().toISOString()\\n};\\n\\nreturn msg;\",\"outputs\":1,\"timeout\":0,\"noerr\":0,\"initialize\":\"\",\"finalize\":\"\",\"libs\":[],\"x\":660,\"y\":1020,\"wires\":[[\"4b50bf631b33bc25\"]]},{\"id\":\"58936bbe1460d6be\",\"type\":\"ff-mqtt-conf\",\"birthTopic\":\"\",\"birthQos\":\"0\",\"birthRetain\":\"false\",\"birthPayload\":\"\",\"birthMsg\":{},\"closeTopic\":\"\",\"closeQos\":\"0\",\"closeRetain\":\"false\",\"closePayload\":\"\",\"closeMsg\":{},\"willTopic\":\"\",\"willQos\":\"0\",\"willRetain\":\"false\",\"willPayload\":\"\",\"willMsg\":{}},{\"id\":\"8c6c2d9875462a7f\",\"type\":\"global-config\",\"env\":[],\"modules\":{\"@flowfuse\u002Fnr-mqtt-nodes\":\"0.3.0\"}}]\n","json",[76,446,447],{"__ignoreMap":179},[183,448,449,453,456,460,462,465,467,471,473,476,478,481,483,485,487,490,492,494,496,499,501,503,505,508,510,512,514,517,519,522,524,528,530,532,534,537,539,541,543,546,548,550,552,555,557,559,561,564,566,568,570,573,575,577,579,582,584,586,588,591,593,595,597,600,602,605,607,610,612,614,616,619,621,623,625,628,630,632,634,637,639,642,644,647,649,652,654,657,659,661,663,666,668,670,672,675,677,679,681,684,686,689,691,694,696,698,702,704,706,709,711,713,716,718,720,723,725,727,730,732,734,737,739,741,744,747,749,751,753,755,757,759,761,763,765,767,769,771,773,776,778,780,782,784,786,788,790,792,794,796,798,801,803,805,807,809,811,813,815,818,820,822,825,827,829,832,834,836,838,840,842,845,847,849,851,854,856,858,860,863,865,867,869,872,874,876,878,881,883,885,887,889,891,894,896,898,900,902,904,907,909,911,913,915,917,920,922,924,926,928,930,933,935,937,939,941,943,946,948,950,952,955,957,959,961,963,965,967,970,972,974,976,978,980,983,985,987,990,992,995,997,999,1001,1003,1005,1007,1009,1011,1013,1015,1017,1019,1021,1024,1026,1028,1030,1032,1034,1036,1038,1040,1042,1044,1046,1048,1050,1052,1054,1056,1058,1060,1062,1064,1066,1068,1070,1073,1075,1077,1079,1082,1084,1087,1089,1091,1093,1095,1097,1099,1101,1103,1105,1108,1110,1112,1114,1117,1119,1121,1123,1126,1128,1130,1132,1135,1137,1139,1141,1143,1145,1147,1149,1152,1154,1156,1158,1160,1162,1164,1166,1168,1170,1172,1174,1176,1178,1180,1182,1184,1186,1189,1191,1194,1196,1198,1200,1202,1204,1207,1209,1211,1213,1215,1217,1220,1222,1225,1227,1230,1232,1234,1237,1239,1241,1243,1245,1247,1249,1251,1253,1255,1257,1259,1262,1264,1266,1268,1270,1272,1275,1277,1279,1281,1283,1286,1288,1290,1292,1295,1297,1299,1301,1303,1305,1307,1309,1311,1313,1315,1317,1319,1321,1323,1325,1327,1329,1331,1333,1335,1337,1339,1341,1343,1345,1347,1349,1351,1353,1355,1357,1359,1361,1363,1365,1367,1369,1372,1374,1376,1378,1380,1382,1384,1386,1388,1390,1392,1394,1396,1398,1400,1402,1404,1406,1408,1410,1412,1414,1416,1418,1420,1422,1424,1426,1428,1430,1432,1434,1436,1438,1440,1442,1444,1446,1448,1450,1452,1454,1456,1458,1460,1462,1464,1466,1468,1470,1472,1474,1476,1478,1480,1482,1484,1486,1488,1490,1492,1494,1496,1498,1500,1502,1504,1506,1508,1510,1512,1514,1516,1518,1520,1522,1524,1526,1528,1530,1532,1534,1536,1538,1540,1542,1544,1547,1549,1551,1553,1555,1557,1560,1562,1564,1566,1568,1570,1572,1574,1576,1578,1580,1582,1584,1586,1588,1590,1592,1594,1596,1598,1600,1602,1604,1607,1609,1611,1613,1615,1617,1619,1621,1623,1625,1627,1629,1631,1633,1635,1637,1639,1641,1643,1645,1647,1649,1651,1653,1656,1658,1660,1662,1665,1667,1669,1671,1674,1678,1681,1684,1687,1689,1692,1695,1698,1700,1703,1705,1707,1709,1712,1714,1717,1719,1722,1724,1727,1729,1732,1734,1737,1739,1742,1744,1746,1748,1751,1753,1755,1757,1759,1761,1764,1766,1768,1770,1772,1774,1777,1779,1781,1783,1785,1787,1790,1792,1794,1796,1798,1800,1803,1805,1807,1809,1811,1813,1816,1818,1821,1823,1825,1827,1829,1832,1834,1836,1838,1840,1842,1844,1846,1848,1850,1852,1854,1856,1858,1860,1862,1864,1866,1868,1870,1872,1874,1876,1878,1880,1882,1884,1886,1888,1891,1893,1895,1897,1900,1902,1904,1906,1908,1910,1913,1915,1917,1919,1921,1923,1925,1927,1930,1932,1934,1936,1938,1940,1942,1944,1947,1949,1951,1953,1955,1957,1960,1962,1965,1967,1970,1972,1974,1976,1978,1980,1983,1985,1987,1989,1991,1993,1995,1997,2000,2002,2004,2006,2008,2010,2012,2014,2017,2019,2021,2023,2025,2027,2030,2032,2034,2036,2039,2041,2043,2045,2047,2049,2052,2054,2056,2058,2060,2062,2064,2066,2069,2071,2073,2075,2077,2079,2081,2083,2086,2088,2090,2092,2094,2096,2099,2101,2104,2106,2108,2110,2112,2114,2117,2119,2121,2123,2125,2127,2129,2131,2134,2136,2138,2140,2143,2145,2147,2149,2152,2154,2156,2158,2161,2163,2165,2167,2170,2172],{"class":185,"line":186},[183,450,452],{"class":451},"sMK4o","[{",[183,454,455],{"class":451},"\"",[183,457,459],{"class":458},"spNyl","id",[183,461,455],{"class":451},[183,463,464],{"class":451},":",[183,466,455],{"class":451},[183,468,470],{"class":469},"sfazB","bfc643d98eb10bb6",[183,472,455],{"class":451},[183,474,475],{"class":451},",",[183,477,455],{"class":451},[183,479,480],{"class":458},"type",[183,482,455],{"class":451},[183,484,464],{"class":451},[183,486,455],{"class":451},[183,488,489],{"class":469},"group",[183,491,455],{"class":451},[183,493,475],{"class":451},[183,495,455],{"class":451},[183,497,498],{"class":458},"z",[183,500,455],{"class":451},[183,502,464],{"class":451},[183,504,455],{"class":451},[183,506,507],{"class":469},"454731c79b51b360",[183,509,455],{"class":451},[183,511,475],{"class":451},[183,513,455],{"class":451},[183,515,516],{"class":458},"style",[183,518,455],{"class":451},[183,520,521],{"class":451},":{",[183,523,455],{"class":451},[183,525,527],{"class":526},"sBMFI","stroke",[183,529,455],{"class":451},[183,531,464],{"class":451},[183,533,455],{"class":451},[183,535,536],{"class":469},"#b2b3bd",[183,538,455],{"class":451},[183,540,475],{"class":451},[183,542,455],{"class":451},[183,544,545],{"class":526},"stroke-opacity",[183,547,455],{"class":451},[183,549,464],{"class":451},[183,551,455],{"class":451},[183,553,554],{"class":469},"1",[183,556,455],{"class":451},[183,558,475],{"class":451},[183,560,455],{"class":451},[183,562,563],{"class":526},"fill",[183,565,455],{"class":451},[183,567,464],{"class":451},[183,569,455],{"class":451},[183,571,572],{"class":469},"#f2f3fb",[183,574,455],{"class":451},[183,576,475],{"class":451},[183,578,455],{"class":451},[183,580,581],{"class":526},"fill-opacity",[183,583,455],{"class":451},[183,585,464],{"class":451},[183,587,455],{"class":451},[183,589,590],{"class":469},"0.5",[183,592,455],{"class":451},[183,594,475],{"class":451},[183,596,455],{"class":451},[183,598,599],{"class":526},"label",[183,601,455],{"class":451},[183,603,604],{"class":451},":true,",[183,606,455],{"class":451},[183,608,609],{"class":526},"label-position",[183,611,455],{"class":451},[183,613,464],{"class":451},[183,615,455],{"class":451},[183,617,618],{"class":469},"nw",[183,620,455],{"class":451},[183,622,475],{"class":451},[183,624,455],{"class":451},[183,626,627],{"class":526},"color",[183,629,455],{"class":451},[183,631,464],{"class":451},[183,633,455],{"class":451},[183,635,636],{"class":469},"#32333b",[183,638,455],{"class":451},[183,640,641],{"class":451},"},",[183,643,455],{"class":451},[183,645,646],{"class":458},"nodes",[183,648,455],{"class":451},[183,650,651],{"class":451},":[",[183,653,455],{"class":451},[183,655,656],{"class":469},"4b50bf631b33bc25",[183,658,455],{"class":451},[183,660,475],{"class":451},[183,662,455],{"class":451},[183,664,665],{"class":469},"c5c148db3ebd75ec",[183,667,455],{"class":451},[183,669,475],{"class":451},[183,671,455],{"class":451},[183,673,674],{"class":469},"6e840436690af375",[183,676,455],{"class":451},[183,678,475],{"class":451},[183,680,455],{"class":451},[183,682,683],{"class":469},"94a7e426af3a534c",[183,685,455],{"class":451},[183,687,688],{"class":451},"],",[183,690,455],{"class":451},[183,692,693],{"class":458},"x",[183,695,455],{"class":451},[183,697,464],{"class":451},[183,699,701],{"class":700},"sbssI","214",[183,703,475],{"class":451},[183,705,455],{"class":451},[183,707,708],{"class":458},"y",[183,710,455],{"class":451},[183,712,464],{"class":451},[183,714,715],{"class":700},"959",[183,717,475],{"class":451},[183,719,455],{"class":451},[183,721,722],{"class":458},"w",[183,724,455],{"class":451},[183,726,464],{"class":451},[183,728,729],{"class":700},"752",[183,731,475],{"class":451},[183,733,455],{"class":451},[183,735,736],{"class":458},"h",[183,738,455],{"class":451},[183,740,464],{"class":451},[183,742,743],{"class":700},"122",[183,745,746],{"class":451},"},{",[183,748,455],{"class":451},[183,750,459],{"class":458},[183,752,455],{"class":451},[183,754,464],{"class":451},[183,756,455],{"class":451},[183,758,656],{"class":469},[183,760,455],{"class":451},[183,762,475],{"class":451},[183,764,455],{"class":451},[183,766,480],{"class":458},[183,768,455],{"class":451},[183,770,464],{"class":451},[183,772,455],{"class":451},[183,774,775],{"class":469},"ff-mqtt-out",[183,777,455],{"class":451},[183,779,475],{"class":451},[183,781,455],{"class":451},[183,783,498],{"class":458},[183,785,455],{"class":451},[183,787,464],{"class":451},[183,789,455],{"class":451},[183,791,507],{"class":469},[183,793,455],{"class":451},[183,795,475],{"class":451},[183,797,455],{"class":451},[183,799,800],{"class":458},"g",[183,802,455],{"class":451},[183,804,464],{"class":451},[183,806,455],{"class":451},[183,808,470],{"class":469},[183,810,455],{"class":451},[183,812,475],{"class":451},[183,814,455],{"class":451},[183,816,817],{"class":458},"name",[183,819,455],{"class":451},[183,821,464],{"class":451},[183,823,824],{"class":451},"\"\"",[183,826,475],{"class":451},[183,828,455],{"class":451},[183,830,831],{"class":458},"topic",[183,833,455],{"class":451},[183,835,464],{"class":451},[183,837,824],{"class":451},[183,839,475],{"class":451},[183,841,455],{"class":451},[183,843,844],{"class":458},"qos",[183,846,455],{"class":451},[183,848,464],{"class":451},[183,850,455],{"class":451},[183,852,853],{"class":469},"0",[183,855,455],{"class":451},[183,857,475],{"class":451},[183,859,455],{"class":451},[183,861,862],{"class":458},"retain",[183,864,455],{"class":451},[183,866,464],{"class":451},[183,868,455],{"class":451},[183,870,871],{"class":469},"false",[183,873,455],{"class":451},[183,875,475],{"class":451},[183,877,455],{"class":451},[183,879,880],{"class":458},"respTopic",[183,882,455],{"class":451},[183,884,464],{"class":451},[183,886,824],{"class":451},[183,888,475],{"class":451},[183,890,455],{"class":451},[183,892,893],{"class":458},"contentType",[183,895,455],{"class":451},[183,897,464],{"class":451},[183,899,824],{"class":451},[183,901,475],{"class":451},[183,903,455],{"class":451},[183,905,906],{"class":458},"userProps",[183,908,455],{"class":451},[183,910,464],{"class":451},[183,912,824],{"class":451},[183,914,475],{"class":451},[183,916,455],{"class":451},[183,918,919],{"class":458},"correl",[183,921,455],{"class":451},[183,923,464],{"class":451},[183,925,824],{"class":451},[183,927,475],{"class":451},[183,929,455],{"class":451},[183,931,932],{"class":458},"expiry",[183,934,455],{"class":451},[183,936,464],{"class":451},[183,938,824],{"class":451},[183,940,475],{"class":451},[183,942,455],{"class":451},[183,944,945],{"class":458},"lwt",[183,947,455],{"class":451},[183,949,464],{"class":451},[183,951,455],{"class":451},[183,953,954],{"class":469},"58936bbe1460d6be",[183,956,455],{"class":451},[183,958,475],{"class":451},[183,960,455],{"class":451},[183,962,693],{"class":458},[183,964,455],{"class":451},[183,966,464],{"class":451},[183,968,969],{"class":700},"870",[183,971,475],{"class":451},[183,973,455],{"class":451},[183,975,708],{"class":458},[183,977,455],{"class":451},[183,979,464],{"class":451},[183,981,982],{"class":700},"1020",[183,984,475],{"class":451},[183,986,455],{"class":451},[183,988,989],{"class":458},"wires",[183,991,455],{"class":451},[183,993,994],{"class":451},":[]},{",[183,996,455],{"class":451},[183,998,459],{"class":458},[183,1000,455],{"class":451},[183,1002,464],{"class":451},[183,1004,455],{"class":451},[183,1006,665],{"class":469},[183,1008,455],{"class":451},[183,1010,475],{"class":451},[183,1012,455],{"class":451},[183,1014,480],{"class":458},[183,1016,455],{"class":451},[183,1018,464],{"class":451},[183,1020,455],{"class":451},[183,1022,1023],{"class":469},"inject",[183,1025,455],{"class":451},[183,1027,475],{"class":451},[183,1029,455],{"class":451},[183,1031,498],{"class":458},[183,1033,455],{"class":451},[183,1035,464],{"class":451},[183,1037,455],{"class":451},[183,1039,507],{"class":469},[183,1041,455],{"class":451},[183,1043,475],{"class":451},[183,1045,455],{"class":451},[183,1047,800],{"class":458},[183,1049,455],{"class":451},[183,1051,464],{"class":451},[183,1053,455],{"class":451},[183,1055,470],{"class":469},[183,1057,455],{"class":451},[183,1059,475],{"class":451},[183,1061,455],{"class":451},[183,1063,817],{"class":458},[183,1065,455],{"class":451},[183,1067,464],{"class":451},[183,1069,455],{"class":451},[183,1071,1072],{"class":469},"Simulate: Downtime Started",[183,1074,455],{"class":451},[183,1076,475],{"class":451},[183,1078,455],{"class":451},[183,1080,1081],{"class":458},"props",[183,1083,455],{"class":451},[183,1085,1086],{"class":451},":[{",[183,1088,455],{"class":451},[183,1090,12],{"class":526},[183,1092,455],{"class":451},[183,1094,464],{"class":451},[183,1096,455],{"class":451},[183,1098,336],{"class":469},[183,1100,455],{"class":451},[183,1102,475],{"class":451},[183,1104,455],{"class":451},[183,1106,1107],{"class":526},"v",[183,1109,455],{"class":451},[183,1111,464],{"class":451},[183,1113,455],{"class":451},[183,1115,1116],{"class":469},"Robot-01",[183,1118,455],{"class":451},[183,1120,475],{"class":451},[183,1122,455],{"class":451},[183,1124,1125],{"class":526},"vt",[183,1127,455],{"class":451},[183,1129,464],{"class":451},[183,1131,455],{"class":451},[183,1133,1134],{"class":469},"str",[183,1136,455],{"class":451},[183,1138,746],{"class":451},[183,1140,455],{"class":451},[183,1142,12],{"class":526},[183,1144,455],{"class":451},[183,1146,464],{"class":451},[183,1148,455],{"class":451},[183,1150,1151],{"class":469},"payload.event",[183,1153,455],{"class":451},[183,1155,475],{"class":451},[183,1157,455],{"class":451},[183,1159,1107],{"class":526},[183,1161,455],{"class":451},[183,1163,464],{"class":451},[183,1165,455],{"class":451},[183,1167,287],{"class":469},[183,1169,455],{"class":451},[183,1171,475],{"class":451},[183,1173,455],{"class":451},[183,1175,1125],{"class":526},[183,1177,455],{"class":451},[183,1179,464],{"class":451},[183,1181,455],{"class":451},[183,1183,1134],{"class":469},[183,1185,455],{"class":451},[183,1187,1188],{"class":451},"}],",[183,1190,455],{"class":451},[183,1192,1193],{"class":458},"repeat",[183,1195,455],{"class":451},[183,1197,464],{"class":451},[183,1199,824],{"class":451},[183,1201,475],{"class":451},[183,1203,455],{"class":451},[183,1205,1206],{"class":458},"crontab",[183,1208,455],{"class":451},[183,1210,464],{"class":451},[183,1212,824],{"class":451},[183,1214,475],{"class":451},[183,1216,455],{"class":451},[183,1218,1219],{"class":458},"once",[183,1221,455],{"class":451},[183,1223,1224],{"class":451},":false,",[183,1226,455],{"class":451},[183,1228,1229],{"class":458},"onceDelay",[183,1231,455],{"class":451},[183,1233,464],{"class":451},[183,1235,1236],{"class":700},"0.1",[183,1238,475],{"class":451},[183,1240,455],{"class":451},[183,1242,831],{"class":458},[183,1244,455],{"class":451},[183,1246,464],{"class":451},[183,1248,824],{"class":451},[183,1250,475],{"class":451},[183,1252,455],{"class":451},[183,1254,693],{"class":458},[183,1256,455],{"class":451},[183,1258,464],{"class":451},[183,1260,1261],{"class":700},"380",[183,1263,475],{"class":451},[183,1265,455],{"class":451},[183,1267,708],{"class":458},[183,1269,455],{"class":451},[183,1271,464],{"class":451},[183,1273,1274],{"class":700},"1000",[183,1276,475],{"class":451},[183,1278,455],{"class":451},[183,1280,989],{"class":458},[183,1282,455],{"class":451},[183,1284,1285],{"class":451},":[[",[183,1287,455],{"class":451},[183,1289,683],{"class":469},[183,1291,455],{"class":451},[183,1293,1294],{"class":451},"]]},{",[183,1296,455],{"class":451},[183,1298,459],{"class":458},[183,1300,455],{"class":451},[183,1302,464],{"class":451},[183,1304,455],{"class":451},[183,1306,674],{"class":469},[183,1308,455],{"class":451},[183,1310,475],{"class":451},[183,1312,455],{"class":451},[183,1314,480],{"class":458},[183,1316,455],{"class":451},[183,1318,464],{"class":451},[183,1320,455],{"class":451},[183,1322,1023],{"class":469},[183,1324,455],{"class":451},[183,1326,475],{"class":451},[183,1328,455],{"class":451},[183,1330,498],{"class":458},[183,1332,455],{"class":451},[183,1334,464],{"class":451},[183,1336,455],{"class":451},[183,1338,507],{"class":469},[183,1340,455],{"class":451},[183,1342,475],{"class":451},[183,1344,455],{"class":451},[183,1346,800],{"class":458},[183,1348,455],{"class":451},[183,1350,464],{"class":451},[183,1352,455],{"class":451},[183,1354,470],{"class":469},[183,1356,455],{"class":451},[183,1358,475],{"class":451},[183,1360,455],{"class":451},[183,1362,817],{"class":458},[183,1364,455],{"class":451},[183,1366,464],{"class":451},[183,1368,455],{"class":451},[183,1370,1371],{"class":469},"Simulate: Downtime Ended",[183,1373,455],{"class":451},[183,1375,475],{"class":451},[183,1377,455],{"class":451},[183,1379,1081],{"class":458},[183,1381,455],{"class":451},[183,1383,1086],{"class":451},[183,1385,455],{"class":451},[183,1387,12],{"class":526},[183,1389,455],{"class":451},[183,1391,464],{"class":451},[183,1393,455],{"class":451},[183,1395,336],{"class":469},[183,1397,455],{"class":451},[183,1399,475],{"class":451},[183,1401,455],{"class":451},[183,1403,1107],{"class":526},[183,1405,455],{"class":451},[183,1407,464],{"class":451},[183,1409,455],{"class":451},[183,1411,1116],{"class":469},[183,1413,455],{"class":451},[183,1415,475],{"class":451},[183,1417,455],{"class":451},[183,1419,1125],{"class":526},[183,1421,455],{"class":451},[183,1423,464],{"class":451},[183,1425,455],{"class":451},[183,1427,1134],{"class":469},[183,1429,455],{"class":451},[183,1431,746],{"class":451},[183,1433,455],{"class":451},[183,1435,12],{"class":526},[183,1437,455],{"class":451},[183,1439,464],{"class":451},[183,1441,455],{"class":451},[183,1443,1151],{"class":469},[183,1445,455],{"class":451},[183,1447,475],{"class":451},[183,1449,455],{"class":451},[183,1451,1107],{"class":526},[183,1453,455],{"class":451},[183,1455,464],{"class":451},[183,1457,455],{"class":451},[183,1459,291],{"class":469},[183,1461,455],{"class":451},[183,1463,475],{"class":451},[183,1465,455],{"class":451},[183,1467,1125],{"class":526},[183,1469,455],{"class":451},[183,1471,464],{"class":451},[183,1473,455],{"class":451},[183,1475,1134],{"class":469},[183,1477,455],{"class":451},[183,1479,1188],{"class":451},[183,1481,455],{"class":451},[183,1483,1193],{"class":458},[183,1485,455],{"class":451},[183,1487,464],{"class":451},[183,1489,824],{"class":451},[183,1491,475],{"class":451},[183,1493,455],{"class":451},[183,1495,1206],{"class":458},[183,1497,455],{"class":451},[183,1499,464],{"class":451},[183,1501,824],{"class":451},[183,1503,475],{"class":451},[183,1505,455],{"class":451},[183,1507,1219],{"class":458},[183,1509,455],{"class":451},[183,1511,1224],{"class":451},[183,1513,455],{"class":451},[183,1515,1229],{"class":458},[183,1517,455],{"class":451},[183,1519,464],{"class":451},[183,1521,1236],{"class":700},[183,1523,475],{"class":451},[183,1525,455],{"class":451},[183,1527,831],{"class":458},[183,1529,455],{"class":451},[183,1531,464],{"class":451},[183,1533,824],{"class":451},[183,1535,475],{"class":451},[183,1537,455],{"class":451},[183,1539,693],{"class":458},[183,1541,455],{"class":451},[183,1543,464],{"class":451},[183,1545,1546],{"class":700},"370",[183,1548,475],{"class":451},[183,1550,455],{"class":451},[183,1552,708],{"class":458},[183,1554,455],{"class":451},[183,1556,464],{"class":451},[183,1558,1559],{"class":700},"1040",[183,1561,475],{"class":451},[183,1563,455],{"class":451},[183,1565,989],{"class":458},[183,1567,455],{"class":451},[183,1569,1285],{"class":451},[183,1571,455],{"class":451},[183,1573,683],{"class":469},[183,1575,455],{"class":451},[183,1577,1294],{"class":451},[183,1579,455],{"class":451},[183,1581,459],{"class":458},[183,1583,455],{"class":451},[183,1585,464],{"class":451},[183,1587,455],{"class":451},[183,1589,683],{"class":469},[183,1591,455],{"class":451},[183,1593,475],{"class":451},[183,1595,455],{"class":451},[183,1597,480],{"class":458},[183,1599,455],{"class":451},[183,1601,464],{"class":451},[183,1603,455],{"class":451},[183,1605,1606],{"class":469},"function",[183,1608,455],{"class":451},[183,1610,475],{"class":451},[183,1612,455],{"class":451},[183,1614,498],{"class":458},[183,1616,455],{"class":451},[183,1618,464],{"class":451},[183,1620,455],{"class":451},[183,1622,507],{"class":469},[183,1624,455],{"class":451},[183,1626,475],{"class":451},[183,1628,455],{"class":451},[183,1630,800],{"class":458},[183,1632,455],{"class":451},[183,1634,464],{"class":451},[183,1636,455],{"class":451},[183,1638,470],{"class":469},[183,1640,455],{"class":451},[183,1642,475],{"class":451},[183,1644,455],{"class":451},[183,1646,817],{"class":458},[183,1648,455],{"class":451},[183,1650,464],{"class":451},[183,1652,455],{"class":451},[183,1654,1655],{"class":469},"Build Event Payload",[183,1657,455],{"class":451},[183,1659,475],{"class":451},[183,1661,455],{"class":451},[183,1663,1664],{"class":458},"func",[183,1666,455],{"class":451},[183,1668,464],{"class":451},[183,1670,455],{"class":451},[183,1672,1673],{"class":469},"const p = msg.payload || {};",[183,1675,1677],{"class":1676},"sTEyZ","\\n\\n",[183,1679,1680],{"class":469},"const machine_id = p.machine_id || ",[183,1682,1683],{"class":1676},"\\\"",[183,1685,1686],{"class":469},"unknown",[183,1688,1683],{"class":1676},[183,1690,1691],{"class":469},";",[183,1693,1694],{"class":1676},"\\n",[183,1696,1697],{"class":469},"const event = p.event || ",[183,1699,1683],{"class":1676},[183,1701,1702],{"class":469},"unknown_event",[183,1704,1683],{"class":1676},[183,1706,1691],{"class":469},[183,1708,1677],{"class":1676},[183,1710,1711],{"class":469},"msg.topic = `factory\u002Fplant2\u002Fline1\u002F${machine_id}\u002Fevents`;",[183,1713,1677],{"class":1676},[183,1715,1716],{"class":469},"msg.payload = {",[183,1718,1694],{"class":1676},[183,1720,1721],{"class":469},"    machine_id,",[183,1723,1694],{"class":1676},[183,1725,1726],{"class":469},"    event,",[183,1728,1694],{"class":1676},[183,1730,1731],{"class":469},"    timestamp: new Date().toISOString()",[183,1733,1694],{"class":1676},[183,1735,1736],{"class":469},"};",[183,1738,1677],{"class":1676},[183,1740,1741],{"class":469},"return msg;",[183,1743,455],{"class":451},[183,1745,475],{"class":451},[183,1747,455],{"class":451},[183,1749,1750],{"class":458},"outputs",[183,1752,455],{"class":451},[183,1754,464],{"class":451},[183,1756,554],{"class":700},[183,1758,475],{"class":451},[183,1760,455],{"class":451},[183,1762,1763],{"class":458},"timeout",[183,1765,455],{"class":451},[183,1767,464],{"class":451},[183,1769,853],{"class":700},[183,1771,475],{"class":451},[183,1773,455],{"class":451},[183,1775,1776],{"class":458},"noerr",[183,1778,455],{"class":451},[183,1780,464],{"class":451},[183,1782,853],{"class":700},[183,1784,475],{"class":451},[183,1786,455],{"class":451},[183,1788,1789],{"class":458},"initialize",[183,1791,455],{"class":451},[183,1793,464],{"class":451},[183,1795,824],{"class":451},[183,1797,475],{"class":451},[183,1799,455],{"class":451},[183,1801,1802],{"class":458},"finalize",[183,1804,455],{"class":451},[183,1806,464],{"class":451},[183,1808,824],{"class":451},[183,1810,475],{"class":451},[183,1812,455],{"class":451},[183,1814,1815],{"class":458},"libs",[183,1817,455],{"class":451},[183,1819,1820],{"class":451},":[],",[183,1822,455],{"class":451},[183,1824,693],{"class":458},[183,1826,455],{"class":451},[183,1828,464],{"class":451},[183,1830,1831],{"class":700},"660",[183,1833,475],{"class":451},[183,1835,455],{"class":451},[183,1837,708],{"class":458},[183,1839,455],{"class":451},[183,1841,464],{"class":451},[183,1843,982],{"class":700},[183,1845,475],{"class":451},[183,1847,455],{"class":451},[183,1849,989],{"class":458},[183,1851,455],{"class":451},[183,1853,1285],{"class":451},[183,1855,455],{"class":451},[183,1857,656],{"class":469},[183,1859,455],{"class":451},[183,1861,1294],{"class":451},[183,1863,455],{"class":451},[183,1865,459],{"class":458},[183,1867,455],{"class":451},[183,1869,464],{"class":451},[183,1871,455],{"class":451},[183,1873,954],{"class":469},[183,1875,455],{"class":451},[183,1877,475],{"class":451},[183,1879,455],{"class":451},[183,1881,480],{"class":458},[183,1883,455],{"class":451},[183,1885,464],{"class":451},[183,1887,455],{"class":451},[183,1889,1890],{"class":469},"ff-mqtt-conf",[183,1892,455],{"class":451},[183,1894,475],{"class":451},[183,1896,455],{"class":451},[183,1898,1899],{"class":458},"birthTopic",[183,1901,455],{"class":451},[183,1903,464],{"class":451},[183,1905,824],{"class":451},[183,1907,475],{"class":451},[183,1909,455],{"class":451},[183,1911,1912],{"class":458},"birthQos",[183,1914,455],{"class":451},[183,1916,464],{"class":451},[183,1918,455],{"class":451},[183,1920,853],{"class":469},[183,1922,455],{"class":451},[183,1924,475],{"class":451},[183,1926,455],{"class":451},[183,1928,1929],{"class":458},"birthRetain",[183,1931,455],{"class":451},[183,1933,464],{"class":451},[183,1935,455],{"class":451},[183,1937,871],{"class":469},[183,1939,455],{"class":451},[183,1941,475],{"class":451},[183,1943,455],{"class":451},[183,1945,1946],{"class":458},"birthPayload",[183,1948,455],{"class":451},[183,1950,464],{"class":451},[183,1952,824],{"class":451},[183,1954,475],{"class":451},[183,1956,455],{"class":451},[183,1958,1959],{"class":458},"birthMsg",[183,1961,455],{"class":451},[183,1963,1964],{"class":451},":{},",[183,1966,455],{"class":451},[183,1968,1969],{"class":458},"closeTopic",[183,1971,455],{"class":451},[183,1973,464],{"class":451},[183,1975,824],{"class":451},[183,1977,475],{"class":451},[183,1979,455],{"class":451},[183,1981,1982],{"class":458},"closeQos",[183,1984,455],{"class":451},[183,1986,464],{"class":451},[183,1988,455],{"class":451},[183,1990,853],{"class":469},[183,1992,455],{"class":451},[183,1994,475],{"class":451},[183,1996,455],{"class":451},[183,1998,1999],{"class":458},"closeRetain",[183,2001,455],{"class":451},[183,2003,464],{"class":451},[183,2005,455],{"class":451},[183,2007,871],{"class":469},[183,2009,455],{"class":451},[183,2011,475],{"class":451},[183,2013,455],{"class":451},[183,2015,2016],{"class":458},"closePayload",[183,2018,455],{"class":451},[183,2020,464],{"class":451},[183,2022,824],{"class":451},[183,2024,475],{"class":451},[183,2026,455],{"class":451},[183,2028,2029],{"class":458},"closeMsg",[183,2031,455],{"class":451},[183,2033,1964],{"class":451},[183,2035,455],{"class":451},[183,2037,2038],{"class":458},"willTopic",[183,2040,455],{"class":451},[183,2042,464],{"class":451},[183,2044,824],{"class":451},[183,2046,475],{"class":451},[183,2048,455],{"class":451},[183,2050,2051],{"class":458},"willQos",[183,2053,455],{"class":451},[183,2055,464],{"class":451},[183,2057,455],{"class":451},[183,2059,853],{"class":469},[183,2061,455],{"class":451},[183,2063,475],{"class":451},[183,2065,455],{"class":451},[183,2067,2068],{"class":458},"willRetain",[183,2070,455],{"class":451},[183,2072,464],{"class":451},[183,2074,455],{"class":451},[183,2076,871],{"class":469},[183,2078,455],{"class":451},[183,2080,475],{"class":451},[183,2082,455],{"class":451},[183,2084,2085],{"class":458},"willPayload",[183,2087,455],{"class":451},[183,2089,464],{"class":451},[183,2091,824],{"class":451},[183,2093,475],{"class":451},[183,2095,455],{"class":451},[183,2097,2098],{"class":458},"willMsg",[183,2100,455],{"class":451},[183,2102,2103],{"class":451},":{}},{",[183,2105,455],{"class":451},[183,2107,459],{"class":458},[183,2109,455],{"class":451},[183,2111,464],{"class":451},[183,2113,455],{"class":451},[183,2115,2116],{"class":469},"8c6c2d9875462a7f",[183,2118,455],{"class":451},[183,2120,475],{"class":451},[183,2122,455],{"class":451},[183,2124,480],{"class":458},[183,2126,455],{"class":451},[183,2128,464],{"class":451},[183,2130,455],{"class":451},[183,2132,2133],{"class":469},"global-config",[183,2135,455],{"class":451},[183,2137,475],{"class":451},[183,2139,455],{"class":451},[183,2141,2142],{"class":458},"env",[183,2144,455],{"class":451},[183,2146,1820],{"class":451},[183,2148,455],{"class":451},[183,2150,2151],{"class":458},"modules",[183,2153,455],{"class":451},[183,2155,521],{"class":451},[183,2157,455],{"class":451},[183,2159,2160],{"class":526},"@flowfuse\u002Fnr-mqtt-nodes",[183,2162,455],{"class":451},[183,2164,464],{"class":451},[183,2166,455],{"class":451},[183,2168,2169],{"class":469},"0.3.0",[183,2171,455],{"class":451},[183,2173,2174],{"class":451},"}}]\n",[12,2176,2177],{},"This gives you two buttons, one that simulates a machine stopping, one that simulates it starting again, wired through a function node that builds the topic and payload, then out over MQTT just like a real device would.",[12,2179,2180],{},"Deploy, click Simulate: Downtime Started, then check your table, a new open record should appear. Click Simulate: Downtime Ended and it should close with a duration.",[12,2182,2183],{},"Next, the dashboard table and the reason form operators use to close and explain a stoppage.",[45,2185,2187],{"id":2186},"building-the-dashboard-table-and-reason-form","Building the Dashboard Table and Reason Form",[12,2189,2190],{},"With events flowing into the database, the next step is showing them to the operator, and giving them a way to log why a machine stopped. Before starting, add a ui-page named \"Downtime Events\" and a ui-group named \"Stoppages\" on that page, this is where the table will live.",[112,2192,2193,2196,2199,2202],{},[56,2194,2195],{},"Go back to your event flow from the last section, after both Query nodes, downtime_started and downtime_ended, add a link out node. Give it a name like \"event processed\" so it's easy to find later.",[56,2197,2198],{},"In this new part of the flow, add a link in node and connect it to that same link out node. This is what lets the dashboard react any time a record opens or closes, without wiring long lines across the canvas.",[56,2200,2201],{},"There's one gap to close before moving on. The table only refreshes when an event comes in, so if a machine stays down for an hour with no new signal, \"Open For\" will sit frozen instead of counting up. Add an inject node set to repeat every 30 seconds, with its own link out wired to the same link in from step 2. This keeps the table and KPI cards refreshing on their own, even when nothing else is happening.",[56,2203,2204],{},"After the link in node, add a Query node that pulls every stoppage that's either still running or missing a reason. This is a triage table, so it only ever shows what still needs attention, once a stoppage is closed and explained, it drops off:",[174,2206,2208],{"className":176,"code":2207,"language":178,"meta":179,"style":179},"SELECT *,\n       EXTRACT(EPOCH FROM start_time) AS start_epoch,\n       TO_CHAR(start_time, 'DD Mon YYYY, HH12:MI AM') AS start_time_display,\n       COALESCE(TO_CHAR(end_time, 'DD Mon YYYY, HH12:MI AM'), '-') AS end_time_display,\n       COALESCE(reason, 'Not logged') AS reason_display,\n       CASE WHEN reason IS NULL THEN true ELSE false END AS needs_review\nFROM downtime_events\nWHERE status = 'Open' OR reason IS NULL\nORDER BY CASE WHEN status = 'Open' THEN 0 ELSE 1 END, start_time DESC;\n",[76,2209,2210,2215,2220,2225,2230,2235,2240,2245,2250],{"__ignoreMap":179},[183,2211,2212],{"class":185,"line":186},[183,2213,2214],{},"SELECT *,\n",[183,2216,2217],{"class":185,"line":192},[183,2218,2219],{},"       EXTRACT(EPOCH FROM start_time) AS start_epoch,\n",[183,2221,2222],{"class":185,"line":198},[183,2223,2224],{},"       TO_CHAR(start_time, 'DD Mon YYYY, HH12:MI AM') AS start_time_display,\n",[183,2226,2227],{"class":185,"line":204},[183,2228,2229],{},"       COALESCE(TO_CHAR(end_time, 'DD Mon YYYY, HH12:MI AM'), '-') AS end_time_display,\n",[183,2231,2232],{"class":185,"line":210},[183,2233,2234],{},"       COALESCE(reason, 'Not logged') AS reason_display,\n",[183,2236,2237],{"class":185,"line":216},[183,2238,2239],{},"       CASE WHEN reason IS NULL THEN true ELSE false END AS needs_review\n",[183,2241,2242],{"class":185,"line":222},[183,2243,2244],{},"FROM downtime_events\n",[183,2246,2247],{"class":185,"line":228},[183,2248,2249],{},"WHERE status = 'Open' OR reason IS NULL\n",[183,2251,2252],{"class":185,"line":234},[183,2253,2254],{},"ORDER BY CASE WHEN status = 'Open' THEN 0 ELSE 1 END, start_time DESC;\n",[12,2256,2257,2258,2261],{},"This formats the timestamps into something readable, like ",[76,2259,2260],{},"07 Jul 2026, 02:45 PM",", sorts open stoppages to the top, and falls back to a dash or \"Not logged\" instead of a blank cell wherever a value is missing.",[112,2263,2264,2267],{"start":210},[56,2265,2266],{},"Add a split node after it, to break the result set into individual rows so each one can be processed on its own.",[56,2268,2269,2270,2273],{},"Add a change node that computes how long each stoppage has been open, using JSONata. Set the rule to ",[76,2271,2272],{},"payload.elapsed_seconds",", type JSONata:",[174,2275,2280],{"className":2276,"code":2278,"language":2279},[2277],"language-text","$floor($millis() \u002F 1000 - $number(payload.start_epoch))\n","text",[76,2281,2278],{"__ignoreMap":179},[112,2283,2284,2287],{"start":222},[56,2285,2286],{},"Add a humanizer node after that, set to read from elapsed_seconds. This turns the raw number into something readable, like \"12 minutes\" instead of \"720\".",[56,2288,2289,2290,2293],{},"Add a function node named ",[59,2291,2292],{},"Colorize Duration",". This wraps the humanized value in a colored badge, so a stoppage that's dragged on stands out without anyone having to read the number:",[155,2295,2296],{},[12,2297,2298,2299,2303],{},"Tip: You don't have to write this JavaScript yourself. Use ",[36,2300,2302],{"href":2301},"\u002Fdocs\u002Fuser\u002Fexpert\u002Fnode-red-embedded-ai\u002F#function-code-generation","FlowFuse Expert"," and describe the logic in plain English. It will generate the code for you.",[174,2305,2309],{"className":2306,"code":2307,"language":2308,"meta":179,"style":179},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const seconds = msg.payload.elapsed_seconds || 0;\nlet color = \"green\";\n\nif (seconds >= 1800) {\n    color = \"red\";\n} else if (seconds >= 300) {\n    color = \"orange\";\n}\n\nmsg.payload.duration_html = `\u003Cspan style=\"background:${color}; color:white; padding:2px 8px; border-radius:4px;\">${msg.payload.humanized}\u003C\u002Fspan>`;\n\nreturn msg;\n","javascript",[76,2310,2311,2344,2364,2370,2391,2408,2430,2445,2450,2454,2509,2513],{"__ignoreMap":179},[183,2312,2313,2316,2319,2322,2325,2327,2330,2332,2335,2338,2341],{"class":185,"line":186},[183,2314,2315],{"class":458},"const",[183,2317,2318],{"class":1676}," seconds ",[183,2320,2321],{"class":451},"=",[183,2323,2324],{"class":1676}," msg",[183,2326,40],{"class":451},[183,2328,2329],{"class":1676},"payload",[183,2331,40],{"class":451},[183,2333,2334],{"class":1676},"elapsed_seconds ",[183,2336,2337],{"class":451},"||",[183,2339,2340],{"class":700}," 0",[183,2342,2343],{"class":451},";\n",[183,2345,2346,2349,2352,2354,2357,2360,2362],{"class":185,"line":192},[183,2347,2348],{"class":458},"let",[183,2350,2351],{"class":1676}," color ",[183,2353,2321],{"class":451},[183,2355,2356],{"class":451}," \"",[183,2358,2359],{"class":469},"green",[183,2361,455],{"class":451},[183,2363,2343],{"class":451},[183,2365,2366],{"class":185,"line":198},[183,2367,2369],{"emptyLinePlaceholder":2368},true,"\n",[183,2371,2372,2376,2379,2382,2385,2388],{"class":185,"line":204},[183,2373,2375],{"class":2374},"s7zQu","if",[183,2377,2378],{"class":1676}," (seconds ",[183,2380,2381],{"class":451},">=",[183,2383,2384],{"class":700}," 1800",[183,2386,2387],{"class":1676},") ",[183,2389,2390],{"class":451},"{\n",[183,2392,2393,2396,2399,2401,2404,2406],{"class":185,"line":210},[183,2394,2395],{"class":1676},"    color",[183,2397,2398],{"class":451}," =",[183,2400,2356],{"class":451},[183,2402,2403],{"class":469},"red",[183,2405,455],{"class":451},[183,2407,2343],{"class":451},[183,2409,2410,2413,2416,2419,2421,2423,2426,2428],{"class":185,"line":216},[183,2411,2412],{"class":451},"}",[183,2414,2415],{"class":2374}," else",[183,2417,2418],{"class":2374}," if",[183,2420,2378],{"class":1676},[183,2422,2381],{"class":451},[183,2424,2425],{"class":700}," 300",[183,2427,2387],{"class":1676},[183,2429,2390],{"class":451},[183,2431,2432,2434,2436,2438,2441,2443],{"class":185,"line":222},[183,2433,2395],{"class":1676},[183,2435,2398],{"class":451},[183,2437,2356],{"class":451},[183,2439,2440],{"class":469},"orange",[183,2442,455],{"class":451},[183,2444,2343],{"class":451},[183,2446,2447],{"class":185,"line":228},[183,2448,2449],{"class":451},"}\n",[183,2451,2452],{"class":185,"line":234},[183,2453,2369],{"emptyLinePlaceholder":2368},[183,2455,2456,2459,2461,2463,2465,2468,2470,2473,2476,2479,2481,2483,2486,2488,2490,2492,2494,2496,2499,2501,2504,2507],{"class":185,"line":240},[183,2457,2458],{"class":1676},"msg",[183,2460,40],{"class":451},[183,2462,2329],{"class":1676},[183,2464,40],{"class":451},[183,2466,2467],{"class":1676},"duration_html ",[183,2469,2321],{"class":451},[183,2471,2472],{"class":451}," `",[183,2474,2475],{"class":469},"\u003Cspan style=\"background:",[183,2477,2478],{"class":451},"${",[183,2480,627],{"class":1676},[183,2482,2412],{"class":451},[183,2484,2485],{"class":469},"; color:white; padding:2px 8px; border-radius:4px;\">",[183,2487,2478],{"class":451},[183,2489,2458],{"class":1676},[183,2491,40],{"class":451},[183,2493,2329],{"class":1676},[183,2495,40],{"class":451},[183,2497,2498],{"class":1676},"humanized",[183,2500,2412],{"class":451},[183,2502,2503],{"class":469},"\u003C\u002Fspan>",[183,2505,2506],{"class":451},"`",[183,2508,2343],{"class":451},[183,2510,2511],{"class":185,"line":246},[183,2512,2369],{"emptyLinePlaceholder":2368},[183,2514,2516,2519,2521],{"class":185,"line":2515},12,[183,2517,2518],{"class":2374},"return",[183,2520,2324],{"class":1676},[183,2522,2343],{"class":451},[12,2524,2525],{},"Under five minutes shows green, under thirty shows orange, anything longer shows red. Adjust the thresholds to whatever counts as concerning on your floor.",[112,2527,2528,2531],{"start":234},[56,2529,2530],{},"Add a join node set to rebuild the rows back into a single array, so the table gets the full list at once instead of one row at a time.",[56,2532,2533],{},"Add a ui-table node, assign it to the Stoppages group you created earlier, and wire it to the join node. Set up the following columns:",[53,2535,2536,2546,2554,2562,2571],{},[56,2537,2538,2541,2542,2545],{},[59,2539,2540],{},"Machine",", key ",[76,2543,2544],{},"machine_id",", type Text",[56,2547,2548,2541,2551,2545],{},[59,2549,2550],{},"Start Time",[76,2552,2553],{},"start_time_display",[56,2555,2556,2541,2559,2545],{},[59,2557,2558],{},"End Time",[76,2560,2561],{},"end_time_display",[56,2563,2564,2541,2567,2570],{},[59,2565,2566],{},"Open For",[76,2568,2569],{},"duration_html",", type HTML",[56,2572,2573],{},"a button column labeled something like \"Close & Log Reason\"",[12,2575,2576,2577,288,2580,2583],{},"The HTML type on Open For is what renders the colored badge instead of showing raw tags. The query also computes ",[76,2578,2579],{},"reason_display",[76,2581,2582],{},"needs_review",", these aren't shown as columns here, but stay available in the row data if you want to add them to the table later.",[12,2585,2586,2590],{},[24,2587],{"alt":2588,"src":2589},"Screenshot: ui-table node column configuration panel","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fui-table-stoppages.png",[29,2591,2592],{},"Column setup for the Stoppages table, including the HTML type on Open For.",[112,2594,2595],{"start":246},[56,2596,2597],{},"Wire the table's button output to a ui-template node. Leave its group field empty and set its page to the same \"Downtime Events\" page, since this needs to render as a popup dialog over the whole page, not sit inside the table's group. This is where the reason form lives, a small custom dialog with a dropdown for reason and a text field for optional comments, built with a bit of Vue, since there's no default form node for this exact popup-on-row-click pattern:",[155,2599,2600],{},[12,2601,2602,2603,2606],{},"Tip: You don't have to write the Vue code yourself. Use ",[36,2604,2302],{"href":2605},"\u002Fdocs\u002Fuser\u002Fexpert\u002Fnode-red-embedded-ai\u002F#css-and-html-generation-for-flowfuse-dashboard"," and describe the interface in plain English. It will generate the ui-template code for you.",[174,2608,2612],{"className":2609,"code":2610,"language":2611,"meta":179,"style":179},"language-html shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Ctemplate>\n  \u003Cv-dialog v-model=\"show\" max-width=\"420\">\n    \u003Cv-card prepend-icon=\"mdi-alert-circle-outline\" title=\"Record Downtime Reason\">\n      \u003Cv-card-subtitle>{{ machine_id }}, Stoppage #{{ id_value }}\u003C\u002Fv-card-subtitle>\n      \u003Cv-card-text>\n        \u003Cv-select v-model=\"reason\" :items=\"reasonOptions\" label=\"Reason*\" required>\u003C\u002Fv-select>\n        \u003Cv-textarea v-model=\"comments\" label=\"Comments (optional)\" rows=\"2\">\u003C\u002Fv-textarea>\n      \u003C\u002Fv-card-text>\n      \u003Cv-divider>\u003C\u002Fv-divider>\n      \u003Cv-card-actions>\n        \u003Cv-spacer>\u003C\u002Fv-spacer>\n        \u003Cv-btn text=\"Close\" variant=\"plain\" @click=\"handleClose\">\u003C\u002Fv-btn>\n        \u003Cv-btn color=\"primary\" text=\"Save\" variant=\"tonal\" :loading=\"submitting\" :disabled=\"!reason || !id_value || submitting\" @click=\"confirmSubmit\">\u003C\u002Fv-btn>\n      \u003C\u002Fv-card-actions>\n    \u003C\u002Fv-card>\n  \u003C\u002Fv-dialog>\n\u003C\u002Ftemplate>\n\n\u003Cscript>\nexport default {\n  data() {\n    return {\n      show: false,\n      id_value: null,\n      machine_id: '',\n      reason: null,\n      comments: '',\n      submitting: false,\n      reasonOptions: [\n        'Mechanical Failure',\n        'Electrical Fault',\n        'Material Shortage',\n        'Changeover',\n        'Operator Break',\n        'Quality Issue',\n        'Other'\n      ]\n    }\n  },\n  mounted() {\n    this.socketHandler = (msg) => {\n      if (msg?.payload?.id) {\n        this.id_value = msg.payload.id;\n        this.machine_id = msg.payload.machine_id;\n        this.reason = null;\n        this.comments = '';\n        this.submitting = false;\n        this.show = true;\n      }\n    };\n    this.$socket.on('msg-input:' + this.id, this.socketHandler);\n  },\n  beforeUnmount() {\n    this.$socket.off('msg-input:' + this.id, this.socketHandler);\n  },\n  methods: {\n    handleClose() {\n      if (this.reason || this.comments) {\n        if (!confirm('Discard the reason you entered?')) return;\n      }\n      this.show = false;\n    },\n    confirmSubmit() {\n      if (!confirm(`Close this stoppage on ${this.machine_id} with reason \"${this.reason}\"?`)) return;\n      this.submitReason();\n    },\n    submitReason() {\n      if (!this.id_value || this.submitting) return;\n      this.submitting = true;\n      this.send({\n        payload: {\n          id: this.id_value,\n          reason: this.reason,\n          comments: this.comments\n        }\n      });\n      this.show = false;\n    }\n  }\n}\n\u003C\u002Fscript>\n","html",[76,2613,2614,2626,2660,2694,2715,2724,2777,2824,2833,2846,2855,2868,2917,2999,3008,3018,3028,3037,3042,3052,3064,3075,3083,3098,3109,3122,3132,3144,3156,3167,3181,3193,3205,3217,3229,3241,3252,3258,3264,3270,3280,3306,3329,3352,3373,3385,3398,3411,3425,3431,3437,3478,3483,3493,3529,3534,3544,3554,3577,3607,3612,3626,3632,3642,3690,3702,3707,3717,3741,3754,3766,3776,3790,3804,3817,3823,3833,3846,3851,3857,3862],{"__ignoreMap":179},[183,2615,2616,2619,2623],{"class":185,"line":186},[183,2617,2618],{"class":451},"\u003C",[183,2620,2622],{"class":2621},"swJcz","template",[183,2624,2625],{"class":451},">\n",[183,2627,2628,2631,2634,2637,2639,2641,2644,2646,2649,2651,2653,2656,2658],{"class":185,"line":192},[183,2629,2630],{"class":451},"  \u003C",[183,2632,2633],{"class":2621},"v-dialog",[183,2635,2636],{"class":458}," v-model",[183,2638,2321],{"class":451},[183,2640,455],{"class":451},[183,2642,2643],{"class":469},"show",[183,2645,455],{"class":451},[183,2647,2648],{"class":458}," max-width",[183,2650,2321],{"class":451},[183,2652,455],{"class":451},[183,2654,2655],{"class":469},"420",[183,2657,455],{"class":451},[183,2659,2625],{"class":451},[183,2661,2662,2665,2668,2671,2673,2675,2678,2680,2683,2685,2687,2690,2692],{"class":185,"line":198},[183,2663,2664],{"class":451},"    \u003C",[183,2666,2667],{"class":2621},"v-card",[183,2669,2670],{"class":458}," prepend-icon",[183,2672,2321],{"class":451},[183,2674,455],{"class":451},[183,2676,2677],{"class":469},"mdi-alert-circle-outline",[183,2679,455],{"class":451},[183,2681,2682],{"class":458}," title",[183,2684,2321],{"class":451},[183,2686,455],{"class":451},[183,2688,2689],{"class":469},"Record Downtime Reason",[183,2691,455],{"class":451},[183,2693,2625],{"class":451},[183,2695,2696,2699,2702,2705,2708,2711,2713],{"class":185,"line":204},[183,2697,2698],{"class":451},"      \u003C",[183,2700,2701],{"class":2621},"v-card-subtitle",[183,2703,2704],{"class":451},">",[183,2706,2707],{"class":1676},"{{ machine_id }}, Stoppage #{{ id_value }}",[183,2709,2710],{"class":451},"\u003C\u002F",[183,2712,2701],{"class":2621},[183,2714,2625],{"class":451},[183,2716,2717,2719,2722],{"class":185,"line":210},[183,2718,2698],{"class":451},[183,2720,2721],{"class":2621},"v-card-text",[183,2723,2625],{"class":451},[183,2725,2726,2729,2732,2734,2736,2738,2741,2743,2746,2748,2750,2753,2755,2758,2760,2762,2765,2767,2770,2773,2775],{"class":185,"line":216},[183,2727,2728],{"class":451},"        \u003C",[183,2730,2731],{"class":2621},"v-select",[183,2733,2636],{"class":458},[183,2735,2321],{"class":451},[183,2737,455],{"class":451},[183,2739,2740],{"class":469},"reason",[183,2742,455],{"class":451},[183,2744,2745],{"class":458}," :items",[183,2747,2321],{"class":451},[183,2749,455],{"class":451},[183,2751,2752],{"class":469},"reasonOptions",[183,2754,455],{"class":451},[183,2756,2757],{"class":458}," label",[183,2759,2321],{"class":451},[183,2761,455],{"class":451},[183,2763,2764],{"class":469},"Reason*",[183,2766,455],{"class":451},[183,2768,2769],{"class":458}," required",[183,2771,2772],{"class":451},">\u003C\u002F",[183,2774,2731],{"class":2621},[183,2776,2625],{"class":451},[183,2778,2779,2781,2784,2786,2788,2790,2793,2795,2797,2799,2801,2804,2806,2809,2811,2813,2816,2818,2820,2822],{"class":185,"line":222},[183,2780,2728],{"class":451},[183,2782,2783],{"class":2621},"v-textarea",[183,2785,2636],{"class":458},[183,2787,2321],{"class":451},[183,2789,455],{"class":451},[183,2791,2792],{"class":469},"comments",[183,2794,455],{"class":451},[183,2796,2757],{"class":458},[183,2798,2321],{"class":451},[183,2800,455],{"class":451},[183,2802,2803],{"class":469},"Comments (optional)",[183,2805,455],{"class":451},[183,2807,2808],{"class":458}," rows",[183,2810,2321],{"class":451},[183,2812,455],{"class":451},[183,2814,2815],{"class":469},"2",[183,2817,455],{"class":451},[183,2819,2772],{"class":451},[183,2821,2783],{"class":2621},[183,2823,2625],{"class":451},[183,2825,2826,2829,2831],{"class":185,"line":228},[183,2827,2828],{"class":451},"      \u003C\u002F",[183,2830,2721],{"class":2621},[183,2832,2625],{"class":451},[183,2834,2835,2837,2840,2842,2844],{"class":185,"line":234},[183,2836,2698],{"class":451},[183,2838,2839],{"class":2621},"v-divider",[183,2841,2772],{"class":451},[183,2843,2839],{"class":2621},[183,2845,2625],{"class":451},[183,2847,2848,2850,2853],{"class":185,"line":240},[183,2849,2698],{"class":451},[183,2851,2852],{"class":2621},"v-card-actions",[183,2854,2625],{"class":451},[183,2856,2857,2859,2862,2864,2866],{"class":185,"line":246},[183,2858,2728],{"class":451},[183,2860,2861],{"class":2621},"v-spacer",[183,2863,2772],{"class":451},[183,2865,2861],{"class":2621},[183,2867,2625],{"class":451},[183,2869,2870,2872,2875,2878,2880,2882,2885,2887,2890,2892,2894,2897,2899,2902,2904,2906,2909,2911,2913,2915],{"class":185,"line":2515},[183,2871,2728],{"class":451},[183,2873,2874],{"class":2621},"v-btn",[183,2876,2877],{"class":458}," text",[183,2879,2321],{"class":451},[183,2881,455],{"class":451},[183,2883,2884],{"class":469},"Close",[183,2886,455],{"class":451},[183,2888,2889],{"class":458}," variant",[183,2891,2321],{"class":451},[183,2893,455],{"class":451},[183,2895,2896],{"class":469},"plain",[183,2898,455],{"class":451},[183,2900,2901],{"class":458}," @click",[183,2903,2321],{"class":451},[183,2905,455],{"class":451},[183,2907,2908],{"class":469},"handleClose",[183,2910,455],{"class":451},[183,2912,2772],{"class":451},[183,2914,2874],{"class":2621},[183,2916,2625],{"class":451},[183,2918,2920,2922,2924,2927,2929,2931,2934,2936,2938,2940,2942,2945,2947,2949,2951,2953,2956,2958,2961,2963,2965,2968,2970,2973,2975,2977,2980,2982,2984,2986,2988,2991,2993,2995,2997],{"class":185,"line":2919},13,[183,2921,2728],{"class":451},[183,2923,2874],{"class":2621},[183,2925,2926],{"class":458}," color",[183,2928,2321],{"class":451},[183,2930,455],{"class":451},[183,2932,2933],{"class":469},"primary",[183,2935,455],{"class":451},[183,2937,2877],{"class":458},[183,2939,2321],{"class":451},[183,2941,455],{"class":451},[183,2943,2944],{"class":469},"Save",[183,2946,455],{"class":451},[183,2948,2889],{"class":458},[183,2950,2321],{"class":451},[183,2952,455],{"class":451},[183,2954,2955],{"class":469},"tonal",[183,2957,455],{"class":451},[183,2959,2960],{"class":458}," :loading",[183,2962,2321],{"class":451},[183,2964,455],{"class":451},[183,2966,2967],{"class":469},"submitting",[183,2969,455],{"class":451},[183,2971,2972],{"class":458}," :disabled",[183,2974,2321],{"class":451},[183,2976,455],{"class":451},[183,2978,2979],{"class":469},"!reason || !id_value || submitting",[183,2981,455],{"class":451},[183,2983,2901],{"class":458},[183,2985,2321],{"class":451},[183,2987,455],{"class":451},[183,2989,2990],{"class":469},"confirmSubmit",[183,2992,455],{"class":451},[183,2994,2772],{"class":451},[183,2996,2874],{"class":2621},[183,2998,2625],{"class":451},[183,3000,3002,3004,3006],{"class":185,"line":3001},14,[183,3003,2828],{"class":451},[183,3005,2852],{"class":2621},[183,3007,2625],{"class":451},[183,3009,3011,3014,3016],{"class":185,"line":3010},15,[183,3012,3013],{"class":451},"    \u003C\u002F",[183,3015,2667],{"class":2621},[183,3017,2625],{"class":451},[183,3019,3021,3024,3026],{"class":185,"line":3020},16,[183,3022,3023],{"class":451},"  \u003C\u002F",[183,3025,2633],{"class":2621},[183,3027,2625],{"class":451},[183,3029,3031,3033,3035],{"class":185,"line":3030},17,[183,3032,2710],{"class":451},[183,3034,2622],{"class":2621},[183,3036,2625],{"class":451},[183,3038,3040],{"class":185,"line":3039},18,[183,3041,2369],{"emptyLinePlaceholder":2368},[183,3043,3045,3047,3050],{"class":185,"line":3044},19,[183,3046,2618],{"class":451},[183,3048,3049],{"class":2621},"script",[183,3051,2625],{"class":451},[183,3053,3055,3058,3061],{"class":185,"line":3054},20,[183,3056,3057],{"class":2374},"export",[183,3059,3060],{"class":2374}," default",[183,3062,3063],{"class":451}," {\n",[183,3065,3067,3070,3073],{"class":185,"line":3066},21,[183,3068,3069],{"class":2621},"  data",[183,3071,3072],{"class":451},"()",[183,3074,3063],{"class":451},[183,3076,3078,3081],{"class":185,"line":3077},22,[183,3079,3080],{"class":2374},"    return",[183,3082,3063],{"class":451},[183,3084,3086,3089,3091,3095],{"class":185,"line":3085},23,[183,3087,3088],{"class":2621},"      show",[183,3090,464],{"class":451},[183,3092,3094],{"class":3093},"sfNiH"," false",[183,3096,3097],{"class":451},",\n",[183,3099,3101,3104,3106],{"class":185,"line":3100},24,[183,3102,3103],{"class":2621},"      id_value",[183,3105,464],{"class":451},[183,3107,3108],{"class":451}," null,\n",[183,3110,3112,3115,3117,3120],{"class":185,"line":3111},25,[183,3113,3114],{"class":2621},"      machine_id",[183,3116,464],{"class":451},[183,3118,3119],{"class":451}," ''",[183,3121,3097],{"class":451},[183,3123,3125,3128,3130],{"class":185,"line":3124},26,[183,3126,3127],{"class":2621},"      reason",[183,3129,464],{"class":451},[183,3131,3108],{"class":451},[183,3133,3135,3138,3140,3142],{"class":185,"line":3134},27,[183,3136,3137],{"class":2621},"      comments",[183,3139,464],{"class":451},[183,3141,3119],{"class":451},[183,3143,3097],{"class":451},[183,3145,3147,3150,3152,3154],{"class":185,"line":3146},28,[183,3148,3149],{"class":2621},"      submitting",[183,3151,464],{"class":451},[183,3153,3094],{"class":3093},[183,3155,3097],{"class":451},[183,3157,3159,3162,3164],{"class":185,"line":3158},29,[183,3160,3161],{"class":2621},"      reasonOptions",[183,3163,464],{"class":451},[183,3165,3166],{"class":2621}," [\n",[183,3168,3170,3173,3176,3179],{"class":185,"line":3169},30,[183,3171,3172],{"class":451},"        '",[183,3174,3175],{"class":469},"Mechanical Failure",[183,3177,3178],{"class":451},"'",[183,3180,3097],{"class":451},[183,3182,3184,3186,3189,3191],{"class":185,"line":3183},31,[183,3185,3172],{"class":451},[183,3187,3188],{"class":469},"Electrical Fault",[183,3190,3178],{"class":451},[183,3192,3097],{"class":451},[183,3194,3196,3198,3201,3203],{"class":185,"line":3195},32,[183,3197,3172],{"class":451},[183,3199,3200],{"class":469},"Material Shortage",[183,3202,3178],{"class":451},[183,3204,3097],{"class":451},[183,3206,3208,3210,3213,3215],{"class":185,"line":3207},33,[183,3209,3172],{"class":451},[183,3211,3212],{"class":469},"Changeover",[183,3214,3178],{"class":451},[183,3216,3097],{"class":451},[183,3218,3220,3222,3225,3227],{"class":185,"line":3219},34,[183,3221,3172],{"class":451},[183,3223,3224],{"class":469},"Operator Break",[183,3226,3178],{"class":451},[183,3228,3097],{"class":451},[183,3230,3232,3234,3237,3239],{"class":185,"line":3231},35,[183,3233,3172],{"class":451},[183,3235,3236],{"class":469},"Quality Issue",[183,3238,3178],{"class":451},[183,3240,3097],{"class":451},[183,3242,3244,3246,3249],{"class":185,"line":3243},36,[183,3245,3172],{"class":451},[183,3247,3248],{"class":469},"Other",[183,3250,3251],{"class":451},"'\n",[183,3253,3255],{"class":185,"line":3254},37,[183,3256,3257],{"class":2621},"      ]\n",[183,3259,3261],{"class":185,"line":3260},38,[183,3262,3263],{"class":451},"    }\n",[183,3265,3267],{"class":185,"line":3266},39,[183,3268,3269],{"class":451},"  },\n",[183,3271,3273,3276,3278],{"class":185,"line":3272},40,[183,3274,3275],{"class":2621},"  mounted",[183,3277,3072],{"class":451},[183,3279,3063],{"class":451},[183,3281,3283,3286,3290,3292,3295,3298,3301,3304],{"class":185,"line":3282},41,[183,3284,3285],{"class":451},"    this.",[183,3287,3289],{"class":3288},"s2Zo4","socketHandler",[183,3291,2398],{"class":451},[183,3293,3294],{"class":451}," (",[183,3296,2458],{"class":3297},"sHdIc",[183,3299,3300],{"class":451},")",[183,3302,3303],{"class":458}," =>",[183,3305,3063],{"class":451},[183,3307,3309,3312,3314,3316,3319,3321,3323,3325,3327],{"class":185,"line":3308},42,[183,3310,3311],{"class":2374},"      if",[183,3313,3294],{"class":2621},[183,3315,2458],{"class":1676},[183,3317,3318],{"class":451},"?.",[183,3320,2329],{"class":1676},[183,3322,3318],{"class":451},[183,3324,459],{"class":1676},[183,3326,2387],{"class":2621},[183,3328,2390],{"class":451},[183,3330,3332,3335,3338,3340,3342,3344,3346,3348,3350],{"class":185,"line":3331},43,[183,3333,3334],{"class":451},"        this.",[183,3336,3337],{"class":1676},"id_value",[183,3339,2398],{"class":451},[183,3341,2324],{"class":1676},[183,3343,40],{"class":451},[183,3345,2329],{"class":1676},[183,3347,40],{"class":451},[183,3349,459],{"class":1676},[183,3351,2343],{"class":451},[183,3353,3355,3357,3359,3361,3363,3365,3367,3369,3371],{"class":185,"line":3354},44,[183,3356,3334],{"class":451},[183,3358,2544],{"class":1676},[183,3360,2398],{"class":451},[183,3362,2324],{"class":1676},[183,3364,40],{"class":451},[183,3366,2329],{"class":1676},[183,3368,40],{"class":451},[183,3370,2544],{"class":1676},[183,3372,2343],{"class":451},[183,3374,3376,3378,3380,3382],{"class":185,"line":3375},45,[183,3377,3334],{"class":451},[183,3379,2740],{"class":1676},[183,3381,2398],{"class":451},[183,3383,3384],{"class":451}," null;\n",[183,3386,3388,3390,3392,3394,3396],{"class":185,"line":3387},46,[183,3389,3334],{"class":451},[183,3391,2792],{"class":1676},[183,3393,2398],{"class":451},[183,3395,3119],{"class":451},[183,3397,2343],{"class":451},[183,3399,3401,3403,3405,3407,3409],{"class":185,"line":3400},47,[183,3402,3334],{"class":451},[183,3404,2967],{"class":1676},[183,3406,2398],{"class":451},[183,3408,3094],{"class":3093},[183,3410,2343],{"class":451},[183,3412,3414,3416,3418,3420,3423],{"class":185,"line":3413},48,[183,3415,3334],{"class":451},[183,3417,2643],{"class":1676},[183,3419,2398],{"class":451},[183,3421,3422],{"class":3093}," true",[183,3424,2343],{"class":451},[183,3426,3428],{"class":185,"line":3427},49,[183,3429,3430],{"class":451},"      }\n",[183,3432,3434],{"class":185,"line":3433},50,[183,3435,3436],{"class":451},"    };\n",[183,3438,3440,3442,3445,3447,3450,3453,3455,3458,3460,3463,3466,3468,3470,3472,3474,3476],{"class":185,"line":3439},51,[183,3441,3285],{"class":451},[183,3443,3444],{"class":1676},"$socket",[183,3446,40],{"class":451},[183,3448,3449],{"class":3288},"on",[183,3451,3452],{"class":2621},"(",[183,3454,3178],{"class":451},[183,3456,3457],{"class":469},"msg-input:",[183,3459,3178],{"class":451},[183,3461,3462],{"class":451}," +",[183,3464,3465],{"class":451}," this.",[183,3467,459],{"class":1676},[183,3469,475],{"class":451},[183,3471,3465],{"class":451},[183,3473,3289],{"class":1676},[183,3475,3300],{"class":2621},[183,3477,2343],{"class":451},[183,3479,3481],{"class":185,"line":3480},52,[183,3482,3269],{"class":451},[183,3484,3486,3489,3491],{"class":185,"line":3485},53,[183,3487,3488],{"class":2621},"  beforeUnmount",[183,3490,3072],{"class":451},[183,3492,3063],{"class":451},[183,3494,3496,3498,3500,3502,3505,3507,3509,3511,3513,3515,3517,3519,3521,3523,3525,3527],{"class":185,"line":3495},54,[183,3497,3285],{"class":451},[183,3499,3444],{"class":1676},[183,3501,40],{"class":451},[183,3503,3504],{"class":3288},"off",[183,3506,3452],{"class":2621},[183,3508,3178],{"class":451},[183,3510,3457],{"class":469},[183,3512,3178],{"class":451},[183,3514,3462],{"class":451},[183,3516,3465],{"class":451},[183,3518,459],{"class":1676},[183,3520,475],{"class":451},[183,3522,3465],{"class":451},[183,3524,3289],{"class":1676},[183,3526,3300],{"class":2621},[183,3528,2343],{"class":451},[183,3530,3532],{"class":185,"line":3531},55,[183,3533,3269],{"class":451},[183,3535,3537,3540,3542],{"class":185,"line":3536},56,[183,3538,3539],{"class":2621},"  methods",[183,3541,464],{"class":451},[183,3543,3063],{"class":451},[183,3545,3547,3550,3552],{"class":185,"line":3546},57,[183,3548,3549],{"class":2621},"    handleClose",[183,3551,3072],{"class":451},[183,3553,3063],{"class":451},[183,3555,3557,3559,3561,3564,3566,3569,3571,3573,3575],{"class":185,"line":3556},58,[183,3558,3311],{"class":2374},[183,3560,3294],{"class":2621},[183,3562,3563],{"class":451},"this.",[183,3565,2740],{"class":1676},[183,3567,3568],{"class":451}," ||",[183,3570,3465],{"class":451},[183,3572,2792],{"class":1676},[183,3574,2387],{"class":2621},[183,3576,2390],{"class":451},[183,3578,3580,3583,3585,3588,3591,3593,3595,3598,3600,3603,3605],{"class":185,"line":3579},59,[183,3581,3582],{"class":2374},"        if",[183,3584,3294],{"class":2621},[183,3586,3587],{"class":451},"!",[183,3589,3590],{"class":3288},"confirm",[183,3592,3452],{"class":2621},[183,3594,3178],{"class":451},[183,3596,3597],{"class":469},"Discard the reason you entered?",[183,3599,3178],{"class":451},[183,3601,3602],{"class":2621},")) ",[183,3604,2518],{"class":2374},[183,3606,2343],{"class":451},[183,3608,3610],{"class":185,"line":3609},60,[183,3611,3430],{"class":451},[183,3613,3615,3618,3620,3622,3624],{"class":185,"line":3614},61,[183,3616,3617],{"class":451},"      this.",[183,3619,2643],{"class":1676},[183,3621,2398],{"class":451},[183,3623,3094],{"class":3093},[183,3625,2343],{"class":451},[183,3627,3629],{"class":185,"line":3628},62,[183,3630,3631],{"class":451},"    },\n",[183,3633,3635,3638,3640],{"class":185,"line":3634},63,[183,3636,3637],{"class":2621},"    confirmSubmit",[183,3639,3072],{"class":451},[183,3641,3063],{"class":451},[183,3643,3645,3647,3649,3651,3653,3655,3657,3660,3662,3664,3666,3668,3671,3673,3675,3677,3679,3682,3684,3686,3688],{"class":185,"line":3644},64,[183,3646,3311],{"class":2374},[183,3648,3294],{"class":2621},[183,3650,3587],{"class":451},[183,3652,3590],{"class":3288},[183,3654,3452],{"class":2621},[183,3656,2506],{"class":451},[183,3658,3659],{"class":469},"Close this stoppage on ",[183,3661,2478],{"class":451},[183,3663,3563],{"class":451},[183,3665,2544],{"class":1676},[183,3667,2412],{"class":451},[183,3669,3670],{"class":469}," with reason \"",[183,3672,2478],{"class":451},[183,3674,3563],{"class":451},[183,3676,2740],{"class":1676},[183,3678,2412],{"class":451},[183,3680,3681],{"class":469},"\"?",[183,3683,2506],{"class":451},[183,3685,3602],{"class":2621},[183,3687,2518],{"class":2374},[183,3689,2343],{"class":451},[183,3691,3693,3695,3698,3700],{"class":185,"line":3692},65,[183,3694,3617],{"class":451},[183,3696,3697],{"class":3288},"submitReason",[183,3699,3072],{"class":2621},[183,3701,2343],{"class":451},[183,3703,3705],{"class":185,"line":3704},66,[183,3706,3631],{"class":451},[183,3708,3710,3713,3715],{"class":185,"line":3709},67,[183,3711,3712],{"class":2621},"    submitReason",[183,3714,3072],{"class":451},[183,3716,3063],{"class":451},[183,3718,3720,3722,3724,3727,3729,3731,3733,3735,3737,3739],{"class":185,"line":3719},68,[183,3721,3311],{"class":2374},[183,3723,3294],{"class":2621},[183,3725,3726],{"class":451},"!this.",[183,3728,3337],{"class":1676},[183,3730,3568],{"class":451},[183,3732,3465],{"class":451},[183,3734,2967],{"class":1676},[183,3736,2387],{"class":2621},[183,3738,2518],{"class":2374},[183,3740,2343],{"class":451},[183,3742,3744,3746,3748,3750,3752],{"class":185,"line":3743},69,[183,3745,3617],{"class":451},[183,3747,2967],{"class":1676},[183,3749,2398],{"class":451},[183,3751,3422],{"class":3093},[183,3753,2343],{"class":451},[183,3755,3757,3759,3762,3764],{"class":185,"line":3756},70,[183,3758,3617],{"class":451},[183,3760,3761],{"class":3288},"send",[183,3763,3452],{"class":2621},[183,3765,2390],{"class":451},[183,3767,3769,3772,3774],{"class":185,"line":3768},71,[183,3770,3771],{"class":2621},"        payload",[183,3773,464],{"class":451},[183,3775,3063],{"class":451},[183,3777,3779,3782,3784,3786,3788],{"class":185,"line":3778},72,[183,3780,3781],{"class":2621},"          id",[183,3783,464],{"class":451},[183,3785,3465],{"class":451},[183,3787,3337],{"class":1676},[183,3789,3097],{"class":451},[183,3791,3793,3796,3798,3800,3802],{"class":185,"line":3792},73,[183,3794,3795],{"class":2621},"          reason",[183,3797,464],{"class":451},[183,3799,3465],{"class":451},[183,3801,2740],{"class":1676},[183,3803,3097],{"class":451},[183,3805,3807,3810,3812,3814],{"class":185,"line":3806},74,[183,3808,3809],{"class":2621},"          comments",[183,3811,464],{"class":451},[183,3813,3465],{"class":451},[183,3815,3816],{"class":1676},"comments\n",[183,3818,3820],{"class":185,"line":3819},75,[183,3821,3822],{"class":451},"        }\n",[183,3824,3826,3829,3831],{"class":185,"line":3825},76,[183,3827,3828],{"class":451},"      }",[183,3830,3300],{"class":2621},[183,3832,2343],{"class":451},[183,3834,3836,3838,3840,3842,3844],{"class":185,"line":3835},77,[183,3837,3617],{"class":451},[183,3839,2643],{"class":1676},[183,3841,2398],{"class":451},[183,3843,3094],{"class":3093},[183,3845,2343],{"class":451},[183,3847,3849],{"class":185,"line":3848},78,[183,3850,3263],{"class":451},[183,3852,3854],{"class":185,"line":3853},79,[183,3855,3856],{"class":451},"  }\n",[183,3858,3860],{"class":185,"line":3859},80,[183,3861,2449],{"class":451},[183,3863,3865,3867,3869],{"class":185,"line":3864},81,[183,3866,2710],{"class":451},[183,3868,3049],{"class":2621},[183,3870,2625],{"class":451},[12,3872,3873],{},"This includes a confirmation step before closing or discarding, and disables Save while a submission is in progress, so an operator can't lose data or submit the same close twice.",[112,3875,3876],{"start":2515},[56,3877,3878,3879,333,3882,3885,3886,333,3889,3892,3893,333,3896,3899,3900,333,3903,344],{},"Wire the template's output to a change node that maps the submitted fields into query parameters. Set four rules: first set ",[76,3880,3881],{},"queryParameters",[76,3883,3884],{},"{}"," (JSON), then set ",[76,3887,3888],{},"queryParameters.id",[76,3890,3891],{},"payload.id"," (msg), ",[76,3894,3895],{},"queryParameters.reason",[76,3897,3898],{},"payload.reason"," (msg), and ",[76,3901,3902],{},"queryParameters.comments",[76,3904,3905],{},"payload.comments",[12,3907,3908,3912],{},[24,3909],{"alt":3910,"src":3911},"Screenshot: change node rules mapping the submitted id, reason, and comments into queryParameters","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fprep-params-2.png",[29,3913,3914],{},"Resetting queryParameters first, then mapping each submitted field from the reason form.",[112,3916,3917],{"start":2919},[56,3918,3919],{},"Add a final Query node to close the record and save the reason:",[174,3921,3923],{"className":176,"code":3922,"language":178,"meta":179,"style":179},"UPDATE downtime_events\nSET reason = $reason,\n    comments = $comments,\n    status = 'Closed',\n    end_time = NOW(),\n    duration_seconds = EXTRACT(EPOCH FROM (NOW() - start_time))\nWHERE id = $id;\n",[76,3924,3925,3929,3934,3939,3944,3949,3954],{"__ignoreMap":179},[183,3926,3927],{"class":185,"line":186},[183,3928,412],{},[183,3930,3931],{"class":185,"line":192},[183,3932,3933],{},"SET reason = $reason,\n",[183,3935,3936],{"class":185,"line":198},[183,3937,3938],{},"    comments = $comments,\n",[183,3940,3941],{"class":185,"line":204},[183,3942,3943],{},"    status = 'Closed',\n",[183,3945,3946],{"class":185,"line":210},[183,3947,3948],{},"    end_time = NOW(),\n",[183,3950,3951],{"class":185,"line":216},[183,3952,3953],{},"    duration_seconds = EXTRACT(EPOCH FROM (NOW() - start_time))\n",[183,3955,3956],{"class":185,"line":222},[183,3957,3958],{},"WHERE id = $id;\n",[112,3960,3961],{"start":3001},[56,3962,3963],{},"Add a link out node after this last query too, wired to the same link in you used in step 2. This way closing a record manually refreshes the table just like an automatic close would.",[12,3965,3966],{},"Deploy, and open your dashboard. You should see the table populate with any open stoppages from the last section. Click \"Close & Log Reason\" on one, pick a reason, confirm, and it should disappear from the unresolved list right away.",[12,3968,3969,3973],{},[24,3970],{"alt":3971,"src":3972},"Screenshot: dashboard table with the reason form dialog open","\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fui-table-with-popup.png",[29,3974,3975],{},"The reason form popping up after clicking Close & Log Reason on a stoppage.",[12,3977,3978],{},"Next, the KPI cards that summarize all of this into a few numbers at a glance.",[45,3980,3982],{"id":3981},"adding-the-kpi-cards","Adding the KPI Cards",[12,3984,3985],{},"With the table and reason form working, the last piece is a quick summary an operator or supervisor can glance at without reading every row. Add three more ui-groups on the same \"Downtime Events\" page, one for each card, so they can sit side by side across the top of the dashboard.",[112,3987,3988],{},[56,3989,3990],{},"In the same part of the flow as your table's link in, add a Query node that calculates four numbers at once:",[174,3992,3994],{"className":176,"code":3993,"language":178,"meta":179,"style":179},"SELECT\n  (SELECT COUNT(*) FROM downtime_events WHERE status = 'Open')::int AS open_count,\n  (SELECT COUNT(*) FROM downtime_events WHERE status = 'Closed' AND reason IS NULL)::int AS missing_reason_count,\n  (SELECT COALESCE(ROUND(AVG(duration_seconds) \u002F 60.0, 1), 0)::float8\n     FROM downtime_events\n     WHERE status = 'Closed' AND start_time::date = CURRENT_DATE) AS avg_downtime,\n  (SELECT COALESCE(\n     (SELECT reason\n      FROM downtime_events\n      WHERE status = 'Closed' AND start_time::date = CURRENT_DATE AND reason IS NOT NULL\n      GROUP BY reason\n      ORDER BY COUNT(*) DESC\n      LIMIT 1),\n     'None yet'\n  )) AS top_reason;\n",[76,3995,3996,4001,4006,4011,4016,4021,4026,4031,4036,4041,4046,4051,4056,4061,4066],{"__ignoreMap":179},[183,3997,3998],{"class":185,"line":186},[183,3999,4000],{},"SELECT\n",[183,4002,4003],{"class":185,"line":192},[183,4004,4005],{},"  (SELECT COUNT(*) FROM downtime_events WHERE status = 'Open')::int AS open_count,\n",[183,4007,4008],{"class":185,"line":198},[183,4009,4010],{},"  (SELECT COUNT(*) FROM downtime_events WHERE status = 'Closed' AND reason IS NULL)::int AS missing_reason_count,\n",[183,4012,4013],{"class":185,"line":204},[183,4014,4015],{},"  (SELECT COALESCE(ROUND(AVG(duration_seconds) \u002F 60.0, 1), 0)::float8\n",[183,4017,4018],{"class":185,"line":210},[183,4019,4020],{},"     FROM downtime_events\n",[183,4022,4023],{"class":185,"line":216},[183,4024,4025],{},"     WHERE status = 'Closed' AND start_time::date = CURRENT_DATE) AS avg_downtime,\n",[183,4027,4028],{"class":185,"line":222},[183,4029,4030],{},"  (SELECT COALESCE(\n",[183,4032,4033],{"class":185,"line":228},[183,4034,4035],{},"     (SELECT reason\n",[183,4037,4038],{"class":185,"line":234},[183,4039,4040],{},"      FROM downtime_events\n",[183,4042,4043],{"class":185,"line":240},[183,4044,4045],{},"      WHERE status = 'Closed' AND start_time::date = CURRENT_DATE AND reason IS NOT NULL\n",[183,4047,4048],{"class":185,"line":246},[183,4049,4050],{},"      GROUP BY reason\n",[183,4052,4053],{"class":185,"line":2515},[183,4054,4055],{},"      ORDER BY COUNT(*) DESC\n",[183,4057,4058],{"class":185,"line":2919},[183,4059,4060],{},"      LIMIT 1),\n",[183,4062,4063],{"class":185,"line":3001},[183,4064,4065],{},"     'None yet'\n",[183,4067,4068],{"class":185,"line":3010},[183,4069,4070],{},"  )) AS top_reason;\n",[12,4072,4073],{},"These four numbers cover different things on purpose, machines down right now, stoppages already closed but still missing a reason, average downtime in minutes today, and today's most common reason.",[112,4075,4076,4079],{"start":192},[56,4077,4078],{},"Wire this Query node to the same link in you already have from the event flow, so the cards refresh the moment a record opens or closes, same as the table.",[56,4080,4081],{},"Add four ui-text nodes, each assigned to its own group from the groups you just created:",[53,4083,4084,4093,4101,4109],{},[56,4085,4086,4089,4090],{},[59,4087,4088],{},"Machines Down"," → ",[76,4091,4092],{},"payload[0].open_count",[56,4094,4095,4089,4098],{},[59,4096,4097],{},"Missing Reason",[76,4099,4100],{},"payload[0].missing_reason_count",[56,4102,4103,4089,4106],{},[59,4104,4105],{},"Avg (min)",[76,4107,4108],{},"payload[0].avg_downtime",[56,4110,4111,4089,4114],{},[59,4112,4113],{},"Top Reason",[76,4115,4116],{},"payload[0].top_reason",[112,4118,4119],{"start":204},[56,4120,4121],{},"Set each group's width so the four sit side by side across the dashboard page.",[12,4123,4124],{},"Deploy and check your dashboard. As you open, close, and log reasons on stoppages, all four numbers should update right along with the table.",[12,4126,4127,4130],{},[24,4128],{"alt":26,"src":4129},"\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fcomplete-dashbaord-downtime-logger.png",[29,4131,31],{},[12,4133,4134,4135,40],{},"That completes the application. You now have a working pipeline: a stoppage gets recorded the moment it happens, stays visible until someone accounts for it, and rolls up into numbers that mean something to a supervisor walking the floor. From here, this same table is the foundation for OEE calculations, shift reports, or feeding a maintenance dashboard, the hard part, capturing clean downtime data, is already done. For where a downtime view sits alongside production, OEE, and quality screens, see our ",[36,4136,4138],{"href":4137},"\u002Fblog\u002F2026\u002F08\u002Fmanufacturing-dashboard-examples\u002F","manufacturing dashboard examples",[516,4140,4141],{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":179,"searchDepth":204,"depth":204,"links":4143},[4144,4145,4146,4147,4148,4149],{"id":47,"depth":192,"text":48},{"id":106,"depth":192,"text":107},{"id":149,"depth":192,"text":150},{"id":269,"depth":192,"text":270},{"id":2186,"depth":192,"text":2187},{"id":3981,"depth":192,"text":3982},{"type":4151,"title":4152,"description":4153},"contact","Want to turn this into full OEE and MES reporting?","Talk to our team about extending this downtime table into production reporting, maintenance dashboards, and MES integrations for your factory floor.","2026-07-08","Learn how to build a machine downtime tracking application in FlowFuse that captures stop and start events over MQTT, calculates downtime duration automatically, lets operators log a reason from a dashboard, and displays live KPI cards.","md",null,"\u002Fblog\u002F2026\u002F07\u002Fimages\u002Fbuild-machine-downtime-tracking-application.png",{"excerpt":4160},{"type":9,"value":4161},[4162],[12,4163,14],{},"\u002Fblog\u002F2026\u002F07\u002Fbuild-downtime-logger",{"title":5,"description":4155},{"loc":4164},"blog\u002F2026\u002F07\u002Fbuild-downtime-logger","Build a FlowFuse dashboard that logs machine stoppages, calculates downtime, and lets operators assign reasons",[4170],"flowfuse","Build a FlowFuse application that captures machine stop and start events over MQTT, logs them to a database, lets operators assign a downtime reason from a dashboard, and displays live KPI cards summarizing downtime across the floor.","stwkNeOlzd7LxI3i3VYfL8HTh0-M4dfG7KKb2o-2fsk",{"id":4174,"extension":4175,"meta":4176,"sections":4177,"stem":4563,"__hash__":4564},"featureCatalog\u002Ffeature-catalog.yml","yml",{},[4178,4229,4328,4389,4466,4545],{"id":4179,"title":4180,"features":4181},"ai-automation","AI & Automation",[4182,4192,4202,4212,4218,4224],{"id":4183,"title":4184,"description":4185,"docsLink":4186,"changelog":4187,"tiers":4191},"flowfuse-expert-ai","FlowFuse Expert AI","Build industrial apps with agents, and query the state of the factory with an agent. Adapt your current hardware and machines so agentic work can be done against them, without ripping and replacing what's already on the plant floor.","\u002Fdocs\u002Fuser\u002Fexpert\u002F",[4188],{"url":4189,"release":4190},"\u002Fchangelog\u002F2026\u002F02\u002Fff-expert-update-banner\u002F","2.28",{"edge":2368,"hub":2368,"fleet":2368},{"id":4193,"title":4194,"description":4195,"docsLink":4196,"changelog":4197,"subfeature":2368,"showOnPricing":4200,"tiers":4201},"flowfuse-expert-support-mode","Support Mode","Chat-based assistance for FlowFuse and Node-RED, including Node-RED instance management through natural language.","\u002Fdocs\u002Fuser\u002Fexpert\u002Fchat\u002F#support-mode",[4198],{"url":4199,"release":4190},"\u002Fchangelog\u002F2026\u002F02\u002Fff-expert-debug-log-context\u002F",false,{"edge":2368,"hub":2368,"fleet":2368},{"id":4203,"title":4204,"description":4205,"docsLink":4206,"changelog":4207,"subfeature":2368,"showOnPricing":4200,"tiers":4211},"flowfuse-expert-application-building","Application Building","Describe what you want to build and FlowFuse Expert assembles it on your workspace, adding tabs, wiring nodes, and configuring properties.","\u002Fdocs\u002Fuser\u002Fexpert\u002Fchat\u002F",[4208],{"url":4209,"release":4210},"\u002Fchangelog\u002F2026\u002F05\u002Fexpert-application-building\u002F","2.30",{"edge":2368,"hub":2368,"fleet":2368},{"id":4213,"title":4214,"description":4215,"docsLink":4216,"subfeature":2368,"beta":2368,"showOnPricing":4200,"tiers":4217},"flowfuse-expert-insights-mode","Insights Mode","Connects FlowFuse Expert to MCP servers in your Node-RED instances, enabling real-time data queries and actions through a single chat interface.","\u002Fdocs\u002Fuser\u002Fexpert\u002Fchat\u002F#insights-mode",{"edge":2368,"hub":2368,"fleet":2368},{"id":4219,"title":4220,"description":4221,"docsLink":4222,"tiers":4223},"mcp-servers","Agentic Operations","Expose your Node-RED flows as tools an AI agent can call directly, so agents can query the state of the factory or trigger actions without custom integration work.","\u002Fnode-red\u002Fflowfuse\u002Fmcp\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4225,"title":4226,"description":4227,"tiers":4228},"onnx-integration","ONNX Integration","Run trained machine learning models directly in your flows, including on edge hardware, without sending data out to an external inference service.",{"edge":2368,"hub":2368,"fleet":2368},{"id":4230,"title":4231,"features":4232},"build","Build",[4233,4239,4245,4253,4259,4265,4269,4275,4281,4289,4295,4299,4303,4312,4320],{"id":4234,"title":4235,"description":4236,"docsLink":4237,"tiers":4238},"edge-development","Edge Development","Develop and test Node-RED flows directly on edge devices with a remote editor proxy.","\u002Fdocs\u002Fdevice-agent\u002Fquickstart\u002F",{"edge":2368,"hub":4200,"fleet":2368},{"id":4240,"title":4241,"description":4242,"docsLink":4243,"tiers":4244},"private-npm-registry","Custom Node-RED Nodes","Create and manage your own private npm registry for Node-RED nodes, so you can share custom nodes across your team and devices without publishing them publicly.","\u002Fdocs\u002Fuser\u002Fcustom-npm-packages\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4246,"title":163,"description":4247,"docsLink":162,"changelog":4248,"tiers":4252},"flowfuse-tables","A managed PostgreSQL database for every application, so you can store and query structured data without standing up and maintaining your own database.",[4249],{"url":4250,"release":4251},"\u002Fchangelog\u002F2026\u002F07\u002Fexpert-tables-automation\u002F","2.33",{"edge":2368,"hub":2368,"fleet":2368},{"id":4254,"title":4255,"description":4256,"docsLink":4257,"tiers":4258},"persistent-files","File Storage","Store and retrieve files from your Node-RED flows, with automatic replication and backup across your devices and hosted instances.","\u002Fdocs\u002Finstall\u002Ffile-storage\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4260,"title":4261,"description":4262,"docsLink":4263,"showOnPricing":4200,"tiers":4264},"persistent-context","Persistent Context","In-memory values defined in a Node-RED flow persist across project restarts and upgrades.","\u002Fdocs\u002Fuser\u002Fpersistent-context\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4266,"title":4267,"showOnPricing":4200,"tiers":4268},"static-assets","Static Assets",{"edge":2368,"hub":2368,"fleet":2368},{"id":4270,"title":4271,"description":4272,"docsLink":4273,"tiers":4274},"team-library","Team Library","Set up standard nodes and flows that can be shared with all team members across your organisation.","\u002Fdocs\u002Fuser\u002Fshared-library\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4276,"title":4277,"description":4278,"docsLink":4279,"tiers":4280},"personalised-multi-user-dashboards","Personalised Multi-User Dashboards","Build applications that provide unique data to each logged-in user using personalised multi-user dashboards.","https:\u002F\u002Fdashboard.flowfuse.com\u002Fuser\u002Fmulti-tenancy.html",{"edge":2368,"hub":2368,"fleet":2368},{"id":4282,"title":4283,"description":4284,"changelog":4285,"subfeature":2368,"showOnPricing":4200,"tiers":4288},"dashboards-view","Dashboards View","Browse and open every dashboard across your team from a dedicated Dashboards view, at both team and application level, without leaving FlowFuse.",[4286],{"url":4287,"release":4251},"\u002Fchangelog\u002F2026\u002F07\u002Fteam-and-application-dashboards\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4290,"title":4291,"description":4292,"docsLink":4293,"tiers":4294},"blueprints-converge","Blueprints","Ready-made starting points for your apps, from cross-team Converge templates to OT and IT specific blueprints.","\u002Fdocs\u002Fuser\u002Fconcepts\u002F#blueprint",{"edge":2368,"hub":2368,"fleet":2368},{"id":4296,"title":4297,"subfeature":2368,"showOnPricing":4200,"tiers":4298},"blueprints-ot-apps","Blueprints - OT APPS",{"edge":2368,"hub":4200,"fleet":2368},{"id":4300,"title":4301,"subfeature":2368,"showOnPricing":4200,"tiers":4302},"blueprints-it-apps","Blueprints - IT APPS",{"edge":4200,"hub":2368,"fleet":4200},{"id":4304,"title":4305,"description":4306,"changelog":4307,"showOnPricing":4200,"tiers":4311},"immersive-editor-snapshots","Snapshot Details in Immersive Editor","View and manage snapshot details directly inside the immersive editor without leaving your editing session.",[4308],{"url":4309,"release":4310},"\u002Fchangelog\u002F2026\u002F03\u002Fsnapshot-detail-modal-immersive-editor\u002F","2.29",{"edge":2368,"hub":2368,"fleet":2368},{"id":4313,"title":4314,"description":4315,"changelog":4316,"showOnPricing":4200,"tiers":4319},"immersive-editor-drawer","Customisable Immersive Editor Drawer","Pin, move, resize, or full-screen the immersive editor drawer. Your preferences are remembered between sessions.",[4317],{"url":4318,"release":4210},"\u002Fchangelog\u002F2026\u002F04\u002Fimmersive-editor-drawer\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4321,"title":4322,"description":4323,"changelog":4324,"showOnPricing":4200,"tiers":4327},"embedded-editor-tab-title","Embedded Editor Browser Tab Title","The browser tab title updates to reflect the active Node-RED canvas tab when working in the embedded editor.",[4325],{"url":4326,"release":4310},"\u002Fchangelog\u002F2026\u002F03\u002Fembedded-editor-tab-title\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4329,"title":4330,"features":4331},"deploy","Deploy",[4332,4338,4347,4353,4358,4364,4370,4376,4381],{"id":4333,"title":4334,"description":4335,"docsLink":4336,"tiers":4337},"hosted-instances","Cloud Instances","Run Node-RED instances managed and hosted by FlowFuse.","\u002Fdocs\u002Fuser\u002Fintroduction\u002F#creating-a-node-red-instance",{"edge":2368,"hub":2368,"fleet":2368},{"id":4339,"title":4340,"description":4341,"docsLink":4342,"changelog":4343,"tiers":4346},"edge-devices","Edge Instances","Deploy and mange your Node-RED instances on edge PLCs and gateways, with full visibility and control from the cloud.","\u002Fdocs\u002Fdevice-agent\u002Fintroduction\u002F",[4344],{"url":4345,"release":4190},"\u002Fchangelog\u002F2026\u002F02\u002Fdevice-agent-nodejs-options\u002F",{"edge":2368,"hub":4200,"fleet":2368},{"id":4348,"title":4349,"description":4350,"docsLink":4351,"tiers":4352},"custom-hostnames","Custom Hostnames","Access your Node-RED application via your own domain name.","\u002Fdocs\u002Fuser\u002Fcustom-hostnames\u002F",{"edge":4200,"hub":2368,"fleet":4200},{"id":4354,"title":4355,"description":4356,"docsLink":279,"tiers":4357},"mqtt-broker","MQTT Broker","Manage and create MQTT clients to transport data for efficient messaging and communication within your applications.",{"edge":2368,"hub":4200,"fleet":2368},{"id":4359,"title":4360,"description":4361,"docsLink":4362,"showOnPricing":4200,"tiers":4363},"project-nodes","Project Nodes aka seamless project comms","FlowFuse Project Nodes enable the passing of data and messages between your Node-RED projects.","\u002Fdocs\u002Fuser\u002Fprojectnodes\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4365,"title":4366,"description":4367,"docsLink":4368,"tiers":4369},"devops-pipelines","DevOps Pipelines","Set up different environments for development, testing, and production Node-RED instances to support a full software delivery lifecycle.","\u002Fdocs\u002Fuser\u002Fdevops-pipelines\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4371,"title":4372,"description":4373,"docsLink":4374,"tiers":4375},"git-integration","Git Integration","Back up your flows to a remote Git repository through a DevOps Pipeline. Supports GitHub and Azure DevOps repositories.","\u002Fdocs\u002Fuser\u002Fdevops-pipelines\u002F#git-repository-stage",{"edge":4200,"hub":2368,"fleet":4200},{"id":4377,"title":4378,"description":4379,"docsLink":4374,"subfeature":2368,"showOnPricing":4200,"tiers":4380},"git-integration-github","GitHub","Push and pull snapshots to GitHub repositories through DevOps Pipeline Git Stages.",{"edge":4200,"hub":2368,"fleet":4200},{"id":4382,"title":4383,"description":4384,"docsLink":4374,"changelog":4385,"subfeature":2368,"showOnPricing":4200,"tiers":4388},"git-integration-azure","Azure DevOps","Push and pull snapshots to Azure DevOps repositories through DevOps Pipeline Git Stages.",[4386],{"url":4387,"release":4310},"\u002Fchangelog\u002F2026\u002F03\u002Fazure-dev-ops-gitops\u002F",{"edge":4200,"hub":2368,"fleet":4200},{"id":4390,"title":4391,"features":4392},"operate-maintain","Operate & Maintain",[4393,4399,4405,4410,4418,4422,4426,4431,4437,4443,4448,4454,4458,4462],{"id":4394,"title":4395,"description":4396,"docsLink":4397,"tiers":4398},"snapshots","Snapshots & Version History","Automatic snapshots on remote devices and hosted instances, plus a full version history timeline so you can roll back to any prior state.","\u002Fdocs\u002Fuser\u002Fsnapshots\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4400,"title":4401,"description":4402,"docsLink":4403,"subfeature":2368,"showOnPricing":4200,"tiers":4404},"auto-snapshot-remote","Auto Snapshot (Remote)","Automatically capture a snapshot every time a remote instance is deployed, so you always have a recoverable history of what was running on each device.","\u002Fdocs\u002Fuser\u002Fsnapshots\u002F#auto-snapshots",{"edge":2368,"hub":2368,"fleet":2368},{"id":4406,"title":4407,"description":4408,"docsLink":4403,"subfeature":2368,"showOnPricing":4200,"tiers":4409},"auto-snapshot-hosted","Auto Snapshot (Hosted)","Automatically capture a snapshot every time a hosted instance is deployed, so you always have a recoverable history of what was running.",{"edge":2368,"hub":2368,"fleet":2368},{"id":4411,"title":4412,"description":4413,"changelog":4414,"subfeature":2368,"showOnPricing":4200,"tiers":4417},"snapshot-comparison","Snapshot Comparison","Compare two snapshots side-by-side with a navigable diff view. Step through every changed, added, or deleted node and see property and code diffs.",[4415],{"url":4416,"release":4310},"\u002Fchangelog\u002F2026\u002F04\u002Fsnapshot-diff-viewer\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4419,"title":4420,"subfeature":2368,"showOnPricing":4200,"tiers":4421},"version-history-timeline","Version History Timeline",{"edge":2368,"hub":2368,"fleet":2368},{"id":4423,"title":4424,"tiers":4425},"unlimited-workflow-executions","Unlimited Workflow Executions",{"edge":2368,"hub":2368,"fleet":2368},{"id":4427,"title":4428,"description":4429,"tiers":4430},"device-fleet-updates","Device Fleet Updates","Connect to edge devices to quickly assess and update logic. Debug one device and roll out improvements to your fleet in minutes, securely without requiring full device access for your whole organisation.",{"edge":2368,"hub":4200,"fleet":2368},{"id":4432,"title":4433,"description":4434,"docsLink":4435,"tiers":4436},"device-group-management","Device Group Management","Logically group devices assigned to an application and integrate device groups into your DevOps Pipeline for coordinated fleet updates.","\u002Fdocs\u002Fuser\u002Fdevice-groups\u002F",{"edge":2368,"hub":4200,"fleet":2368},{"id":4438,"title":4439,"description":4440,"docsLink":4441,"tiers":4442},"high-availability","High Availability","Leverage horizontal scaling for reliable and scalable processing of your data through Node-RED.","\u002Fdocs\u002Fuser\u002Fhigh-availability\u002F",{"edge":4200,"hub":2368,"fleet":4200},{"id":4444,"title":4445,"description":4446,"tiers":4447},"performance-monitoring","Performance Monitoring & Alerts","Track CPU, memory, and event loop performance across your instances and devices, with email alerts when something needs your attention.",{"edge":2368,"hub":2368,"fleet":2368},{"id":4449,"title":4450,"description":4451,"docsLink":4452,"subfeature":2368,"showOnPricing":4200,"tiers":4453},"instance-monitoring","Instance Monitoring","Enable alerts to be sent via email when your Node-RED instances encounter issues.","\u002Fdocs\u002Fuser\u002Finstance-settings\u002F#alerts",{"edge":2368,"hub":2368,"fleet":2368},{"id":4455,"title":4456,"subfeature":2368,"showOnPricing":4200,"tiers":4457},"email-alerts","Email Alerts",{"edge":2368,"hub":2368,"fleet":2368},{"id":4459,"title":4460,"showOnPricing":4200,"tiers":4461},"api-debug-length-limit","API\u002FDebug Length Limit",{"edge":2368,"hub":2368,"fleet":2368},{"id":4463,"title":4464,"tiers":4465},"protected-instances","Protected Instances",{"edge":4200,"hub":2368,"fleet":4200},{"id":4467,"title":4468,"features":4469},"govern-secure","Govern and Secure",[4470,4479,4485,4491,4496,4502,4508,4514,4522,4528,4534,4540],{"id":4471,"title":4472,"description":4473,"docsLink":4474,"changelog":4475,"tiers":4478},"single-sign-on","Single Sign-On (SSO)","Configure FlowFuse to work with your own SSO provider, allowing users to access FlowFuse with a single set of login credentials.","\u002Fdocs\u002Fadmin\u002Fsso\u002F",[4476],{"url":4477,"release":4251},"\u002Fchangelog\u002F2026\u002F07\u002Fapplication-sso-groups\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4480,"title":4481,"description":4482,"docsLink":4483,"tiers":4484},"two-factor-authentication","Two-Factor Authentication","Two-factor authentication adds an extra layer of security to your FlowFuse account.","\u002Fdocs\u002Fuser\u002Fuser-settings\u002F#two-factor-authentication",{"edge":2368,"hub":2368,"fleet":2368},{"id":4486,"title":4487,"description":4488,"docsLink":4489,"tiers":4490},"certified-nodes-it","Certified Nodes - IT","IT certified node bundle includes: Redis, MQTT, HTTP Request, AI nodes (Gemini, Claude, ChatGPT, Ollama), MCP Server","\u002Fblog\u002F2025\u002F07\u002Fcertified-nodes-v2\u002F",{"edge":4200,"hub":2368,"fleet":2368},{"id":4492,"title":4493,"description":4494,"tiers":4495},"certified-nodes-ot","Certified OT Connections - OPC-UA, Modbus, etc.","OT certified node bundle includes: OPC-UA, Modbus TCP & RTU, RTSP, EtherNet\u002FIP, AI nodes (Gemini, Claude, ChatGPT, Ollama), MCP Server",{"edge":2368,"hub":4200,"fleet":4200},{"id":4497,"title":4498,"description":4499,"docsLink":4500,"tiers":4501},"audit-log","Audit Log","Keep track of everything going on in your Node-RED instances and FlowFuse. Audit Logs provide details on what actions have taken place, when they happened, and who did them.","\u002Fdocs\u002Fuser\u002Flogs\u002F#audit-log",{"edge":2368,"hub":2368,"fleet":2368},{"id":4503,"title":4504,"description":4505,"docsLink":4506,"tiers":4507},"role-based-access-control","Role-Based Access Control","Control who can do what at both the team and application level, from viewers to admins.","\u002Fdocs\u002Fuser\u002Frole-based-access-control\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4509,"title":4510,"description":4511,"docsLink":4512,"subfeature":2368,"showOnPricing":4200,"tiers":4513},"application-level-rbac","Application-Level RBAC","Fine-grained access control per application, allowing team members to have different permission levels across different applications without requiring separate teams.","\u002Fdocs\u002Fuser\u002Frole-based-access-control\u002F#application-level-rbac",{"edge":2368,"hub":2368,"fleet":2368},{"id":4515,"title":4516,"description":4517,"changelog":4518,"subfeature":2368,"showOnPricing":4200,"tiers":4521},"scoped-personal-access-tokens","Scoped Personal Access Tokens","Restrict a Personal Access Token to specific teams, limit it to read-only operations, or control whether it carries admin privileges.",[4519],{"url":4520,"release":4251},"\u002Fchangelog\u002F2026\u002F07\u002Fscoped-pats\u002F",{"edge":2368,"hub":2368,"fleet":2368},{"id":4523,"title":4524,"description":4525,"docsLink":4526,"showOnPricing":4200,"tiers":4527},"team-members","Team Members","Invite multiple team members to collaborate on the same Node-RED flows.","\u002Fdocs\u002Fuser\u002Fteam\u002F#teams",{"edge":2368,"hub":2368,"fleet":2368},{"id":4529,"title":4530,"description":4531,"docsLink":4532,"showOnPricing":4200,"tiers":4533},"endpoint-security","Endpoint Security","Secure HTTP endpoints for hosted Node-RED instances using FlowFuse credentials.","\u002Fdocs\u002Fuser\u002Finstance-settings\u002F#security",{"edge":2368,"hub":2368,"fleet":2368},{"id":4535,"title":4536,"description":4537,"docsLink":4538,"tiers":4539},"baa-for-hipaa","BAA for HIPAA","FlowFuse can sign a Business Associate Agreement to ensure proper safeguarding of protected health information handled on your behalf.","\u002Fhandbook\u002Fsales\u002Fsubscription-agreement-1.5\u002F",{"edge":4200,"hub":2368,"fleet":4200},{"id":4541,"title":4542,"description":4543,"tiers":4544},"sbom","Software Bill of Materials","A complete list of all software components used in your Node-RED instances and hosted applications, including version numbers and license information.",{"edge":4200,"hub":2368,"fleet":4200},{"id":4546,"title":4547,"features":4548},"support","Support",[4549,4554,4558],{"id":4550,"title":4551,"docsLink":4552,"tiers":4553},"installation-support","Installation Support","\u002Fdocs\u002Finstall\u002Fintroduction\u002F#do-you-need-help-installation-service",{"edge":2368,"hub":2368,"fleet":2368},{"id":4555,"title":4556,"showOnPricing":4200,"tiers":4557},"live-chat-support","Live Chat Support",{"edge":2368,"hub":2368,"fleet":2368},{"id":4559,"title":4560,"docsLink":4561,"tiers":4562},"enterprise-support","Enterprise Support","\u002Fdocs\u002Fpremium-support\u002F",{"edge":2368,"hub":2368,"fleet":2368},"feature-catalog","0AnkhTIPCECCwP9NmbTWP5HvRYx4FTSao4lG93-HaWM",[4566,4569,4572,4575,4578,4581,4583,4586,4589,4592,4595,4597,4600,4603,4606,4609,4612,4615,4618,4621,4624,4627,4630,4633,4636,4639,4642,4645,4648,4651,4654,4657,4660,4663,4666,4669,4672,4675,4678,4681,4684,4687,4690,4693,4696,4699,4702,4705,4708,4710,4713,4716,4719,4722,4725,4728,4731,4733,4736,4739,4742,4745,4748,4750,4753,4756,4759,4762,4765,4768,4771,4774,4777,4780,4782,4785,4788,4791,4794,4797,4800,4803,4806,4809,4812,4815,4818,4821,4824,4826,4829,4832,4835,4838,4841,4844,4847,4850,4853,4856,4859,4862,4865,4868,4871,4874,4877,4880,4882,4885,4888,4891,4894,4897,4900,4903,4905,4908,4911,4914,4917,4920,4923,4926,4929,4932,4935,4938,4941,4944,4947,4950,4953,4956,4959,4962,4965,4968,4971,4974,4977,4980,4983,4986,4989,4992,4995,4998,5001,5004,5007,5010,5013,5016,5019,5022,5025,5028,5031,5034,5037,5040,5043,5046,5049,5052,5055,5057,5060,5063,5066,5069,5072,5075,5078,5081,5084,5087,5090,5093,5096],{"path":4567,"title":4568},"\u002Fchangelog\u002F2023\u002F09\u002Fcustom-node-support","Custom Node Support",{"path":4570,"title":4571},"\u002Fchangelog\u002F2023\u002F09\u002Fdevops-actions","DevOps Pipeline with action selection",{"path":4573,"title":4574},"\u002Fchangelog\u002F2023\u002F09\u002Fintroduction-enterprise-tier","Introducing the Enterprise Tier",{"path":4576,"title":4577},"\u002Fchangelog\u002F2023\u002F09\u002Fpipeline-api","API Endpoint for DevOps Pipeline",{"path":4579,"title":4580},"\u002Fchangelog\u002F2023\u002F09\u002Fsnapshots-devices","Usability improvements to Device Management",{"path":4582,"title":4291},"\u002Fchangelog\u002F2023\u002F10\u002Fblueprints",{"path":4584,"title":4585},"\u002Fchangelog\u002F2023\u002F10\u002Fcertified-nodes","Certified Nodes",{"path":4587,"title":4588},"\u002Fchangelog\u002F2023\u002F10\u002Fdevice-snapshot-selection","Enhanced Snapshot Selection",{"path":4590,"title":4591},"\u002Fchangelog\u002F2023\u002F10\u002Fpath-bug-fix","Device Agent path bug fix",{"path":4593,"title":4594},"\u002Fchangelog\u002F2023\u002F10\u002Fresource-alerts","Resource Monitoring in Audit Log",{"path":4596,"title":4481},"\u002Fchangelog\u002F2023\u002F11\u002F2fa",{"path":4598,"title":4599},"\u002Fchangelog\u002F2023\u002F11\u002Fdefault-editor","Device Editor enabled by default",{"path":4601,"title":4602},"\u002Fchangelog\u002F2023\u002F11\u002Fdevices-in-pipelines","Devices in DevOps Pipelines",{"path":4604,"title":4605},"\u002Fchangelog\u002F2023\u002F11\u002Fproject-nodes-devices","Project Nodes for Devices",{"path":4607,"title":4608},"\u002Fchangelog\u002F2023\u002F12\u002Fbilling","No Credit Card required for billing",{"path":4610,"title":4611},"\u002Fchangelog\u002F2023\u002F12\u002Fblueprint-selection","Blueprint Selection Update",{"path":4613,"title":4614},"\u002Fchangelog\u002F2023\u002F12\u002Fdevice-groups","Device Groups",{"path":4616,"title":4617},"\u002Fchangelog\u002F2023\u002F12\u002Femail-alerting-node-red-crash","Email Alerts for Audit Log Events",{"path":4619,"title":4620},"\u002Fchangelog\u002F2023\u002F12\u002Fnode-red-updated","Node-RED 3.1.3 now available",{"path":4622,"title":4623},"\u002Fchangelog\u002F2024\u002F01\u002Fdevice-audit-log","Introducing the Device Auditlog Feature",{"path":4625,"title":4626},"\u002Fchangelog\u002F2024\u002F01\u002Fdevice-groups-snapshot","Device Groups - Automatic snapshot assignment",{"path":4628,"title":4629},"\u002Fchangelog\u002F2024\u002F01\u002Ffleet-mode","Renaming \"Default Device Mode\" to \"Fleet Mode\"",{"path":4631,"title":4632},"\u002Fchangelog\u002F2024\u002F01\u002Fhelm-v2","Helm Chart v2.0",{"path":4634,"title":4635},"\u002Fchangelog\u002F2024\u002F01\u002Fnew-blueprints","New Blueprints added",{"path":4637,"title":4638},"\u002Fchangelog\u002F2024\u002F01\u002Fsecurity-updates","Security Updates",{"path":4640,"title":4641},"\u002Fchangelog\u002F2024\u002F01\u002Fsso-team-membership","Managing Team Membership via SSO",{"path":4643,"title":4644},"\u002Fchangelog\u002F2024\u002F01\u002Fstreamlined-device-assignment","Streamlined Device assignment",{"path":4646,"title":4647},"\u002Fchangelog\u002F2024\u002F02\u002Fdevice-auto-snapshot","Device Auto Snapshots",{"path":4649,"title":4650},"\u002Fchangelog\u002F2024\u002F02\u002Fdevice-instance-audit-logs","Device Instance Audit Logging",{"path":4652,"title":4653},"\u002Fchangelog\u002F2024\u002F02\u002Fdevice-onboarding-improvements","Device Onboarding Improvements",{"path":4655,"title":4656},"\u002Fchangelog\u002F2024\u002F02\u002Fdevice-pricing-change","Pricing change for Devices",{"path":4658,"title":4659},"\u002Fchangelog\u002F2024\u002F02\u002Finstance-auto-snapshots","Instance Auto Snapshots",{"path":4661,"title":4662},"\u002Fchangelog\u002F2024\u002F02\u002Fpostgresql-upgrade","PostgreSQL Version update",{"path":4664,"title":4665},"\u002Fchangelog\u002F2024\u002F03\u002Fbearer-token-authentication","Bearer Token Authentication for Node-RED Instances",{"path":4667,"title":4668},"\u002Fchangelog\u002F2024\u002F03\u002Finstance-protection-mode","Instance Protection Mode",{"path":4670,"title":4671},"\u002Fchangelog\u002F2024\u002F03\u002Flimits-debug-payload","Configure HTTP Payload and Debug Message size",{"path":4673,"title":4674},"\u002Fchangelog\u002F2024\u002F03\u002Frestart-devices-remotly","Remote Device Restart",{"path":4676,"title":4677},"\u002Fchangelog\u002F2024\u002F04\u002Fcustom-nodes-on-devices","Custom Nodes Support on Devices",{"path":4679,"title":4680},"\u002Fchangelog\u002F2024\u002F04\u002Fdevice-auto-snapshot","Direct Dashboard Access",{"path":4682,"title":4683},"\u002Fchangelog\u002F2024\u002F04\u002Fimproving-device-groups","Improving Device Groups",{"path":4685,"title":4686},"\u002Fchangelog\u002F2024\u002F04\u002Fpricing-change","Pricing change Enterprise & Teams Tier",{"path":4688,"title":4689},"\u002Fchangelog\u002F2024\u002F04\u002Ftougher-rate-limiting","Tougher Rate Limiting on Public Routes",{"path":4691,"title":4692},"\u002Fchangelog\u002F2024\u002F05\u002Finstance-healthcheck","Customizing instance health-check settings",{"path":4694,"title":4695},"\u002Fchangelog\u002F2024\u002F05\u002Flibrary-blueprints","Blueprints added to Library",{"path":4697,"title":4698},"\u002Fchangelog\u002F2024\u002F05\u002Flibrary-flowviewer","Team Library - Flow Viewer",{"path":4700,"title":4701},"\u002Fchangelog\u002F2024\u002F05\u002Fmanaging-node-red-version-on-devices","Managing Node-RED versions on Devices",{"path":4703,"title":4704},"\u002Fchangelog\u002F2024\u002F05\u002Fsnapshot-improvements","Snapshot Improvements",{"path":4706,"title":4707},"\u002Fchangelog\u002F2024\u002F05\u002Fsnapshot-improvements-pt3","Snapshot Upload",{"path":4709,"title":4707},"\u002Fchangelog\u002F2024\u002F05\u002Fsnapshot-upload",{"path":4711,"title":4712},"\u002Fchangelog\u002F2024\u002F06\u002Fdevice-agent-proxy-support","Running the Device Agent behind an HTTP proxy",{"path":4714,"title":4715},"\u002Fchangelog\u002F2024\u002F06\u002Flibrary-blueprints","Custom hostnames for your instances",{"path":4717,"title":4718},"\u002Fchangelog\u002F2024\u002F06\u002Fmultiline-env-vars","Multi-line Environment Variables",{"path":4720,"title":4721},"\u002Fchangelog\u002F2024\u002F06\u002Fsnapshot-flow-compare","Compare Snapshots flows",{"path":4723,"title":4724},"\u002Fchangelog\u002F2024\u002F07\u002Fapplications-search","Applications Search",{"path":4726,"title":4727},"\u002Fchangelog\u002F2024\u002F07\u002Fdevice-group-clear-snapshot","Device Groups Snapshots",{"path":4729,"title":4730},"\u002Fchangelog\u002F2024\u002F07\u002Fdevice-management-bulk-delete","Managing devices",{"path":4732,"title":4730},"\u002Fchangelog\u002F2024\u002F07\u002Fdevice-management-bulk-move",{"path":4734,"title":4735},"\u002Fchangelog\u002F2024\u002F07\u002Fedit-snapshots","Edit Snapshots",{"path":4737,"title":4738},"\u002Fchangelog\u002F2024\u002F07\u002Fflowfuse-assistant","The FlowFuse Expert",{"path":4740,"title":4741},"\u002Fchangelog\u002F2024\u002F07\u002Fflowfuse-assistant-json","FlowFuse Expert Writes JSON",{"path":4743,"title":4744},"\u002Fchangelog\u002F2024\u002F07\u002Fimmersive-editor","Immersive Editor Experience",{"path":4746,"title":4747},"\u002Fchangelog\u002F2024\u002F07\u002Fnotifications-inbox","Notifications Inbox",{"path":4749,"title":4747},"\u002Fchangelog\u002F2024\u002F07\u002Fnotifications-update",{"path":4751,"title":4752},"\u002Fchangelog\u002F2024\u002F07\u002Fpersistent-storage","Persistent Storage on FlowFuse Cloud",{"path":4754,"title":4755},"\u002Fchangelog\u002F2024\u002F07\u002Fsso","Single Sign On Updates",{"path":4757,"title":4758},"\u002Fchangelog\u002F2024\u002F08\u002Fbill-of-materials","Bill of Materials",{"path":4760,"title":4761},"\u002Fchangelog\u002F2024\u002F08\u002Fenterprise-license-update","Enforcing Enterprise Restrictions",{"path":4763,"title":4764},"\u002Fchangelog\u002F2024\u002F08\u002Fldap-sso-groups","LDAP Single Sign On Updates",{"path":4766,"title":4767},"\u002Fchangelog\u002F2024\u002F08\u002Fstatic-file-service-navigation-visibility","Static File Service Navigation and Visibility",{"path":4769,"title":4770},"\u002Fchangelog\u002F2024\u002F10\u002Fdevice-group-env-vars","Environment Variables for your Device Groups",{"path":4772,"title":4773},"\u002Fchangelog\u002F2024\u002F10\u002Fmqtt-service","MQTT Broker Service",{"path":4775,"title":4776},"\u002Fchangelog\u002F2024\u002F10\u002Fnotifications-bulk-actions","Managing Notifications",{"path":4778,"title":4779},"\u002Fchangelog\u002F2024\u002F10\u002Fsnapshot-download-upload-options","Snapshot Upload and Download Improvements",{"path":4781,"title":4420},"\u002Fchangelog\u002F2024\u002F10\u002Fversion-history-timeline",{"path":4783,"title":4784},"\u002Fchangelog\u002F2024\u002F11\u002Faudit-log-hierarchy","Audit logs show hierarchical events",{"path":4786,"title":4787},"\u002Fchangelog\u002F2024\u002F11\u002Fdevice-agent-release","Device Agent 3.0 released",{"path":4789,"title":4790},"\u002Fchangelog\u002F2024\u002F11\u002Fmqtt-topic-hierarchy","MQTT Topic Hierarchy view",{"path":4792,"title":4793},"\u002Fchangelog\u002F2024\u002F11\u002Fteam-search","Team-wide search",{"path":4795,"title":4796},"\u002Fchangelog\u002F2024\u002F12\u002Fdashboad-iframe","Allow Dashboards to be embedded in iFrames",{"path":4798,"title":4799},"\u002Fchangelog\u002F2024\u002F12\u002Fdevice-editor-cache","Device Editor Access Speed Up",{"path":4801,"title":4802},"\u002Fchangelog\u002F2024\u002F12\u002Fteam-bom-timeline","Team BOM and Pipeline Views",{"path":4804,"title":4805},"\u002Fchangelog\u002F2025\u002F01\u002Ffree-tier-onboarding","New Onboarding Tour for Free Tier Users",{"path":4807,"title":4808},"\u002Fchangelog\u002F2025\u002F01\u002Fhidden-env-vars","Hidden Environment Variables",{"path":4810,"title":4811},"\u002Fchangelog\u002F2025\u002F01\u002Fimproved-diagnostics","Improved Diagnostics",{"path":4813,"title":4814},"\u002Fchangelog\u002F2025\u002F01\u002Fteam-level-groups","Team level view of Groups",{"path":4816,"title":4817},"\u002Fchangelog\u002F2025\u002F02\u002Fadditional-device-version-history-events","New Remote Instances Version History Events",{"path":4819,"title":4820},"\u002Fchangelog\u002F2025\u002F02\u002Fbroker-error-feedback","Improved Broker Connection Feedback",{"path":4822,"title":4823},"\u002Fchangelog\u002F2025\u002F02\u002Fdevice-agent-updates","FlowFuse User Authentication on Remote Instances",{"path":4825,"title":4420},"\u002Fchangelog\u002F2025\u002F02\u002Fdevice-version-history-timeline",{"path":4827,"title":4828},"\u002Fchangelog\u002F2025\u002F02\u002Fexternal-brokers","External MQTT Brokers",{"path":4830,"title":4831},"\u002Fchangelog\u002F2025\u002F02\u002Fmqtt-schema-suggestions","MQTT Smart Schema Suggestions",{"path":4833,"title":4834},"\u002Fchangelog\u002F2025\u002F02\u002Fresend-and-extend-team-invitation-expiration","Re-send Team Invitations",{"path":4836,"title":4837},"\u002Fchangelog\u002F2025\u002F02\u002Fschema-docs","Personalized Schema Documentation",{"path":4839,"title":4840},"\u002Fchangelog\u002F2025\u002F02\u002Ftopic-hierarchy-search","Search & Filter for Topic Hierarchy List",{"path":4842,"title":4843},"\u002Fchangelog\u002F2025\u002F03\u002Fcontainer-tags","Changes to tags for flowfuse\u002Fnode-red",{"path":4845,"title":4846},"\u002Fchangelog\u002F2025\u002F03\u002Fdevice-groups","Multiple Device Groups in a pipeline",{"path":4848,"title":4849},"\u002Fchangelog\u002F2025\u002F03\u002Fdevice-local-login","Local Login for Remote Instances",{"path":4851,"title":4852},"\u002Fchangelog\u002F2025\u002F03\u002Ffree-tier","Free Tier now more accessible to all",{"path":4854,"title":4855},"\u002Fchangelog\u002F2025\u002F03\u002Fresource-notifications","Resource Alerts",{"path":4857,"title":4858},"\u002Fchangelog\u002F2025\u002F03\u002Fsnapshot-filter","Filtering Snapshots",{"path":4860,"title":4861},"\u002Fchangelog\u002F2025\u002F03\u002Fteam-npm-registry","NPM Package Hosting",{"path":4863,"title":4864},"\u002Fchangelog\u002F2025\u002F03\u002Ftopic-deletion","MQTT Topic Management",{"path":4866,"title":4867},"\u002Fchangelog\u002F2025\u002F04\u002Fdevice-provisioning","Remote Instance Provisioning",{"path":4869,"title":4870},"\u002Fchangelog\u002F2025\u002F04\u002Fgit-integration","Git Integration with Pipelines",{"path":4872,"title":4873},"\u002Fchangelog\u002F2025\u002F04\u002Finstance-log-browsing","Better Node-RED log handling",{"path":4875,"title":4876},"\u002Fchangelog\u002F2025\u002F05\u002Fimport-node-red-flows","Import Node-RED Flows During Remote Instance Setup",{"path":4878,"title":4879},"\u002Fchangelog\u002F2025\u002F06\u002Fflowfuse-assistant","FlowFuse Expert just got smarter",{"path":4881,"title":4879},"\u002Fchangelog\u002F2025\u002F06\u002Fflowfuse-assistant-2",{"path":4883,"title":4884},"\u002Fchangelog\u002F2025\u002F06\u002Fgit-integration","Pulling snapshots from Git with Pipelines",{"path":4886,"title":4887},"\u002Fchangelog\u002F2025\u002F06\u002Finstance-performance-memory","Memory Metrics in Instance Performance View",{"path":4889,"title":4890},"\u002Fchangelog\u002F2025\u002F06\u002Fnew-home-page","Introducing the New Home Page Experience",{"path":4892,"title":4893},"\u002Fchangelog\u002F2025\u002F06\u002Fteam-performance","Team Performance Feature",{"path":4895,"title":4896},"\u002Fchangelog\u002F2025\u002F06\u002Fteam-performance-view","Instance Performance View",{"path":4898,"title":4899},"\u002Fchangelog\u002F2025\u002F06\u002Fui-refresh","Navigation UI Refresh",{"path":4901,"title":4902},"\u002Fchangelog\u002F2025\u002F07\u002Fbrowse-node-red-flows","Browse for Node-RED Flows During Remote Instance Setup",{"path":4904,"title":163},"\u002Fchangelog\u002F2025\u002F07\u002Fflowfuse-tables",{"path":4906,"title":4907},"\u002Fchangelog\u002F2025\u002F07\u002Fimport-blueprints","Import blueprints directly into your existing instances",{"path":4909,"title":4910},"\u002Fchangelog\u002F2025\u002F07\u002Fsimplified-applications-overview","Simplified Applications Page with Summary Tiles",{"path":4912,"title":4913},"\u002Fchangelog\u002F2025\u002F07\u002Fsmart-suggestions","Smart Suggestions",{"path":4915,"title":4916},"\u002Fchangelog\u002F2025\u002F07\u002Fteam-to-pro-plan-rename","Team Plan Renamed to Pro Plan",{"path":4918,"title":4919},"\u002Fchangelog\u002F2025\u002F08\u002Fai-generated-snapshot-descriptions-hosted","Generate snapshot descriptions with AI",{"path":4921,"title":4922},"\u002Fchangelog\u002F2025\u002F08\u002Fai-generated-snapshot-descriptions-remote","AI Snapshot Descriptions Now Work with Remote Instances",{"path":4924,"title":4925},"\u002Fchangelog\u002F2025\u002F08\u002Fdevice-performance","FlowFuse Remote Instance Performance Data",{"path":4927,"title":4928},"\u002Fchangelog\u002F2025\u002F08\u002Fdirect-sso","Direct SSO Login",{"path":4930,"title":4931},"\u002Fchangelog\u002F2025\u002F08\u002Fflowfuse-assistant","FlowFuse Expert documents your flows",{"path":4933,"title":4934},"\u002Fchangelog\u002F2025\u002F08\u002Fflowfuse-mqtt","FlowFuse MQTT",{"path":4936,"title":4937},"\u002Fchangelog\u002F2025\u002F08\u002Fhttp-cors","Configure HTTP CORS",{"path":4939,"title":4940},"\u002Fchangelog\u002F2025\u002F08\u002Fsubflow-export","Export SubFlow as Node-RED module",{"path":4942,"title":4943},"\u002Fchangelog\u002F2025\u002F08\u002Ftables-assistant","FlowFuse Tables with a little help from the Assistant",{"path":4945,"title":4946},"\u002Fchangelog\u002F2025\u002F09\u002Fexpose-saml-groups-to-dashboard","Allow SSO groups to be shared with the Node-RED Dashboard",{"path":4948,"title":4949},"\u002Fchangelog\u002F2025\u002F09\u002Finline-assist","FlowFuse Expert can help you write code",{"path":4951,"title":4952},"\u002Fchangelog\u002F2025\u002F09\u002Fretiring-flowforge-device-agent","No more @flowforge\u002Fflowforge-device-agent releases",{"path":4954,"title":4955},"\u002Fchangelog\u002F2025\u002F09\u002Frevised-instance-snapshot-ui","Streamlined Snapshot Management",{"path":4957,"title":4958},"\u002Fchangelog\u002F2025\u002F09\u002Fteam-broker-async-api","Capture Async API data from FlowFuse Team Broker",{"path":4960,"title":4961},"\u002Fchangelog\u002F2025\u002F10\u002Fapplication-level-rbac","Application-level access control for Enterprise teams",{"path":4963,"title":4964},"\u002Fchangelog\u002F2025\u002F10\u002Fbulk-device-group-assignment","Easier Access to Bulk Device Group Management",{"path":4966,"title":4967},"\u002Fchangelog\u002F2025\u002F10\u002Fduplicate-instances-across-applications","Duplicate Instances Across Different Applications",{"path":4969,"title":4970},"\u002Fchangelog\u002F2025\u002F10\u002Fimport-flows-on-instance-creation","Import flows during instance creation",{"path":4972,"title":4973},"\u002Fchangelog\u002F2025\u002F10\u002Fmcp-nodes","FlowFuse MCP Server Nodes",{"path":4975,"title":4976},"\u002Fchangelog\u002F2025\u002F10\u002Fonnx-nodes","FlowFuse AI Nodes",{"path":4978,"title":4979},"\u002Fchangelog\u002F2025\u002F10\u002Fsettings-page-device-group-management","Device Group Management from Settings Page",{"path":4981,"title":4982},"\u002Fchangelog\u002F2025\u002F11\u002Fff-expert-update","FlowFuse Expert Update",{"path":4984,"title":4985},"\u002Fchangelog\u002F2025\u002F11\u002Fminimum-nodejs-version","Node.js v20 Minimum Version Requirement",{"path":4987,"title":4988},"\u002Fchangelog\u002F2025\u002F11\u002Fsso-session","SSO control over Session life",{"path":4990,"title":4991},"\u002Fchangelog\u002F2025\u002F12\u002Fff-expert-mcp-insights","FlowFuse Expert: Now with MCP-Powered Insights",{"path":4993,"title":4994},"\u002Fchangelog\u002F2025\u002F12\u002Fscheduled-maintenance","Scheduled Maintenance Mode",{"path":4996,"title":4997},"\u002Fchangelog\u002F2026\u002F01\u002Fdevice-agent-containers","Device Agent Docker Containers updated",{"path":4999,"title":5000},"\u002Fchangelog\u002F2026\u002F01\u002Fff-expert-manage-palette","FlowFuse Expert: Enhanced Palette Integration",{"path":5002,"title":5003},"\u002Fchangelog\u002F2026\u002F01\u002Fff-expert-nr-actions","FlowFuse Expert: Integration with Node-RED",{"path":5005,"title":5006},"\u002Fchangelog\u002F2026\u002F01\u002Fff-expert-palette-queries","FlowFuse Expert: Palette Queries",{"path":5008,"title":5009},"\u002Fchangelog\u002F2026\u002F01\u002Fff-expert-select-flows","FlowFuse Expert: Ask about your flows",{"path":5011,"title":5012},"\u002Fchangelog\u002F2026\u002F01\u002Fmcp-rbacs","FlowFuse Expert: MCP-Powered Insights with RBACs",{"path":5014,"title":5015},"\u002Fchangelog\u002F2026\u002F01\u002Fmcp-security","FlowFuse Expert: MCP-Powered Insights",{"path":5017,"title":5018},"\u002Fchangelog\u002F2026\u002F02\u002Fdevice-agent-nodejs-options","Set Node.js Options for Remote Instances",{"path":5020,"title":5021},"\u002Fchangelog\u002F2026\u002F02\u002Fff-expert-debug-log-context","FlowFuse Expert: Helping you make sense of your debug log",{"path":5023,"title":5024},"\u002Fchangelog\u002F2026\u002F02\u002Fff-expert-update-banner","FlowFuse Expert: Never Miss an Update",{"path":5026,"title":5027},"\u002Fchangelog\u002F2026\u002F02\u002Fha-instance-rolling-restart","HA Hosted Instance Rolling Restart",{"path":5029,"title":5030},"\u002Fchangelog\u002F2026\u002F02\u002Fremote-instances-immersive-editor","Immersive Mode for Remote Instances",{"path":5032,"title":5033},"\u002Fchangelog\u002F2026\u002F02\u002Frestoring-snapshots-to-remote-instances","Restoring snapshots to developer-mode Remote Instances",{"path":5035,"title":5036},"\u002Fchangelog\u002F2026\u002F03\u002Fazure-dev-ops-gitops","Azure DevOps Pipeline support",{"path":5038,"title":5039},"\u002Fchangelog\u002F2026\u002F03\u002Fdeveloper-mode-in-immersive-editor","Developer Mode Now Accessible from the Immersive Editor",{"path":5041,"title":5042},"\u002Fchangelog\u002F2026\u002F03\u002Fembedded-editor-tab-title","Embedded Editor Now Shows Active Tab",{"path":5044,"title":5045},"\u002Fchangelog\u002F2026\u002F03\u002Fmarch-scheduled-maintenance","Updated: Upcoming Scheduled Server Maintenance on March 28th, 2026",{"path":5047,"title":5048},"\u002Fchangelog\u002F2026\u002F03\u002Fsnapshot-detail-modal-immersive-editor","View Snapshot Details in the Immersive Editor",{"path":5050,"title":5051},"\u002Fchangelog\u002F2026\u002F04\u002Fexpert-action-links","FlowFuse expert action links",{"path":5053,"title":5054},"\u002Fchangelog\u002F2026\u002F04\u002Fhosted-instance-url-env-var","Hosted Instances know their own URL",{"path":5056,"title":4314},"\u002Fchangelog\u002F2026\u002F04\u002Fimmersive-editor-drawer",{"path":5058,"title":5059},"\u002Fchangelog\u002F2026\u002F04\u002Fsnapshot-diff-viewer","Richer snapshot comparison view",{"path":5061,"title":5062},"\u002Fchangelog\u002F2026\u002F05\u002Fai-opt-out","AI Feature Opt-Out for Teams",{"path":5064,"title":5065},"\u002Fchangelog\u002F2026\u002F05\u002Fexpert-application-building","FlowFuse Expert Builds Your Application",{"path":5067,"title":5068},"\u002Fchangelog\u002F2026\u002F05\u002Fsingle-sso-provider","Single SSO provider for all users",{"path":5070,"title":5071},"\u002Fchangelog\u002F2026\u002F06\u002Fdark-mode","Dark Mode",{"path":5073,"title":5074},"\u002Fchangelog\u002F2026\u002F06\u002Fdevice-agent-v4-released","Device Agent v4 released",{"path":5076,"title":5077},"\u002Fchangelog\u002F2026\u002F06\u002Fgeneric-git-server-support","Connect Pipelines to Any Git Server",{"path":5079,"title":5080},"\u002Fchangelog\u002F2026\u002F06\u002Fjuly-scheduled-maintenance","Updated: Upcoming Scheduled Server Maintenance on July 11th, 2026",{"path":5082,"title":5083},"\u002Fchangelog\u002F2026\u002F07\u002Fapplication-sso-groups","Application Roles from SSO Groups",{"path":5085,"title":5086},"\u002Fchangelog\u002F2026\u002F07\u002Fdevice-agent-onboarding","Getting started with FlowFuse straight from the terminal",{"path":5088,"title":5089},"\u002Fchangelog\u002F2026\u002F07\u002Fexpert-enhancements","FlowFuse Expert Enhancements",{"path":5091,"title":5092},"\u002Fchangelog\u002F2026\u002F07\u002Fexpert-tables-automation","FlowFuse Expert Can Now Work With Your Tables",{"path":5094,"title":5095},"\u002Fchangelog\u002F2026\u002F07\u002Fscoped-pats","Team Scoped Personal Access Tokens",{"path":5097,"title":5098},"\u002Fchangelog\u002F2026\u002F07\u002Fteam-and-application-dashboards","A Dedicated Home for Your Dashboards",[],1786105902431]