> For the complete documentation index, see [llms.txt](https://easyedge.gitbook.io/easyedge/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://easyedge.gitbook.io/easyedge/connect-to-applications/namespace-placeholders.md).

# Namespace Placeholders

## Introduction

A namespace provides a structured way to organize and reference data, ensuring that information from different systems can be identified, contextualized, and reused consistently across the enterprise.

### Unified Namespace (UNS)

A Unified Namespace (UNS) is an architectural concept used in modern industrial and IIoT (Industrial Internet of Things) environments to create a **single source of truth** for all data streams within an enterprise. By establishing a **common hierarchical naming structure** (often dot- or slash-delimited), the UNS lets different systems—PLCs, SCADA, MES, ERP, IoT devices—publish and consume data within one consistent framework.

Key benefits of a UNS:

* **Central Data Repository**: All real-time data is collected, published, and consumed in a single place (e.g., an MQTT broker).
* **Hierarchical Organization**: Commonly forms paths like <mark style="color:blue;">factory.line1.machineA.temperature</mark>, conveying clear context.
* **Semantic Context**: Each level of the hierarchy reflects a real-world concept (site, line, machine, sensor, etc.).
* **Scalability and Extensibility**: Adding new devices or systems is easier when they join the already-defined structure.

### ISA-95 Standard

ISA-95 (ANSI/ISA-95 / IEC 62264) is an international standard that defines models and terminology for integrating control systems with enterprise systems. In essence, it:

* **Describes Manufacturing Operations Levels:**
  * Levels 0–1: Sensors, actuators, the physical process.
  * Level 2: Control systems (PLCs, DCS, SCADA).
  * Level 3: Manufacturing Execution Systems (MES).
  * Level 4: Business systems like ERP.
* **Promotes Interoperability**: Provides a framework for how data and functionality should flow between these levels.
* **Defines Hierarchies**: Enterprise → Site → Area → Line → Cell → Machine → etc.

#### How UNS and ISA-95 Work Together

A UNS typically leverages the ISA-95 hierarchy to organize topics and data points (e.g., <mark style="color:blue;">Enterprise.Site.Area.Line.Machine.Sensor</mark>). This alignment:

* Ensures **consistent naming** across IT and OT.
* Simplifies integration for new devices or software.
* Creates a foundation for advanced analytics (digital twins, machine learning, etc.).

***

## Overview: EasyEdge Namespace Placeholders

EasyEdge uses **placeholders** to dynamically build payloads (e.g., MQTT topics, REST payloads) by inserting runtime data such as hierarchical names, values, timestamps, and more.

This document details the **namespace-based placeholders**, how to configure them, and how to use them for flexible custom payload generation. Below you will find:

1. **Namespace Structure Placeholders**
2. **Dynamic Segmenting** (head\[x], tail\[x], segment\[x], parent\[x])
3. **Separators Configuration** (prefix, defaultSeparator, lastSeparator)
4. **Tag Value and Metadata Placeholders** (including conversions)
5. **Timestamp Placeholders** (real, emulated, last touch, fallback)

***

## Namespace Structure Placeholders

### namespace.tag.name

* **Description**: Represents the entire path (formerly known as “fullName”).
* **Example**:

  * If the hierarchical path is: <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>

  <mark style="color:blue;">namespace.tag.name → "Enterprise1.SiteA.Area02.Line1.MachineA.Temperature"</mark>

### namespace.tag.leaf

* **Description**: Returns the **last segment** in the hierarchy (sometimes called the “leaf”). An **alias** for <mark style="color:blue;">namespace.tag.rsegment\[0]</mark>.
* Example:
  * For <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature:</mark>\ <mark style="color:blue;">namespace.tag.leaf → "Temperature"</mark>
  * For <mark style="color:blue;">MachineA → Pressure:</mark>\ <mark style="color:blue;">namespace.tag.leaf → "Pressure"</mark>
  * For a single-segment namespace (e.g., <mark style="color:blue;">Temperature</mark>):\ <mark style="color:blue;">namespace.tag.leaf → "Temperature"</mark>

### namespace.tag.root

* **Description**: Returns the **first (top) segment** in the hierarchy.
* **Example**:
  * For <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature:</mark>\ <mark style="color:blue;">namespace.tag.root → "Enterprise1"</mark>
  * For <mark style="color:blue;">Temperature</mark> (only one segment):\ <mark style="color:blue;">namespace.tag.root → "Temperature"</mark>

### namespace.tag.thing

* **Description**: An **alias** for <mark style="color:blue;">namespace.tag.parent\[0]</mark>, i.e., the entire path minus the leaf (one-level parent).
* **Behavio**r:
  * If multiple segments exist, it returns all but the last.
  * If only one segment exists, it returns an empty string.
* Example:
  * For <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature:</mark>\ <mark style="color:blue;">namespace.tag.thing → "Enterprise1.SiteA.Area02.Line1.MachineA"</mark>
  * For <mark style="color:blue;">MachineA → Temperature:</mark>\ <mark style="color:blue;">namespace.tag.thing → "MachineA"</mark>
  * For a single segment (<mark style="color:blue;">Temperature</mark>):\ <mark style="color:blue;">namespace.tag.thing → ""</mark>

***

## Dynamic Segmenting

EasyEdge provides several ways to dynamically access or build partial paths from the namespace.

### namespace.tag.segment\[x]

* **Description**:
  * Returns the segment at position x using **forward indexing (left to right)**.
  * Index 0 corresponds to the leftmost segment (the very beginning of the path).
  * Counting then continues one by one toward the right.
* **Example** (Namespace: <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>):
  * <mark style="color:blue;">namespace.tag.segment\[0] → "Enterprise1"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[1] → "SiteA"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[2] → "Area02"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[3] → "Line1"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[4] → "MachineA"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[5] → "Temperature"</mark>

### namespace.tag.rsegment\[x]

* **Description**:&#x20;
  * Returns the segment at position x using **reverse indexing (right to left)**.
  * Index 0 corresponds to the rightmost segment (the very end of the path).
  * Counting then continues one by one toward the left.
* Example (Namespace: <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>):
  * <mark style="color:blue;">namespace.tag.segment\[0] → "Temperature"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[1] → "MachineA"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[2] → "Line1"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[3] → "Area02"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[4] → "SiteA"</mark>
  * <mark style="color:blue;">namespace.tag.segment\[5] → "Enterprise1"</mark>

### namespace.tag.head\[x]

* **Description**: Returns the **first (x+1) segments** of the namespace.
* **Example** (Namespace: <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>):
  * <mark style="color:blue;">namespace.tag.head\[0] → "Enterprise1"</mark>
  * <mark style="color:blue;">namespace.tag.head\[1] → "Enterprise1.SiteA"</mark>
  * <mark style="color:blue;">namespace.tag.head\[2] → "Enterprise1.SiteA.Area02"</mark>
  * <mark style="color:blue;">...</mark>

### namespace.tag.tail\[x]

* **Description**: Returns the **last (x+1) segments** of the namespace.
* **Example** (Namespace: <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>):
  * <mark style="color:blue;">namespace.tag.tail\[0] → "Temperature"</mark>
  * <mark style="color:blue;">namespace.tag.tail\[1] → "MachineA.Temperature"</mark>
  * <mark style="color:blue;">namespace.tag.tail\[2] → "Line1.MachineA.Temperature"</mark>
  * <mark style="color:blue;">...</mark>

### namespace.tag.parent\[x]

* **Description**: Returns the **entire path minus the last (x+1) segments**, 0-based indexing.
* **Interpretation**:
  * <mark style="color:blue;">parent\[0]</mark> = the path minus the **last** segment (equivalent to namespace.tag.thing).
  * <mark style="color:blue;">parent\[1]</mark> = the path minus the **last two** segments.
  * <mark style="color:blue;">parent\[2]</mark> = minus the **last three**, etc.
* **Example** (Namespace: <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>):
  * <mark style="color:blue;">namespace.tag.parent\[0] → "Enterprise1.SiteA.Area02.Line1.MachineA"</mark>
  * <mark style="color:blue;">namespace.tag.parent\[1] → "Enterprise1.SiteA.Area02.Line1"</mark>
  * <mark style="color:blue;">namespace.tag.parent\[2] → "Enterprise1.SiteA.Area02"</mark>
  * <mark style="color:blue;">namespace.tag.parent\[5] → "" (empty if removing 6 segments from a 6-segment name)</mark>

***

## Configuring Separators

EasyEdge allows **runtime configuration** of how segments are joined together, enabling flexible display or payload-building patterns.

You can set three parameters:

1. <mark style="color:blue;">namespace.prefix</mark>
   1. A string inserted **before the first segment**, even before any separator.
   2. Default could be "" (empty) or something like "/".
2. <mark style="color:blue;">namespace.lastSeparator</mark>
   1. The separator used **only before the final (leaf) segment**.
   2. Useful if you want the last delimiter to differ from the default, e.g., . instead of /.
3. <mark style="color:blue;">namespace.defaultSeparator</mark>
   1. The main separator used **between all other segment**s (except the last).

### Example Configuration

<mark style="color:blue;">namespace.prefix = ""</mark>

<mark style="color:blue;">namespace.lastSeparator = "."</mark>

<mark style="color:blue;">namespace.defaultSeparator = "/"</mark>

Given an original path: <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>

* Segments are: \[<mark style="color:blue;">Enterprise1, SiteA, Area02, Line1, MachineA, Temperature</mark>]
* Using the above config:
  * **Between all but the last**: use "<mark style="color:blue;">/</mark>"
  * **Before the last element**: use "<mark style="color:blue;">.</mark>"
  * **No prefix** (empty string)
* **Result**:\ <mark style="color:blue;">Enterprise1/SiteA/Area02/Line1/MachineA.Temperature</mark>

This flexibility lets you produce specialized topic or path formats without manually concatenating strings.

***

## Tag Value and Metadata Placeholder

### Tag Value

<mark style="color:blue;">namespace.tag.value</mark> returns the latest value in its native format. However, sometimes you need conversions:

| **Placeholder**              | **Description**                                    | **Example**                                                                    |
| ---------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------ |
| namespace.tag.value          | Latest value in native format                      | <p><mark style="color:blue;">23.5</mark> </p><p>(for a float sensor value)</p> |
| namespace.tag.value.asString | Converts the value to a string representation      | <mark style="color:blue;">"23.5"</mark>                                        |
| namespace.tag.value.asFloat  | Converts to floating-point                         | <mark style="color:blue;">23.5</mark>                                          |
| namespace.tag.value.asInt    | Converts to integer (truncating decimals)          | <mark style="color:blue;">23</mark>                                            |
| namespace.tag.value.asBool   | Converts to boolean (nonzero → true, zero → false) | <mark style="color:blue;">true</mark>                                          |
| namespace.tag.value.asHex    | Converts to hexadecimal format                     | <p><mark style="color:blue;">"17"</mark> </p><p>(if value = 23)</p>            |

### Additional Tag Metadata

EasyEdge also provides unit- and data-type–related placeholders for richer contextualization.

| **Placeholder**             | **Description**                                                            | **Example**                                                                                 |
| --------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| namespace.tag.unit.name     | The user-friendly name of the unit of measure                              | <mark style="color:blue;">"Celsius"</mark> or <mark style="color:blue;">"Fahrenheit"</mark> |
| namespace.tag.unit.symbol   | The symbolic representation of the unit                                    | <mark style="color:blue;">"ºC"</mark> or <mark style="color:blue;">"ºF"</mark>              |
| namespace.tag.unit.exponent | <p>The exponent factor for scaling the unit</p><p>(if applicable)</p>      | <mark style="color:blue;">0</mark>                                                          |
| namespace.tag.dataType      | <p>The data type used for the tag </p><p>(e.g., REAL, INTEGER, STRING)</p> | <mark style="color:blue;">"REAL"</mark>                                                     |

Examples:

* <mark style="color:blue;">namespace.tag.unit.name → "Fahrenheit"</mark>
* <mark style="color:blue;">namespace.tag.unit.symbol → "ºF"</mark>
* <mark style="color:blue;">namespace.tag.unit.exponent → 0</mark>
* <mark style="color:blue;">namespace.tag.dataType → "REAL"</mark>

***

## Timestamp Placeholders

EasyEdge tracks multiple timestamps for each tag to reflect different points in its data lifecycle:

1. **Real** (asset-provided) – <mark style="color:blue;">extRealTimestamp\*</mark>
2. **Emulated** (when the eNode receives data) – <mark style="color:blue;">extEmulTimestamp\*</mark>
3. **Last Touch** (last time the eNode processed the data) – <mark style="color:blue;">lastTouchTimestamp\*</mark>
4. **Default / Fallback** – tries Real → Emulated → Last Touch

### Real Timestamps: <mark style="color:blue;">namespace.tag.timestamp.real.\*</mark>

* **Examples**:
  * <mark style="color:blue;">namespace.tag.timestamp.real.sec</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.real.milli</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.real.micro</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.real.nano</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.real.iso</mark>\
    If the sensor includes an internal timestamp, these placeholders expose it.

### Emulated Timestamps: <mark style="color:blue;">namespace.tag.timestamp.emulated.\*</mark>

* **Examples**:
  * <mark style="color:blue;">namespace.tag.timestamp.emulated.sec</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.emulated.milli</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.emulated.micro</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.emulated.nano</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.emulated.iso</mark>\
    Created automatically upon data arrival if a “real” timestamp is missing or not used.

### Last Touch Timestamps: <mark style="color:blue;">namespace.tag.timestamp.lastTouch.\*</mark>

* **Examples**:
  * <mark style="color:blue;">namespace.tag.timestamp.lastTouch.sec</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.lastTouch.milli</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.lastTouch.micro</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.lastTouch.nano</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.lastTouch.iso</mark>\
    Indicates the most recent time the eNode processed or updated the value.

### Default / Fallback Timestamps: <mark style="color:blue;">namespace.tag.timestamp.\*</mark>

* **Description**: If you only want **one** timestamp that picks the best available, use these placeholders. They follow the chain **Real → Emulated → Last Touch**.
* **Examples**:
  * <mark style="color:blue;">namespace.tag.timestamp.sec</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.milli</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.micro</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.nano</mark>
  * <mark style="color:blue;">namespace.tag.timestamp.iso</mark>

***

## Putting It All Together

### Example 1: Simple MQTT Payload

```
{
"path": "${namespace.tag.name}",
  "leaf": "${namespace.tag.leaf}",
  "thing": "${namespace.tag.thing}",
  "value": ${namespace.tag.value},
  "timestampIso": "${namespace.tag.timestamp.iso}"
}
```

Given a namespace like <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark> and default fallback timestamp logic:

* **path** → <mark style="color:blue;">"Enterprise1.SiteA.Area02.Line1.MachineA.Temperature"</mark>
* **leaf** → <mark style="color:blue;">"Temperature"</mark>
* **thing** → <mark style="color:blue;">"Enterprise1.SiteA.Area02.Line1.MachineA"</mark> (minus last segment)
* **value** → e.g., <mark style="color:blue;">23.5</mark>
* **timestampIso** → e.g., <mark style="color:blue;">"2025-02-23T14:30:00Z"</mark>

### Example 2: <mark style="color:blue;">Using parent\[x]</mark>

<mark style="color:blue;">topic = "${namespace.tag.parent\[1]}/${namespace.tag.leaf}"</mark>

<mark style="color:blue;">payload = "temp=${namespace.tag.value.asFloat}\&ts=${namespace.tag.timestamp.milli}"</mark>

* For <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>,
  * <mark style="color:blue;">namespace.tag.parent\[1]</mark> = <mark style="color:blue;">"Enterprise1.SiteA.Area02.Line1"</mark>
  * <mark style="color:blue;">namespace.tag.leaf</mark> = <mark style="color:blue;">"Temperature"</mark>
  * Topic → <mark style="color:blue;">Enterprise1.SiteA.Area02.Line1/Temperature</mark>
  * Payload → <mark style="color:blue;">temp=23.5\&ts=1708706400123</mark>

### Example 3: Configurable Separators

If you set:

<mark style="color:blue;">namespace.prefix        = "/"</mark>

<mark style="color:blue;">namespace.defaultSeparator = "/"</mark>

<mark style="color:blue;">namespace.lastSeparator    = "."</mark>

And the original segments are <mark style="color:blue;">Enterprise1 → SiteA → Area02 → Line1 → MachineA → Temperature</mark>,\
You will get <mark style="color:blue;">/Enterprise1/SiteA/Area02/Line1/MachineA.Temperature</mark>.

### Example 4: Converting Value Formats

```
{
  "fullName": "${namespace.tag.name}",
  "valueString": "${namespace.tag.value.asString}",
  "valueHex": "${namespace.tag.value.asHex}",
  "timestampSec": ${namespace.tag.timestamp.sec}
}
```

For a sensor reading <mark style="color:blue;">45</mark>, you might get:

```
{
  "fullName": "Line1.MachineA.Speed",
  "valueString": "45",
  "valueHex": "0x2D",
  "timestampSec": 1708706400
}
```

### Example 5: Displaying Unit and Data Type

```
{
  "path": "${namespace.tag.name}",
  "dataType": "${namespace.tag.dataType}",
  "unitName": "${namespace.tag.unit.name}",
  "unitSymbol": "${namespace.tag.unit.symbol}",
  "value": ${namespace.tag.value},
  "timestampMilli": ${namespace.tag.timestamp.milli}
}
```

If <mark style="color:blue;">dataType</mark> is <mark style="color:blue;">REAL</mark>, <mark style="color:blue;">unit.name</mark> is <mark style="color:blue;">"Celsius"</mark>, and <mark style="color:blue;">unit.symbo</mark>l is <mark style="color:blue;">"ºC"</mark>, then:

```
{
  "path": "Enterprise1.SiteA.Area02.Line1.MachineA.Temperature",
  "dataType": "REAL",
  "unitName": "Celsius",
  "unitSymbol": "ºC",
  "value": 23.5,
  "timestampMilli": 1708706400123
}
```

***

## Best Practices

1. **Adopt an ISA-95-Aligned Hierarchy**\
   Use the standard’s structure (Enterprise → Site → Area → Line → Machine, etc.) to keep data organized.
2. **Use** <mark style="color:blue;">namespace.prefix</mark> **Sparingly**\
   Only if you need a global prefix like <mark style="color:blue;">"/"</mark> or <mark style="color:blue;">"\\\\"</mark> for certain protocols or systems.
3. **Differentiate** <mark style="color:blue;">namespace.tag.name</mark> **vs.** <mark style="color:blue;">namespace.tag.leaf</mark>
   1. <mark style="color:blue;">name</mark> = entire path
   2. <mark style="color:blue;">leaf</mark> = last segment only
4. <mark style="color:blue;">namespace.tag.thing</mark> **for** **“All But Leaf”**\
   This is an alias for <mark style="color:blue;">parent\[0]</mark>. If you need to climb higher up, use <mark style="color:blue;">parent\[x]</mark>.
5. **Value Conversions**\
   Use <mark style="color:blue;">.asString</mark>, <mark style="color:blue;">.asFloat</mark>, <mark style="color:blue;">.asInt</mark>, etc. to ensure the payload format matches your use case.
6. **Units and Data Types**
   1. Use <mark style="color:blue;">namespace.tag.unit.\*</mark> placeholders to provide context for the measurement.
   2. Use <mark style="color:blue;">namespace.tag.dataType</mark> to clarify the underlying data format.
7. **Choose the Right Timestamp**
   1. **Real** if you trust the device clock.
   2. **Emulated** if the device clock is missing or inaccurate.
   3. **Last Touch** if you specifically need the eNode’s last-processing time.
   4. **Default** if you want a “best guess” automatically.
8. **Combine Head/Tail**\
   If you need a partial path from the top or bottom, head\[x] and tail\[x] are simpler than manual substring operations.
9. **Check Single-Segment Names**\
   If your namespace is just <mark style="color:blue;">"Temperature"</mark>, <mark style="color:blue;">thing</mark> or <mark style="color:blue;">parent\[0]</mark> will be empty.

***

## Conclusion

By leveraging these **EasyEdge namespace placeholders**, you can build **custom payloads** that:

* **Fully reflect** a UNS-based, ISA-95-aligned structure,
* Dynamically adjust **separators** and partial paths,
* Include **converted values, unit information, data types**, and **rich timestamp data**.

This **flexible architecture** means you can handle any depth of hierarchy, any data format, and multiple time sources, without resorting to clumsy string manipulations or ad-hoc code. As your operation scales or modifies devices and systems, your data remains consistently organized and easily consumable.
