Files
2026-07-15 18:00:11 +02:00

104 lines
4.9 KiB
Racket

#lang scribble/manual
@(require (for-label racket/base
racket/contract
(file "../main.rkt")))
@title{UPnP Devices and Services}
@defmodule[@racketmodname[racket-upnp] #:module-paths ((file "../main.rkt"))]
The main module provides general UPnP device discovery and a generic service
interface.
@section{Discovering devices}
@defproc[(query-upnp-devices
[kinds (or/c 'all symbol? (listof symbol?)) 'all]
[#:interface interface (or/c #f string?) #f]
[#:dns? dns? boolean? #f])
(listof upnp-device?)]{
Discovers and describes matching UPnP devices.
@racket['all] returns all described devices. A symbol such as
@racket['media-renderer] selects one known kind, and a list selects several
kinds. When @racket[interface] is a local IPv4 address, SSDP multicast is sent
through that interface. Reverse DNS lookup is only attempted when
@racket[dns?] is true.
}
@defproc[(upnp-device-kinds) (listof (cons/c symbol? string?))]{
Returns the friendly device kinds understood by @racket[query-upnp-devices],
together with short descriptions. Devices with an unrecognised device type
are classified as @racket['unknown] and retain their original UPnP type.
}
@section{Device values}
@defproc[(upnp-device? [value any/c]) boolean?]{Recognises a described UPnP device.}
@defproc[(upnp-device-kind [device upnp-device?]) symbol?]{Returns a friendly kind such as @racket['media-renderer], @racket['scanner], or @racket['unknown].}
@defproc[(upnp-device-name [device upnp-device?]) string?]{Returns the friendly name, with model name and address as fallbacks.}
@defproc[(upnp-device-udn [device upnp-device?]) (or/c #f string?)]{Returns the Unique Device Name from the device description.}
@defproc[(upnp-device-address [device upnp-device?]) string?]{Returns the address from which the SSDP response was received.}
@defproc[(upnp-device-dns-name [device upnp-device?]) (or/c #f string?)]{Returns the optional reverse-DNS name.}
@defproc[(upnp-device-manufacturer [device upnp-device?]) (or/c #f string?)]{Returns the advertised manufacturer.}
@defproc[(upnp-device-model [device upnp-device?]) (or/c #f string?)]{Returns a combined model name and model number.}
@defproc[(upnp-device-type [device upnp-device?]) (or/c #f string?)]{Returns the original device-type URN.}
@defproc[(upnp-device-services [device upnp-device?]) (listof upnp-service?)]{Returns the services belonging directly to the device.}
@section{Generic services}
@defproc[(upnp-service? [value any/c]) boolean?]{Recognises a UPnP service.}
@defproc[(upnp-service-kind [service upnp-service?]) symbol?]{Returns a friendly service kind or @racket['unknown].}
@defproc[(upnp-service-type [service upnp-service?]) (or/c #f string?)]{Returns the original service-type URN.}
@defproc[(upnp-service-id [service upnp-service?]) (or/c #f string?)]{Returns the advertised service identifier.}
@defproc[(upnp-service-kinds) (listof (cons/c symbol? string?))]{Returns the known friendly service kinds and descriptions.}
@defproc[(upnp-device-service [device upnp-device?] [kind symbol?])
(or/c #f upnp-service?)]{
Returns the highest advertised version of the requested service kind belonging
to @racket[device], or @racket[#f] when the service is absent.
}
@defproc[(upnp-service-actions [service upnp-service?]) (listof string?)]{
Downloads the service's SCPD document and returns its advertised action names.
The result is cached for the service value.
}
@defproc[(upnp-service-supports-action? [service upnp-service?]
[action (or/c string? symbol?)])
boolean?]{
Reports whether the SCPD advertises @racket[action].
}
@defproc[(upnp-service-call [service upnp-service?]
[action (or/c string? symbol?)]
[arguments list? '()])
hash?]{
Invokes a SOAP action. @racket[arguments] is an association list containing
UPnP argument names and values. The immutable result hash uses the exact
output argument names as string keys. This function is intended for
vendor-specific services and standard services for which no typed module has
been written.
A failed SOAP request raises @racket[exn:fail:upnp?].
}
@defproc[(exn:fail:upnp? [value any/c]) boolean?]{Recognises a UPnP SOAP error.}
@defproc[(exn:fail:upnp-code [error exn:fail:upnp?]) (or/c #f exact-integer?)]{Returns the numeric UPnP error code, when supplied by the device.}
@defproc[(exn:fail:upnp-description [error exn:fail:upnp?]) (or/c #f string?)]{Returns the UPnP error description, when supplied by the device.}
@section[#:tag "device-discovery-example"]{Example}
@racketblock[
(define renderers
(query-upnp-devices 'media-renderer
#:interface "10.7.3.118"
#:dns? #t))
(for ([device (in-list renderers)])
(printf "~a (~a)\n"
(upnp-device-name device)
(upnp-device-address device)))
]