# Served nodes

> The list of what the embedded OPC UA server serves, and all it serves: tags, Logic variables, alarms and device commands, each read only until you allow writing, where a client finds each, and what an updated station needs.

**Served nodes** is the fourth card of the OPC UA server's panel on the Connector. The server serves this list and nothing else: a client that connects finds the tags, Logic variables, alarms and device commands listed here, and none other. The card says so under its title: "The server serves this list and nothing else: each row is a tag, a Logic variable, an alarm or a device command. A row stays read only until you allow writing. A client's write then takes the same path as every other write and is recorded in the journal with the client's session." View connector reads the card; Configure connector changes it.

## An empty list {#an-empty-list}

The list starts empty, on a new station and on a station updated from a version that served every device whole. While it is empty, a caution note on the card says: "The list is empty, so the server serves nothing of the station: an OPC UA client finds no tag, variable, alarm or command until you add rows." The server still listens and still accepts the sessions [Client access](connector-opcua-client-access) allows; they browse an address space with nothing of the station in it. An agent reads the same thing on `server_status`, whose `servesNothing` is true while the list is empty.

## The table {#the-table}

| Column | What it shows |
| --- | --- |
| **Source** | What the row serves, as the picker names it, or "No source yet" while its source is not chosen. |
| **Access** | **Read only** or **Read and write**, and **Callable** for a device command. |
| **Node** | The address a client is configured with, in the form `nsu=<namespace>;s=<identifier>`; empty while the row serves nothing. |

The rows are listed by kind (tags, variables, alarms, commands), then by name. With none, the table reads "No node is served yet. Add one with New row." Clicking a row selects it and opens its fields under the table; which row is selected belongs to the window you are in.

| Command | What it does | Greyed when (situation) | Not drawn when (role) |
| --- | --- | --- | --- |
| **New row** | Adds a read only row that serves nothing yet and selects it, so its source is picked next. The feed says "Row added to the OPC UA server's list. Pick its source." | A run holds the station, or the runtime is stopped. | Without Configure connector. |
| **Delete row** (danger ink) | Deletes the row the table has selected, at once and with no question; its tooltip names the source the row serves, and the feed confirms it. The source is not touched: a client no longer finds its node. | No row is selected ("Select a row of the list to delete it."), a run holds the station, or the runtime is stopped. | Without Configure connector. |

## A row's fields {#a-rows-fields}

Each field is stored the moment it changes, and the server serves the new row a moment later, without dropping a session: it reads its list ten times a second.

| Field | What it does | Values and default |
| --- | --- | --- |
| **Source** | What the row serves. The list opens with "(none)", then every enabled tag of an enabled device, named after its driver, its device and itself ("Tag · Simulated · Oven · Temperature"), then every Logic variable that holds a value, by its folders and its name ("Variable · Oven / Setpoint"), then every alarm, named the same way ("Alarm · Oven / High temperature"), and last every command of an enabled device: the commands declared on the device page and those a protocol fixes, such as a charge point's ("Command · OCPP · Charger · Reset"). A source is listed once. The row holds its source by identity, so a rename leaves the row on the same source, which the server then serves under its new name. A source the list no longer offers stays selected and named, a disabled tag or command with what keeps it out, and only a source that no longer exists reads as missing, with its identity. A tag's [Used by](connector-tags#the-used-by-card) card lists the rows that serve it. | "(none)" for a new row. |
| **Access** | Whether a client may write the row. **Read and write** stays listed and greyed where the source takes no write, its tooltip saying "This source takes no write: only a tag with write access or a memory variable does." Picking an alarm sets the row back to read only. For a command the field shows **Callable** as a fixed value, with no picker, because a command is called, never read or written. | **Read only** or **Read and write**; **Callable**, fixed, for a command. Read only for a new row. |

Under the fields a line says what the row does for a client:

| The card says | When |
| --- | --- |
| "This row serves nothing yet: pick its source." | No source is chosen. |
| "The source of this row no longer exists, so the server serves nothing for it." | The tag, the variable, the alarm or the command was deleted. |
| "A client may read this node and not write it." | A tag or a variable, read only. |
| "A client may read and write this node: each write is recorded in the journal with the client's session." | A tag or a variable marked read and write. |
| "A client reads the alarm's Active, Acked, State, Priority and Message, and never writes them." | An alarm. |
| "A client calls this command as a method of its device for as long as it is in the list." | A device command. |

Under that line, **A client finds it at** is followed by the node.

## What a row refuses {#what-a-row-refuses}

A change the list's rules refuse is not stored: the reason is said in red above the row's fields, the change stays on the screen so you can correct it, and the row keeps serving what it served.

| The card says | When |
| --- | --- |
| "This source is already in the list: a client finds it at the node that row serves." | The source is listed in another row. |
| "The source cannot be written: pick a tag with write access or a memory variable, or keep the row read only." | Read and write on a read-only tag, a tag of a driver that never writes, an expression variable, an alarm, a command or a source that no longer exists. |
| "A row that takes writes needs the tag or the variable they go to." | Read and write on a row with no source, which only an agent can ask for. |
| "This row of the list no longer exists. Reload and retry." | The row was deleted elsewhere, in another window or by an agent, while you were editing it. |

While a run holds the station or the runtime is stopped, a change is refused the way every change of the page is, with the reason in the action feed, and nothing is stored.

## Where a client finds each source {#where-a-client-finds-each-source}

| Source | Where it is | What a client reads |
| --- | --- | --- |
| Tag | Where it has always been: in its device's namespace, `http://opcfoundation.org/UA/<driver>.<device>/`, under the tag's own name. A client configured before the list existed finds it at the same address. A client that browses finds it in the `Devices` folder under Objects, inside the object named after its device. | The value the device answered, with its quality and its stamp, as the Connector reads it. |
| Logic variable | In the `Logic` folder under Objects, inside the Logic's own folders, in the server's namespace `http://opcfoundation.org/UA/EdgeTranslator/` under its Logic address (`Variables.Oven.Setpoint`). | Its value, typed by the station's one conversion: Boolean, Int64 for an Integer, Double for a Decimal, String for a Text and DateTime for a Date and time. A variable with no good value reads BadDataUnavailable. |
| Alarm | In the `Alarms` folder under Objects, inside the Logic's own folders, as one object under its Logic address (`Alarms.Oven.HighTemperature`). | Five read-only members: Active and Acked (Boolean), State (Int32: 0 normal, 1 active and unacknowledged, 2 active and acknowledged, 3 cleared and unacknowledged), Priority and Message (String). While the alarm holds its state through bad quality, Active, Acked and State read UncertainLastUsableValue. |
| Command | A method of its device, beside the device's tags. | Called with the values the command declares, it answers with what the equipment answered. |

Every device keeps its namespace whatever the list serves of it, so the index a client finds a namespace at does not move when another device's tags join or leave the list. A device the list names nothing of has no node.

## Writing {#writing}

A client's write reaches the station only on a row marked read and write, and the list is asked again the moment the write arrives, so a row made read only a moment ago is never written. A tag's write goes to its device's delivery queue as every write from outside does, and the answer waits for the equipment; a memory variable's write goes through the Logic's write funnel and is converted to the variable's type. The source locks apply: a source a running Process holds is refused. Every write is journaled with the client's application and session. An expression variable and an alarm never take a write, and the server answers BadNotWritable. A command is called rather than written, and a client calls only a command that is in the list.

## An updated station {#an-updated-station}

A station updated from a version without the list served every tag of every device. Its list starts empty, so after the update its OPC UA server serves nothing until the list is built: add a row for each tag a client reads, mark read and write the ones a client writes, and add the commands a client calls. A client configured before the update finds each tag at the address it had, so it needs no change of its own.

## With an agent {#with-an-agent}

```text
server_list_upsert(source: "Connector.Simulated.Oven.Temperature")
server_list_upsert(source: "Variables.Oven.Setpoint", access: "ReadAndWrite")
server_list_upsert(source: "Alarms.Oven.HighTemperature")
server_status()
```

A row created by an agent is read only unless `access` says otherwise, and `server_list_delete` deletes one by its id. The tools are described on [The tools, area by area](agent-tools#connector--configure).

## What the list does not do {#what-the-list-does-not-do}

It does not turn the server on (the command bar's Enable does), it does not decide which client may connect ([Client access](connector-opcua-client-access) does), and it does not acknowledge an alarm from outside: acknowledging stays an operator's command. It serves the values above and no OPC UA alarms and conditions events. A variable that holds an image, an icon or a colour is not offered, and a constant of a device's description is not served.
