This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Unified Namespace

Describes all available _schema and their structure

Topic structure

flowchart LR umh --> v1 v1 --> enterprise enterprise -->|Optional| site site -->|Optional| area area -->|Optional| productionLine productionLine -->|Optional| workCell workCell -->|Optional| originID originID -->|Optional| _schema["_schema (Ex: _historian, _analytics, _local)"] _schema -->_opt["Schema dependent context"] classDef mqtt fill:#00dd00,stroke:#333,stroke-width:4px; class umh,v1,enterprise,_schema mqtt; classDef optional fill:#77aa77,stroke:#333,stroke-width:4px; class site,area,productionLine,workCell,originID optional; enterprise -.-> _schema site -.-> _schema area -.-> _schema productionLine -.-> _schema workCell -.-> _schema click _schema href "#_schema" click umh href "#versioning-prefix" click v1 href "#versioning-prefix"
flowchart LR umh --> v1 v1 --> enterprise enterprise -->|Optional| site site -->|Optional| area area -->|Optional| productionLine productionLine -->|Optional| workCell workCell -->|Optional| originID originID -->|Optional| _schema["_schema (Ex: _historian, _analytics, _local)"] _schema -->_opt["Schema dependent context"] classDef mqtt fill:#00dd00,stroke:#333,stroke-width:4px; class umh,v1,enterprise,_schema mqtt; classDef optional fill:#77aa77,stroke:#333,stroke-width:4px; class site,area,productionLine,workCell,originID optional; enterprise -.-> _schema site -.-> _schema area -.-> _schema productionLine -.-> _schema workCell -.-> _schema click _schema href "#_schema" click umh href "#versioning-prefix" click v1 href "#versioning-prefix"

Versioning Prefix

The umh/v1 at the beginning is obligatory. It ensures that the structure can evolve over time without causing confusion or compatibility issues.

Topic Names & Rules

All part of this structure, except for enterprise and _schema are optional. They can consist of any letters (a-z, A-Z), numbers (0-9) and therein symbols (- & _). Be careful to avoid ., +, # or / as these are special symbols in Kafka or MQTT. Ensure that your topic always begins with umh/v1, otherwise our system will ignore your messages.

Be aware that our topics are case-sensitive, therefore umh.v1.ACMEIncorperated is not the same as umh.v1.acmeincorperated.

Throughout this documentation we will use the MQTT syntax for topics (umh/v1), the corresponding Kafka topic names are the same but / replaced with .

Topic validator



OriginID

This part identifies where the data is coming from. Good options include the senders MAC address, hostname, container id. Examples for originID: 00-80-41-ae-fd-7e, E588974, e5f484a1791d

_schema

_historian

Messages tagged with _historian will be stored in our database and are available via Grafana.

_analytics

Messages tagged with _analytics will be processed by our analytics pipeline. They are used for automatic calculation of KPI’s and other statistics.

_local

This key might contain any data, that you do not want to bridge to other nodes (it will however be MQTT-Kafka bridged on its node).

For example this could be data you want to pre-process on your local node, and then put into another _schema. This data must not necessarily be JSON.

Other

Any other schema, which starts with an underscore (for example: _images), will be forwarded by both MQTT-Kafka & Kafka-Kafka bridges but never processed or stored.

This data must not necessarily be JSON.

Converting other data models

Most data models already follow a location based naming structure.

KKS Identification System for Power Stations

KKS (Kraftwerk-Kennzeichensystem) is a standardized system for identifying and classifying equipment and systems in power plants, particularly in German-speaking countries.

In a flow diagram, the designation is: 1 2LAC03 CT002 QT12

  • Level 0 Classification:

    Block 1 of a power plant site is designated as 1 in this level.

  • Level 1 Classification:

    The designation for the 3rd feedwater pump in the 2nd steam-water circuit is 2LAC03. This means:

    Main group 2L: 2nd steam, water, gas circuit Subgroup (2L)A: Feedwater system Subgroup (2LA)C: Feedwater pump system Counter (2LAC)03: third feedwater pump system

  • Level 2 Classification:

    For the 2nd temperature measurement, the designation CT002 is used. This means:

    Main group C: Direct measurement Subgroup (C)T: Temperature measurement Counter (CT)002: second temperature measurement

  • Level 3 Classification:

    For the 12th immersion sleeve as a sensor protection, the designation QT12 is used. This means:

    • Main group Q: Control technology equipment
    • Subgroup (Q)T: Protective tubes and immersion sleeves as sensor protection
    • Counter (QT)12: twelfth protective tube or immersion sleeve

The above example refers to the 12th immersion sleeve at the 2nd temperature measurement of the 3rd feed pump in block 1 of a power plant site. Translating this in our data model could result in: umh/v1/nuclearCo/1/2LAC03/CT002/QT12/_schema

Where:

  • nuclearCo: Represents the enterprise or the name of the nuclear company.
  • 1: Maps to the site, corresponding to Block 1 of the power plant as per the KKS number.
  • 2LAC03: Fits into the area, representing the 3rd feedwater pump in the 2nd steam-water circuit.
  • CT002: Aligns with productionLine, indicating the 2nd temperature measurement in this context.
  • QT12: Serves as the workCell or originID, denoting the 12th immersion sleeve.
  • _schema: Placeholder for the specific data schema being applied.

1 - _analytics

Messages for our analytics feature

Topic structure

flowchart LR topicStart["umh.v1..."] --> _analytics _analytics --> wo[work-order] wo --> wo-create[create] wo --> wo-start[start] wo --> wo-stop[stop] _analytics --> pt[product-type] pt --> pt-create[create] _analytics --> p[product] p --> p-add[add] p --> p-set-bad-quantity[setBadQuantity] _analytics --> s[shift] s --> s-add[add] s --> s-delete[delete] _analytics --> st[state] st --> st-add[add] st --> st-overwrite[overwrite] classDef mqtt fill:#00dd00,stroke:#333,stroke-width:4px; class umh,v1,enterprise,_analytics mqtt; classDef type fill:#00ffbb,stroke:#333,stroke-width:4px; class wo,pt,p,s,st type; classDef func fill:#8899dd,stroke:#333,stroke-width:4px; class wo-create,wo-start,wo-stop,pt-create,p-add,p-set-bad-quantity,s-add,s-delete,st-add,st-overwrite func; click topicStart href "../" click wo href "#work-order" click pt href "#product-type" click p href "#product" click s href "#shift" click wo-create href "#create" click wo-start href "#start" click wo-stop href "#stop" click pt-create href "#create-1" click p-add href "#add" click p-set-bad-quantity href "#set-bad-quantity" click s-add href "#add-1" click s-delete href "#delete" click st-add href "#add-2" click st-overwrite href "#overwrite"
flowchart LR topicStart["umh.v1..."] --> _analytics _analytics --> wo[work-order] wo --> wo-create[create] wo --> wo-start[start] wo --> wo-stop[stop] _analytics --> pt[product-type] pt --> pt-create[create] _analytics --> p[product] p --> p-add[add] p --> p-set-bad-quantity[setBadQuantity] _analytics --> s[shift] s --> s-add[add] s --> s-delete[delete] _analytics --> st[state] st --> st-add[add] st --> st-overwrite[overwrite] classDef mqtt fill:#00dd00,stroke:#333,stroke-width:4px; class umh,v1,enterprise,_analytics mqtt; classDef type fill:#00ffbb,stroke:#333,stroke-width:4px; class wo,pt,p,s,st type; classDef func fill:#8899dd,stroke:#333,stroke-width:4px; class wo-create,wo-start,wo-stop,pt-create,p-add,p-set-bad-quantity,s-add,s-delete,st-add,st-overwrite func; click topicStart href "../" click wo href "#work-order" click pt href "#product-type" click p href "#product" click s href "#shift" click wo-create href "#create" click wo-start href "#start" click wo-stop href "#stop" click pt-create href "#create-1" click p-add href "#add" click p-set-bad-quantity href "#set-bad-quantity" click s-add href "#add-1" click s-delete href "#delete" click st-add href "#add-2" click st-overwrite href "#overwrite"

Work Order

Create

Use this topic to create a new work order.

This replaces the addOrder message from our v0 data model.

Fields

  • external_work_order_id (string): The work order ID from your MES or ERP system.
  • product (object): The product being produced.
    • external_product_id (string): The product ID from your MES or ERP system.
    • cycle_time_ms (number) (optional): The cycle time for the product in seconds. Only include this if the product has not been previously created.
  • quantity (number): The quantity of the product to be produced.
  • status (number) (optional): The status of the work order. Defaults to 0 (created).
    • 0 - Planned
    • 1 - In progress
    • 2 - Completed
  • start_time_unix_ms (number) (optional): The start time of the work order. Will be set by the corresponding start message if not provided.
  • end_time_unix_ms (number) (optional): The end time of the work order. Will be set by the corresponding stop message if not provided.

Example

{
  "external_work_order_id": "1234",
  "product": {
    "external_product_id": "5678"
  },
  "quantity": 100,
  "status": 0
}

Start

Use this topic to start a previously created work order.

Each work order can only be started once. Only work orders with status 0 (planned) and no start time can be started.

Fields

  • external_work_order_id (string): The work order ID from your MES or ERP system.
  • start_time_unix_ms (number): The start time of the work order.

Example

{
  "external_work_order_id": "1234",
  "start_time_unix_ms": 1719931704927
}

Stop

Use this topic to stop a previously started work order.

Stopping an already stopped work order will have no effect. Only work orders with status 1 (in progress) and no end time can be stopped.

Fields

  • external_work_order_id (string): The work order ID from your MES or ERP system.
  • end_time_unix_ms (number): The end time of the work order.

Example

{
  "external_work_order_id": "1234",
  "end_time_unix_ms": 1719931704927
}

Product Type

Create

Announce a new product type.

We recommend using the work-order/create message to create products on the fly.

Fields

  • external_product_type_id (string): The product type ID from your MES or ERP system.
  • cycle_time_ms (number) (optional): The cycle time for the product in milliseconds.

Example

{
  "external_product_type_id": "5678",
  "cycle_time_ms": 60
}

Product

Add

Communicates the completion of part of a work order.

Fields

  • external_product_type_id (string): The product type ID from your MES or ERP system.
  • product_batch_id (string) (optional): Unique identifier for the product. This could for example be a barcode or serial number.
  • start_time_unix_ms (number): The start time of the product.
  • end_time_unix_ms (number): The end time of the product.
  • quantity (number): The quantity of the product produced.
  • bad_quantity (number) (optional): The quantity of bad products produced.

Example

{
  "external_product_type_id": "5678",
  "product_batch_id": "1234",
  "start_time_unix_ms": 1719931604927,
  "end_time_unix_ms": 1719931704927,
  "quantity": 100,
  "bad_quantity": 5
}

Set Bad Quantity

Modify the quantity of bad products produced.

Fields

  • external_product_type_id (string): The product type ID from your MES or ERP system.
  • end_time_unix_ms (string): The end time of the product, used to identify an existing product.
  • bad_quantity (number): The new quantity of bad products produced.

Example

{
  "external_product_type_id": "5678",
  "end_time": 1719931704927,
  "bad_quantity": 10
}

Shift

Add

Announce a new shift.

Fields

  • start_time_unix_ms (number): The start time of the shift.
  • end_time_unix_ms (number): The end time of the shift.

Example

{
  "start_time_unix_ms": 1719931604927,
  "end_time_unix_ms": 1719931704927
}

Delete

Delete a previously created shift.

Fields

  • start_time_unix_ms (number): The start time of the shift.

Example

{
  "start_time_unix_ms": 1719931604927
}

State

Add

Announce a state change.

Checkout the state documentation for a list of available states.

Fields

  • state (number): The state of the machine.
  • start_time_unix_ms (number): The start time of the state.

Example

{
  "state": 10000,
  "start_time_unix_ms": 1719931604927
}

Overwrite

Overwrite one or more states between two times.

Fields

  • state (number): The state of the machine.
  • start_time_unix_ms (number): The start time of the state.
  • end_time_unix_ms (number): The end time of the state.

2 - _historian

Messages for our historian feature

Topic structure

flowchart LR topicStart["umh.v1..."] --> _historian _historian --> |Optional| tagName _historian --> |Optional| tagGroup tagGroup --> tagName classDef mqtt fill:#00dd00,stroke:#333,stroke-width:4px; class umh,v1,enterprise,_historian mqtt; classDef optional fill:#77aa77,stroke:#333,stroke-width:4px; class site,area,productionLine,workCell,originID,tagGroup,tagName optional; tagGroup -.-> |1-N| tagGroup click topicStart href "../"
flowchart LR topicStart["umh.v1..."] --> _historian _historian --> |Optional| tagName _historian --> |Optional| tagGroup tagGroup --> tagName classDef mqtt fill:#00dd00,stroke:#333,stroke-width:4px; class umh,v1,enterprise,_historian mqtt; classDef optional fill:#77aa77,stroke:#333,stroke-width:4px; class site,area,productionLine,workCell,originID,tagGroup,tagName optional; tagGroup -.-> |1-N| tagGroup click topicStart href "../"

Message structure

Our _historian messages are JSON containing a unix timestamp as milliseconds (timestamp_ms) and one or more key value pairs. Each key value pair will be inserted at the given timestamp into the database.

Show JSON Schema

Examples:

{
    "timestamp_ms": 1702286893,
    "temperature_c": 154.1
}
{
    "timestamp_ms": 1702286893,
    "temperature_c": 154.1,
    "pressure_bar": 5,
    "notes": "sensor 1 is faulty"
}

If you use a boolean value, it will be interpreted as a number.

Tag grouping

Sometimes it makes sense to further group data together. In the following example we have a CNC cutter, emitting data about it’s head position. If we want to group this for easier access in Grafana, we could use two types of grouping.

  1. Using Tags / Tag Groups in the Topic: This will result in 3 new database entries, grouped by head & pos.

    Topic: umh/v1/cuttingincorperated/cologne/cnc-cutter/_historian/head/pos

    {
     "timestamp_ms": 1670001234567,
      "x": 12.5,
      "y": 7.3,
      "z": 3.2
    }
    

    This method allows very easy monitoring of the data in tools like our Management Console or MQTT Explorer, as each new / will be displayed as a Tree.

  2. Using JSON subobjects:

    Equivalent to the above we could also send: Topic: umh/v1/cuttingincorperated/cologne/cnc-cutter/_historian

    {
     "timestamp_ms": 1670001234567,
      "head": {
         "pos": {
            "x": 12.5,
            "y": 7.3,
            "z": 3.2   
         }
      }
    }
    

    It’s usefull if the machine cannot send to multiple topics, but grouping is still desired.

  3. Combining Both Methods: Equivalent to the above we could also send:

    Topic: umh/v1/cuttingincorperated/cologne/cnc-cutter/_historian/head

    {
     "timestamp_ms": 1670001234567,
      "pos": {
         "x": 12.5,
         "y": 7.3,
         "z": 3.2
      }
    }
    

    This can be useful, if we also want to monitor the cutter head temperature and other attributes, while still preserving most of the readability of the above method.

    {
     "timestamp_ms": 1670001234567,
      "pos": {
         "x": 12.5,
         "y": 7.3,
         "z": 3.2
      },
      "temperature": 50.0,
      "collision": false
    }
    

What’s next?

Find out how the data is stored and can be retrieved from our database.