[{"data":1,"prerenderedAt":289},["ShallowReactive",2],{"application-guide-nav":3,"agmd-node-red-oee-edge-aggregator":118},[4,12,16,22,25,31,36,42,47,53,58,64,70,75,81,87,93,98,103,108,112],{"guide":5,"slug":6,"title":7,"navOrder":8,"parent":9,"blurb":10,"path":11},"flowfuse","overview","Overview",1,null,"The map of the FlowFuse guide — apps, architectures, and a worked example.","\u002Fapplication-guide\u002Fflowfuse\u002Foverview\u002F",{"guide":13,"slug":6,"title":7,"navOrder":8,"parent":9,"blurb":14,"path":15},"node-red","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":5,"slug":17,"title":18,"navOrder":19,"parent":9,"blurb":20,"path":21},"foundations","Foundations",2,"The foundation to build on: what FlowFuse is, its core pieces, and how code is shared across teams.","\u002Fapplication-guide\u002Fflowfuse\u002Ffoundations\u002F",{"guide":13,"slug":17,"title":18,"navOrder":19,"parent":9,"blurb":23,"path":24},"The handful of concepts you need to build with Node-RED, and how they fit together.","\u002Fapplication-guide\u002Fnode-red\u002Ffoundations\u002F",{"guide":5,"slug":26,"title":27,"navOrder":28,"parent":9,"blurb":29,"path":30},"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":13,"slug":32,"title":33,"navOrder":28,"parent":9,"blurb":34,"path":35},"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":5,"slug":37,"title":38,"navOrder":39,"parent":26,"blurb":40,"path":41},"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).","\u002Fapplication-guide\u002Fflowfuse\u002Fhardware-apps\u002F",{"guide":13,"slug":43,"title":44,"navOrder":39,"parent":32,"blurb":45,"path":46},"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.","\u002Fapplication-guide\u002Fnode-red\u002Fdesign-patterns\u002F",{"guide":5,"slug":48,"title":49,"navOrder":50,"parent":26,"blurb":51,"path":52},"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":13,"slug":54,"title":55,"navOrder":50,"parent":32,"blurb":56,"path":57},"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.","\u002Fapplication-guide\u002Fnode-red\u002Fhandling-data\u002F",{"guide":13,"slug":59,"title":60,"navOrder":61,"parent":32,"blurb":62,"path":63},"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.","\u002Fapplication-guide\u002Fnode-red\u002Fgood-form\u002F",{"guide":5,"slug":65,"title":66,"navOrder":67,"parent":9,"blurb":68,"path":69},"data-plane","Data plane",4,"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":13,"slug":71,"title":72,"navOrder":67,"parent":9,"blurb":73,"path":74},"worked-examples","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":13,"slug":76,"title":77,"navOrder":78,"parent":71,"blurb":79,"path":80},"oee-edge-aggregator","OEE - Edge Aggregator",4.1,"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.","\u002Fapplication-guide\u002Fnode-red\u002Foee-edge-aggregator\u002F",{"guide":13,"slug":82,"title":83,"navOrder":84,"parent":71,"blurb":85,"path":86},"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":5,"slug":88,"title":89,"navOrder":90,"parent":9,"blurb":91,"path":92},"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":5,"slug":94,"title":95,"navOrder":96,"parent":88,"blurb":9,"path":97},"it-architectures","IT architectures",5.1,"\u002Fapplication-guide\u002Fflowfuse\u002Fit-architectures\u002F",{"guide":5,"slug":99,"title":100,"navOrder":101,"parent":88,"blurb":9,"path":102},"ot-architectures","OT architectures",5.2,"\u002Fapplication-guide\u002Fflowfuse\u002Fot-architectures\u002F",{"guide":5,"slug":104,"title":105,"navOrder":106,"parent":88,"blurb":9,"path":107},"iiot-architectures","IIoT architectures",5.3,"\u002Fapplication-guide\u002Fflowfuse\u002Fiiot-architectures\u002F",{"guide":5,"slug":71,"title":72,"navOrder":109,"parent":9,"blurb":110,"path":111},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":5,"slug":113,"title":114,"navOrder":115,"parent":71,"blurb":116,"path":117},"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.","\u002Fapplication-guide\u002Fflowfuse\u002Fworked-example\u002F",{"id":119,"title":77,"blurb":79,"body":120,"description":281,"extension":282,"guide":13,"meta":283,"navOrder":78,"navTitle":77,"navigation":284,"parent":71,"path":285,"seo":286,"slug":76,"stem":287,"__hash__":288},"applicationGuideDoc\u002Fapplication-guide\u002Fnode-red\u002Foee-edge-aggregator.md",{"type":121,"value":122,"toc":275},"minimark",[123,126,135,140,201,205,213,217,265],[124,125,77],"h1",{"id":76},[127,128,129,130,134],"p",{},"The edge app from the FlowFuse ",[131,132,133],"a",{"href":117},"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.",[136,137,139],"h2",{"id":138},"definition","Definition",[141,142,143,151,170,189,195],"ul",{},[144,145,146,150],"li",{},[147,148,149],"strong",{},"The app"," — reads a line's machine signals and publishes its state.",[144,152,153,156,157,160,161,165,166,169],{},[147,154,155],{},"Design pattern"," — ",[131,158,159],{"href":46},"subflow",", applied to the ",[162,163,164],"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 ",[131,167,168],{"href":41},"Configurable App"," pattern.",[144,171,172,156,175,178,179,182,183,188],{},[147,173,174],{},"Data handling",[131,176,177],{"href":57},"classify"," (the signals are a telemetry ",[147,180,181],{},"stream",", read at the poll cadence) → hold the running run\u002Fstop counts in ",[147,184,185],{},[131,186,187],{"href":57},"context",".",[144,190,191,194],{},[147,192,193],{},"Runs on"," — a Remote Instance, one per line.",[144,196,197,200],{},[147,198,199],{},"Why this shape"," — the same complete job runs identically on every line, right next to the equipment, and keeps working if the link drops.",[136,202,204],{"id":203},"the-flow","The flow",[206,207],"flow-diagram",{":edges":208,":groups":209,":legend":210,":nodes":211,"align":212},"[{\"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",[136,214,216],{"id":215},"why-these-choices","Why these choices",[141,218,219,229,239,245,251],{},[144,220,221,224,225,228],{},[147,222,223],{},"Subflow, applied whole-flow"," — the flow itself is a straight line with no seams to extract, so there's no ",[162,226,227],{},"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.",[144,230,231,234,235,238],{},[147,232,233],{},"Configured per line — why it's a Configurable App"," — a config UI node sets this line's PLC tag names into context; a ",[162,236,237],{},"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.",[144,240,241,244],{},[147,242,243],{},"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.",[144,246,247,250],{},[147,248,249],{},"Context for the counts"," — running run\u002Fstop counts live in flow context, not threaded through the wires.",[144,252,253,256,257,260,261,264],{},[147,254,255],{},"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 ",[162,258,259],{},"from"," the read — it registers to catch errors in its scope, so the dashed line shows that scope, not a connection. Catching errors is ",[131,262,263],{"href":63},"good form",", not a per-flow choice.",[266,267,269],"callout",{"icon":268},"i-lucide-check",[127,270,271,274],{},[147,272,273],{},"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":276,"searchDepth":67,"depth":67,"links":277},"",[278,279,280],{"id":138,"depth":19,"text":139},{"id":203,"depth":19,"text":204},{"id":215,"depth":19,"text":216},"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",{},true,"\u002Fapplication-guide\u002Fnode-red\u002Foee-edge-aggregator",{"title":77,"description":281},"application-guide\u002Fnode-red\u002Foee-edge-aggregator","QgC-jBpb-CdFxFBcCqH0t9WM3SdTqkGDECXhtn7GW8k",1787070953999]