diff --git a/acs-admin/src/components/EdgeManager/Devices/ISA95HierarchyPanel.vue b/acs-admin/src/components/EdgeManager/Devices/ISA95HierarchyPanel.vue
new file mode 100644
index 000000000..1633be8f7
--- /dev/null
+++ b/acs-admin/src/components/EdgeManager/Devices/ISA95HierarchyPanel.vue
@@ -0,0 +1,164 @@
+
+
+
+
+
+
+
+
+ {{ level }}
+
+
on_select(level, v, index)"
+ :reset-search-term-on-select="true"
+ >
+
+
+
+
+
+
+
+ No results
+
+ {{ opt.name }}
+
+
+
+
+
+
+
+
+
diff --git a/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/OriginMapEditor.vue b/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/OriginMapEditor.vue
index 0587116c4..713ed1763 100644
--- a/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/OriginMapEditor.vue
+++ b/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/OriginMapEditor.vue
@@ -158,6 +158,7 @@ import { useConnectionStore } from '@store/useConnectionStore.js'
import _ from 'lodash'
import NewObjectOverlayForm from './NewObjectOverlayForm.vue'
import { updateEdgeAgentConfig } from '@/utils/edgeAgentConfigUpdater'
+import { ISA95_LEVELS } from '@/store/useISA95Store.js'
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { generateCsv, downloadCsv, parseCsv, applyCsvToModel } from '@/composables/useOriginMapCsv.js'
import Papa from 'papaparse'
@@ -275,11 +276,14 @@ export default {
immediate: true,
handler(newOriginMap) {
console.debug('Origin map changed:', newOriginMap)
- // If the origin map is null or undefined, reset our model
if (newOriginMap === null || newOriginMap === undefined) {
console.debug('Resetting origin map model')
this.resetModel()
- // Trigger a re-render of the schema group
+ this.groupRerenderTrigger = +new Date()
+ } else if (!this.isDirty) {
+ // Accept external updates (e.g. from the ISA-95 sidebar panel)
+ // when there are no unsaved local changes in the editor.
+ this.model = newOriginMap
this.groupRerenderTrigger = +new Date()
}
}
@@ -888,6 +892,46 @@ export default {
this.isDirty = true
},
+ /* Called by Device.vue when the ISA-95 sidebar panel selects a value.
+ * Applies the mutation directly to this.model (the object that gets
+ * saved) rather than relying on device.deviceInformation.originMap,
+ * which may be a different reference after a Pinia store refresh.
+ * Also clears all lower hierarchy levels and triggers a tree re-render. */
+ applyISA95Selection ({ level, value, level_index }) {
+ if (!this.model.Device_Information) this.model.Device_Information = {}
+ if (!this.model.Device_Information.ISA95_Hierarchy) this.model.Device_Information.ISA95_Hierarchy = {}
+
+ const hierarchy = this.model.Device_Information.ISA95_Hierarchy
+
+ if (!hierarchy[level]) hierarchy[level] = {}
+ hierarchy[level].Value = value
+ if (!hierarchy[level].Sparkplug_Type)
+ hierarchy[level].Sparkplug_Type = 'String'
+
+ /* Clear all levels below the one just set.
+ * Use null rather than delete: the save uses a JSON merge patch, where
+ * absent keys are preserved (not deleted). Setting Value to null is the
+ * RFC 7396 signal that tells ConfigDB to delete that key. */
+ for (const lower of ISA95_LEVELS.slice(level_index + 1)) {
+ if (hierarchy[lower] !== undefined) {
+ if (!hierarchy[lower]) hierarchy[lower] = {}
+ hierarchy[lower].Value = null
+ }
+ }
+
+ /* For fresh devices that have no originMap yet, wire device.deviceInformation.originMap
+ * to this.model so the ISA-95 panel's display (which reads from the device prop)
+ * stays in sync with what we will actually save. Once the user saves, Pinia
+ * refreshes the store with the real saved reference, and the two stay aligned
+ * via the existing originMap watcher. */
+ if (this.device?.deviceInformation && !this.device.deviceInformation.originMap) {
+ this.device.deviceInformation.originMap = this.model
+ }
+
+ this.isDirty = true
+ this.groupRerenderTrigger = +new Date()
+ },
+
resetModel() {
// Reset the model to an empty object
this.model = {}
@@ -1066,7 +1110,7 @@ export default {
},
applyParsedCsv () {
- if (!this.csvParsedData) return { applied: 0, skipped: 0 }
+ if (!this.csvParsedData) return { applied: 0, skipped: 0, ignored: 0 }
// Pass the schema to applyCsvToModel so missing metrics can be created
const result = applyCsvToModel(this.csvParsedData, this.model, this.schema, this.set)
@@ -1089,7 +1133,12 @@ export default {
})
}
- toast.warning("Test message", { pauseOnHover: true })
+ if (result.ignored > 0) {
+ toast.warning(`${result.ignored} ISA-95 row${result.ignored === 1 ? '' : 's'} ignored`, {
+ description: 'Set the hierarchy in the ISA-95 Hierarchy panel.',
+ pauseOnHover: true,
+ })
+ }
this.markDirty()
this.groupRerenderTrigger = +new Date()
diff --git a/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/SchemaGroup.vue b/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/SchemaGroup.vue
index 3d869d166..ef71273fe 100644
--- a/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/SchemaGroup.vue
+++ b/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/SchemaGroup.vue
@@ -116,7 +116,6 @@ import { SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar'
import { ChevronRight } from 'lucide-vue-next'
import { Button } from '@/components/ui/button'
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'
-
export default {
name: 'SchemaGroup',
@@ -903,9 +902,11 @@ export default {
computed: {
filteredKeys() {
// Get all keys that aren't reserved words in the order they appear in the schema
- // We use Object.keys to get the keys in the order they were defined in the schema
+ // We use Object.keys to get the keys in the order they were defined in the schema.
+ // ISA95_Hierarchy is always hidden from the tree — it is managed exclusively via
+ // the dedicated ISA-95 Hierarchy panel in the device sidebar.
const allKeys = Object.keys(this.schema.properties).filter(e =>
- !['patternProperties', '$meta', 'Schema_UUID', 'Instance_UUID', 'required'].includes(e)
+ !['patternProperties', '$meta', 'Schema_UUID', 'Instance_UUID', 'required', 'ISA95_Hierarchy'].includes(e)
);
// If not filtering, return all keys in their original order
diff --git a/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/SparkplugMetric.vue b/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/SparkplugMetric.vue
index 2eecc9e07..4bd752ef8 100644
--- a/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/SparkplugMetric.vue
+++ b/acs-admin/src/components/EdgeManager/Devices/OriginMapEditor/SparkplugMetric.vue
@@ -24,7 +24,34 @@
-
+
+
+
+
+
+
+
+
+ No results
+
+ {{ opt.name }}
+
+
+
+
@@ -125,15 +152,21 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import DetailCard from '@components/DetailCard.vue'
import { Button } from '@/components/ui/button'
import { useConnectionStore } from '@/store/useConnectionStore'
-import { useDriverStore } from '@/store/useDriverStore'
+import { useDriverStore } from '@/store/useDriverStore'
+import { useISA95Store, ISA95_LEVELS } from '@/store/useISA95Store.js'
+import {
+ Combobox, ComboboxAnchor, ComboboxEmpty,
+ ComboboxInput, ComboboxItem, ComboboxList, ComboboxTrigger,
+} from '@/components/ui/combobox'
export default {
name: 'SparkplugMetric',
setup() {
return {
- conn: useConnectionStore(),
+ conn: useConnectionStore(),
driver: useDriverStore(),
+ isa95: useISA95Store(),
}
},
@@ -147,6 +180,13 @@ export default {
SelectItem,
SelectTrigger,
SelectValue,
+ Combobox,
+ ComboboxAnchor,
+ ComboboxEmpty,
+ ComboboxInput,
+ ComboboxItem,
+ ComboboxList,
+ ComboboxTrigger,
Control,
LinkUserDialog,
GroupList,
@@ -251,12 +291,59 @@ export default {
// This handles cases where any part of the path is missing
return this.driverInfo?.presentation?.path?.hidden === true
},
+
+ /* Which ISA-95 level this metric represents, or null if it isn't one.
+ * Detection is based on the metric path: the parent key must be
+ * 'ISA95_Hierarchy' and the leaf key must be one of the five level names. */
+ isa95Level () {
+ const path = this.selectedMetric?.path
+ if (!path || path.length < 2) return null
+ const leaf = path[path.length - 1]
+ const parent = path[path.length - 2]
+ if (parent === 'ISA95_Hierarchy' && ISA95_LEVELS.includes(leaf))
+ return leaf
+ return null
+ },
+
+ /* Valid options for the dropdown at the current ISA-95 level.
+ * For Enterprise this is all enterprises; for lower levels it is the
+ * children of whichever parent node is currently selected. */
+ isa95Options () {
+ if (!this.isa95Level) return []
+
+ const level_index = ISA95_LEVELS.indexOf(this.isa95Level)
+
+ if (level_index === 0) {
+ return this.isa95.enterprises
+ }
+
+ const parent_level = ISA95_LEVELS[level_index - 1]
+ const parent_value = this.model
+ ?.Device_Information
+ ?.ISA95_Hierarchy
+ ?.[parent_level]
+ ?.Value
+
+ console.log('isa95Options', { level: this.isa95Level, parent_level, parent_value, data: this.isa95.data })
+
+ if (!parent_value) return []
+
+ const parent_node = this.isa95.find_by_name(parent_level, parent_value)
+ console.log('parent_node', parent_node)
+
+ const children = this.isa95.children_of(parent_node.uuid)
+
+ console.log('children', {raw_children: parent_node.children, resolved: children, all_data: this.isa95.data})
+
+ return children
+ },
},
mounted() {
// Start the stores
this.conn.start()
this.driver.start()
+ this.isa95.start()
},
watch: {
@@ -338,6 +425,24 @@ export default {
this.isToggling = false;
}, 100);
},
+ /* Handle selection of an ISA-95 hierarchy value. Sets the local value
+ * and clears all levels below this one in the full originMap so the
+ * hierarchy stays consistent. */
+ on_isa95_select (new_value) {
+ this.localModel.Value = new_value
+
+ const level_index = ISA95_LEVELS.indexOf(this.isa95Level)
+ const hierarchy = this.model?.Device_Information?.ISA95_Hierarchy
+ if (!hierarchy) return
+
+ for (const level of ISA95_LEVELS.slice(level_index + 1)) {
+ if (hierarchy[level] !== undefined) {
+ if (!hierarchy[level]) hierarchy[level] = {}
+ hierarchy[level].Value = null
+ }
+ }
+ },
+
isValidType (val, options) {
return options.some(e => e.value === val)
},
diff --git a/acs-admin/src/composables/useOriginMapCsv.js b/acs-admin/src/composables/useOriginMapCsv.js
index f53c39d11..2441d8883 100644
--- a/acs-admin/src/composables/useOriginMapCsv.js
+++ b/acs-admin/src/composables/useOriginMapCsv.js
@@ -3,10 +3,24 @@
*/
import Papa from 'papaparse';
+import { ISA95_HIERARCHY_KEY } from '@/store/useISA95Store.js';
// No 'set' export from vue in Vue 3. Use plain assignment; reactivity is handled by the parent component's set helper if needed.
const RESERVED_KEYS = ['Schema_UUID', 'Instance_UUID', 'patternProperties', '$meta', 'required'];
+/**
+ * Read the value at a path of segments, without creating anything along the
+ * way. Returns undefined if any segment is missing.
+ */
+function valueAt(obj, segments) {
+ let current = obj;
+ for (const segment of segments) {
+ if (current == null || typeof current !== 'object') return undefined;
+ current = current[segment];
+ }
+ return current;
+}
+
/**
* Determine the node type of a schema property.
* @param {object} prop - A value from schema.properties
@@ -86,10 +100,14 @@ function collectMetricRows(schema, model, pathSegments = [], inPlaceholder = fal
* @param {Object} model - The model to mutate
* @param {Object} schema - The schema
* @param {Function} setFn - (optional) function(path, value, obj, delimiter) to set nested properties reactively
+ * @returns {{applied: number, skipped: number, ignored: number}} skipped counts
+ * rows whose path is absent from the schema; ignored counts ISA-95 hierarchy
+ * rows whose value the CSV tried to change.
*/
export function applyCsvToModel(rows, model, schema, setFn) {
let applied = 0;
let skipped = 0;
+ let ignored = 0;
function getMetricSchema(schema, segments) {
let currentSchema = schema;
@@ -125,6 +143,19 @@ export function applyCsvToModel(rows, model, schema, setFn) {
for (const { tagPath, fields } of rows) {
const segments = tagPath.split('/');
+
+ // The ISA-95 hierarchy is a controlled vocabulary, managed exclusively
+ // by ISA95HierarchyPanel. Never let free-text CSV values write to it.
+ // Skip before traversal so we don't create the parent objects either.
+ if (segments.includes(ISA95_HIERARCHY_KEY)) {
+ // Only report rows where the CSV would actually have changed the
+ // value, so an unmodified round-trip stays quiet.
+ const csvValue = String(fields.Value ?? '').trim();
+ const modelValue = String(valueAt(model, segments)?.Value ?? '');
+ if (csvValue !== modelValue) ignored++;
+ continue;
+ }
+
let current = model;
let found = true;
let pathSoFar = [];
@@ -218,7 +249,7 @@ export function applyCsvToModel(rows, model, schema, setFn) {
}
// ...existing code...
- return { applied, skipped };
+ return { applied, skipped, ignored };
}
/**
diff --git a/acs-admin/src/pages/EdgeManager/Devices/Device.vue b/acs-admin/src/pages/EdgeManager/Devices/Device.vue
index 2e69856c9..e012ed4ea 100644
--- a/acs-admin/src/pages/EdgeManager/Devices/Device.vue
+++ b/acs-admin/src/pages/EdgeManager/Devices/Device.vue
@@ -61,7 +61,7 @@
-
+
@@ -135,6 +135,8 @@
:value="connection?.name"
/>
+
+
@@ -159,7 +161,8 @@ import { useSchemaStore } from '@store/useSchemaStore.js'
import ChangeSchemaDialog from '@components/EdgeManager/Devices/ChangeSchemaDialog.vue'
import { useConnectionStore } from '@store/useConnectionStore.js'
import ChangeConnectionDialog from '@components/EdgeManager/Devices/ChangeConnectionDialog.vue'
-import OriginMapEditor from '@components/EdgeManager/Devices/OriginMapEditor/OriginMapEditor.vue'
+import OriginMapEditor from '@components/EdgeManager/Devices/OriginMapEditor/OriginMapEditor.vue'
+import ISA95HierarchyPanel from '@components/EdgeManager/Devices/ISA95HierarchyPanel.vue'
export default {
components: {
@@ -179,6 +182,7 @@ export default {
SidebarDetail,
ChangeSchemaDialog,
ChangeConnectionDialog,
+ ISA95HierarchyPanel,
},
setup () {
@@ -293,6 +297,10 @@ export default {
}
},
+ on_isa95_change (payload) {
+ this.$refs.originMapEditor?.applyISA95Selection(payload)
+ },
+
handleSchemaChanged(schemaUuid) {
// Force refresh the device data
this.d.stop()
diff --git a/acs-admin/src/store/useISA95Store.js b/acs-admin/src/store/useISA95Store.js
new file mode 100644
index 000000000..454193cf6
--- /dev/null
+++ b/acs-admin/src/store/useISA95Store.js
@@ -0,0 +1,118 @@
+/*
+ * ACS Admin
+ * Pinia store for ISA-95 vocabulary — enterprises, sites, areas, etc.
+ * Copyright 2026 University of Sheffield AMRC
+ */
+
+import { defineStore } from 'pinia'
+import * as rx from 'rxjs'
+import * as rxu from '@amrc-factoryplus/rx-util'
+import { UUIDs } from '@amrc-factoryplus/service-client'
+
+import { useServiceClientStore } from '@/store/serviceClientStore.js'
+import { serviceClientReady } from '@store/useServiceClientReady.js'
+
+/* The Device Information schema key holding the ISA-95 level metrics. These
+ * are a controlled vocabulary: they are written only via ISA95HierarchyPanel,
+ * never by free-text entry. */
+export const ISA95_HIERARCHY_KEY = 'ISA95_Hierarchy'
+
+/* Ordered list of ISA-95 levels, matching the metric key names used in the
+ * Device Information schema (spaces included). */
+export const ISA95_LEVELS = [
+ 'Enterprise',
+ 'Site',
+ 'Area',
+ 'Work Center',
+ 'Work Unit',
+]
+
+export const useISA95Store = defineStore('isa95', {
+ state: () => ({
+ data: [],
+ ready: false,
+ rxsub: null,
+ }),
+
+ getters: {
+ /* All enterprise-level nodes. */
+ enterprises: (state) => state.data.filter(n => n.level === 'Enterprise'),
+
+ /* Look up a single node by UUID. */
+ by_uuid: (state) => (uuid) => state.data.find(n => n.uuid === uuid),
+
+ /* Children of a given node UUID, resolved to full node objects. */
+ children_of: (state) => (uuid) => {
+ const node = state.data.find(n => n.uuid === uuid)
+ if (!node) return []
+ return node.children
+ .map(child_uuid => state.data.find(n => n.uuid === child_uuid))
+ .filter(Boolean)
+ },
+
+ /* Find a node at a given level by its canonical name or an alias. */
+ find_by_name: (state) => (level, name) =>
+ state.data.find(n =>
+ n.level === level &&
+ (n.name === name || n.aliases.includes(name))
+ ),
+ },
+
+ actions: {
+ async start () {
+ if (this.rxsub) return
+
+ await serviceClientReady()
+ const cdb = useServiceClientStore().client.ConfigDB
+
+ const level_classes = {
+ 'Enterprise': UUIDs.Class.ISA95Enterprise,
+ 'Site': UUIDs.Class.ISA95Site,
+ 'Area': UUIDs.Class.ISA95Area,
+ 'Work Center': UUIDs.Class.ISA95WorkCenter,
+ 'Work Unit': UUIDs.Class.ISA95WorkUnit,
+ }
+
+ const member_obs = Object.fromEntries(
+ Object.entries(level_classes).map(([level, class_uuid]) => [
+ level,
+ cdb.watch_members(class_uuid),
+ ])
+ )
+
+ const vocab = cdb.search_app(UUIDs.App.ISA95Vocabulary)
+ const info = cdb.search_app(UUIDs.App.Info)
+
+ this.rxsub = rxu.rx(
+ rx.combineLatest({ ...member_obs, vocab, info }),
+ rx.map(({ vocab, info, ...members_by_level }) => {
+ const nodes = []
+ for (const [level, uuids] of Object.entries(members_by_level)) {
+ for (const uuid of uuids) {
+ const v = vocab.get(uuid) ?? {}
+ const i = info.get(uuid) ?? {}
+ nodes.push({
+ uuid,
+ name: i.name ?? uuid,
+ aliases: v.aliases ?? [],
+ children: v.children ?? [],
+ level,
+ })
+ }
+ }
+ return nodes
+ }),
+ rx.share(),
+ ).subscribe(nodes => {
+ this.data = nodes
+ this.ready = true
+ })
+ },
+
+ stop () {
+ this.rxsub?.unsubscribe()
+ this.rxsub = null
+ this.ready = false
+ },
+ },
+})
diff --git a/acs-service-setup/dumps/isa95.yaml b/acs-service-setup/dumps/isa95.yaml
new file mode 100644
index 000000000..6907a841d
--- /dev/null
+++ b/acs-service-setup/dumps/isa95.yaml
@@ -0,0 +1,53 @@
+service: !u UUIDs.Service.ConfigDB
+version: 2
+objects:
+ !u ConfigDB.Class.R2Class:
+ !u UUIDs.Class.ISA95Level:
+ name: "ISA-95 hierarchy level"
+
+ !u UUIDs.Class.ISA95Level:
+ !u UUIDs.Class.ISA95Enterprise:
+ name: "ISA-95 Enterprise"
+ !u UUIDs.Class.ISA95Site:
+ name: "ISA-95 Site"
+ !u UUIDs.Class.ISA95Area:
+ name: "ISA-95 Area"
+ !u UUIDs.Class.ISA95WorkCenter:
+ name: "ISA-95 Work Center"
+ !u UUIDs.Class.ISA95WorkUnit:
+ name: "ISA-95 Work Unit"
+
+ !u UUIDs.Class.App:
+ !u UUIDs.App.ISA95Vocabulary:
+ name: "ISA-95 vocabulary"
+ subclassOf:
+ - !u MetaDB.Class.ConfigEntry
+
+configs:
+ !u UUIDs.App.ConfigSchema:
+ !u UUIDs.App.ISA95Vocabulary:
+ type: object
+ properties:
+ aliases:
+ type: array
+ items:
+ type: string
+ description: "Alternative labels that resolve to this node's canonical name"
+ children:
+ type: array
+ items:
+ type: string
+ format: uuid
+ description: "UUIDs of the next-level ISA-95 nodes under this node"
+ additionalProperties: false
+---
+service: !u UUIDs.Service.Authentication
+version: 2
+grants:
+ # Any authenticated principal can read the vocabulary (needed by the
+ # Manager UI to populate ISA-95 dropdowns for device configurers).
+ # Administrators already have full ConfigDB access via ACS.PermGroup.ConfigDB,
+ # which covers WriteConfig and ManageObjects on ISA-95 objects.
+ !u Auth.Class.Principal:
+ !u UUIDs.Permission.ConfigDB.ReadConfig:
+ !u UUIDs.App.ISA95Vocabulary: false
diff --git a/lib/js-service-client/lib/uuids.js b/lib/js-service-client/lib/uuids.js
index 14fe21718..263fc0ea4 100644
--- a/lib/js-service-client/lib/uuids.js
+++ b/lib/js-service-client/lib/uuids.js
@@ -3,42 +3,48 @@
*/
export const Class = {
- Individual: "2494ae9b-cd87-4c01-98db-437a303b43e9",
- R1Class: "04a1c90d-2295-4cbe-b33a-74eded62cbf1",
- Class: "04a1c90d-2295-4cbe-b33a-74eded62cbf1",
- R2Class: "705888ce-53fa-434d-afee-274b331d4642",
- R3Class: "52b80183-6998-4bf9-9b30-132755e7dede",
+ Individual: "2494ae9b-cd87-4c01-98db-437a303b43e9",
+ R1Class: "04a1c90d-2295-4cbe-b33a-74eded62cbf1",
+ Class: "04a1c90d-2295-4cbe-b33a-74eded62cbf1",
+ R2Class: "705888ce-53fa-434d-afee-274b331d4642",
+ R3Class: "52b80183-6998-4bf9-9b30-132755e7dede",
- App: "d319bd87-f42b-4b66-be4f-f82ff48b93f0",
- Device: "18773d6d-a70d-443a-b29a-3f1583195290",
- EdgeAgent: "00da3c0b-f62b-4761-a689-39ad0c33f864",
- EdgeAgentConnection: "f371cbfc-de3e-11ef-b361-7b31622bc42f",
- EdgeAgentDriver: "3874e06c-de4a-11ef-a68c-0f1c2d4d555c",
- EdgeCluster: "f24d354d-abc1-4e32-98e1-0667b3e40b61",
- EdgeDeployment: "e6f6a6e6-f6b2-422a-bc86-2dcb417a362a",
- Bridge: "178506d2-af52-4c79-8e5d-4958ae7ddfa9",
- File: 'b8fae5ab-678e-4d35-802f-2dd8ee3b5b02',
- FileType: "923801b3-c97a-48d8-8af9-da97dc13fe2d",
- GitRepo: "d25f2afc-1ab8-4d27-b51b-d02314624e3e",
- GitRepoGroup: "b03d4dfe-7e78-4252-8e62-af594cf316c9",
- HelmChart: "f9be0334-0ff7-43d3-9d8a-188d3e4d472b",
- PermGroup: "ac0d5288-6136-4ced-a372-325fbbcdd70d",
- Permission: "8ae784bb-c4b5-4995-9bf6-799b3c7f21ad",
- Principal: "11614546-b6d7-11ef-aebd-8fbb45451d7c",
- Private: "eda329ca-4e55-4a92-812d-df74993c47e2",
- Requirement: "b419cbc2-ab0f-4311-bd9e-f0591f7e88cb",
- Schema: "83ee28d4-023e-4c2c-ab86-12c24e86372c",
- Service: "265d481f-87a7-4f93-8fc6-53fa64dc11bb",
- Special: "ddb132e4-5cdd-49c8-b9b1-2f35879eab6d",
- SystemHelmChart: "a5c54a2e-8f7b-4b2a-9e8d-3f7c9e7d1c6a",
+ App: "d319bd87-f42b-4b66-be4f-f82ff48b93f0",
+ Device: "18773d6d-a70d-443a-b29a-3f1583195290",
+ ISA95Level: "3866b165-6b31-46e3-a801-cb367e04e726",
+ ISA95Enterprise: "2980293e-4a82-49a3-b121-9a8fa109d0a8",
+ ISA95Site: "70a948a7-7d99-400c-896a-ae63ab4362e0",
+ ISA95Area: "d0ac7371-41d6-45b2-8a42-781f8d4c8d54",
+ ISA95WorkCenter: "b0633e7c-e0c1-4350-9f86-72b83e3e9cb0",
+ ISA95WorkUnit: "00074ce8-2142-40a6-aff3-1057a83ddad2",
+ EdgeAgent: "00da3c0b-f62b-4761-a689-39ad0c33f864",
+ EdgeAgentConnection: "f371cbfc-de3e-11ef-b361-7b31622bc42f",
+ EdgeAgentDriver: "3874e06c-de4a-11ef-a68c-0f1c2d4d555c",
+ EdgeCluster: "f24d354d-abc1-4e32-98e1-0667b3e40b61",
+ EdgeDeployment: "e6f6a6e6-f6b2-422a-bc86-2dcb417a362a",
+ Bridge: "178506d2-af52-4c79-8e5d-4958ae7ddfa9",
+ File: 'b8fae5ab-678e-4d35-802f-2dd8ee3b5b02',
+ FileType: "923801b3-c97a-48d8-8af9-da97dc13fe2d",
+ GitRepo: "d25f2afc-1ab8-4d27-b51b-d02314624e3e",
+ GitRepoGroup: "b03d4dfe-7e78-4252-8e62-af594cf316c9",
+ HelmChart: "f9be0334-0ff7-43d3-9d8a-188d3e4d472b",
+ PermGroup: "ac0d5288-6136-4ced-a372-325fbbcdd70d",
+ Permission: "8ae784bb-c4b5-4995-9bf6-799b3c7f21ad",
+ Principal: "11614546-b6d7-11ef-aebd-8fbb45451d7c",
+ Private: "eda329ca-4e55-4a92-812d-df74993c47e2",
+ Requirement: "b419cbc2-ab0f-4311-bd9e-f0591f7e88cb",
+ Schema: "83ee28d4-023e-4c2c-ab86-12c24e86372c",
+ Service: "265d481f-87a7-4f93-8fc6-53fa64dc11bb",
+ Special: "ddb132e4-5cdd-49c8-b9b1-2f35879eab6d",
+ SystemHelmChart: "a5c54a2e-8f7b-4b2a-9e8d-3f7c9e7d1c6a",
};
export const Special = {
- Null: "00000000-0000-0000-0000-000000000000",
- FactoryPlus: "11ad7b32-1d32-4c4a-b0c9-fa049208939a",
- Self: "5855a1cc-46d8-4b16-84f8-ab3916ecb230",
- Unowned: "091e796a-65c0-4080-adff-c3ce01a65b2e",
- Mine: "724c0316-4cfd-11f0-b355-0b70840faae8",
+ Null: "00000000-0000-0000-0000-000000000000",
+ FactoryPlus: "11ad7b32-1d32-4c4a-b0c9-fa049208939a",
+ Self: "5855a1cc-46d8-4b16-84f8-ab3916ecb230",
+ Unowned: "091e796a-65c0-4080-adff-c3ce01a65b2e",
+ Mine: "724c0316-4cfd-11f0-b355-0b70840faae8",
};
/* back-compat */
@@ -47,72 +53,73 @@ export const FactoryPlus = Special.FactoryPlus;
export const App = {
- Registration: "cb40bed5-49ad-4443-a7f5-08c75009da8f",
- Info: "64a8bfa9-7772-45c4-9d1a-9e6290690957",
- SparkplugAddress: "8e32801b-f35a-4cbf-a5c3-2af64d3debd7",
- ConfigSchema: "dbd8a535-52ba-4f6e-b4f8-9b71aefe09d3",
- GitRepositoryConfig: "38d62a93-b6b4-4f63-bad4-d433e3eaff29",
- ServiceConfig: "5b47881c-b012-4040-945c-eacafca539b2",
- EdgeAgentConfig: "aac6f843-cfee-4683-b121-6943bfdf9173",
- EdgeAgentDeployment: "f2b9417a-ef7f-421f-b387-bb8183a48cdb",
- EdgeClusterStatus: "747a62c9-1b66-4a2e-8dd9-0b70a91b6b75",
- EdgeClusterSetupStatus: "f6c67e6f-e48e-4f69-b4bb-bfbddcc2a517",
- EdgeClusterConfiguration: "bdb13634-0b3d-4e38-a065-9d88c12ee78d",
- HelmChartTemplate: "729fe070-5e67-4bc7-94b5-afd75cb42b03",
- DeviceInformation: "a98ffed5-c613-4e70-bfd3-efeee250ade5",
- DriverDefinition: "454e5bec-de4a-11ef-bfea-4bc400f636a5",
- ConnectionConfiguration: "fa8b429c-de3e-11ef-87fd-6382f0eac944",
- SchemaInformation: "32093857-9d29-470e-a897-d2b56d5aa978",
- Schema: "b16e85fb-53c2-49f9-8d83-cdf6763304ba",
- ServiceSetup: "5b47881c-b012-4040-945c-eacafca539b2",
- FilesConfig: "731cb924-71bb-49fa-8cb8-1584bd1ebad3",
+ Registration: "cb40bed5-49ad-4443-a7f5-08c75009da8f",
+ Info: "64a8bfa9-7772-45c4-9d1a-9e6290690957",
+ SparkplugAddress: "8e32801b-f35a-4cbf-a5c3-2af64d3debd7",
+ ConfigSchema: "dbd8a535-52ba-4f6e-b4f8-9b71aefe09d3",
+ GitRepositoryConfig: "38d62a93-b6b4-4f63-bad4-d433e3eaff29",
+ ServiceConfig: "5b47881c-b012-4040-945c-eacafca539b2",
+ EdgeAgentConfig: "aac6f843-cfee-4683-b121-6943bfdf9173",
+ EdgeAgentDeployment: "f2b9417a-ef7f-421f-b387-bb8183a48cdb",
+ EdgeClusterStatus: "747a62c9-1b66-4a2e-8dd9-0b70a91b6b75",
+ EdgeClusterSetupStatus: "f6c67e6f-e48e-4f69-b4bb-bfbddcc2a517",
+ EdgeClusterConfiguration: "bdb13634-0b3d-4e38-a065-9d88c12ee78d",
+ HelmChartTemplate: "729fe070-5e67-4bc7-94b5-afd75cb42b03",
+ DeviceInformation: "a98ffed5-c613-4e70-bfd3-efeee250ade5",
+ ISA95Vocabulary: "11096075-acc6-4eae-b682-9b27d776384d",
+ DriverDefinition: "454e5bec-de4a-11ef-bfea-4bc400f636a5",
+ ConnectionConfiguration: "fa8b429c-de3e-11ef-87fd-6382f0eac944",
+ SchemaInformation: "32093857-9d29-470e-a897-d2b56d5aa978",
+ Schema: "b16e85fb-53c2-49f9-8d83-cdf6763304ba",
+ ServiceSetup: "5b47881c-b012-4040-945c-eacafca539b2",
+ FilesConfig: "731cb924-71bb-49fa-8cb8-1584bd1ebad3",
};
export const Schema = {
- Device_Information: "2dd093e9-1450-44c5-be8c-c0d78e48219b",
- Service: "05688a03-730e-4cda-9932-172e2c62e45c",
+ Device_Information: "2dd093e9-1450-44c5-be8c-c0d78e48219b",
+ Service: "05688a03-730e-4cda-9932-172e2c62e45c",
};
export const Service = {
- Directory: "af4a1d66-e6f7-43c4-8a67-0fa3be2b1cf9",
- ConfigDB: "af15f175-78a0-4e05-97c0-2a0bb82b9f3b",
- /* Compatibility. This was a failed attempt to rename the service. */
- Registry: "af15f175-78a0-4e05-97c0-2a0bb82b9f3b",
- Auth: "cab2642a-f7d9-42e5-8845-8f35affe1fd4",
- /* Compatibility. This is no longer an authentication service. */
- Authentication: "cab2642a-f7d9-42e5-8845-8f35affe1fd4",
- Command_Escalation: "78ea7071-24ac-4916-8351-aa3e549d8ccd",
- MQTT: "feb27ba3-bd2c-4916-9269-79a61ebc4a47",
- Git: "7adf4db0-2e7b-4a68-ab9d-376f4c5ce14b",
- Clusters: "2706aa43-a826-441e-9cec-cd3d4ce623c2",
- Manager: "619eecab-742d-4824-8b97-bcae472e5c04",
- Files: 'a2a6efc5-9793-4486-9fd9-7caf9e3b5451',
- DataAccess: "06cee697-29d3-4972-9479-bc392e24946e",
- i3x: "018854a1-a312-46d3-b904-c274b59088c7",
+ Directory: "af4a1d66-e6f7-43c4-8a67-0fa3be2b1cf9",
+ ConfigDB: "af15f175-78a0-4e05-97c0-2a0bb82b9f3b",
+ /* Compatibility. This was a failed attempt to rename the service. */
+ Registry: "af15f175-78a0-4e05-97c0-2a0bb82b9f3b",
+ Auth: "cab2642a-f7d9-42e5-8845-8f35affe1fd4",
+ /* Compatibility. This is no longer an authentication service. */
+ Authentication: "cab2642a-f7d9-42e5-8845-8f35affe1fd4",
+ Command_Escalation: "78ea7071-24ac-4916-8351-aa3e549d8ccd",
+ MQTT: "feb27ba3-bd2c-4916-9269-79a61ebc4a47",
+ Git: "7adf4db0-2e7b-4a68-ab9d-376f4c5ce14b",
+ Clusters: "2706aa43-a826-441e-9cec-cd3d4ce623c2",
+ Manager: "619eecab-742d-4824-8b97-bcae472e5c04",
+ Files: 'a2a6efc5-9793-4486-9fd9-7caf9e3b5451',
+ DataAccess: "06cee697-29d3-4972-9479-bc392e24946e",
+ i3x: "018854a1-a312-46d3-b904-c274b59088c7",
};
/* This list is not meant to be exhaustive, but these are commonly used
* well-known permissions. */
export const Permission = {
- Auth: {
- ReadACL: "ba566181-0e8a-405b-b16e-3fb89130fbee",
- ManageKerberos: "327c4cc8-9c46-4e1e-bb6b-257ace37b0f6",
- ManageACL: "3a41f5ce-fc08-4669-9762-ec9e71061168",
- ManageGroup: "be9b6d47-c845-49b2-b9d5-d87b83f11c3b",
- },
- CmdEsc: {
- Rebirth: "fbb9c25d-386d-4966-a325-f16471d9f7be",
- },
- ConfigDB: {
- ReadConfig: "4a339562-cd57-408d-9d1a-6529a383ea4b",
- WriteConfig: "6c799ccb-d2ad-4715-a2a7-3c8728d6c0bf",
- ManageObjects: "f0b7917b-d475-4888-9d5a-2af96b3c26b6",
- },
- Directory: {
- AdvertiseService: "4db4c39a-f18d-4e83-aeb0-5af2c14ddc2b",
- },
+ Auth: {
+ ReadACL: "ba566181-0e8a-405b-b16e-3fb89130fbee",
+ ManageKerberos: "327c4cc8-9c46-4e1e-bb6b-257ace37b0f6",
+ ManageACL: "3a41f5ce-fc08-4669-9762-ec9e71061168",
+ ManageGroup: "be9b6d47-c845-49b2-b9d5-d87b83f11c3b",
+ },
+ CmdEsc: {
+ Rebirth: "fbb9c25d-386d-4966-a325-f16471d9f7be",
+ },
+ ConfigDB: {
+ ReadConfig: "4a339562-cd57-408d-9d1a-6529a383ea4b",
+ WriteConfig: "6c799ccb-d2ad-4715-a2a7-3c8728d6c0bf",
+ ManageObjects: "f0b7917b-d475-4888-9d5a-2af96b3c26b6",
+ },
+ Directory: {
+ AdvertiseService: "4db4c39a-f18d-4e83-aeb0-5af2c14ddc2b",
+ },
};
export const Group = {
- UNS_Ingester: "e03152b8-cdab-11ef-8ee9-77393064507e",
+ UNS_Ingester: "e03152b8-cdab-11ef-8ee9-77393064507e",
};