Summary

The Monitor Audio IMS-4 is a multi-source music streamer built on the BluOS platform. Control is exposed as an HTTP API (TCP port 11000) returning UTF-8 encoded XML, with the player IP and port discoverable via mDNS service types musc.tcp and musp.tcp. A UDP broadcast discovery protocol (LSDP, port 11430) is also documented as a fallback for networks where multicast is unreliable. This spec covers the upstream BluOS Custom Integration API v1.7, which is the protocol surface for the IMS-4.

Transport

# BluOS Custom Integration API uses HTTP GET requests over TCP, returning
# UTF-8 encoded XML. Discovery via mDNS service types musc.tcp and musp.tcp.
# LSDP uses UDP broadcast on port 11430 as a fallback discovery mechanism.
protocols:
  - http
  - tcp
  - udp
addressing:
  port: 11000
auth:
  type: none  # inferred: no auth procedure in source

Traits

# Inferred from source evidence: playback commands present, volume control
# present, mute present, queue management present, grouping present,
# input routing (Capture/RadioBrowse) present.
- powerable  # inferred from power command examples
- levelable  # inferred from volume/mute command examples
- queryable  # inferred from /Status and /SyncStatus query examples
- routable  # inferred from input selection and grouping examples

Actions

# Section 2 - Status Queries
- id: status_query
  label: Playback Status Query
  kind: query
  command: "/Status"
  params: []
- id: status_long_poll
  label: Playback Status (Long Poll)
  kind: query
  command: "/Status?timeout={timeout}&etag={etag}"
  params:
    - name: timeout
      type: integer
      description: Long-polling interval in seconds (recommended 100, never faster than 10).
    - name: etag
      type: string
      description: Etag attribute from previous /Status response.
- id: sync_status_query
  label: Player and Group Sync Status
  kind: query
  command: "/SyncStatus"
  params: []
- id: sync_status_long_poll
  label: Sync Status (Long Poll)
  kind: query
  command: "/SyncStatus?timeout={timeout}&etag={etag}"
  params:
    - name: timeout
      type: integer
      description: Long-polling interval in seconds (recommended 180).
    - name: etag
      type: string
      description: Etag attribute from previous /SyncStatus response.

# Section 3 - Volume Control
- id: set_volume
  label: Set Volume (Level 0-100)
  kind: action
  command: "/Volume?level={level}&tell_slaves={tell_slaves}"
  params:
    - name: level
      type: integer
      description: Absolute volume level 0-100.
    - name: tell_slaves
      type: integer
      description: 0 = only selected player; 1 = apply to all players in group.
- id: set_volume_abs_db
  label: Set Volume (Absolute dB)
  kind: action
  command: "/Volume?abs_db={db}&tell_slaves={tell_slaves}"
  params:
    - name: db
      type: number
      description: Absolute volume in dB.
    - name: tell_slaves
      type: integer
      description: 0 = only selected player; 1 = apply to all players in group.
- id: set_volume_relative_db
  label: Set Volume (Relative dB)
  kind: action
  command: "/Volume?db={delta_db}&tell_slaves={tell_slaves}"
  params:
    - name: delta_db
      type: number
      description: Positive or negative dB delta from current volume.
    - name: tell_slaves
      type: integer
      description: 0 = only selected player; 1 = apply to all players in group.
- id: volume_up
  label: Volume Up
  kind: action
  command: "/Volume?db={db_value}"
  params:
    - name: db_value
      type: number
      description: Volume increase in dB (typical 2).
- id: volume_down
  label: Volume Down
  kind: action
  command: "/Volume?db=-{db_value}"
  params:
    - name: db_value
      type: number
      description: Volume decrease in dB (typical 2).
- id: mute_on
  label: Mute On
  kind: action
  command: "/Volume?mute=1"
  params: []
- id: mute_off
  label: Mute Off
  kind: action
  command: "/Volume?mute=0"
  params: []

# Section 4 - Playback Control
- id: play
  label: Play
  kind: action
  command: "/Play"
  params: []
- id: play_seek
  label: Play with Seek
  kind: action
  command: "/Play?seek={seconds}"
  params:
    - name: seconds
      type: integer
      description: Seconds to jump into current track (requires totlen in /Status).
- id: play_seek_id
  label: Play with Seek and Track ID
  kind: action
  command: "/Play?seek={seconds}&id={trackid}"
  params:
    - name: seconds
      type: integer
      description: Seconds to jump into target track.
    - name: trackid
      type: integer
      description: Track id in queue (1-based).
- id: play_url
  label: Play Streamed URL
  kind: action
  command: "/Play?url={encodedStreamURL}"
  params:
    - name: encodedStreamURL
      type: string
      description: URL of streamed custom audio (must be URL encoded).
- id: pause
  label: Pause
  kind: action
  command: "/Pause"
  params: []
- id: pause_toggle
  label: Pause Toggle
  kind: action
  command: "/Pause?toggle=1"
  params: []
- id: stop
  label: Stop
  kind: action
  command: "/Stop"
  params: []
- id: skip
  label: Skip to Next Track
  kind: action
  command: "/Skip"
  params: []
- id: back
  label: Back to Previous Track
  kind: action
  command: "/Back"
  params: []
- id: shuffle
  label: Shuffle On/Off
  kind: action
  command: "/Shuffle?state={state}"
  params:
    - name: state
      type: integer
      description: "0 = disable shuffle, 1 = enable shuffle."
- id: repeat
  label: Set Repeat Mode
  kind: action
  command: "/Repeat?state={state}"
  params:
    - name: state
      type: integer
      description: "0 = repeat queue, 1 = repeat track, 2 = repeat off."
- id: radio_action
  label: Streaming Radio Action (Skip/Love/Ban)
  kind: action
  command: "/Action?service={service}&{action_key}={action_value}"
  params:
    - name: service
      type: string
      description: Music service name (e.g., Slacker).
    - name: action_key
      type: string
      description: Action key (skip, love, ban) per /Status <action> element.
    - name: action_value
      type: string
      description: Action value from /Status <action> element URL.

# Section 5 - Play Queue Management
- id: playlist_list
  label: List Play Queue Tracks
  kind: query
  command: "/Playlist"
  params: []
- id: playlist_status
  label: Play Queue Status Only
  kind: query
  command: "/Playlist?length=1"
  params: []
- id: playlist_range
  label: Play Queue Range (Pagination)
  kind: query
  command: "/Playlist?start={first}&end={last}"
  params:
    - name: first
      type: integer
      description: First entry to include (0-based).
    - name: last
      type: integer
      description: Last entry to include.
- id: delete_track
  label: Delete Track from Queue
  kind: action
  command: "/Delete?id={position}"
  params:
    - name: position
      type: integer
      description: Track id (position) in queue to delete.
- id: move_track
  label: Move Track in Queue
  kind: action
  command: "/Move?new={destination}&old={origin}"
  params:
    - name: destination
      type: integer
      description: New position for the track.
    - name: origin
      type: integer
      description: Old position of the track.
- id: clear_queue
  label: Clear Play Queue
  kind: action
  command: "/Clear"
  params: []
- id: save_queue
  label: Save Queue as Playlist
  kind: action
  command: "/Save?name={playlist_name}"
  params:
    - name: playlist_name
      type: string
      description: Name for the saved BluOS playlist.

# Section 6 - Presets
- id: list_presets
  label: List Presets
  kind: query
  command: "/Presets"
  params: []
- id: load_preset
  label: Load Preset by ID
  kind: action
  command: "/Preset?id={presetId}"
  params:
    - name: presetId
      type: integer
      description: Preset id from /Presets response.
- id: load_next_preset
  label: Load Next Preset
  kind: action
  command: "/Preset?id=+1"
  params: []
- id: load_previous_preset
  label: Load Previous Preset
  kind: action
  command: "/Preset?id=-1"
  params: []

# Section 7 - Content Browsing and Searching
- id: browse
  label: Browse Music Content
  kind: query
  command: "/Browse?key={key-value}"
  params:
    - name: key-value
      type: string
      description: URL-encoded browseKey/nextKey/parentKey/contextMenuKey from prior response.
- id: browse_with_context_menu
  label: Browse with Inline Context Menu
  kind: query
  command: "/Browse?key={key-value}&withContextMenuItems=1"
  params:
    - name: key-value
      type: string
      description: URL-encoded key from prior response.
- id: search
  label: Search Music Content
  kind: query
  command: "/Browse?key={key-value}&q={searchText}"
  params:
    - name: key-value
      type: string
      description: URL-encoded searchKey from prior response.
    - name: searchText
      type: string
      description: Search string.

# Section 8 - Player Grouping
- id: add_slave
  label: Group One Secondary Player
  kind: action
  command: "/AddSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}&group={GroupName}"
  params:
    - name: secondaryPlayerIP
      type: string
      description: IP address of secondary player.
    - name: secondaryPlayerPort
      type: integer
      description: Port of secondary player (default 11000).
    - name: GroupName
      type: string
      description: Optional group name.
- id: add_slaves
  label: Group Multiple Secondary Players
  kind: action
  command: "/AddSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
  params:
    - name: secondaryPlayerIPs
      type: string
      description: Comma-separated secondary player IPs.
    - name: secondaryPlayerPorts
      type: string
      description: Comma-separated secondary player ports.
- id: remove_slave
  label: Remove One Secondary Player
  kind: action
  command: "/RemoveSlave?slave={secondaryPlayerIP}&port={secondaryPlayerPort}"
  params:
    - name: secondaryPlayerIP
      type: string
      description: IP of secondary player to remove.
    - name: secondaryPlayerPort
      type: integer
      description: Port of secondary player to remove.
- id: remove_slaves
  label: Remove Multiple Secondary Players
  kind: action
  command: "/RemoveSlave?slaves={secondaryPlayerIPs}&ports={secondaryPlayerPorts}"
  params:
    - name: secondaryPlayerIPs
      type: string
      description: Comma-separated secondary player IPs to remove.
    - name: secondaryPlayerPorts
      type: string
      description: Comma-separated secondary player ports to remove.

# Section 9 - Player Reboot
- id: reboot
  label: Soft Reboot Player
  kind: action
  command: "POST /reboot"
  params:
    - name: yes
      type: string
      description: "Any value (e.g. 1) sent as POST body parameter."

# Section 10 - Doorbell Chimes
- id: doorbell_play
  label: Play Doorbell Chime
  kind: action
  command: "/Doorbell?play=1"
  params: []

# Section 11 - Direct Input
- id: play_input_url
  label: Select Active Input (via URL)
  kind: action
  command: "/Play?url={URL_value}"
  params:
    - name: URL_value
      type: string
      description: URL attribute from /RadioBrowse?service=Capture response.
- id: play_input_index
  label: Select External Input by Index (firmware 3.8.0-4.2.0)
  kind: action
  command: "/Play?inputIndex={IndexId}"
  params:
    - name: IndexId
      type: integer
      description: Index (1-based) of input in /Settings?id=capture&schemaVersion=32 response. Bluetooth excluded.
- id: play_input_type_index
  label: Select External Input by Type and Index (firmware 4.2.0+)
  kind: action
  command: "/Play?inputTypeIndex={type-index}"
  params:
    - name: type-index
      type: string
      description: 'Format "type-index" - type in {spdif, analog, coax, bluetooth, arc, earc, phono, computer, aesebu, balanced, microphone}, index starts at 1.'

# Section 12 - Bluetooth
- id: set_bluetooth_mode
  label: Set Bluetooth Autoplay Mode
  kind: action
  command: "/audiomodes?bluetoothAutoplay={value}"
  params:
    - name: value
      type: integer
      description: "0 = Manual, 1 = Automatic, 2 = Guest, 3 = Disabled."

Feedbacks

# Volume state from /Volume response
- id: volume_level
  type: integer
  description: Player volume level 0-100 (-1 = fixed volume).
- id: volume_db
  type: number
  description: Volume level in dB (typical range -80..0).
- id: mute_state
  type: boolean
  description: "1 if muted, 0 if unmuted."
- id: mute_db
  type: number
  description: Pre-mute volume in dB (only present when muted).
- id: mute_volume
  type: integer
  description: Pre-mute volume in 0..100 scale (only present when muted).
- id: volume_offset_db
  type: number
  description: Volume offsetDb attribute.
- id: volume_etag
  type: string
  description: Etag attribute for long-polling.

# Playback state from /Status response
- id: playback_state
  type: enum
  values: "play, pause, stop, stream, connecting"
- id: track_title
  type: string
  description: Current playing track title (title1/title2/title3 used for UI).
- id: track_artist
  type: string
  description: Current artist name.
- id: track_album
  type: string
  description: Current album name.
- id: track_totlen
  type: integer
  description: Total track length in seconds.
- id: track_secs
  type: integer
  description: Seconds played into current track.
- id: track_quality
  type: string
  description: "Source quality: cd, hd, dolbyAudio, mqa, mqaAuthored, or numeric bitrate."
- id: repeat_state
  type: integer
  description: "0 = repeat queue, 1 = repeat track, 2 = off."
- id: shuffle_state
  type: integer
  description: "0 = off, 1 = on."
- id: sleep_remaining
  type: integer
  description: Minutes remaining before sleep timer activates.
- id: can_seek
  type: integer
  description: "1 if track supports seek."
- id: can_move_playback
  type: boolean
  description: True if current content can be moved to another player.
- id: indexing
  type: integer
  description: Indexing status.
- id: stream_format
  type: string
  description: Format of the playing audio.
- id: service
  type: string
  description: Music service id of current audio.
- id: service_icon
  type: string
  description: URL of current service icon.
- id: image_url
  type: string
  description: URL of current artwork image.
- id: song_id
  type: integer
  description: Current track position in queue.
- id: playlist_id
  type: integer
  description: Current play queue id (pid).
- id: preset_id
  type: integer
  description: Current preset id (prid).
- id: sync_stat
  type: integer
  description: Sync status change indicator.

# Sync status from /SyncStatus
- id: player_name
  type: string
  description: Player name.
- id: player_brand
  type: string
  description: Player brand name.
- id: player_model
  type: string
  description: Player model id.
- id: player_model_name
  type: string
  description: Player model name.
- id: player_mac
  type: string
  description: Player unique network id (often a MAC address).
- id: player_id
  type: string
  description: Player IP and port.
- id: player_icon
  type: string
  description: URL of player icon image.
- id: player_initialized
  type: boolean
  description: True if player is set up.
- id: group_name
  type: string
  description: Group name (if primary player).
- id: master_ip
  type: string
  description: Master player IP (if secondary player).
- id: master_port
  type: integer
  description: Master player port (if secondary player).
- id: slave_ips
  type: string
  description: Comma list of slave IPs (if primary player).
- id: slave_ports
  type: string
  description: Comma list of slave ports (if primary player).
- id: schema_version
  type: integer
  description: Software schema version.

# Doorbell chime status
- id: chime_enable
  type: integer
  description: Indicates chime enabled state.
- id: chime_volume
  type: integer
  description: Chime volume.
- id: chime_audio
  type: string
  description: Chime audio path.

Variables

# Volume range is configurable via BluOS Controller app - out of scope here.
# Bluetooth mode is a discrete set of values, expressed via /audiomodes action.

Events

# UNRESOLVED: source documents long-polling responses as the notification
# mechanism, not unsolicited events. No push/event subscription API described.

Macros

# UNRESOLVED: source describes commands but no multi-step macro definitions.

Safety

confirmation_required_for: []
interlocks: []
# UNRESOLVED: no explicit safety warnings or interlock procedures in source.
# Note: /Volume mute=0 unmutes; /Stop cancels alarm timeout. These are
# described behavior, not safety interlocks.

Notes

All commands are HTTP GET requests (except /reboot, which is HTTP POST) sent to http://<player_ip>:11000/<request>. Responses are UTF-8 encoded XML. Player IP and port are discoverable via mDNS service types musc.tcp and musp.tcp; the CI580 uses ports 11000/11010/11020/11030 for its four streamer nodes.

Long-polling rate limits: regular polling should not exceed one request every 30 seconds; long-polling requests for the same resource must not be made less than one second apart. Recommended /Status long-poll timeout is 100 seconds (never faster than 10); recommended /SyncStatus long-poll timeout is 180 seconds.

/Pause?toggle=1 and /Stop cancel the alarm timeout if an alarm is currently playing.

/Skip//Back are only meaningful when there is no <streamUrl> element in the /Status response (i.e., the play queue is the audio source). For streaming radio skip/back/love/ban, use /Action with the URL from the <action> element in /Status.

/Preset?id=+1 and /Preset?id=-1 loop around the preset list.

/Play?inputIndex requires BluOS firmware between v3.8.0 and v4.2.0 (Bluetooth excluded from index). /Play?inputTypeIndex requires firmware v4.2.0 or newer and uses type-index format (e.g., spdif-2).

The LSDP appendix (section 13) describes a UDP broadcast discovery protocol on port 11430 as a fallback for networks where mDNS multicast is unreliable. The BluOS Custom Integration API document explicitly omits fixed grouping ("BluOS also supports fixed grouping, which is out of scope for this document").


Self-check: status=draft, declared_confidence=low, derived_from=vendor_manual, port 11000 stated in source, no auth inferred, firmware marked UNRESOLVED, every action carries literal command path, YAML blocks valid (no bare list lines, no trailing content after fences).

## Provenance

```yaml
source_domains:
  - bluos.io
source_urls:
  - https://bluos.io/wp-content/uploads/2025/06/BluOS-Custom-Integration-API_v1.7.pdf
  - https://bluos.io/downloads/
retrieved_at: 2026-07-14T18:06:24.210Z
last_checked_at: 2026-09-12T22:17:52.700Z

Verification Summary

verdict: verified
checked_at: 2026-09-12T22:17:52.700Z
matched_actions: 47
action_count: 47
confidence: medium
summary: "All 47 spec actions are present in the BluOS Custom Integration API source with matching paths, parameters, and shapes; transport values port 11000 and HTTP/UDP are documented. (4 unresolved item(s) noted in Known Gaps.)"

Known Gaps

- "firmware version compatibility not stated in source; IMS-4-specific quirks not in scope of upstream BluOS doc"
- "source documents long-polling responses as the notification"
- "source describes commands but no multi-step macro definitions."
- "no explicit safety warnings or interlock procedures in source."

From the AI4AV catalog (https://ai4av.net) · ODbL-1.0