Skip to content

Instantly share code, notes, and snippets.

@tobstarr
Created November 8, 2022 08:04
Show Gist options
  • Save tobstarr/054a16d1af31a757afab7682d3ab6b2e to your computer and use it in GitHub Desktop.
Save tobstarr/054a16d1af31a757afab7682d3ab6b2e to your computer and use it in GitHub Desktop.
defmodule Dynasty.Sonos.Discovery do
use GenServer
@playersearch ~S"""
M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1
"""
@multicastaddr [{239, 255, 255, 250}, {255, 255, 255, 255}]
def init(state) do
{:ok, socket} = :gen_udp.open(8989)
Process.send_after(self(), :discover, 1000)
{:ok, state |> Map.put(:socket, socket)}
end
def discover() do
GenServer.cast(__MODULE__, :discover)
end
def handle_info(:discover, state) do
discover(state)
{:noreply, state}
end
def handle_info({:udp, _pid, _addr, _port, msg}, state) do
host = parse_msg(msg)
desc = Dynasty.Sonos.Player.get_device_description(host.location)
IO.inspect(host: host, desc: desc)
{:noreply, state}
end
def handle_info(msg, state) do
IO.inspect(info: msg, state: state)
{:noreply, state}
end
def handle_cast(:discover, state) do
discover(state)
{:noreply, state}
end
def handle_cast(msg, state) do
IO.inspect(msg: msg, state: state)
{:noreply, state}
end
def parse_msg(msg) do
msg
|> to_string()
|> String.split("\r\n")
|> Enum.flat_map(fn
"LOCATION: " <> v -> [{:location, v}]
"SERVER: " <> v -> [{:server, v}]
"USN: " <> v -> [{:usn, v}]
"ST: " <> v -> [{:st, v}]
_ -> []
end)
|> Map.new()
end
def discover(%{socket: socket}) do
for addr <- @multicastaddr do
:gen_udp.send(socket, addr, 1900, @playersearch)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment