# 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://easyedge.gitbook.io/easyedge/connect-to-applications/namespace-placeholders.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
