now a working radio controller
This commit is contained in:
+53
-4
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import socket
|
||||
import ssl
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
@@ -10,6 +11,8 @@ from urllib.error import URLError
|
||||
from urllib.parse import quote
|
||||
from urllib.request import Request, urlopen
|
||||
|
||||
import lib_heos
|
||||
|
||||
|
||||
_host = "192.168.178.177"
|
||||
_port = 8080
|
||||
@@ -54,12 +57,44 @@ def off() -> None:
|
||||
_command("PWSTANDBY")
|
||||
|
||||
|
||||
def _power_state() -> str:
|
||||
"""Return ON or STANDBY using Denon's control-protocol status query."""
|
||||
try:
|
||||
with socket.create_connection((_host, 23), timeout=_timeout) as connection:
|
||||
connection.settimeout(_timeout)
|
||||
connection.sendall(b"PW?\r")
|
||||
with connection.makefile("r", encoding="ascii", newline="\r") as stream:
|
||||
while line := stream.readline():
|
||||
response = line.strip()
|
||||
if response.startswith("PW"):
|
||||
state = response[2:]
|
||||
if state in {"ON", "STANDBY"}:
|
||||
return state
|
||||
except OSError as error:
|
||||
raise RuntimeError(f"Cannot query Denon power state: {error}") from error
|
||||
raise RuntimeError("Denon did not return a valid power state")
|
||||
|
||||
|
||||
def next() -> None:
|
||||
"""Select the next preset or source."""
|
||||
"""Play the next HEOS favorite according to the receiver's power state."""
|
||||
lib_heos.configure(_host, timeout=_timeout)
|
||||
if _power_state() == "STANDBY":
|
||||
lib_heos.play_favorite(1)
|
||||
return
|
||||
# Deliberately do nothing when the receiver is on but its current media is
|
||||
# not one of the configured HEOS favorites.
|
||||
lib_heos.next_favorite()
|
||||
|
||||
|
||||
def previous() -> None:
|
||||
"""Select the previous preset or source."""
|
||||
"""Play the previous HEOS favorite according to the receiver's power state."""
|
||||
lib_heos.configure(_host, timeout=_timeout)
|
||||
if _power_state() == "STANDBY":
|
||||
lib_heos.play_favorite(1)
|
||||
return
|
||||
# Deliberately do nothing when the receiver is on but its current media is
|
||||
# not one of the configured HEOS favorites.
|
||||
lib_heos.previous_favorite()
|
||||
|
||||
|
||||
def volume_up() -> None:
|
||||
@@ -74,12 +109,25 @@ def volume_down() -> None:
|
||||
_command("MVDOWN")
|
||||
|
||||
|
||||
def volume_mute() -> None:
|
||||
"""Mute the volume."""
|
||||
_command("MUON")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""Run a receiver action from the command line."""
|
||||
parser = argparse.ArgumentParser(description="Control the Denon receiver")
|
||||
parser.add_argument(
|
||||
"action",
|
||||
choices=("on", "off", "next", "previous", "volume-up", "volume-down"),
|
||||
choices=(
|
||||
"on",
|
||||
"off",
|
||||
"next",
|
||||
"previous",
|
||||
"volume-up",
|
||||
"volume-down",
|
||||
"volume-mute",
|
||||
),
|
||||
)
|
||||
parser.add_argument("--host", default=_host, help=f"receiver address (default: {_host})")
|
||||
parser.add_argument("--port", type=int, default=_port, help=f"HTTP port (default: {_port})")
|
||||
@@ -116,10 +164,11 @@ def main() -> int:
|
||||
"previous": previous,
|
||||
"volume-up": volume_up,
|
||||
"volume-down": volume_down,
|
||||
"volume-mute": volume_mute,
|
||||
}
|
||||
try:
|
||||
actions[args.action]()
|
||||
except (OSError, URLError) as error:
|
||||
except (OSError, URLError, RuntimeError, lib_heos.HeosError) as error:
|
||||
print(f"Denon {args.action} failed: {error}", file=sys.stderr)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user