# `IEC60870.FileService.Server`
[🔗](https://github.com/Ultraluv/ex_iec60870/blob/main/lib/iec60870/file_service/server.ex#L1)

IEC 60870-5-101 / 104 File Transfer Server (`file_server.c`) for Slave stations.

Supports:
1. Directory read requests (`F_SC_NA_1` / `F_SC_NB_1` with `COT = :request` -> `F_DR_TA_1`)
2. File upload (Master reads file from Slave: `F_SC_NA_1` -> `F_FR_NA_1` -> `F_SR_NA_1` -> `F_SG_NA_1` -> `F_LS_NA_1` -> `F_AF_NA_1`)
3. File download (Master writes file to Slave: `F_FR_NA_1` -> `F_SC_NA_1` -> `F_SR_NA_1` -> `F_SC_NA_1` -> `F_SG_NA_1` -> `F_LS_NA_1` -> `F_AF_NA_1`)

Can be attached to a `CS104.Slave` or `CS101.Slave` by calling `handle_asdu/3` inside the Slave's `asdu_handler`.

# `add_file`

```elixir
@spec add_file(GenServer.server(), IEC60870.FileService.TransparentFile.t()) :: :ok
```

Adds or replaces an available `%TransparentFile{}` on the server.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `get_received_files`

```elixir
@spec get_received_files(GenServer.server()) :: map()
```

Returns a map of all files received from the Master (`%{{ca, ioa, nof} => binary()}`).

# `handle_asdu`

```elixir
@spec handle_asdu(GenServer.server(), pid(), IEC60870.ASDU.t()) :: boolean()
```

Processes a received ASDU from `CS104.Slave` or `CS101.Slave`.
Returns `true` if the ASDU is a file service ASDU and was handled, or `false` otherwise.

# `remove_file`

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

Removes a file by `{ca, ioa, nof}`.

# `start_link`

Starts a `FileService.Server` GenServer.

Options:
- `:files` - list of `%TransparentFile{}` initially available for Master to read
- `:max_segment_size` - max segment payload size in bytes (default `200`)
- `:timeout_ms` - transfer timeout in milliseconds (default `10_000`)
- `:owner` - PID to receive `{:iec60870_file_server, server_pid, event}` notifications
- `:file_ready_handler` - `fn ca, ioa, nof, lof -> :ok | {:error, :unknown_ca | :unknown_ioa | :not_ready} end`
- `:file_received_handler` - `fn %Receiver{} -> any() end`

---

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