diff --git a/homeassistant/components/onkyo/media_player.py b/homeassistant/components/onkyo/media_player.py index 2cd4faaf314..c127d4150c5 100644 --- a/homeassistant/components/onkyo/media_player.py +++ b/homeassistant/components/onkyo/media_player.py @@ -93,6 +93,9 @@ TIMEOUT_MESSAGE = "Timeout waiting for response." ATTR_HDMI_OUTPUT = "hdmi_output" ATTR_PRESET = "preset" +ATTR_AUDIO_INFORMATION = "audio_information" +ATTR_VIDEO_INFORMATION = "video_information" +ATTR_VIDEO_OUT = "video_out" ACCEPTED_VALUES = [ "no", @@ -115,6 +118,22 @@ ONKYO_SELECT_OUTPUT_SCHEMA = vol.Schema( SERVICE_SELECT_HDMI_OUTPUT = "onkyo_select_hdmi_output" +def _parse_onkyo_tuple(tup): + """Parse a tuple returned from the eiscp library.""" + if len(tup) < 2: + return None + + if isinstance(tup[1], str): + return tup[1].split(",") + + return tup[1] + + +def _tuple_get(tup, index, default=None): + """Return a tuple item at index or a default value if it doesn't exist.""" + return (tup[index : index + 1] or [default])[0] + + def determine_zones(receiver): """Determine what zones are available for the receiver.""" out = {"zone2": False, "zone3": False} @@ -229,9 +248,17 @@ class OnkyoDevice(MediaPlayerEntity): self._muted = False self._volume = 0 self._pwstate = STATE_OFF - self._name = ( - name or f"{receiver.info['model_name']}_{receiver.info['identifier']}" - ) + if name: + # not discovered + self._name = name + self._unique_id = None + else: + # discovered + self._unique_id = ( + f"{receiver.info['model_name']}_{receiver.info['identifier']}" + ) + self._name = self._unique_id + self._max_volume = max_volume self._receiver_max_volume = receiver_max_volume self._current_source = None @@ -265,6 +292,10 @@ class OnkyoDevice(MediaPlayerEntity): self._pwstate = STATE_ON else: self._pwstate = STATE_OFF + self._attributes.pop(ATTR_AUDIO_INFORMATION, None) + self._attributes.pop(ATTR_VIDEO_INFORMATION, None) + self._attributes.pop(ATTR_PRESET, None) + self._attributes.pop(ATTR_VIDEO_OUT, None) return volume_raw = self.command("volume query") @@ -278,20 +309,19 @@ class OnkyoDevice(MediaPlayerEntity): else: hdmi_out_raw = [] preset_raw = self.command("preset query") + audio_information_raw = self.command("audio-information query") + video_information_raw = self.command("video-information query") if not (volume_raw and mute_raw and current_source_raw): return - # eiscp can return string or tuple. Make everything tuples. - if isinstance(current_source_raw[1], str): - current_source_tuples = (current_source_raw[0], (current_source_raw[1],)) - else: - current_source_tuples = current_source_raw + sources = _parse_onkyo_tuple(current_source_raw) - for source in current_source_tuples[1]: + for source in sources: if source in self._source_mapping: self._current_source = self._source_mapping[source] break - self._current_source = "_".join(current_source_tuples[1]) + self._current_source = "_".join(sources) + if preset_raw and self._current_source.lower() == "radio": self._attributes[ATTR_PRESET] = preset_raw[1] elif ATTR_PRESET in self._attributes: @@ -303,12 +333,20 @@ class OnkyoDevice(MediaPlayerEntity): self._receiver_max_volume * self._max_volume / 100 ) + self._parse_audio_inforamtion(audio_information_raw) + self._parse_video_inforamtion(video_information_raw) + if not hdmi_out_raw: return - self._attributes["video_out"] = ",".join(hdmi_out_raw[1]) + self._attributes[ATTR_VIDEO_OUT] = ",".join(hdmi_out_raw[1]) if hdmi_out_raw[1] == "N/A": self._hdmi_out_supported = False + @property + def unique_id(self): + """Return unique ID for this device.""" + return self._unique_id + @property def name(self): """Return the name of the device.""" @@ -402,6 +440,37 @@ class OnkyoDevice(MediaPlayerEntity): """Set hdmi-out.""" self.command(f"hdmi-output-selector={output}") + def _parse_audio_inforamtion(self, audio_information_raw): + values = _parse_onkyo_tuple(audio_information_raw) + if values: + info = { + "format": _tuple_get(values, 1), + "input_frequency": _tuple_get(values, 2), + "input_channels": _tuple_get(values, 3), + "listening_mode": _tuple_get(values, 4), + "output_channels": _tuple_get(values, 5), + "output_frequency": _tuple_get(values, 6), + } + self._attributes[ATTR_AUDIO_INFORMATION] = info + else: + self._attributes.pop(ATTR_AUDIO_INFORMATION, None) + + def _parse_video_inforamtion(self, video_information_raw): + values = _parse_onkyo_tuple(video_information_raw) + if values: + info = { + "input_resolution": _tuple_get(values, 1), + "input_color_schema": _tuple_get(values, 2), + "input_color_depth": _tuple_get(values, 3), + "output_resolution": _tuple_get(values, 5), + "output_color_schema": _tuple_get(values, 6), + "output_color_depth": _tuple_get(values, 7), + "picture_mode": _tuple_get(values, 8), + } + self._attributes[ATTR_VIDEO_INFORMATION] = info + else: + self._attributes.pop(ATTR_VIDEO_INFORMATION, None) + class OnkyoDeviceZone(OnkyoDevice): """Representation of an Onkyo device's extra zone."""