# `Meshcore.Commands.Messaging`
[🔗](https://github.com/nyannus/meshcore_ex/blob/v0.1.0/lib/meshcore/commands/messaging.ex#L1)

Sending and receiving messages, remote logins, path discovery, traces and
flood scopes.

# `mc`

```elixir
@type mc() :: GenServer.server()
```

# `result`

```elixir
@type result() :: {:ok, Meshcore.Event.t()} | {:error, Meshcore.Event.t()}
```

# `force_unscoped`

```elixir
@spec force_unscoped(mc()) :: result()
```

Forces unscoped flood messages.

# `get_default_flood_scope`

```elixir
@spec get_default_flood_scope(mc()) :: result()
```

Reads the default flood scope (`:default_flood_scope`).

# `get_msg`

```elixir
@spec get_msg(mc(), keyword()) :: result()
```

Fetches the next queued message. The result is a `:contact_msg_recv`,
`:channel_msg_recv` or `:channel_data_recv` event, or `:no_more_msgs`.

Options: `:timeout`.

# `reset_default_flood_scope`

```elixir
@spec reset_default_flood_scope(mc()) :: result()
```

Disables the default flood scope.

# `reset_flood_scope`

```elixir
@spec reset_flood_scope(mc()) :: result()
```

Resets the flood scope (sends an empty scope key).

# `send_chan_msg`

```elixir
@spec send_chan_msg(mc(), 0..255, String.t(), keyword()) :: result()
```

Sends a message to channel `chan`.

Options: `:timestamp` – Unix seconds as an integer or a 4 byte little-endian
binary (default now).

# `send_channel_data`

```elixir
@spec send_channel_data(mc(), 0..255, 1..65535, binary(), keyword()) :: result()
```

Sends a binary datagram to a channel (`CMD_SEND_CHANNEL_DATA`).

`data_type` is `0x0001..0xFFFF` (`0xFFFF` is the developer namespace),
`payload` at most 163 bytes. Options: `:path` (default `nil` = flood) and
`:path_hash_mode` (default `0`).

# `send_cmd`

```elixir
@spec send_cmd(mc(), Meshcore.Util.destination(), String.t(), keyword()) :: result()
```

Sends a CLI command to a remote node as a text message.

Options: `:timestamp`, `:dst_type` (`:chat | :repeater | :room | :sensor` or the
numeric type; taken from a contact map when available, else a repeater is
assumed).

# `send_login`

```elixir
@spec send_login(mc(), Meshcore.Util.destination(), String.t()) :: result()
```

Sends a login request and returns once it has been queued (`:msg_sent`).
Prefer `send_login_sync/4`.

# `send_login_sync`

```elixir
@spec send_login_sync(mc(), Meshcore.Util.destination(), String.t(), keyword()) ::
  result()
```

Logs in to a remote node (repeater, room server) and waits for the
`:login_success` event. Returns `{:error, event}` when the request could not
be sent or no success arrived in time.

Options: `:timeout`, `:min_timeout` (ms; default: derived from the device's
suggestion).

# `send_logout`

```elixir
@spec send_logout(mc(), Meshcore.Util.destination()) :: result()
```

Logs out of a remote node.

# `send_msg`

```elixir
@spec send_msg(mc(), Meshcore.Util.destination(), String.t(), keyword()) :: result()
```

Sends a direct message. Returns `:msg_sent` with `expected_ack` (raw bytes)
and `suggested_timeout` (ms); wait for the matching `:ack` event to confirm
delivery (or use `send_msg_with_retry/4`).

Options: `:timestamp` (Unix seconds, default now), `:attempt` (default `0`).

# `send_msg_with_retry`

```elixir
@spec send_msg_with_retry(mc(), Meshcore.Util.destination(), String.t(), keyword()) ::
  {:ok, Meshcore.Event.t()} | {:error, :not_acknowledged}
```

Sends a direct message and retries until it is acknowledged.

After `:flood_after` unacknowledged attempts the stored path is reset so the
message is flooded. Returns `{:ok, msg_sent_event}` of the acknowledged
attempt or `{:error, :not_acknowledged}`.

Options: `:timestamp`, `:max_attempts` (3), `:max_flood_attempts` (2),
`:flood_after` (2), `:timeout` / `:min_timeout` (ms per attempt; default
derived from the device's suggestion × 1.2).

Must be called from a process that can receive messages (it subscribes to
`:ack` events temporarily).

# `send_path_discovery`

```elixir
@spec send_path_discovery(mc(), Meshcore.Util.destination()) :: result()
```

Starts path discovery towards `dst`; returns once queued. Prefer `send_path_discovery_sync/3`.

# `send_path_discovery_sync`

```elixir
@spec send_path_discovery_sync(mc(), Meshcore.Util.destination(), keyword()) ::
  result()
```

Discovers the path to `dst` and waits for the `:path_response` event.
Options: `:timeout`, `:min_timeout`.

# `send_raw_data`

```elixir
@spec send_raw_data(mc(), binary(), binary()) :: result()
```

Sends raw data via `CMD_SEND_RAW_DATA`. `payload` must be at least 4 bytes;
`path` holds the intermediate hops (empty = zero-hop direct).

# `send_statusreq`

```elixir
@spec send_statusreq(mc(), Meshcore.Util.destination()) :: result()
```

Requests the status of a remote node and returns once queued.
Prefer `Meshcore.Commands.Binary.req_status_sync/3`.

# `send_telemetry_req`

```elixir
@spec send_telemetry_req(mc(), Meshcore.Util.destination()) :: result()
```

Requests telemetry from a remote node and returns once queued.
Prefer `Meshcore.Commands.Binary.req_telemetry_sync/3`.

# `send_trace`

```elixir
@spec send_trace(mc(), keyword()) :: result()
```

Sends a trace packet through a chain of repeaters. The `:msg_sent` result
carries the `tag`; the outcome arrives as a `:trace_data` event with the same
`tag` attribute.

Options:

  * `:auth_code` – 32 bit auth code (default `0`; `nil` = random)
  * `:tag` – 32 bit tag (default random)
  * `:flags` – the two low bits select the hash size (`1 <<< n` bytes)
  * `:path` – a string of comma separated hex hashes (`"23,5f,3a"`) or
    `{:raw, binary}` with the raw path bytes

# `set_default_flood_scope`

```elixir
@spec set_default_flood_scope(mc(), String.t() | nil) :: result()
```

Sets the device's default flood scope region (`nil`, `""`, `"0"`, `"None"`
or `"*"` disable it). Raises `ArgumentError` for names of 31 bytes or more.

# `set_flood_scope`

```elixir
@spec set_flood_scope(mc(), nil | String.t() | {:key, binary()}, keyword()) ::
  result()
```

Sets the flood scope for outgoing flood packets.

  * `nil`, `""`, `"0"` or `"None"` – reset to the default scope
  * `"*"` – force unscoped
  * any other string – region name (a `#` is prepended if missing); the key is
    the first 16 bytes of its SHA-256
  * `{:key, binary}` – use a raw scope key

Option `:force_unscoped` forces unscoped messages.

---

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