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

IEC 60870-5-101 / 104 File Transfer Client for Master stations.

Supports:
1. `request_directory/4`: Calls directory on Slave and returns `{:ok, [directory_entry]}`
2. `get_file/5`: Selects and reads (uploads) a 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. `send_file/3`: Sends (downloads) a `%TransparentFile{}` from Master 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 work over either `IEC60870.CS104.Connection` or `IEC60870.CS101.Master` by passing a `send_asdu_fun`
(or `:master` option) and forwarding received ASDUs via `handle_asdu/2`.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `get_file`

```elixir
@spec get_file(
  GenServer.server(),
  non_neg_integer(),
  non_neg_integer(),
  non_neg_integer(),
  term()
) ::
  {:ok, binary() | IEC60870.FileService.Receiver.Memory.t()} | {:error, term()}
```

Reads (uploads) a file `(ca, ioa, nof)` from the Slave.
Returns `{:ok, binary()}` (or `{:ok, %Receiver.Memory{}}` if passed as receiver) upon completion.

# `handle_asdu`

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

Feeds an incoming ASDU from `CS104.Connection` or `CS101.Master` into the FileService Client.
Returns `true` if handled, `false` otherwise.

# `query_log`

Queries the file directory filtered by creation time range (`F_SC_NB_1` with `COT = :request`).
Returns `{:ok, entries}` when the last directory entry (`SOF` bit `0x20`) is received.

# `request_directory`

```elixir
@spec request_directory(
  GenServer.server(),
  non_neg_integer(),
  non_neg_integer(),
  timeout()
) ::
  {:ok, [map()]} | {:error, term()}
```

Requests the file directory from the Slave (`F_SC_NA_1` with `COT = :request`).
Returns `{:ok, entries}` when the last directory entry (`SOF` bit `0x20`) is received.

# `send_file`

```elixir
@spec send_file(
  GenServer.server(),
  non_neg_integer() | IEC60870.FileService.TransparentFile.t(),
  IEC60870.FileService.TransparentFile.t() | timeout(),
  timeout()
) :: :ok | {:error, term()}
```

Writes (downloads) a `%TransparentFile{}` from the Master to the Slave.
Returns `:ok` upon receiving positive file ACK (`F_AF_NA_1` with `afq = 1`).

# `start_link`

Starts a `FileService.Client` GenServer.

Options:
- `:send_asdu_fun` (required or `:connection` / `:master`) - `fn %ASDU{} -> :ok end`
- `:connection` - `CS104.Connection` pid (automatically builds `send_asdu_fun`)
- `:master` - `CS101.Master` pid (automatically builds `send_asdu_fun`)
- `:oa` - Originator Address (default `0`)
- `:max_segment_size` - max segment payload size in bytes when sending files (default `200`)

---

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