samuelspagl / ha_samsung_soundbar

YASSI (Yet another Samsung Soundbar integration) is a HomeAssistant integration for Samsung Soundbars.
https://ha-samsung-soundbar.vercel.app
MIT License
41 stars 2 forks source link

Update custom capabilities (soundmode, woofer, eq, advanced_audio) fails #26

Closed royf007 closed 3 months ago

royf007 commented 5 months ago

So, I have been using this great integration with no issues on 2 Samsung Q990C soundbars for a few weeks.

I recently bought a 3rd Q990C. It's on the same network, same firmware version as the other 2. I'm able to use the Yamaha MusicCast API (api.smartthings.com) through Postman, obtain the device ID, send commands, etc. I'm also able to see it in the SmartThings integration in Home Assistant.

When I go to try to add the 3rd soundbar to this integration as a new "hub", it always fails to configure. I've even tried to remove and add back the other 2 soundbars that were previously working, and there are no issues adding them back.

I'm not really sure why I can't add this 3rd soundbar.

Any help would be appreciated. Here is the log entry:

Log Entry ``` Logger: homeassistant.config_entries Source: config_entries.py:504 First occurred: 12:13:07 AM (4 occurrences) Last logged: 12:15:29 AM Error setting up entry samsung_soundbar for samsung_soundbar Error setting up entry Living Room Soundbar for samsung_soundbar Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/config_entries.py", line 504, in async_setup result = await component.async_setup_entry(hass, self) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/samsung_soundbar/__init__.py", line 52, in async_setup_entry await soundbar_device.update() File "/config/custom_components/samsung_soundbar/api_extension/SoundbarDevice.py", line 52, in update await self._update_soundmode() File "/config/custom_components/samsung_soundbar/api_extension/SoundbarDevice.py", line 74, in _update_soundmode payload = await self.get_execute_status() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/samsung_soundbar/api_extension/SoundbarDevice.py", line 390, in get_execute_status return dict["data"]["value"]["payload"] ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ TypeError: 'NoneType' object is not subscriptable ```
royf007 commented 5 months ago

@samuelspagl , sure, no problem at all to adjust the description!

samuelspagl commented 5 months ago

Hello everyone! πŸ‘‹

A new Beta of the integration comes fresh out of my development oven. πŸŽ‰ While I understand the frustration of lacking entities for custom capabilities, I’ve made some improvements to enhance your experience and added service calls for:

And that’s not all! I’ve also fixed and added some essential controls:

Link to the beta release (And yeah, I know that I need to make a nicer description πŸ€“) Remember, this is a beta version, so your feedback is invaluable. Let’s make our soundbar experience even better! 😊

Wishing you all a fantastic start into the weekend! 🌟

royf007 commented 5 months ago

Hello @samuelspagl ! Thank you for doing this. I will be playing with the new Beta release. I like how you implemented the new configuration flow. I was able to add the problematic "Living Room" soundbar and used the "Woofer number" capability only in order to have the setup complete:

image

Cheers, and have a great weekend!

cristhianerg commented 5 months ago

I'm exactly on the same page as royf007, finally I'm able to config the soundbar but only woofer extra capability.

Then I try adding a "new hub" with same device_Id and it worked with the other 3 capabilities that where giving me problems earlier

image
samuelspagl commented 5 months ago

Interesting, so you enabled things like "soundmode" again in the other "hub" right? but still, the select entity should not be populated, and there should still be errors in the log, right?

Maybe I should add a validation for those "extra capabilities".

cristhianerg commented 5 months ago

@samuelspagl I got it "all working" with no error log. Let me explain what I did:

  1. Add a hub and select only "Enable 'Woofer number' capability" this enables 1 device and 5 entities: _select.soundbar_input_preset, sensor.soundbar_volume_level, media_player.soundbar, image.soundbar_image_url, number.soundbar_q990c_wooferlevel.
  2. Add a second hub selecting "Enable 'Advanced Audio switches' capabilities (NightMode, BassMode, VoiceEnhancer)", this enables 1 device and 3 entities: _switch.soundbar_q990c_bassmode, switch.soundbar_q990c_nightmode and switch.soundbar_q990c_voiceamplifier
  3. Then add a third hub and select "Enable 'EQ selector' capabilities" and "Enable 'Soundmode selector' capabilities", this enables 1 device and 2 entities: _select.soundbar_q990c_eq_preset and select.soundbar_q990c_sound_modepreset. Unfurtunately this 2 entities doesn't have attributes so it doesn't works

As I said, there's no error log for any interaction with this entities.

Cheers

Coinficient commented 5 months ago

@cristhianerg Good suggestion there your method worked better than mine mine was a bit forceful, as for the sound modes I guess @samuelspagl was trying to be mindful in case the API does come back so looking at the code although I can't say with certainty, I think it does try to retrieve the sound modes, I have modified that part of the code and I can say with 100% confidence it works instantly to change the sound mode, it does work a bit like "IR Setup" since it's one way but that's only if you do not use the Smartthings app which I'd rather not guess that's the case for everyone who's here, although there's a small caveat you cannot change the sound mode from the "select" directly you have to call it by service, I have not found a service for the EQ to confirm that one as well, but oh boy let's just say the Sound mode change Is instant same goes for Woofer as well, hope that helps everyone with the sound mode until @samuelspagl can work within the constraints and "limitations" SmartThings brings to us for our own Safety along with the many CVE's this soundbar brings, cheers to @samuelspagl for justice it brings to our soundbars as this is the last one I'll buy from Samsung πŸ˜‚

PS I've enabled Bass and Voice mode as they do reset to 0 when home assistant restarts and I keep them on most of time enabled so that's not essential. same goes for "Active Sound mode" as well.

🌁 Show picture ![Screenshot_20240407_014424_Home Assistant](https://github.com/samuelspagl/ha_samsung_soundbar/assets/165610201/87671082-6f61-4892-86a0-d048c7b3c2a2)
Coinficient commented 5 months ago

So I've made some changes to the code, no longer needed to add multiple soundbars and it will keep in mind if the API ever comes back to normal, now the first piece of code needed to be modified is this, add your supported sound modes, same goes for EQ as well although It doesn't work for me,

πŸ’» Show code ``` self.__enable_soundmode = enable_soundmode self.__supported_soundmodes = ["standard","surround","game","adaptive sound"] self.__active_soundmode = "" self.__selected_soundmode = None ``` ``` self.__enable_eq = enable_eq self.__active_eq_preset = "" self.__supported_eq_presets = ["NONE","POP","JAZZ","CLASSICAL","CUSTOM"] self.__eq_action = "setEQmode" self.__eq_bands = ["0","0","0","0","0","0","0"] ```

Now we modify this part of the code here

πŸ’» Show code ``` async def update(self): await self.device.status.refresh() await self._update_media() if self.__enable_soundmode: await self._update_soundmode() if self.__enable_advanced_audio: await self._update_advanced_audio() if self.__enable_soundmode: await self._update_woofer() if self.__enable_eq: await self._update_equalizer() ```

Into this, this part here ensures that you can add a single soundbar without the need of multiple ones, it will also keep in mind when the API ever comes back to update itself.

πŸ’» Show code ``` async def update(self): await self.device.status.refresh() await self._update_media() try: if self.__enable_soundmode: await self._update_soundmode() except Exception as e: print(f"Failed to update sound mode: {e}") try: if self.__enable_advanced_audio: await self._update_advanced_audio() except Exception as e: print(f"Failed to update advanced audio: {e}") try: if self.__enable_soundmode: await self._update_woofer() except Exception as e: print(f"Failed to update woofer: {e}") try: if self.__enable_eq: await self._update_equalizer() except Exception as e: print(f"Failed to update equalizer: {e}") ```

Further more on Sound mode, this is not required but it does make it easier to see what sound mode, basically instead of trying to get the sound mode selected from the API it will use the sound mode selected from the "select" entity, this part of the code needs to be changed if you want to reflect the changes immediately into the media player.

πŸ’» Show code ``` # ------------- SOUND MODE -------------- @property def sound_mode(self): return self.__active_soundmode @property def supported_soundmodes(self): return self.__supported_soundmodes async def select_sound_mode(self, sound_mode: str): await self.set_custom_execution_data( href="/sec/networkaudio/soundmode", property="x.com.samsung.networkaudio.soundmode", value=sound_mode, ) ```

To this, do note that I've introduced "__selected_soundmode" which is defined here "self.__selected_soundmode = None" this is the part of the code that ensures it reflects the sound mode selected without the need of API, but if the API comes back online it will get updated automatically anyway, now this should work without the need of multiple soundbars and it works pretty well, the EQ I haven't managed to get it working but at this point I am happy to have this which is really really good specially the woofer levels.

πŸ’» Show code ``` @property def sound_mode(self): return self.__selected_soundmode @property def supported_soundmodes(self): return self.__supported_soundmodes async def select_sound_mode(self, sound_mode: str): if sound_mode in self.__supported_soundmodes: # Set the selected sound mode self.__selected_soundmode = sound_mode await self.set_custom_execution_data( href="/sec/networkaudio/soundmode", property="x.com.samsung.networkaudio.soundmode", value=sound_mode) else: print("Unsupported sound mode") ```
Coinficient commented 5 months ago

I've also made a script on Home Assistant for more easier automations for anyone who's interested

πŸ’» Show code ``` alias: Soundbar Control sequence: - alias: Soundbar Sound Modes if: - alias: SOUNDBAR_SOUND_PRESENT condition: template value_template: "{{ sound_mode is defined and sound_mode != '' }}" then: - service: samsung_soundbar.select_soundmode target: entity_id: "{{ soundbar_player }}" data: sound_mode: "{{ sound_mode }}" - alias: Soundbar Inputs if: - alias: SOUNDBAR_INPUT_PRESENT condition: template value_template: "{{ source_input is defined and source_input != '' }}" then: - alias: Conditions if Soundbar is On or Off choose: - conditions: - alias: Soundbar Defined condition: template value_template: "{{ soundbar_player is defined and soundbar_player == 'off' }}" sequence: - service: media_player.turn_on data: {} target: entity_id: - "{{ soundbar_player }}" - wait_template: "{{is_state('soundbar_player', 'on')}}" continue_on_timeout: false alias: Turn On Soundbar If Off - service: media_player.select_source target: entity_id: "{{ soundbar_player }}" data: source: "{{ source_input }}" - alias: Turn Off Soundbar if: - alias: If Turn off Players is On and Players are defined condition: and conditions: - condition: template value_template: "{{ turn_off_media_players == True }}" alias: TURN_OFF_MEDIA_PLAYERS - alias: Soundbar Defined condition: template value_template: "{{ soundbar_player is defined and soundbar_player != '' }}" then: - service: media_player.turn_off data: {} target: entity_id: - "{{ soundbar_player }}" - alias: Set Woofer Level if: - alias: WOOFER VOLUME LEVEL condition: template value_template: "{{ woofer_level is defined and woofer_level != '' }}" then: - service: samsung_soundbar.set_woofer_level target: entity_id: - "{{ soundbar_player }}" data: level: >- {% set new_level = woofer_level | int %} {% if -12 <= new_level <= -7 %} -12 {% else %} {{ new_level }} {% endif %} fields: source_input: example: HDMI1 required: false selector: select: options: - HDMI1 - HDMI2 - digital - wifi - bluetooth name: Source Input description: >- Choose the desired input source for your soundbar, including HDMI options, digital, wifi, and bluetooth. woofer_level: selector: number: min: -12 max: 6 name: Woofer Level description: Adjust the bass level of your Subwoofer. soundbar_player: selector: entity: domain: media_player name: Soundbar Player description: Select your soundbar required: true sound_mode: example: game required: false selector: select: options: - standard - surround - game - adaptive sound name: Sound Mode description: >- Tailor your audio experience by choosing the preferred sound mode for your soundbar, with options like standard, surround, game, and adaptive sound. turn_off_media_players: selector: boolean: {} required: false description: Initiate a shutdown sequence for all media players simultaneously. name: Turn Off Media Players mode: parallel icon: mdi:application-settings-outline max: 4 ```
Coinficient commented 5 months ago

From the looks of it SmartThings team will take some years before they respond, the changes I've shared here makes the soundbar functional again, although it's "one way" anything you change to will make it seem like it "update itself", so for now although EQ doesn't work for me, I didn't use it that much to begin with, I guess this should do it for me, thanks again @samuelspagl for the hard work.

Peace.

samuelspagl commented 5 months ago

@Coinficient Yeah I didn't do the EQ service yet πŸ˜‚πŸ˜… I simply forgot about it 😁 I'll add it in a few days

samuelspagl commented 5 months ago

PS I've enabled Bass and Voice mode as they do reset to 0 when home assistant restarts and I keep them on most of time enabled so that's not essential. same goes for "Active Sound mode" as well.

Fine if you change it for you, but as Soundmode "may" be changed by Samsung at some point or differ from soundbar to soundbar, I will not add something like this to the main codebase ^^ jfyi

@Coinficient I added some

tags to your posts that they don't seem as long :D

Coinficient commented 5 months ago

@samuelspagl Thank you for that, believe it or not I am still new to Github when it comes to exchanging information πŸ˜‚, as for the sound mode code, of course it was meant to be more as a guide for people to get it working until you find a more efficient solution, in fact the whole code I shared was more as a guide rather than a direct implementation, for now this works good on my side until you find a more balanced option.

samuelspagl commented 3 months ago

I will close this issue with the merge of #28. Additionally I will create a new Issue, pin that one, and keep it open for the future. I still hope, that at some point things get back to normal again.

Ilovetowin commented 2 months ago

Hello @samuelspagl , I have managed to successfully configure the device (Samsung Soundbar S61B) using this method https://github.com/samuelspagl/ha_samsung_soundbar/issues/26#issuecomment-2041027513

The problem is that if I restart the homeassistant container the EQ and soundmode and also the Advanced audio switches go into Failed to setup: check logs

If I reconfigure them in the correct order from the method above it is working again but after every restart it goes in the same error state.

Can this be fixed somehow? Or is there anything I can do to mitigate this? I am mostly interested in automating turning on/off Night Mode.

I'm using the latest version 0.4.0

Thank you!