# Control authority

> Learn how Synnax decides which writer controls a channel, and how to set it.

A writer is anything that sends values to a channel: a schematic, an Arc automation, a script, or a task. More than one writer can write to the same command channel, but only one writer at a time controls it. Control authority, a number from 0 to 255, decides which writer that is. With control authority, you can hand off control:

* Between an operator and an automation.
* Between two operators.
* Between two automations, such as a nominal sequence and an abort sequence.

Arc automations and scripts write at 255 if you do not set an authority. An operator cannot take a channel from them, so give them a lower authority on each channel that an operator must be able to take. See [default authorities](https://docs.synnaxlabs.com/reference/control/authority#default-authorities).

## How authority works

1. [](https://docs.synnaxlabs.com/reference/control/authority#higher-authority-takes-control)

   Higher authority takes control

   When a writer opens on a channel, or raises its authority, with a higher authority than the controlling writer, it takes control.

2. [](https://docs.synnaxlabs.com/reference/control/authority#on-equal-authority-the-first-writer-to-open-keeps-control)

   On equal authority, the first writer to open keeps control

   When two writers have the same authority, the one that opened on the channel first controls it. A writer that releases control and takes it again counts as a new writer.

3. [](https://docs.synnaxlabs.com/reference/control/authority#control-passes-on-when-the-controlling-writer-leaves)

   Control passes on when the controlling writer leaves

   When the controlling writer closes or lowers its authority, rules 1 and 2 pick the new controlling writer from the writers that are still open.

4. [](https://docs.synnaxlabs.com/reference/control/authority#values-from-other-writers-are-dropped)

   Values from other writers are dropped

   Synnax ignores the values from a writer that does not control the channel. The writer gets no error.

5. [](https://docs.synnaxlabs.com/reference/control/authority#255-is-the-highest-authority)

   255 is the highest authority

   A writer at 255 keeps control against every writer that opened after it.

6. [](https://docs.synnaxlabs.com/reference/control/authority#the-index-channel-decides-for-its-data-channels)

   The index channel decides for its data channels

   A writer that loses control of an index channel loses its writes to every channel on that index, even the channels it controls.

### Virtual channels

A [virtual channel](https://docs.synnaxlabs.com/reference/channels#virtual-channels) can have more than one writer at a time. Every writer with an authority equal to or higher than the controlling writer can write to it. For example, if a schematic and an Arc automation both write to a virtual `press_vlv_cmd` at 255, the values from both reach the channel.

## Example: operator and abort

A Press sequence controls `press_vlv_cmd`, a command channel with an index. It writes at 100, and at 255 in its abort stage. An operator watches the test on a schematic that writes at 200, and at 255 from a control chip.

123456Press sequenceArc automation100100100100255SchematicOperator200200200255

**Controls the channel**Open, values dropped255Authority

1. 1The Press sequence starts.**Press sequence** takes control. No other writer is open.
2. 2The operator takes control.**Schematic** takes control. 200 is higher than 100.
3. 3The operator releases control.**Press sequence** takes control. It is the only writer left.
4. 4The operator takes control again.**Schematic** takes control. 200 is higher than 100.
5. 5The Press sequence enters its abort stage.**Press sequence** takes control. 255 is higher than 200.
6. 6The operator clicks the control chip (255).**Press sequence** keeps control. Equal authority, and it opened first.

In this recording, an automation named Valve Guard writes at 100, and a schematic at 200 takes control, opens the valve, and releases control. The legend shows which writer controls the valve at each step.

[](https://synnax.nyc3.cdn.digitaloceanspaces.com/docs/control/authority/hand-off-dark.mp4#t=0.001)

## Set authority

[Enterprise](https://docs.synnaxlabs.com/reference/get-started/editions "Needs Synnax Enterprise")

**Console**

Each schematic writes at one authority, 1 by default. To change it, see [set the schematic authority](https://docs.synnaxlabs.com/reference/control/manual#set-the-schematic-authority).

**Python**

Open a writer with the `authorities` parameter, then change the authority while the writer is open.

Pass one authority for every channel, or one authority for each channel:

```python
writer = client.open_writer(
    start=sy.TimeStamp.now(),
    channels=["press_time", "press_vlv_cmd"],
    authorities=100,
)
```

Change the authority of every channel, or of the channels you name:

```python
writer.set_authority(200)
writer.set_authority({"press_time": 255, "press_vlv_cmd": 255})
```

Set `err_on_unauthorized=True` to make `open_writer` raise an error when a different writer controls one of the channels. Writes made later without control still return no error.

To control hardware from a script with waits and conditions, see [write a control sequence in Python](https://docs.synnaxlabs.com/reference/control/python/write-sequences).

**TypeScript**

Open a writer with the `authorities` parameter, then change the authority while the writer is open.

Pass one authority for every channel, or one authority for each channel:

```typescript
const writer = await client.openWriter({
  start: TimeStamp.now(),
  channels: ["press_time", "press_vlv_cmd"],
  authorities: 100,
});
```

Change the authority of every channel, or of the channels you name:

```typescript
await writer.setAuthority(200);
await writer.setAuthority({ press_time: 255, press_vlv_cmd: 255 });
```

Set `errOnUnauthorized: true` to make `openWriter` throw an error when a different writer controls one of the channels. Writes made later without control still return no error.

**Arc**

1. In the Arc editor, after the `import` lines, add `authority 100`. It sets the authority for every channel that the automation writes.
2. In each stage that an operator must not override, add `control.set_authority{value=255}`. The automation raises its authority when the stage starts.
3. Start the automation.

The finished automation:

```arc
import control

authority 100

sequence main {
    stage pressurize {
        1 -> press_vlv_cmd
        0 -> vent_vlv_cmd
        tank_pt > 450 => abort
        abort_cmd == 1 => abort
        tank_pt > 300 => hold
    }
    stage hold {
        0 -> press_vlv_cmd
        abort_cmd == 1 => abort
    }
    stage abort {
        control.set_authority{value=255}
        0 -> press_vlv_cmd
        1 -> vent_vlv_cmd
    }
}

start_cmd == 1 => main
```

A schematic that shows these channels now lists the automation in its control legend. An operator who takes control at more than 100 takes the valves until the abort stage starts.

To set a different authority on one channel, list it after the default: `authority (100 vent_vlv_cmd 200)`. Always give a default. Without one, the channels you do not list stay at 255, and so do their index channels. An operator who takes a listed channel then loses every write to it, because the automation keeps the index (see [the index channel rule](https://docs.synnaxlabs.com/reference/control/authority#the-index-channel-decides-for-its-data-channels)). See the [`control` module](https://docs.synnaxlabs.com/reference/control/arc/standard-library/control).

## See which writer controls a channel

On a schematic, the [control chips](https://docs.synnaxlabs.com/reference/control/manual#control-chips) and the control legend show which writer controls each channel. In code:

[Enterprise](https://docs.synnaxlabs.com/reference/get-started/editions "Needs Synnax Enterprise")

**Python**

```python
state = client.control.retrieve(name="press_vlv_cmd")
if state is None:
    print("No writer controls press_vlv_cmd")
else:
    print(state.subject.name, state.authority)
```

`retrieve` returns `None` when no writer controls the channel.

**TypeScript**

```typescript
const ch = await client.channels.retrieve("press_vlv_cmd");
const state = await client.control.retrieve(ch.key);
console.log(state.subject.name, state.authority);
```

`retrieve` takes channel keys, and throws a `NotFoundError` when no writer controls the channel.

## Default authorities

| Writer                                     | Default | Where to change it                                                                                                                                                         |
| ------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Schematic                                  | 1       | [Schematic authority](https://docs.synnaxlabs.com/reference/control/manual#set-the-schematic-authority). Each Console keeps its own value. The schematic does not save it. |
| Schematic, after a click on a control chip | 255     | Cannot change                                                                                                                                                              |
| Arc automation                             | 255     | [`authority` line](https://docs.synnaxlabs.com/reference/control/authority#set-authority)                                                                                  |
| Python or TypeScript writer                | 255     | [`authorities` parameter](https://docs.synnaxlabs.com/reference/control/authority#set-authority)                                                                           |
| Read task and write task                   | 255     | Cannot change                                                                                                                                                              |

A read task writes the channels it reads at 255, so a script cannot write to them while the task runs. A write task writes its [state channels](https://docs.synnaxlabs.com/reference/hardware/tasks#state-channels) at 255.
