# UpnpControl Binding

This binding acts as a UPnP control point to control UPnP AV media servers and media renderers as defined by the UPnP Forum (opens new window). It discovers UPnP media servers and renderers in the local network. UPnP AV media servers generally allow selecting content from a content directory. UPnP AV media renderers take care of playback of the content.

You can select a renderer to play the media served from a server. The full content hierarchy of the media on the server can be browsed hierarchically. Searching the media library is also supported using UPnP search syntax. Playlists can be created and maintained.

Controls are available to control the playback of the media on the renderer. Currently playing media can be stored as a favorite. Each discovered renderer will also be registered as an openHAB audio sink.

# Supported Things

Two thing types are supported, a server thing, upnpserver, and a renderer thing, upnprenderer.

The binding has been tested with the AV Media Server and AV Media Renderer from Intel Developer Tools for UPnP Technology, available here (opens new window). A second test set included a TVersity Media Server (opens new window). It complies with part of the UPnP AV Media standard, but has not been verified to comply with the full specification. Tests have focused on the playback of audio, but if the server and renderer support it, other media types should play as well.

# Binding Configuration

The binding has one configuration parameter, path. This is used as the disk location for storing and retrieving playlists and favorites. The default location is $OPENHAB_USERDATA/upnpcontrol.

# Discovery

UPnP media servers and media renderers in the network will be discovered automatically.

# Thing Configuration

Both the upnprenderer and upnpserver thing require a configuration parameter, udn (Universal Device Name). This udn uniquely defines the UPnP device. It can be retrieved from the thing ID when using auto discovery.

Both also have refresh configuration parameter. This parameter defines a polling interval for polling the state of the upnprenderer or upnpserver. The default polling interval is 60s. 0 turns off polling.

An advanced configuration parameter responseTimeout permits tweaking how long the upnprenderer and upnpserver will wait for GENA events from the UPnP device. This timeout is checked when there is a dependency between an action invocation and an event with expected result. The default is 2500ms. It should not be changed in normal circumstances.

Additionally, a upnpserver device has the following optional configuration parameters:

  • filter: when true, only list content that is playable on the renderer, default is false.

  • sortCriteria: sort criteria for the titles in the selection list and when sending for playing to a renderer.

    The criteria are defined in UPnP sort criteria format, examples: +dc:title, -dc:creator, +upnp:album. Support for sort criteria will depend on the media server. The default is to sort ascending on title, +dc:title.

  • browseDown: when browse or search results in exactly one container entry, iteratively browse down until the result contains multiple container entries or at least one media entry, default is true.

  • searchFromRoot: always start search from root instead of the current id, default is false.

A upnprenderer has the following optional configuration parameters:

  • seekStep: step in seconds when sending fast forward or rewind command on the player control, default 5s.

  • notificationVolumeAdjustment: volume adjustment from current volume in percent (range -100 to +100) for notifications when no volume is set in playSound command, default 10.

  • maxNotificationDuration: maximum duration for notifications (default 15s), no maximum duration when set to 0s.

The full syntax for manual configuration is:

Thing upnpcontrol:upnpserver:<serverId> [udn="<udn of media server>", refresh=<polling interval>, seekStep=<step>]
Thing upnpcontrol:upnprenderer:<rendererId> [udn="<udn of media renderer>", refresh=<polling interval>, filter=<true/false>, sortCriteria="<sort criteria string>", browseDown=<true/false>, searchfromroot=<true/false>]

# Channels

# upnpserver

The upnpserver has the following channels (item type and access mode indicated in brackets):

  • upnprenderer (String, RW): The renderer to receive media content for playback.

    The channel allows selecting from all discovered media renderers. This list is dynamically adjusted as media renderers are being added/removed.

  • currenttitle (String, R): Current title of media container or entry ready for playback.

  • browse (String, RW): Browse and serve media content, current ID of media container or entry ready for playback.

    The browsing will start at the top of the content directory tree and allows you to go down and up (represented by ..) in the tree. The list of containers (directories) and media entries for selection in the content hierarchy is updated dynamically when selecting a container or entry.

    This channel can also be used to skip to a specific container or entry in the content directory. Setting it to 0 will reposition to the top of the content hierarchy.

    All media in the selection list, playable on the currently selected upnprenderer channel, are automatically queued to the renderer as next media for playback.

    The browseDown configuration parameter influences the result in such a way that, for browseDown = true, if the result only contains exactly one container entry, the result will be the content of the container and not the container itself.

  • search (String, W): Search for media content on the server.

    Search criteria are defined in UPnP search criteria format. Examples: dc:title contains "song", dc:creator contains "SpringSteen", unp:class = "object.item.audioItem", upnp:album contains "Born in".

    The search, by default, starts at the value of the currentid and searches down from there unless the searchfromroot thing configuration parameter is set to true. The result (media and containers) will be available in the browse command option list. The currentid channel will be put to the id of the top container where the search started.

    All media in the search result list, playable on the current selected upnprenderer channel, are automatically queued to the renderer as next media for playback.

    The browseDown configuration parameter influences the result in such a way that, for browseDown = true, if the result only contains exactly one container entry, the result will be the content of the container and not the container itself.

  • playlistselect (String, W): Select a playlist from the available playlists currently saved on disk.

    This will also update playlist with the selected value.

  • playlist (String, RW): Name of existing or new playlist.

  • playlistaction (String, W): action to perform with playlist.

    Possible command options are:

    • RESTORE: restore the playlist from playlist.

      If the restored playlist contains content from the current server, this content will update the browse command option list. Note that playlists can contain a mix of media entries and container references.

      All media in the result list, playable on the current selected upnprenderer channel, are automatically queued to the renderer as next media for playback.

    • SAVE: save the current browse command option list into playlist.

      If playlist already exists, it will be overwritten.

    • APPEND: append the current browse command option list to playlist.

      If playlist does not exist yet, a new playlist will be created.

    • DELETE: delete playlist from disk and remove from playlistselect command option list.

A number of convenience channels replicate the basic control channels from the upnprenderer thing for the currently selected renderer on the upnprenderer channel. These channels are volume, mute and control.

# upnprenderer

The upnprenderer has the following default channels:

Channel Type ID Item Type Access Mode Description
volume Dimmer RW playback master volume
mute Switch RW playback master mute
control Player RW play, pause, next, previous, fast forward, rewind
stop Switch W stop media playback
repeat Switch RW continuous play of media queue, restart at end
shuffle Switch RW continuous random play of media queue
onlyplayone Switch RW only play one media entry from the queue at a time
uri String RW URI of currently playing media
favoriteselect String W play favorite from list of saved favorites
favorite String RW set name for existing of new favorite
favoriteaction String W SAVE or DELETE favorite
playlistselect String W play playlist from list of saved playlists
title String R media title
album String R media album
albumart Image R image for media album
creator String R media creator
artist String R media artist
publisher String R media publisher
genre String R media genre
tracknumber Number R track number of current track in album
trackduration Number:Time R track duration of current track in album
trackposition Number:Time RW current position in track during playback or pause
reltrackposition Dimmer RW current position relative to track duration

A numer of upnprenderer audio control channels may be dynamically created depending on the specific renderer capabilities. Examples of these are:

Channel Type ID Item Type Access Mode Description
loudness Switch RW playback master loudness
lfvolume Dimmer RW playback front left volume
lfmute Switch RW playback front left mute
rfvolume Dimmer RW playback front right volume
rfmute Switch RW playback front right mute

# Audio Support

Two audio sinks are registered for each media renderer. playSound and playStream commands can be used in rules to play back audio fragments or audio streams to a renderer.

The first audio sink has the renderer id as a name. It is used for normal playback of a sound or stream.

The second audio sink has -notify appended to the renderer id for its name, and has a special behavior. This audio sink is used to play notifications. When setting the volume parameter in the playSound command, the volume of the renderer will only change for the duration of playing the notification. The maxNotificationDuration configuration parameter of the renderer will limit the notification duration the value of the parameter in seconds. Normal playing will resume after the notification has played or when the maximum notification duration has been reached, whichever happens first. Longer sounds or streams will be cut off.

# Managing a Playback Queue

There are multiple ways to serve content to a renderer for playback.

  • Directly provide a URI on the URI channel or through playSound or playStream actions:

    Playing will start immediately, interrupting currently playing media. No metadata for the media is available, therefore will be provided in the media channels for metadata (e.g. title, album, ...).

  • Content served from one or multiple upnpserver servers:

    This is done on the upnpserver thing with the upnprenderer set the the renderer for playback. The media at any point in time in the upnpserver browse option list (result from browse, search or restoring a playlist), will be queued to the upnprenderer for playback. Playback does not start automatically if not yet playing. When already playing a queue, the first entry of the new queue will be playing as the next entry. When playing an URI or media provided through an action, playback will immediately switch to the new queue.

    The upnprenderer will use that queue until it is replaced by another queue from the same or another upnpserver. Note that querying the content hierarchy on the upnpserver will update the upnpserver browse option list each time, and therefore the queue on the upnprenderer will be updated each time as long as upnprenderer is selected on upnpserver.

  • Selecting a favorite or playlist on the renderer.

    Playback of the favorite or playlist will start immediately.

When playing from a directly provided URI, at the end of the media, the renderer will try to move to the next entry in a queue previously provided by a server. Playing will stop when no such entry is available.

Multiple renderers can be sent the same or different playback queue from the same server sequentially. Select content on the server and select the first renderer for playback. The content queue will be served to the renderer, a play command on the renderer will start playing the queue. Select another renderer on the server. The same or new (after another content selection) queue will be served to the second renderer. Both renderers will keep on playing the full queue they received.

When serving a queue from a server, the renderer can be put in "only play one" mode by putting the onlyplayone channel to true. A subsequent play command will only play one media entry from the queue while respecting shuffle and repeat. To play the next media from the queue, a new play command will be required after the player stopped. An example of usage could be playing a single random sound from a playlist when you are away from home and an intrusion is detected. A script could put the player in shuffle and onlyplayone mode and serve a playlist. Only one random sound from the playlist would be played.

# Favorites

Currently playing media can be saved as favorites on the renderer. This is especially useful when playing streams, such as online radio, but is valid for any media. If the currently playing media has metadata, it will be saved with the favorite.

A favorite only contains one media item. Selecting the favorite will only play that one item. The favorite will start playing immediately. Playing the server queue will resume after playing the favorite.

# Playlists

Playlists provide a way to define lists of server content for playback.

A new playlist can be created on a server thing from the selection in the upnpserver browse selection list. When restoring a playlist on the server, the media in the playlist from the upnpserver thing used for restoring, will be put in the upnpserver browse selection list.

The current selection of media playable on the currently selected renderer will automatically be stored as a playlist with name current.

A playlist can contain media from different servers. Only the media from the current server will be visible in the server when restoring. It is possible to append content to a playlist that already contains content from a different server. That way, it is possible to combine multiple sources for playback.

When selecting a playlist on a renderer, the playlist will be queued for playback, replacing the current queue. Playback will start immediately.

Searching content on a media server may take a lot of time, depending on the functionality and the performance of the media server. Therefore, it may very well be that media server searches time out.

Rather than searching for individual items, it is therefore often better to search for containers or playlists.

For example:

  • upnp:class derivedfrom "object.item.audioItem.musicTrack" and dc:title contains "Fight For Your Right" would search for all music tracks with "Fight For Your Right" in the title. This search is potentially slow.

  • dc:title contains "Evening" and upnp:class = "object.container.playlistContainer" would search for all playlists with "Evening" in the name.

  • dc:title = "Donnie Darko" and upnp:class = "object.container.playlistContainer" would search for a playlist with a specific name.

With the last example, if the browseDown configuration parameter is true, the result will not be the playlist, but the content of the playlist. This allows immediately starting a play command without having to browse down to the first result of the list (the unique container). This is especially useful when doing searches and starting to play in scripts, as the play command can immediately follow the search for a unique container, without a need to browse down to a media ID that is hidden in the browse option list. For interactive use through a UI, you may opt to switch the browseDown configuration parameter to false to see all levels in the browsing hierarchy.

The searchfromroot configuration parameter always forces searching to start from the directory root. This will also always reset the browse channel to the root. This option is helpful if you do not want to limit search to a selected container in the directory.

# Limitations

BasicUI has a number of limitations that impact the way some of the channels can be used from it:

  • BasicUI does not support dynamic refreshing of the selection list in the upnpserver channels renderer, browse, playlistselect and in the upnprenderer channel favoriteselect. A refresh of the browser will be required to show the adjusted selection list.

  • The upnpserver search channel requires input of a string to trigger a search. The upnpserver playlist channel and upnprenderer favorite channel require input of a string to set a playlist or favorite. This cannot be done with BasicUI, but can be achieved with rules.

  • The player control in BasicUI does not support fast forward or rewind.

None of these are limitations when using the main UI.

# Full Example

.things:

Thing upnpcontrol:upnpserver:mymediaserver [udn="0ec457ae-6c50-4e6e-9012-dee7bb25be2d", refresh=120, filter=true, sortCriteria="+dc:title"]
Thing upnpcontrol:upnprenderer:mymediarenderer [udn="538cf6e8-d188-4aed-8545-73a1b905466e", refresh=600, seekStep=1]

.items:

Group MediaServer <player>
Group MediaRenderer <player>

Dimmer Volume    "Volume [%.1f %%]" <soundvolume>      (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:volume"}
Switch Mute      "Mute"             <soundvolume_mute> (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:mute"}
Switch Loudness  "Loudness"                            (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:loudness"}
Dimmer LeftVolume "Volume [%.1f %%]" <soundvolume>     (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:lfvolume"}
Dimmer RightVolume "Volume [%.1f %%]" <soundvolume>    (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:rfvolume"}
Player Controls  "Controller"                          (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:control"}
Switch Stop      "Stop"                                (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:stop"}
Switch Repeat    "Repeat"                              (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:repeat"}
Switch Shuffle   "Shuffle"                             (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:shuffle"}
String URI       "URI"                                 (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:uri"}
String FavoriteSelect "Favorite"                       (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:favoriteselect"}
String Favorite  "Favorite"                            (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:favorite"}
String FavoriteAction "Favorite Action"                (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:favoriteaction"}
String PlaylistPlay "Playlist"                         (MediaRenderer)   {channel="upnpcontrol:upnprenderer:mymediarenderer:playlistselect"}
String Title     "Now playing [%s]" <text>             (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:title"}
String Album     "Album"            <text>             (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:album"}
Image AlbumArt   "Album Art"                           (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:albumart"}
String Creator   "Creator"          <text>             (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:creator"}
String Artist    "Artist"           <text>             (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:artist"}
String Publisher "Publisher"        <text>             (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:publisher"}
String Genre     "Genre"            <text>             (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:genre"}
Number TrackNumber "Track Number"                      (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:tracknumber"}
Number:Time TrackDuration "Track Duration [%d %unit%]" (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:trackduration"}
Number:Time TrackPosition "Track Position [%d %unit%]" (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:trackposition"}
Dimmer RelTrackPosition "Relative Track Position ´[%d %%]" (MediaRenderer) {channel="upnpcontrol:upnprenderer:mymediarenderer:reltrackposition"}

String Renderer  "Renderer [%s]"    <text>             (MediaServer)   {channel="upnpcontrol:upnpserver:mymediaserver:title"}
String CurrentTitle "Current Entry [%s]" <text>        (MediaServer)   {channel="upnpcontrol:upnpserver:mymediaserver:currenttitle"}
String Browse    "Browse"                              (MediaServer)   {channel="upnpcontrol:upnpserver:mymediaserver:browse"}
String Search    "Search"                              (MediaServer)   {channel="upnpcontrol:upnpserver:mymediaserver:search"}
String PlaylistSelect "Playlist"                       (MediaServer)   {channel="upnpcontrol:upnpserver:mymediaserver:playlistselect"}
String Playlist  "Playlist"                            (MediaServer)   {channel="upnpcontrol:upnpserver:mymediaserver:playlist"}
String PlaylistAction "Playlist Action"                (MediaServer)   {channel="upnpcontrol:upnpserver:mymediaserver:playlistaction"}

.sitemap:

Slider    item=Volume
Switch    item=Mute
Switch    item=Loudness
Slider    item=LeftVolume
Slider    item=RightVolume
Default   item=Controls
Switch    item=Stop mappings=[ON="STOP"]
Switch    item=Repeat
Switch    item=Shuffle
Text      item=URI
Selection item=FavoriteSelect
Text      item=Favorite
Switch    item=FavoriteAction
Selection item=PlaylistPlay
Text      item=Title
Text      item=Album
Default   item=AlbumArt
Text      item=Creator
Text      item=Artist
Text      item=Publisher
Text      item=Genre
Text      item=TrackNumber
Text      item=TrackDuration
Text      item=TrackPosition
Slider    item=RelTrackPosition

Selection item=Renderer
Text      item=CurrentTitle
Selection item=Browse
Text      item=Search
Selection item=PlaylistSelect
Text      item=Playlist
Switch    item=PlaylistAction

Audio sink usage examples in rules:

playSound(“doorbell.mp3”)
playStream("upnpcontrol:upnprenderer:mymediarenderer", "http://icecast.vrtcdn.be/stubru_tijdloze-high.mp3”)
playSound("upnpcontrol:upnprenderer:mymediarenderer-notify", "doorbell.mp3", new PercentType(80))