README.md

# yell

[![Package Version](https://img.shields.io/hexpm/v/yell)](https://hex.pm/packages/yell)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/yell/)

A Simple Service Discovery Protocol (SSDP) library for Gleam on Erlang.

SSDP is a UDP multicast protocol for discovering services on a local area network. It is a component of the Universal Plug and Play (UPnP) architecture but can be used independently. This library includes Gleam OTP [Actors](https://hexdocs.pm/gleam_otp/gleam/otp/actor.html) to handle each of the tasks involved in the protocol: 

- **`yell/discoverer`** - Send multicast discovery requests to find services
- **`yell/replier`** - Listen for discovery requests and reply with service information
- **`yell/notifier`** - Send multicast notifications to advertise service availability
- **`yell/listener`** - Listen for notifications and discovery replies

Applications can pick and choose which actors to use. For example, a typical service will use a `replier` and a `notifier`. A typical control point will use a `discoverer` and `listener` to find services. To install:

```sh
gleam add yell
```

## Quick Start

### Advertising a Service

```gleam
import glip
import yell
import yell/notifier
import yell/replier

pub fn main() {
  let assert Ok(addr) = glip.parse_ip("192.168.1.100")
  let assert Ok(service) = yell.new_service(
    "urn:schemas-upnp-org:service:ContentDirectory:1",
    "uuid:my-service-id::urn:schemas-upnp-org:service:ContentDirectory:1"
  )
  let service = service
    |> yell.with_location("http://192.168.1.100:8008/device.xml")
    |> yell.max_age(1800)

  let assert Ok(notifier) = notifier.start(service)
  let assert Ok(replier) = 
    service
	|> replier.new(addr)
	|> replier.start
	
  notifier.loop(notifier, 30_000)  // Send Alive notifications every 30 seconds
  
}
```

### Discovering Services

```gleam
import gleam/erlang/process
import glip
import yell/discoverer
import yell/listener

pub fn main() {
  let assert Ok(addr) = glip.parse_ip("192.168.1.101")
  let assert Ok(builder) = discoverer.new("ssdp:all")
  let assert Ok(actor) = discoverer.start(builder)

  let listen_subject = process.new_subject()
  let assert Ok(_listener) = 
    listener.new(addr)
	|> listener.subscribe(with: listen_subject)
	|> listener.start
  
  // Start periodic discovery
  discoverer.loop(actor, 5000)  // Every 5 seconds
  
  // do something with the replies and notifications
  let notification = process.receive_forever(listen_subject)
}
```

Further documentation can be found at <https://hexdocs.pm/yell>.

## Development

```sh
gleam test  # Run the tests
```