[{"data":1,"prerenderedAt":289},["ShallowReactive",2],{"agmd-node-red-oee-edge-aggregator":3,"application-guide-nav":187},{"id":4,"title":5,"blurb":6,"body":7,"description":176,"extension":177,"guide":178,"meta":179,"navOrder":180,"navTitle":5,"navigation":181,"parent":182,"path":183,"seo":184,"slug":13,"stem":185,"__hash__":186},"applicationGuideDoc\u002Fapplication-guide\u002Fnode-red\u002Foee-edge-aggregator.md","OEE - Edge Aggregator","The edge app from the OEE use case as a Node-RED flow — a straight-line flow packaged as a subflow and configured per line (its PLC tags, via a config UI and a get-config node), with the data treated as a stream and its counts held in context.",{"type":8,"value":9,"toc":168},"minimark",[10,14,24,29,93,97,105,109,158],[11,12,5],"h1",{"id":13},"oee-edge-aggregator",[15,16,17,18,23],"p",{},"The edge app from the FlowFuse ",[19,20,22],"a",{"href":21},"\u002Fapplication-guide\u002Fflowfuse\u002Fworked-example\u002F","OEE worked example"," — it reads a line's machine signals and publishes its state, one Remote Instance per line. The flow logic is a simple straight line; the choices that matter are packaging it for reuse and treating the data as a stream.",[25,26,28],"h2",{"id":27},"definition","Definition",[30,31,32,40,61,81,87],"ul",{},[33,34,35,39],"li",{},[36,37,38],"strong",{},"The app"," — reads a line's machine signals and publishes its state.",[33,41,42,45,46,50,51,55,56,60],{},[36,43,44],{},"Design pattern"," — ",[19,47,49],{"href":48},"\u002Fapplication-guide\u002Fnode-red\u002Fdesign-patterns\u002F","subflow",", applied to the ",[52,53,54],"em",{},"whole"," flow (not to extract an internal seam): the straight-line flow is packaged as one subflow and dropped onto every line, each configured with its own line's PLC tags as per-instance config — the Node-RED side of the ",[19,57,59],{"href":58},"\u002Fapplication-guide\u002Fflowfuse\u002Fhardware-apps\u002F","Configurable App"," pattern.",[33,62,63,45,66,70,71,74,75,80],{},[36,64,65],{},"Data handling",[19,67,69],{"href":68},"\u002Fapplication-guide\u002Fnode-red\u002Fhandling-data\u002F","classify"," (the signals are a telemetry ",[36,72,73],{},"stream",", read at the poll cadence) → hold the running run\u002Fstop counts in ",[36,76,77],{},[19,78,79],{"href":68},"context",".",[33,82,83,86],{},[36,84,85],{},"Runs on"," — a Remote Instance, one per line.",[33,88,89,92],{},[36,90,91],{},"Why this shape"," — the same complete job runs identically on every line, right next to the equipment, and keeps working if the link drops.",[25,94,96],{"id":95},"the-flow","The flow",[98,99],"flow-diagram",{":edges":100,":groups":101,":legend":102,":nodes":103,"align":104},"[{\"from\":\"ui\",\"to\":\"cfg\",\"label\":\"save tags\"},{\"from\":\"cfg\",\"to\":\"getcfg\",\"dashed\":true,\"label\":\"load tags\"},\"tick>getcfg\",\"getcfg>read\",\"read>calc\",\"calc>pub\",{\"from\":\"read\",\"to\":\"catch\",\"dashed\":true,\"accent\":\"red\",\"label\":\"catches (scope)\"}]","[{\"label\":\"Edge Aggregator · one subflow, dropped on every line\",\"accent\":\"teal\",\"nodes\":[\"ui\",\"cfg\",\"tick\",\"getcfg\",\"read\",\"calc\",\"pub\"]}]","[{\"line\":\"neutral\",\"dashed\":true,\"label\":\"context read\"},{\"line\":\"red\",\"dashed\":true,\"label\":\"Catch scope · not a wire\"}]","[{\"id\":\"ui\",\"label\":\"config UI\",\"sub\":\"set this line's tags\",\"accent\":\"blue\",\"col\":2,\"row\":1},{\"id\":\"cfg\",\"label\":\"context\",\"sub\":\"tag config\",\"accent\":\"green\",\"col\":3,\"row\":1},{\"id\":\"tick\",\"label\":\"inject \u002F timer\",\"sub\":\"poll tick\",\"accent\":\"indigo\",\"col\":1,\"row\":2},{\"id\":\"getcfg\",\"label\":\"get config\",\"sub\":\"load the tags\",\"col\":2,\"row\":2},{\"id\":\"read\",\"label\":\"PLC read\",\"sub\":\"reads those tags\",\"col\":3,\"row\":2},{\"id\":\"calc\",\"label\":\"compute state\",\"sub\":\"counts in context\",\"col\":4,\"row\":2},{\"id\":\"pub\",\"label\":\"MQTT out\",\"sub\":\"publish line state\",\"accent\":\"indigo\",\"col\":5,\"row\":2},{\"id\":\"catch\",\"label\":\"Catch\",\"sub\":\"scoped to the read\",\"accent\":\"red\",\"col\":3,\"row\":3}]","left",[25,106,108],{"id":107},"why-these-choices","Why these choices",[30,110,111,121,131,137,143],{},[33,112,113,116,117,120],{},[36,114,115],{},"Subflow, applied whole-flow"," — the flow itself is a straight line with no seams to extract, so there's no ",[52,118,119],{},"internal"," pattern to reach for. But because the same complete flow runs on every line, it's packaged as a subflow — reuse across instances is exactly the subflow rung. The pattern is applied to the whole flow, not to a piece inside it.",[33,122,123,126,127,130],{},[36,124,125],{},"Configured per line — why it's a Configurable App"," — a config UI node sets this line's PLC tag names into context; a ",[52,128,129],{},"get config"," node in front of the PLC read loads them, so the one subflow reads different tags on every line without changing the build. That per-line configuration is exactly what makes it a Configurable App.",[33,132,133,136],{},[36,134,135],{},"Classify: it's a stream"," — the signals are telemetry read at the poll cadence, so the latest value matters more than any single earlier one. One read → one compute → one publish per tick; the poll interval already paces it, so there's no fast-in \u002F slow-out to rate-limit.",[33,138,139,142],{},[36,140,141],{},"Context for the counts"," — running run\u002Fstop counts live in flow context, not threaded through the wires.",[33,144,145,148,149,152,153,157],{},[36,146,147],{},"Catch the read"," — a PLC read can time out; a Catch scoped to the read handles a dropped read so it doesn't stall the publish. A Catch node isn't wired ",[52,150,151],{},"from"," the read — it registers to catch errors in its scope, so the dashed line shows that scope, not a connection. Catching errors is ",[19,154,156],{"href":155},"\u002Fapplication-guide\u002Fnode-red\u002Fgood-form\u002F","good form",", not a per-flow choice.",[159,160,162],"callout",{"icon":161},"i-lucide-check",[15,163,164,167],{},[36,165,166],{},"In one line"," — a subflow per line: set the tags in a config UI, load them, then poll → read → compute → publish (with a scoped catch); the data call is treating it as a stream and holding the counts in context.",{"title":169,"searchDepth":170,"depth":170,"links":171},"",4,[172,174,175],{"id":27,"depth":173,"text":28},2,{"id":95,"depth":173,"text":96},{"id":107,"depth":173,"text":108},"The edge app from the FlowFuse OEE worked example — it reads a line's machine signals and publishes its state, one Remote Instance per line. The flow logic is a simple straight line; the choices that matter are packaging it for reuse and treating the data as a stream.","md","node-red",{},4.1,true,"worked-examples","\u002Fapplication-guide\u002Fnode-red\u002Foee-edge-aggregator",{"title":5,"description":176},"application-guide\u002Fnode-red\u002Foee-edge-aggregator","QgC-jBpb-CdFxFBcCqH0t9WM3SdTqkGDECXhtn7GW8k",[188,196,199,204,207,213,218,223,227,233,237,242,247,251,253,259,265,270,275,280,284],{"guide":189,"slug":190,"title":191,"navOrder":192,"parent":193,"blurb":194,"path":195},"flowfuse","overview","Overview",1,null,"The map of the FlowFuse guide — apps, architectures, and a worked example.","\u002Fapplication-guide\u002Fflowfuse\u002Foverview\u002F",{"guide":178,"slug":190,"title":191,"navOrder":192,"parent":193,"blurb":197,"path":198},"The map of the Node-RED guide — the pattern families that turn an app into a clean flow.","\u002Fapplication-guide\u002Fnode-red\u002Foverview\u002F",{"guide":189,"slug":200,"title":201,"navOrder":173,"parent":193,"blurb":202,"path":203},"foundations","Foundations","The foundation to build on: what FlowFuse is, its core pieces, and how code is shared across teams.","\u002Fapplication-guide\u002Fflowfuse\u002Ffoundations\u002F",{"guide":178,"slug":200,"title":201,"navOrder":173,"parent":193,"blurb":205,"path":206},"The handful of concepts you need to build with Node-RED, and how they fit together.","\u002Fapplication-guide\u002Fnode-red\u002Ffoundations\u002F",{"guide":189,"slug":208,"title":209,"navOrder":210,"parent":193,"blurb":211,"path":212},"app-delivery-methods","App delivery methods",3,"Two different units of code, delivered two ways. Ship the whole app — a complete, versioned project promoted through environments — or publish one reusable piece — a package the whole team installs and upgrades in one place. Pick by what you're shipping: the app, or a part of it.","\u002Fapplication-guide\u002Fflowfuse\u002Fapp-delivery-methods\u002F",{"guide":178,"slug":214,"title":215,"navOrder":210,"parent":193,"blurb":216,"path":217},"patterns","Patterns","The moves that turn an architecture into a clean, reusable flow — find the seams and reuse well, then handle data on the right paths.","\u002Fapplication-guide\u002Fnode-red\u002Fpatterns\u002F",{"guide":189,"slug":219,"title":220,"navOrder":221,"parent":208,"blurb":222,"path":58},"hardware-apps","Hardware apps",3.1,"The three shapes a FlowFuse app takes when it runs on a device. Pick by how much varies per site: nothing (Packaged App), a few settings (Configurable App), or you assemble it yourself (Edge Building Block).",{"guide":178,"slug":224,"title":225,"navOrder":221,"parent":214,"blurb":226,"path":48},"design-patterns","Design patterns","The structural choices you select for a flow: find the seams it breaks into, then reuse each piece at the lightest level that solves it — link in\u002Fout, link call, subflow, or packaged node.",{"guide":189,"slug":228,"title":229,"navOrder":230,"parent":208,"blurb":231,"path":232},"software-apps","Software apps",3.2,"The three shapes a FlowFuse app takes when it runs on the platform. Pick by what it needs: a headless job (Packaged App), a user-facing app driven by data (Data-Driven App), or a reusable piece other apps embed (Shared Building Block).","\u002Fapplication-guide\u002Fflowfuse\u002Fsoftware-apps\u002F",{"guide":178,"slug":234,"title":235,"navOrder":230,"parent":214,"blurb":236,"path":68},"handling-data","Handling data","Classify each signal by shape, purpose and direction, then pick the methods it needs — separate the paths, pace the flow, hold state in context, and manage config. The methods you select to move a flow's data.",{"guide":178,"slug":238,"title":239,"navOrder":240,"parent":214,"blurb":241,"path":155},"good-form","Good form",3.3,"A clean flow isn't luck — it's a handful of habits. Wire for reading, lay it out on a grid, decouple UI from logic, catch errors where you can see them, and keep data on a stable contract. Follow these and a flow stays readable, reusable, and out of spaghetti.",{"guide":189,"slug":243,"title":244,"navOrder":170,"parent":193,"blurb":245,"path":246},"data-plane","Data plane","Before you pick where things run, decide how data is handled. Two stores come built into every FlowFuse server install — the Team Broker and relational Tables — exposed to every instance with nothing extra to stand up. Everything else you bring your own: run it (a time-series DB, an existing database, a model) and expose it to the fleet over Project Link, no inbound ports. This is the data plane the architectures on the next pages all sit on.","\u002Fapplication-guide\u002Fflowfuse\u002Fdata-plane\u002F",{"guide":178,"slug":182,"title":248,"navOrder":170,"parent":193,"blurb":249,"path":250},"Worked examples","Turn an app concept into a Node-RED flow — or a few — leaning on the design patterns and data handling. The method, then the OEE apps end to end.","\u002Fapplication-guide\u002Fnode-red\u002Fworked-examples\u002F",{"guide":178,"slug":13,"title":5,"navOrder":180,"parent":182,"blurb":6,"path":252},"\u002Fapplication-guide\u002Fnode-red\u002Foee-edge-aggregator\u002F",{"guide":178,"slug":254,"title":255,"navOrder":256,"parent":182,"blurb":257,"path":258},"oee-central-dashboard","OEE - Central Dashboard",4.2,"The cloud app from the OEE use case as a Node-RED flow — one link out fanning to two link ins on separate tabs (dashboard and batched history), so the live and history paths stay separate and easy to read.","\u002Fapplication-guide\u002Fnode-red\u002Foee-central-dashboard\u002F",{"guide":189,"slug":260,"title":261,"navOrder":262,"parent":193,"blurb":263,"path":264},"architectures","Architectures",5,"Every FlowFuse deployment is the same building blocks arranged for where it runs — pick the world you're designing for.","\u002Fapplication-guide\u002Fflowfuse\u002Farchitectures\u002F",{"guide":189,"slug":266,"title":267,"navOrder":268,"parent":260,"blurb":193,"path":269},"it-architectures","IT architectures",5.1,"\u002Fapplication-guide\u002Fflowfuse\u002Fit-architectures\u002F",{"guide":189,"slug":271,"title":272,"navOrder":273,"parent":260,"blurb":193,"path":274},"ot-architectures","OT architectures",5.2,"\u002Fapplication-guide\u002Fflowfuse\u002Fot-architectures\u002F",{"guide":189,"slug":276,"title":277,"navOrder":278,"parent":260,"blurb":193,"path":279},"iiot-architectures","IIoT architectures",5.3,"\u002Fapplication-guide\u002Fflowfuse\u002Fiiot-architectures\u002F",{"guide":189,"slug":182,"title":248,"navOrder":281,"parent":193,"blurb":282,"path":283},6,"Start from a use case, break it into apps, and draw the architecture that ties them together — the same method a FlowFuse Proof of Value runs.","\u002Fapplication-guide\u002Fflowfuse\u002Fworked-examples\u002F",{"guide":189,"slug":285,"title":286,"navOrder":287,"parent":182,"blurb":288,"path":21},"worked-example","OEE, end to end",6.1,"One use case — OEE across three lines — broken into two apps and two shared services, then drawn out end to end.",1787914463051]