# `IEC60870.CS101.Master`
[🔗](https://github.com/Ultraluv/ex_iec60870/blob/main/lib/iec60870/cs101/master.ex#L1)

IEC 60870-5-101 Master (`cs101_master.c`), supporting both `:balanced` and `:unbalanced` link layer modes.

Features:
- Multi-slave polling and addressing in `:unbalanced` mode (`add_slave/2`, `use_slave_address/2`, `poll_single_slave/2`, `request_class_1_data/2`, `request_class_2_data/2`)
- Automatic Class 1 polling when `ACD` (Access Demand) bit is set by a slave
- Full-duplex peer-to-peer transmission in `:balanced` mode (`DIR = true` by default)
- Convenience command functions (`send_interrogation_command/4`, `send_clock_sync_command/3`, `send_process_command/4`, `send_asdu/2`, etc.)

# `mode`

```elixir
@type mode() :: :balanced | :unbalanced
```

# `add_slave`

```elixir
@spec add_slave(GenServer.server(), non_neg_integer()) :: :ok
```

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `get_app_layer_parameters`

```elixir
@spec get_app_layer_parameters(GenServer.server()) :: IEC60870.AppLayerParameters.t()
```

# `get_link_layer_parameters`

```elixir
@spec get_link_layer_parameters(GenServer.server()) ::
  IEC60870.LinkLayerParameters.t()
```

# `is_channel_ready?`

```elixir
@spec is_channel_ready?(GenServer.server(), non_neg_integer()) :: boolean()
```

# `poll_single_slave`

```elixir
@spec poll_single_slave(GenServer.server(), non_neg_integer()) :: :ok
```

# `request_class_1_data`

```elixir
@spec request_class_1_data(GenServer.server(), non_neg_integer()) :: :ok
```

# `request_class_2_data`

```elixir
@spec request_class_2_data(GenServer.server(), non_neg_integer()) :: :ok
```

# `send_asdu`

```elixir
@spec send_asdu(GenServer.server(), IEC60870.ASDU.t(), non_neg_integer() | nil) ::
  :ok | {:error, term()}
```

# `send_clock_sync_command`

# `send_counter_interrogation_command`

# `send_interrogation_command`

# `send_link_layer_test_function`

```elixir
@spec send_link_layer_test_function(GenServer.server()) :: :ok
```

# `send_process_command`

# `send_read_command`

# `send_test_command`

# `set_dir`

```elixir
@spec set_dir(GenServer.server(), boolean()) :: :ok
```

Sets the DIR bit in balanced link layer mode.

# `set_idle_timeout`

```elixir
@spec set_idle_timeout(GenServer.server(), pos_integer()) :: :ok
```

Sets idle timeout in milliseconds.

# `set_own_address`

```elixir
@spec set_own_address(GenServer.server(), non_neg_integer()) :: :ok
```

Sets own link layer address in balanced mode.

# `start`

```elixir
@spec start(GenServer.server()) :: :ok
```

# `start_link`

Starts a `CS101.Master` GenServer.

Options:
- `:transport` (required) - `{transport_mod, handle}` (e.g. `VirtualBus.attach(bus)`)
- `:mode` - `:unbalanced` or `:balanced` (default `:unbalanced`)
- `:ll_params` - `%IEC60870.LinkLayerParameters{}`
- `:al_params` - `%IEC60870.AppLayerParameters{}`
- `:own_address` - own link layer address for balanced mode (default `0`)
- `:slave_address` - default target slave link address (default `1`)
- `:slaves` - list of slave link addresses to register initially in unbalanced mode
- `:dir` - `DIR` bit in balanced mode (default `true`)
- `:queue_size` - max ASDU queue size in balanced mode (default `100`)
- `:owner` - PID to receive `{:iec60870_cs101_master, master_pid, event}` messages
- `:asdu_handler` - `fn master_pid, slave_addr, asdu -> any() end`
- `:link_state_handler` - `fn master_pid, slave_addr, new_state -> any() end`
- `:raw_message_handler` - `fn master_pid, bytes, sent? -> any() end`

# `stop`

```elixir
@spec stop(GenServer.server()) :: :ok
```

# `use_slave_address`

```elixir
@spec use_slave_address(GenServer.server(), non_neg_integer()) :: :ok
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
