Skip to content

Commit

Permalink
feat: add buttons to control phoniebox (#36)
Browse files Browse the repository at this point in the history
* feat: add random button

* refactor: remove hardcoded phoniebox strings

* feat: add missing buttons

adds shuffle, scan, rewind, replay, restart, shutdown and shutdown silent

fixes #30

* test: add tests for buttons

* test: fixes tests
  • Loading branch information
c0un7-z3r0 authored Feb 3, 2022
1 parent 765218a commit ef6e3d7
Show file tree
Hide file tree
Showing 7 changed files with 315 additions and 73 deletions.
5 changes: 5 additions & 0 deletions custom_components/phoniebox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ async def async_publish(self, topic, payload) -> None:
full_topic = self.base_topic + "/" + topic
await mqtt.async_publish(self.hass, full_topic, payload)

async def async_publish_cmd(self, topic, payload) -> None:
""" Send a command to phoniebox. """
await self.async_publish("cmd/" + topic, payload)


async def async_setup(hass: HomeAssistant, config: Config):
"""Set up this integration using YAML is not supported."""
Expand Down Expand Up @@ -70,6 +74,7 @@ def __init__(self, mqtt_client: MqttClient) -> None:
self.mqtt_client = mqtt_client
self.sensors = {}
self.switches = {}
self.buttons = {}
self.version = "unknown"


Expand Down
105 changes: 105 additions & 0 deletions custom_components/phoniebox/button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""Buttons to control the phoniebox."""
from __future__ import annotations

import logging
from abc import ABC

from homeassistant.components.button import ButtonEntity, ButtonDeviceClass
from homeassistant.config_entries import ConfigEntries

from . import DataCoordinator
from .const import CONF_PHONIEBOX_NAME, DOMAIN, PHONIEBOX_CMD_PLAYER_SHUFFLE, \
PHONIEBOX_CMD_SCAN, PHONIEBOX_CMD_PLAYER_REWIND, PHONIEBOX_CMD_PLAYER_REPLAY, PHONIEBOX_CMD_REBOOT, \
PHONIEBOX_CMD_SHUTDOWN, PHONIEBOX_CMD_SHUTDOWN_SILENT, BUTTON_RESTART, BUTTON_SHUFFLE, BUTTON_SCAN, BUTTON_REWIND, \
BUTTON_REPLAY, BUTTON_SHUTDOWN, BUTTON_SHUTDOWN_SILENT, ALL_BUTTONS
from .entity import PhonieboxEntity
from .sensor import _slug

_LOGGER: logging.Logger = logging.getLogger(__package__)


def find_device_class(name: str) -> ButtonDeviceClass | None:
"""
Based on the button name find the corresponding device class
"""
if name == BUTTON_RESTART:
return ButtonDeviceClass.RESTART
return None


def find_mqtt_topic(name: str) -> str:
"""
Based on the button name find the corresponding mqtt command
"""
if name == BUTTON_SHUFFLE:
return PHONIEBOX_CMD_PLAYER_SHUFFLE
if name == BUTTON_SCAN:
return PHONIEBOX_CMD_SCAN
if name == BUTTON_REWIND:
return PHONIEBOX_CMD_PLAYER_REWIND
if name == BUTTON_REPLAY:
return PHONIEBOX_CMD_PLAYER_REPLAY
if name == BUTTON_RESTART:
return PHONIEBOX_CMD_REBOOT
if name == BUTTON_SHUTDOWN:
return PHONIEBOX_CMD_SHUTDOWN
if name == BUTTON_SHUTDOWN_SILENT:
return PHONIEBOX_CMD_SHUTDOWN_SILENT


async def async_setup_entry(hass, entry, async_add_devices):
"""Setup button platform."""
coordinator = hass.data[DOMAIN][entry.entry_id]
buttons: list[PhonieboxButton] = []
store = coordinator.buttons

for button_name in ALL_BUTTONS:
buttons.append(
PhonieboxButton(
config_entry=entry,
name=button_name,
coordinator=coordinator,
device_class=find_device_class(button_name),
on_press_mqtt_topic=find_mqtt_topic(button_name),
)
)

if len(buttons) == 0:
return

for button in buttons:
if button.name not in store:
button.hass = hass
store[button.name] = button
_LOGGER.debug(
"Registering buttons %(name)s",
{"name": button.name},
)
async_add_devices((button,), True)


class PhonieboxButton(PhonieboxEntity, ButtonEntity, ABC):
"""phoniebox button class."""

_attr_should_poll = False

def __init__(
self,
config_entry: ConfigEntries,
name: str,
coordinator: DataCoordinator,
device_class: ButtonDeviceClass = None,
on_press_mqtt_topic=None,
):
super().__init__(config_entry, coordinator)
self.entity_id = _slug(name, config_entry.data[CONF_PHONIEBOX_NAME])
self._attr_name = name
self._attr_device_class = device_class
self._on_press_mqtt_topic = on_press_mqtt_topic

async def async_press(self) -> None:
"""Press the button."""
if self._on_press_mqtt_topic:
await self.mqtt_client.async_publish(
"cmd/" + self._on_press_mqtt_topic, {}
)
140 changes: 113 additions & 27 deletions custom_components/phoniebox/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from homeassistant.const import (
STATE_IDLE,
STATE_PAUSED,
STATE_PLAYING,
STATE_PLAYING, Platform,
)

NAME = "Phoniebox"
Expand Down Expand Up @@ -70,7 +70,7 @@
SENSOR = "sensor"
SWITCH = "switch"
MEDIA_PLAYER = "media_player"
PLATFORMS = [SENSOR, BINARY_SENSOR, SWITCH, MEDIA_PLAYER]
PLATFORMS = [SENSOR, BINARY_SENSOR, SWITCH, MEDIA_PLAYER, Platform.BUTTON]

# Player
SUPPORT_MQTTMEDIAPLAYER = (
Expand Down Expand Up @@ -127,38 +127,124 @@
# Defaults
DEFAULT_NAME = DOMAIN

# Phoniebox attributes
PHONIEBOX_ATTR_GPIO = "gpio"
PHONIEBOX_ATTR_RFID = "rfid"
PHONIEBOX_ATTR_MUTE = "mute"
PHONIEBOX_ATTR_RANDOM = "random"
PHONIEBOX_ATTR_SCAN = "scan"
PHONIEBOX_ATTR_PLAYER_REWIND = "playerrewind"
PHONIEBOX_ATTR_REPEAT = "repeat"
PHONIEBOX_ATTR_THROTTLING = "throttling"
PHONIEBOX_ATTR_VERSION = "version"
PHONIEBOX_ATTR_LAST_CARD = "last_card"
PHONIEBOX_ATTR_ALBUM = "album"
PHONIEBOX_ATTR_ARTIST = "artist"
PHONIEBOX_ATTR_ALBUM_ARTIST = "albumartist"
PHONIEBOX_ATTR_EDITION = "edition"
PHONIEBOX_ATTR_REMAINING_STOP_AFTER = "remaining_stopafter"
PHONIEBOX_ATTR_REMAINING_SHUTDOWN_AFTER = "remaining_shutdownafter"
PHONIEBOX_ATTR_REMAINING_IDLE = "remaining_idle"
PHONIEBOX_ATTR_VOLUME_STEPS = "volstep"
PHONIEBOX_ATTR_MAX_VOLUME = "maxvolume"
PHONIEBOX_ATTR_IDLE_TIME = "idletime"
PHONIEBOX_ATTR_DISK_AVAILABLE = "disk_avail"
PHONIEBOX_ATTR_DISK_TOTAL = "disk_total"
PHONIEBOX_ATTR_TITLE = "title"
PHONIEBOX_ATTR_TRACK = "track"
PHONIEBOX_ATTR_TRACK_DATE = "trackdate"
PHONIEBOX_ATTR_ELAPSED = "elapsed"
PHONIEBOX_ATTR_DURATION = "duration"
PHONIEBOX_ATTR_VOLUME = "volume"

# Phoniebox commands
PHONIEBOX_CMD_DISABLE_WIFI = "disablewifi"
PHONIEBOX_CMD_SCAN = "scan"
PHONIEBOX_CMD_REBOOT = "reboot"
PHONIEBOX_CMD_SHUTDOWN_SILENT = "shutdownsilent"
PHONIEBOX_CMD_PLAYER_REPLAY = "playerreplay"
PHONIEBOX_CMD_PLAYER_REWIND = "playerrewind"
PHONIEBOX_CMD_PLAYER_SEEK = "playerseek"
PHONIEBOX_CMD_PLAY_FOLDER_RECURSIVE = "playfolderrecursive"
PHONIEBOX_CMD_PLAY_FOLDER = "playfolder"
PHONIEBOX_CMD_SWIPE_CARD = "swipecard"
PHONIEBOX_CMD_SET_GPIO = "gpio"
PHONIEBOX_CMD_SET_RFID = "rfid"
PHONIEBOX_CMD_PLAYER_STOP_AFTER = "playerstopafter"
PHONIEBOX_CMD_SHUTDOWN_AFTER = "shutdownafter"
PHONIEBOX_CMD_SET_IDLE_TIME = "setidletime"
PHONIEBOX_CMD_SET_MAX_VOLUME = "setmaxvolume"
PHONIEBOX_CMD_SET_VOLUME_STEPS = "setvolstep"
PHONIEBOX_CMD_SET_VOLUME = "setvolume"
PHONIEBOX_CMD_SHUTDOWN = "shutdown"
PHONIEBOX_CMD_PLAYER_REPEAT = "playerrepeat"
PHONIEBOX_CMD_PLAYER_SHUFFLE = "playershuffle"
PHONIEBOX_CMD_PLAYER_NEXT = "playernext"
PHONIEBOX_CMD_PLAYER_PREV = "playerprev"
PHONIEBOX_CMD_PLAYER_STOP = "playerstop"
PHONIEBOX_CMD_PLAYER_PAUSE = "playerpause"
PHONIEBOX_CMD_PLAYER_PLAY = "playerplay"
PHONIEBOX_CMD_MUTE = "mute"
PHONIEBOX_CMD_VOLUME_DOWN = "volumedown"
PHONIEBOX_CMD_VOLUME_UP = "volumeup"

BINARY_SWITCHES = [
"gpio",
"rfid",
"random",
"mute",
PHONIEBOX_ATTR_GPIO,
PHONIEBOX_ATTR_RFID,
PHONIEBOX_ATTR_MUTE,
]
BOOLEAN_SENSORS = [
"gpio",
"rfid",
"repeat",
"random",
"mute",
PHONIEBOX_ATTR_GPIO,
PHONIEBOX_ATTR_RFID,
PHONIEBOX_ATTR_REPEAT,
PHONIEBOX_ATTR_RANDOM,
PHONIEBOX_ATTR_MUTE,
]
STRING_SENSORS = [
"throttling",
"version",
"last_card",
"album",
"artist",
"albumartist",
"edition",
PHONIEBOX_ATTR_THROTTLING,
PHONIEBOX_ATTR_VERSION,
PHONIEBOX_ATTR_LAST_CARD,
PHONIEBOX_ATTR_ALBUM,
PHONIEBOX_ATTR_ARTIST,
PHONIEBOX_ATTR_ALBUM_ARTIST,
PHONIEBOX_ATTR_EDITION
]
NUMBER_SENSORS = [
"remaining_stopafter",
"remaining_shutdownafter",
"remaining_idle",
"volstep",
"maxvolume",
"idletime",
PHONIEBOX_ATTR_REMAINING_STOP_AFTER,
PHONIEBOX_ATTR_REMAINING_SHUTDOWN_AFTER,
PHONIEBOX_ATTR_REMAINING_IDLE,
PHONIEBOX_ATTR_VOLUME_STEPS,
PHONIEBOX_ATTR_MAX_VOLUME,
PHONIEBOX_ATTR_IDLE_TIME,
]
GIGABYTE_SENSORS = [
"disk_avail",
"disk_total",
PHONIEBOX_ATTR_DISK_AVAILABLE,
PHONIEBOX_ATTR_DISK_TOTAL,
]
IGNORE_SENSORS = [
PHONIEBOX_ATTR_TITLE,
PHONIEBOX_ATTR_TRACK,
PHONIEBOX_ATTR_TRACK_DATE,
PHONIEBOX_ATTR_ELAPSED,
PHONIEBOX_ATTR_DURATION,
PHONIEBOX_ATTR_VOLUME,
]

# Buttons
BUTTON_SHUFFLE = "Shuffle"
BUTTON_SCAN = "Start Scan"
BUTTON_REWIND = "Rewind"
BUTTON_REPLAY = "Replay"
BUTTON_RESTART = "Restart Phoniebox"
BUTTON_SHUTDOWN = "Shutdown Phoniebox"
BUTTON_SHUTDOWN_SILENT = "Shutdown Phoniebox silently"

ALL_BUTTONS = [
BUTTON_SCAN,
BUTTON_REWIND,
BUTTON_REPLAY,
BUTTON_RESTART,
BUTTON_SHUTDOWN,
BUTTON_SHUFFLE,
BUTTON_SHUTDOWN_SILENT,
]
IGNORE_SENSORS = ["title", "track", "trackdate", "elapsed", "duration", "volume"]
Loading

0 comments on commit ef6e3d7

Please sign in to comment.