npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

denon-mqtt

v0.0.10

Published

MQTT Provider for Denon Receivers

Readme

denon-mqtt

[!NOTE] Note: you must have access to an MQTT server for this interface to work (See below for information on running MQTT via Docker).

This project provides MQTT support for Denon and Marantz Audio Video Receivers (AVRs). While it does not provide 100% compatibility with the protocol, it has been developed in line with documentation for version ("Application model") AVR-3312CI/AVR-3312 and version 0.06 of the specification for AVR-S700, S900, X1100, X3100, X4100, X5200, and X7200. It has been tested with the following receiver models:

  • S950H
  • X4500H

Quick Start

# Create folder to store configuration:
mkdir denon-mqtt
cd denon-mqtt
# Install globally
yarn global add denon-mqtt # OR npm i -g denon-mqtt
# Discover receiver configuration (EXPERIMENTAL):
denon-mqtt -d -a your.avr.ip.address
# Run with discovered configuration
denon-mqtt -f receivers-discovered.json -m mqtt_host_or_ip -u mqtt_username -p mqtt_password

If discovery fails, most features are supported by simply providing the AVR IP address via the command line:

denon-mqtt -a your.avr.ip.address -m mqtt_host_or_ip -u mqtt_username -p mqtt_password

If your AVR supports more than 2 zones, you will need to specify names for each zone separated with |:

denon-mqtt -a your.avr.ip.address -z Main Zone|Zone 2|Zone 3  -m mqtt_host_or_ip -u mqtt_username -p mqtt_password

See below for the full list of command line options.

Getting Started

Install with yarn or npm

This method requires installing Node.js first.

# Install:
yarn global add denon-mqtt
# OR
npm i -g denon-mqtt

# Run:
denon-mqtt

Run with Docker

Run using environment variables:

docker run douglampe/denon-mqtt:latest -e DMQTT_IP="your.avr.ip.address" \
  -e DMQTT_ZONES="Main|Zone 2|Zone 3" \
  -e DMQTT_HOST="mqtt_host_or_ip" \
  -e DMQTT_USER="mqtt_username" \
  -e DMQTT_PASSWORD="mqtt_password"

Run using a configuration file:

docker run douglampe/denon-mqtt:latest -v ./receivers.json:/app/receivers.json

Docker compose:

services:
  denon-mqtt:
    container_name: denon-mqtt
    image: douglampe/denon-mqtt:latest
    volumes:
      - ./receivers.json:/app/receivers.json

Environment variables supported for setting parameters in Docker container:

  • DMQTT_FILE: config JSON file
  • DMQTT_HOST: MQTT URL (default: "localhost")
  • DMQTT_USER: MQTT Username (default: "user")
  • DMQTT_PASSWORD: MQTT Password (default: "password")
  • DMQTT_PORT: MQTT Port (default: 1883)
  • DMQTT_PREFIX: MQTT Topic Prefix (default: "denon")
  • DMQTT_IP: Comma-separated list of AVR IP addresses
  • DMQTT_NAME: Comma-separated list of AVR friendly names (default: "Home Theater")
  • DMQTT_ID: Comma-separated list of AVR unique IDs (default: "denon")
  • DMQTT_ZONES: Comma-separated list of | separated AVR zone names (default: "Main|Zone 2")
  • DMQTT_AVAILABILITY_TOPIC: Availability topic (default: "availability")
  • DMQTT_STATE_TOPIC: State topic (default: "state")
  • DMQTT_CHANGE_TOPIC: Change topic (default: "state")

Run MQTT

You can use the below Docker compose configuration to run MQTT. Reference the mosquitto docker documentation for more details.

services:
  eclipse-mosquitto:
    container_name: mosquitto
    image: eclipse-mosquitto:latest
    restart: always
    ports:
      - 9001:9001
      - 1883:1883
    volumes:
      - ./mosquitto.conf:/mosquitto/config/mosquitto.conf
      - ./mosquitto-users.txt:/mosquitto/config/mosquitto-users.txt

Usage

Command Line Options

Options:

  -i, --info                             Display current version number
  -a, --avr <list>                       Comma-separated list of AVR IP addresses (default: "192.168.1.34,192.168.1.58")
  -d, --discover                         Discover configuration and write to JSON file (default is
                                         receivers-discovered.json)
  -f, --file <file>                      Name of configuration JSON file (default: "receivers-discovered.json")
  -m, --mqtt <url>                       MQTT URL (default: "192.168.1.131")
  -u, --username <username>              MQTT Username (default: "user")
  -p, --password <password>              MQTT Password (default: "password")
  --port                                 MQTT Port <port>
  --prefix                               MQTT Topic Prefix <prefix>
  --name <list>                          Comma-separated list of AVR friendly names (default: "Home Theater")
  --id <list>                            Comma-separated list of AVR unique IDs (default: "denon")
  -z --zones <list>                      Comma-separated list of | separated AVR zone names (default: "Main|Zone 2")
  -l --availability <availabilityTopic>  Availability topic (default: "availability")
  -s --state-topic <stateTopic>          State topic (default: "state")
  -c --change-topic <changeTopic>        Change topic (default: "state")
  -h, --help                             display help for command

AVR Discovery (EXPERIMENTAL)

Automated discovery is supported using the AVR native web interface. This process will discover every aspect of the supported configuration including the AVR name, zone names, and full data for each source (display name, internal index, and code used by the Telnet interface). It also maps source to zones where they are supported.

If discovery fails, you will need to manually configure your AVR. See below for the full configuration syntax.

Use the -d or --discover option run the discovery process. The only other required variable is -a or --avr to specify AVR IP address(es).

denon-mqtt -d -a your.avr.ip.address

The configuration file will be saved in the current path as receivers-discovered.json. Any existing files with this name will be overwritten. To specify a different filename, use the -f or --file options:

denon-mqtt -d -a your.avr.ip.address -f your-very-special-file-name.json

AVR Configuration

While it is possible to get the interface up and running with only command-line options, accessing all features requires a configuration file to configure each AVR controlled by the interface. The interface will look for a file named receivers.json using the following format(see receivers.json.sample for an example). In the example below, "Home Theater" is the configuration for a Denon X4500H and "Office" is the configuration for a Denon S950H.

Note that the code value of each source must match the code expected by the control protocol. For the list of sources for each zone, the value must match a code value in the receiver source list.

The id value for the AVR is used in the names of MQTT topics and must be unique within the configuraiton.

[
  {
    "name": "Home Theater",
    "ip": "192.168.0.1234",
    "id": "home_theater",
    "sources": [
      {"code": "SAT/CBL", "display": "Fire TV"},
      {"code": "DVD", "display": "AppleTV"},
      {"code": "BD", "display": "Blu-ray"},
      {"code": "GAME", "display": "XBox"},
      {"code": "MPLAY", "display": "Karaoke"},
      {"code": "TV", "display": "TV Audio"},
      {"code": "AUX1", "display": "pi"},
      {"code": "AUX2", "display": "AUX2"},
      {"code": "CD", "display": "Alexa"},
      {"code": "PHONO", "display": "Phono"},
      {"code": "TUNER", "display": "Tuner"},
      {"code": "NET", "display": "HEOS Music"}
    ],
    "zones": [
      {
        "index": "1",
        "name": "Living Room",
        "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
      },
      {
        "index": "2",
        "name": "Rumpus Room",
        "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
      },
      {
        "index": "3",
        "name": "Back Porch",
        "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
      }
    ]
  },
  {
    "name": "Office",
    "ip": "192.168.0.5678",
    "id": "office_avr",
    "sources": [
      {"code": "SAT/CBL", "display": "Xbox One"},
      {"code": "DVD", "display": "DVD"},
      {"code": "BD", "display": "Blu-ray"},
      {"code": "GAME", "display": "Xbox One"},
      {"code": "MPLAY", "display": "Media Player"},
      {"code": "TV", "display": "TV Audio"},
      {"code": "AUX1", "display": "AUX1"},
      {"code": "AUX2", "display": "AUX2"},
      {"code": "CD", "display": "Alexa"},
      {"code": "PHONO", "display": "Phono"},
      {"code": "TUNER", "display": "Tuner"},
      {"code": "NET", "display": "HEOS Music"}
    ],
    "zones": [
      {
        "index": "1",
        "name": "Living Room",
        "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
      },
      {
        "index": "2",
        "name": "Rumpus Room",
        "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
      },
      {
        "index": "3",
        "name": "Back Porch",
        "sources": ["SAT/CBL","DVD","BD","GAME","MPLAY","TV","AUX1","AUX2","CD","PHONO","TUNER","NET"]
      }
    ]
  }
]

MQTT Syntax

[!NOTE] Note: Verion 0.0.5 introduced a BREAKING CHANGE to the MQTT schema.

In addition to the below topics and payloads, you can request updated status data from the receiver by posting a text payload of REFRESH to topic {prefix}/{id}/device/command.

Availability Topic and Payload

The topic for all availability is {prefix}/{id}/{zone}/{suffix} where {prefix} is the global prefix (default: denon), {id} is the unique identifier of the AVR, {zone} is the zone identifier (main_zone, zone1, zone2), and {suffix} is the availability topic as configured on launch.

The payload for availability is { available: {availability} } where {availability} is true if the Telnet connection to the receiver is available, otherwise false. A true value is sent when the telnet connection is established and whenever a message is received from the recewiver. A false value is sent whenever the Telnet session disconnects or an error occurs reading from the Telnet connection.

Command Topic and Payload

The topic for all commands is {prefix}/{id}/{zone}/command where {prefix} is the global prefix (default: denon), {id} is the unique identifier of the AVR, and {zone} is the zone identifier (main_zone, zone1, zone2).

The following payloads formats are required for each listed setting:

Text

  • digital_input
  • eco_mode
  • main_power
  • mute
  • power
  • sd
  • sleep
  • source
  • standby
  • surround_mode
  • video_select
  • video_select_source
  • hpf
  • quick_select
  • refresh

[!NOTE] Note: the refresh setting is used to request the latest settings from the specified zone. The text value of the payload for refresh is ignored, but should follow the syntax (ex: { "refresh": { "text": "ON" }}).

Schema:

{ "[setting]": { "text": "[text]" } }

Example:

{ "power": { "test": "ON" } }

Numeric

  • max_volume
  • volume

Schema:

{ "[setting]": { "numeric": [number] } }

Example:

{ "volume": { "numeric": 50 } }

Key/Value Pairs

  • channel_setting
  • channel_volume
  • ss_levels
  • ss_speakers
  • parameters

Schema:

{ "[setting]": { "key": "[key]", "value": "[value]" } }

Example:

{ "channel_volume": { "key": "C", "value": "50" } }

State Topic and Payload

All state changes are published to {prefix}/{id}/{zone}/{suffix} where {prefix} is the global prefix (default: denon), {id} is the unique identifier of the AVR, {zone} is the zone identifier (main_zone, zone1, zone2), and {suffix} is the state topic as configured at launch.

The payload syntax varies based on the setting updated as follows:

Text

  • digital_input
  • eco_mode
  • main_power
  • mute
  • power
  • sd
  • sleep
  • source
  • standby
  • surround_mode
  • video_select
  • video_select_source
  • hpf
  • quick_select

Schema:

{ "[setting]": "[text]" }

Example:

{ "power": "ON" }

Numeric

  • max_volume
  • volume

Schema:

{ "[setting]": [number] }

Example:

{ "volume": 55 }

Key/Value Pairs

  • channel_setting
  • channel_volume
  • ss_levels
  • ss_speakers
  • parameters

Schema:

{ "[setting]": { "key": "[key]", "value": "[value]" } }

Example:

{ "channel_volume": { "key": "C", "value": "55" } }

Full State

In addition to individual messages for each setting, the full state is sent every time a value is changed with the following payload:

Schema:

{
  "state": [state]
}

Where [state] is a JSON object with a key for each setting for the zone.

[!NOTE] Note: While the interface maintains state whenever a command is received by the interface, not every value may be available at all times.

Each value follows the same syntax as above. For Key/Value pairs, the value is a JSON object containing all values.

For example, below is a valid state from a Denon X4500H:

Example:

{
  "state": {
    "channel_volume": {
      "FL": "50",
      "FR": "50",
      "C": "50",
      "SL": "50",
      "SR": "50"
    },
    "digital_input": "AUTO",
    "main_power": "ON",
    "max_volume": 98,
    "mute": "OFF",
    "parameters": {
      "DRC": "OFF",
      "LFE": "00",
      "BAS": "50",
      "TRE": "50",
      "TONE CTRL": "OFF",
      "CLV": "50",
      "SWL": "50"
    },
    "power": "ON",
    "sd": "AUTO",
    "sleep": "OFF",
    "source": "SAT/CBL",
    "ss_levels": {
      "C": "50",
      "FL": "50",
      "FR": "50",
      "SL": "50",
      "SR": "50",
      "SBL": "50",
      "SBR": "50",
      "SB": "50",
      "FHL": "50",
      "FHR": "50",
      "TFL": "50",
      "TFR": "50",
      "TML": "50",
      "TMR": "50",
      "FDL": "50",
      "FDR": "50",
      "SDL": "50",
      "SDR": "50",
      "FWL": "50",
      "FWR": "50",
      "TRL": "50",
      "TRR": "50",
      "RHL": "50",
      "RHR": "50",
      "BDL": "50",
      "BDR": "50",
      "SHL": "50",
      "SHR": "50",
      "TS": "50",
      "SW": "50",
      "SW2": "50"
    },
    "ss_speakers": {
      "FRO": "LAR",
      "CEN": "SMA",
      "SUA": "SMA",
      "SBK": "2SP",
      "FRH": "NON",
      "TFR": "NON",
      "TPM": "NON",
      "FRD": "NON",
      "SUD": "NON",
      "TPR": "NON",
      "RHE": "NON",
      "BKD": "NON",
      "SHE": "NON",
      "TPS": "NON",
      "SWF": "NON"
    },
    "standby": "OFF",
    "surround_mode": "DOLBY AUDIO-DSUR",
    "video_select": "OFF",
    "volume": 56
  }
}

Contributing

Clone the repository

git clone https://github.com/douglampe/denon-mqtt.git

Install dependencies

yarn
# OR
npm i

Start eclipse mosquito MQTT and Home Assistant via Docker

docker compose up -d

Start the interface in dev mode

yarn dev
# OR
npm run dev

Run discovery (must set IP address as DMQTT_IP in .env file first)

yarn dev:discover
# OR
npm run dev:discover

Start the interface in dev mode using receivers.json to configure AVRs

yarn dev:file
# OR
npm run dev:file

Why Does This Exist?

Denon AVRs support both RS-232C and Ethernet interfaces. The Ethernet interface is a TCP interface which does not require any authentication or authorization. The interface is bi-directional meaning that changes made to the reciever by other sources (ex: using the remote control) are broadcasted to the interface. This makes the interface ideal for integrating with systems which operate best while maitaining accurate state such as the Home Automation platform Home Assistant. While integrating directly with Home Assistant has advantages such as reduced latency, there are disadvantages such as platform lock-in. Existing Denon integrations also have limitations. By creating an MQTT interface, multiple Denon AVRs can be integrated with Home Assistant using the supported MQTT integration while also providing direct support for any platform that supports MQTT such as Node Red. I also get to write this in Node.js instead of python which is a win for me IMHO.