---
title: How to calculate OEE in a unified namespace with the HiveMQ Platform
description: "Build a unified namespace with the HiveMQ Platform and calculate OEE from PLC, MES and ERP data with distributed compute. A step-by-step guide for IT/OT teams."
date: 2026-10-20
author: Sven Kobow
tags:
  - HiveMQ Platform
  - Unified Namespace
source: https://www.hivemq.com/blog/calculate-oee-unified-namespace-hivemq-platform
---

# How to calculate OEE in a unified namespace with the HiveMQ Platform

Two production lines report an OEE of 85 percent. Can anyone show that both lines measure the same thing? Usually not, because the inputs come from different systems: counters from the PLC, planned time from the MES and ideal cycle times from master data, each with its own topics, units and payloads.

A UNS gives all of that data one structure and one meaning. This article shows how to build one with the HiveMQ Platform and how to calculate OEE inside it. It continues our series on the data foundation for real-time operational intelligence.

In the previous article, [De-mystifying MQTT vs. OPC UA: What the comparisons get wrong](/blog/mqtt-vs-opc-ua-what-comparisons-get-wrong/), we looked at MQTT and OPC UA in the Connect layer. This one covers Contextualize, the layer from the [whitepaper on building a scalable data foundation](/resources/building-a-scalable-data-foundation-for-real-time-operational-intelligence/) that gives data its meaning.

## What does a unified namespace need beyond a topic tree?

A [Unified Namespace](/blog/what-is-unified-namespace-uns-iiot-industry-40/) is a single, structured, event-driven source of truth for operational data across a site or an enterprise. It builds on Event-Driven Architecture (EDA): systems publish events and consume them, instead of polling each other. [MQTT's publish/subscribe model](/blog/mqtt-essentials-part2-publish-subscribe/) is what makes this work, and a hierarchy based on [ISA-95](https://www.isa.org/standards-and-publications/isa-standards/isa-standards-committees/isa95) (enterprise, site, area, line, cell) is the most common way to organize the topics.

The hierarchy is only the addressing scheme. Three more things turn it into a namespace. First, shared meaning: two systems that publish to well-named topics still have to agree on what a value, a unit or a state means. Second, governance: someone defines what a valid payload looks like before bad data reaches every consumer at once. Third, reuse: the model has to survive a new line, a new site or a new vendor without a rebuild.

UNS is an open concept, not a product. [The HiveMQ Platform](/platform/) provides a way to implement it and its Contextualize layer covers exactly these three points.

The hierarchy tells you where data lives, but not how to arrange what sits below a line. There is no single correct topic schema for that and several patterns are in use. This article uses one of them, the Orthogonal Planes pattern. It keeps the ISA-95 prefix and separates data by its purpose into planes that sit side by side in the same tree. Each plane has its own kind of content and its own writer. The physical plane holds raw machine data such as state, telemetry and metadata, written by PLCs and SCADA. The business plane holds ERP data such as production orders. The context plane holds computed values such as KPIs, written by a compute layer. The pattern could, for example, also include a batch plane and further planes, depending on your requirements.

We use this pattern because OEE draws on several sources: separate planes show where each input comes from and keep computed values apart from raw signals. It fits this use case well, but it is one possible schema and not the schema for every unified namespace.

![Unified Namespace hierarchy showing physical, business and context data planes organized using ISA-95 on HiveMQ Platform](https://a.storyblok.com/f/243938/41f5cf5ca5/oee-uns-uns-orthogonal-planes-pattern.png)

*The Orthogonal Planes naming pattern: physical, business and context plane side by side under the same ISA-95 prefix*

## OEE calculation example: Connecting PLC, MES and ERP data in a Unified Namespace

The example is a fictional waffle producer, SweetHarmonyTreats, with one site in Berlin and one packaging cell at the end of its line. OEE is the product of three factors: availability (run time divided by planned time), performance (actual output against the output possible at the ideal cycle time) and quality (good units divided by total units).

The inputs come from four sources:

| Source      | Data                                     | Topic (below the line)                     |
| ----------- | ---------------------------------------- | ------------------------------------------ |
| PLC         | State, run time, total count, good count | packaging/state and packaging/telemetry/\* |
| MES         | Planned production time                  | packaging/telemetry/planned-time           |
| Master data | Ideal cycle time and rated speed         | packaging/metadata/capacity-spec           |
| ERP         | Production order                         | business/production-order                  |

We apply the Orthogonal Planes pattern from above: raw machine data (physical plane), business data (business plane) and computed values (context plane) live in separate branches under the same ISA-95 prefix. They have different owners, update rates and access needs, and a computed KPI must never be mistaken for a raw signal. The target tree looks like this:

Payloads are plain JSON. Counters carry a value, a unit where it applies and a timestamp. Master data and orders use descriptive field names:

Two assumptions keep the example simple. The counters are cumulative: they count from the start of the source, so the OEE describes that period. If your source resets them at shift change, the OEE starts again with the new shift. Planned time is the planned production time that has elapsed since the counters started, not the length of a whole shift. You need HiveMQ 4.55 (LTS) or later. Cloud Serverless and Starter clusters are not eligible for the data intelligence features.

## Step 1: Connecting MQTT brokers on HiveMQ Platform for OEE data collection

Open Connect and add the Broker or Edge instance that receives your machine data. The Data Intelligence column shows whether it is connected to the Contextualize and Analyze features. Nothing changes for your publishers: the PLC gateway, the MES and the ERP integration keep publishing to the same broker. The namespace is a layer over live MQTT traffic, not a new transport.

![HiveMQ Platform Connect interface showing connected MQTT brokers and Data Intelligence status](https://a.storyblok.com/f/243938/461ad1938a/oee-uns-connect-broker-data-intelligence.png)

*The Connect page with the broker and its Data Intelligence status*

## Step 2: Discovering existing MQTT data sources with HiveMQ Contextualize

Open Contextualize and the Discovery tab. It lists the ungoverned MQTT traffic of your connected brokers: topics that are flowing but are not part of any namespace yet. For each topic you see a suggested data type and serialization format, the message rate and an example payload. Approve the topics you want to keep into the namespace or ignore the rest. Approving creates the matching nodes and any missing parent nodes, and the new nodes start inactive. Topics that publish rarely, such as master data, appear only after their next message.

This bottom-up route is the fastest start. You accept what already exists and refine the structure in the next step.

![HiveMQ Contextualize Discovery tab displaying MQTT topics available for namespace creation](https://a.storyblok.com/f/243938/952754dc87/oee-uns-discovery-tab-topics.png)

*The Discovery tab with the seven discovered topics*

![HiveMQ Contextualize showing an MQTT topic with its message payload and detected data format](https://a.storyblok.com/f/243938/afba03d68d/oee-uns-discovered-topic-payload.png)

*Details of a discovered topic with a preview of its payload*

![HiveMQ Contextualize displaying fields automatically inferred from an MQTT JSON payload](https://a.storyblok.com/f/243938/f06dca595c/oee-uns-discovery-inferred-fields.png)

*The fields Discovery inferred from the payload*

![HiveMQ Contextualize interface for approving discovered MQTT topics into the Unified Namespace](https://a.storyblok.com/f/243938/dceb5f3b3f/oee-uns-approve-topics.png)

*Approving the selected topics into the namespace*

## Step 3: Structuring and activating your Unified Namespace

Discovery has already created most of the tree, including the *Field* nodes it inferred from the JSON payloads, so there is nothing to build from scratch. Switch to the Namespace tab to refine what is there. The Platform offers the node types *Enterprise*, *Site*, *Area*, *Line*, *Asset*, *Folder*, *Tag* and *Field*. Two things are left to do: activate the nodes you need and set the node types, which we cover in the next section. The folders for the calculated values do not exist yet: we add them in step 5 as part of the cell model. The topic level of a node is a segment of its MQTT topic, so tree and topic stay identical.

*Tags* with JSON payloads get *Field* nodes, one per JSON key. Discovery infers them from the example payload, so you only check them and do not create them by hand. *Fields* give your expressions readable names. In capacity-spec they are rated\_units\_per\_min and ideal\_cycle\_time\_s, so a formula can refer to ideal\_cycle\_time\_s and not to a generic value. Related data in one tag is also consumed together.

New nodes are inactive: they store no history, calculate nothing and report no deviations until you activate them. Activating a node also activates the nodes it depends on. By default a *Tag* keeps its latest value, so raise the history limits where a calculation needs more. Before you change or delete a node, check its Consumers tab.

![Unified Namespace tree showing MQTT tags and fields organized in HiveMQ Contextualize](https://a.storyblok.com/f/243938/7af20c561d/oee-uns-namespace-tree-tags-fields.png)

*The namespace tree with the tags and fields*

![HiveMQ Contextualize dialog showing node activation and dependent nodes in the Unified Namespace](https://a.storyblok.com/f/243938/45bbad0e13/oee-uns-activate-node-dependencies.png)

*Activating a node also activates the nodes it depends on*

![HiveMQ Contextualize settings for configuring MQTT tag history limits](https://a.storyblok.com/f/243938/e1454dcb7e/oee-uns-tag-history-limits.png)

*History limits of a tag*

![HiveMQ Contextualize Consumers tab showing dependencies between Unified Namespace nodes](https://a.storyblok.com/f/243938/eaaf053e2a/oee-uns-consumers-tab.png)

*The Consumers tab shows which nodes depend on a node*

### How do you adjust the ISA-95 node types after Discovery?

Discovery creates the missing parent nodes of an approved topic by itself, but it only knows the topic path, not what each level stands for. The meaning comes from the node type, so set the types now, before you build on them in the next steps.

Select a node, choose Edit in the node header and set the type. Work from the top:

sweetharmonytreats becomes an *Enterprise*, berlin a *Site*, bakery an *Area* and waffleline01 a *Line*. The cell packaging stays a *Folder*, as do telemetry, metadata and business. The topics you approved, such as state, run-time and capacity-spec, stay *Tags*.

*Enterprise*, *Site*, *Area* and *Line* are specializations of *Folder*.

They group nodes the same way, but the type says what a level is, and the Platform builds on it. The computations in step 5, for example, need a *Site* that has a relation to the broker.

![HiveMQ Contextualize interface for assigning node types in an ISA-95 namespace hierarchy](https://a.storyblok.com/f/243938/ec7dac5457/oee-uns-set-node-type.png)

*Setting the node type with Edit in the node header*

![ISA-95 Unified Namespace hierarchy showing enterprise, site, area, line and production cell nodes](https://a.storyblok.com/f/243938/e11257dafe/oee-uns-namespace-node-types.png)

*The namespace tree with the node types set*

## Step 4: Creating reusable data models for consistent OEE calculations

Wouldn't it be nice if you did not have to start every cell from scratch? The packaging cell is only the first of many. A real plant has dozens of cells, and each one needs the same nodes, the same field names and the same KPIs. Building them by hand does not scale, and every copy is a chance for a small difference that makes the numbers incomparable.

A data model solves this. In general, a data model is a blueprint: it describes the structure and meaning of a part of the namespace once, and you create instances of it wherever you need it. In the HiveMQ Platform you derive a model from an existing node and its subtree, replace the parts that differ with variables and publish it as a versioned model. You then instantiate it below a matching node, and existing instances can be upgraded to a new version.

Select the cell and choose *Derive New Model*. Replace the cell name with a variable such as . Variables work in node names and MQTT topic levels and let you specify the actual values during instantiation. Publish version 1. Published versions are immutable, so every change becomes a new version, and existing instances can be upgraded to it but not downgraded.

To apply the model to the cell we already have, you currently need a detour. The topic level of an instance must be unique below its parent, so the discovered node packaging has to go first. Check its *Consumers* tab, delete the node, then open waffleline01 and choose *Instantiate Data Model*. Select production-cell in version 1 and enter packaging as the value of *CELL*. The Platform recreates the cell with its whole subtree.

To add a second cell, instantiate the model below a line, enter the instance name and the variable value, and the Platform creates the whole subtree. Connected brokers receive the updated information model automatically. This is what makes results comparable: a second line, in Berlin or anywhere else, gets the same structure, units and field names, so an OEE of 85 percent on one line means the same on the other. The approach could also be applied to whole lines: a model derived from a line would carry its cells and their KPIs, so a new line arrives complete.

![HiveMQ Contextualize menu for deriving a reusable data model from a production cell](https://a.storyblok.com/f/243938/510251fa25/oee-uns-derive-new-model.png)

*Derive New Model on the cell packaging*

![HiveMQ production-cell data model with configurable CELL variable and MQTT topic hierarchy](https://a.storyblok.com/f/243938/af67961a65/oee-uns-model-draft-cell-variable.png)

*Draft of the model production-cell, with the cell name replaced by the variable CELL*

![HiveMQ Contextualize dialog for publishing a reusable production-cell data model](https://a.storyblok.com/f/243938/8ed5b8b24a/oee-uns-publish-model-draft.png)

*Publishing the draft makes the model available for instantiation*

![HiveMQ Contextualize showing published version 1 of the production-cell data model](https://a.storyblok.com/f/243938/30b50bd418/oee-uns-model-v1-published.png)

*Version v1 of production-cell is published*

![HiveMQ Contextualize menu for creating a production-cell data model instance](https://a.storyblok.com/f/243938/1aeab47a34/oee-uns-instantiate-data-model.png)

*Instantiate Data Model on waffleline01, after the discovered node packaging has been deleted*

![HiveMQ Contextualize dialog for selecting version 1 of the production-cell data model](https://a.storyblok.com/f/243938/e976e744e7/oee-uns-select-model-v1.png)

*Select production-cell in version v1*

![HiveMQ Contextualize form for configuring a production-cell model instance and CELL variable](https://a.storyblok.com/f/243938/5b117f04d8/oee-uns-instance-name-cell-variable.png)

*Instance name and the value of the variable CELL*

![Unified Namespace tree showing the instantiated packaging cell and its MQTT data structure](https://a.storyblok.com/f/243938/54ae54c77c/oee-uns-instantiated-packaging-cell.png)

*The instance below waffleline01 with the cell packaging and its subtree*

## Step 5: Calculating OEE using distributed intelligence in HiveMQ Platform

The HiveMQ Platform is a [distributed intelligence](/blog/why-intelligence-must-be-distributed-not-centralized/) platform: computations are not tied to one central system. The Platform distributes the compute across your connected infrastructure, for example to [HiveMQ Edge](/products/hivemq-edge/) instances or local site brokers. The calculation runs where the data is, with no separate stream processing system and no additional network hop. For this, a computation needs a relation between the site and a connected broker. Open the site, go to *General* and create a new relation with the broker as destination if necessary.

All inputs of the OEE sit in the cell, so the KPIs belong into the cell model as well. Open the production-cell data model and create a new version, v2, based on v1. Add the folders context and kpi below the cell and one tag per result below kpi. For each tag choose *Expression* as the data source and enter the formula. Every variable in a formula becomes an input of the tag: pick the node it reads from. Only nodes of the same model are available, which is why the counters and the KPIs live in one model.

![HiveMQ production-cell data model with context and KPI nodes for OEE calculations](https://a.storyblok.com/f/243938/95aa3a9a09/oee-uns-model-v2-context-kpi.png)

*Version v2 of the production-cell model with the folders context and kpi*

![HiveMQ Contextualize expression editor showing OEE formula and mapped input data nodes](https://a.storyblok.com/f/243938/9cb47177c2/oee-uns-expression-tag-formula.png)

*An expression tag with its formula and the inputs mapped to nodes of the model*

Publish v2 and upgrade the instance of packaging to it. The result appears in the *Data Output* tab. Because the formulas are part of the model, every cell that uses it calculates OEE the same way.

![HiveMQ Contextualize interface for upgrading the packaging cell data model from version 1 to version 2](https://a.storyblok.com/f/243938/0a6affe8df/oee-uns-upgrade-instance-v2.png)

*Upgrading the instance of packaging to v2*

![HiveMQ Contextualize Data Output tab showing calculated KPI values](https://a.storyblok.com/f/243938/4f16cf3bcb/oee-uns-data-output-kpis.png)

*The calculated values in the Data Output tab*

| Result            | Formula                                                          | Inputs                                                             |
| ----------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------ |
| availability\_pct | (run\_time / planned\_time) \* 100                               | packaging/telemetry/run-time, planned-time                         |
| performance\_pct  | ((total\_count \* ideal\_cycle\_time\_s) / run\_time) \* 100     | total-count, run-time, capacity-spec (field ideal\_cycle\_time\_s) |
| quality\_pct      | (good\_count / total\_count) \* 100                              | packaging/telemetry/good-count, total-count                        |
| oee\_pct          | (availability\_pct \* performance\_pct \* quality\_pct) / 10,000 | the three results above                                            |

Performance deserves a closer look. The counters show how many units the cell produced during its run time. Multiplied by the ideal cycle time, that is the time the same output would have needed at ideal speed. The ratio of both is the performance factor. A cell that needs more time per unit than the ideal cycle time loses performance, and the factor drops below 100 percent accordingly.

A general example shows how the factors fit together. Assume a planned time of 600 seconds, a run time of 450 seconds, an ideal cycle time of 4 seconds, 90 units in total and 85 good units. Availability is 450 / 600, so 75 percent. Performance is (90 × 4) / 450, so 80 percent: the cell needed 5 seconds per unit instead of 4. Quality is 85 / 90, so 94.4 percent. Multiplied, this gives an OEE of 56.7 percent. The three factors share terms that cancel out, so the product shortens to good units × ideal cycle time / planned time: 85 × 4 / 600 gives the same 56.7 percent. The values in your own namespace differ with the counters of the cell, but the calculation stays the same.

![Dashboard displaying calculated OEE, availability, performance and quality metrics](https://a.storyblok.com/f/243938/9984a46625/oee-uns-oee-dashboard.png)

*The OEE and its factors on a dashboard*

If you prefer state-based reliability KPIs, the same namespace supports them. The state topic and the BetweenState function calculate MTBF, MTTR and availability, as described in our article on [real-time reliability KPIs](/blog/real-time-reliability-kpis-mtbf-mttr-availability/).

![Dashboard displaying MTBF, MTTR and availability metrics calculated from machine states](https://a.storyblok.com/f/243938/199430d32b/oee-uns-mtbf-mttr-availability.png)

*MTBF, MTTR and availability calculated from the state topic*

Computations can also run over the stored history with the Windowed option, for example for a rolling window instead of a shift.

![HiveMQ Contextualize Data Output showing a computation over stored MQTT data history](https://a.storyblok.com/f/243938/bc7eafbada/oee-uns-windowed-computation.png)

*A computation over the stored history with the Windowed option*

### How do you calculate the OEE of the line?

The cell model gives every cell its own OEE. The line needs a value of its own, and it is not the average of its cells. In this example the line has one cell, and its output at the end of the line is what counts. Create the folders context and kpi directly below waffleline01, outside the model, and add the tag oee\_pct. Choose *Expression*, enter (good\_count \* ideal\_cycle\_time\_s) / planned\_time \* 100 and map the variables with *Add Source* to the nodes of the packaging cell. With a single cell the result equals the OEE of the cell, but it now sits at the level of the line, where a dashboard or an agent looks for it.

With several cells the formula changes, not the approach. For parallel cells of the same kind, add up the good units times the ideal cycle time of every cell and divide by the sum of their planned times. For cells in series, use the output at the end of the line against the ideal cycle time of the slowest cell. A simple average of the cell values would be misleading, because a cell with a short planned time would weigh as much as the others. An expression outside a model can read the nodes of any cell, so it can combine them.

### How do you add the running order to the KPIs?

Computations are not the only way to derive a value. A *Tag* can also use *Link* as its data source, which mirrors another node. That carries context from one plane into another without a new interface. Create a tag current-order-id in the context folder of the line, choose *Link* as the data source and point it at the order\_id field of business/production-order. The order stays in the business plane, and the context plane now shows which order is running while the KPIs are calculated.

Keep the limit in mind: the counters run over time, not per order. The link tells you which order is running. It does not turn the KPIs into order KPIs.

![HiveMQ Contextualize configuration linking production order ID to the manufacturing KPI context](https://a.storyblok.com/f/243938/08e86dbe9c/oee-uns-link-current-order-id.png)

*The tag current-order-id with Link as its data source*

## Step 6: Validating OEE data quality with HiveMQ Platform

Open *Analyze* and the *Data Health* tab. Total traffic splits into governed and ungoverned traffic. Governed traffic splits into healthy traffic, which matches the expected types and structure, and deviating traffic. The *Deviations* tab shows the details. Values that do not match the expected type are skipped and flagged. Governed traffic can show up with a delay.

Check this before you share the number. If a PLC starts to send text where the namespace expects a number, the OEE underneath changes silently, and *Data Health* is where you see it first.

![HiveMQ Analyze Data Health dashboard showing governed, ungoverned, healthy and deviating MQTT traffic](https://a.storyblok.com/f/243938/6531acb6fd/oee-uns-data-health-tab.png)

*The Data Health tab with governed, ungoverned, healthy and deviating traffic*

![HiveMQ Analyze Deviations tab displaying MQTT messages that do not match expected data types](https://a.storyblok.com/f/243938/85cd7b7ca2/oee-uns-deviations-tab.png)

*The Deviations tab with the details of non-matching values*

## How UNS in HiveMQ makes OEE data available to downstream and AI systems in manufacturing

The result is a tag in the namespace, in the context/kpi branch of the cell. Dashboards, the MES, a historian or an AI agent read it from there, and none of them needs its own interface to the PLC, the MES or the ERP. A Grafana dashboard with an MQTT data source, for example, can show the three factors and the OEE live, as soon as the cell publishes them. That is what makes the namespace an integration point: each source publishes once, and every consumer uses the same governed data. There is one more consumer worth a closer look. An OEE of 56 percent tells a person that something is wrong. But what if an AI agent could read the same tag, check it against the state, the production order and the machine data around it, and work out why the value is low and what to do about it? Because the result sits next to the raw data and the business context in one governed structure, an agent finds everything it needs in one place.

That is the idea behind the Act layer of the HiveMQ Platform, and it is the topic of a later article in this series: from a calculated KPI to agents that act on it.

## What comes next: From a calculated Manufacturing KPI to AI agents that can act

Connect moved the data, and Contextualize gave it structure, meaning and a first KPI. The next article in this series covers Analyze: standardized KPIs across lines and sites, and what you can do once the data is governed.

Read the whitepaper this series builds on, [Building a Scalable Data Foundation for Real-Time Operational Intelligence](/resources/building-a-scalable-data-foundation-for-real-time-operational-intelligence/) or [explore the HiveMQ Platform](/platform/) and build your own unified namespace.

## Frequently asked questions

Does a unified namespace replace my existing MES or SCADA system?

No. It sits alongside them as a shared, governed data layer that they publish to and consume from. The systems of record stay where they are.

Where does the HiveMQ Platform calculate OEE?

Where it makes the most sense. The HiveMQ Platform is a distributed intelligence platform: expressions run on the connected infrastructure, for example on a local site broker or a HiveMQ Edge instance, so the calculation can sit close to the data. You need neither a separate stream processing system nor an additional network hop.

Can I calculate the OEE of an entire production line?

Yes, but not by averaging the cell values. The OEE in the data model describes one cell. For parallel cells, add up the good output times the ideal cycle time of each cell and divide by the sum of their planned times. For cells in series, measure the end-of-line output against the ideal cycle time of the slowest cell. In this article we calculate the line value by hand for the single packaging cell, and the same approach extends to more cells.

How does an OEE calculation handle shift changes and counter resets in your factory?

In this example the counters are cumulative, so the OEE describes the time since they started. If your source resets the counters at shift change, the OEE values start again with the new shift. For a rolling window instead of a shift, use the Windowed option.

Is a unified namespace a product or an architecture?

No. It is an open architectural concept. The HiveMQ Platform is one way to implement it, and the model, the topic design and the governance rules remain yours to define.

What data is required to calculate OEE in a Unified Namespace?

Calculating OEE requires planned production time, actual run time, total production count, good unit count and ideal cycle time. In the article's example, these inputs come from PLCs, MES and master data. The Unified Namespace organizes the inputs so they can be used in a consistent calculation. Read our blog, Why is Overall Equipment Effectiveness (OEE) an Important KPI for Industrial Processes? To learn more.

Can HiveMQ Platform calculate OEE in real time?

Yes. HiveMQ Platform uses expressions to calculate OEE from data flowing through the Unified Namespace. Computations run on connected infrastructure, such as a local broker or HiveMQ Edge instance, and the results are available as KPI tags for downstream consumers.
