Integrating HTD Into HomeAssistant

Hello everyone.
I’m still a bit fresh to homeassistant and only have limited automations running presently. So please bear with my inexperience.

I’m having some difficulty either understanding how to integrate python scripts or simply how to leverage the homeassistant interface properly.

A friend and I worked on a python script that we cobbled together from online sources to be able to get the HTD Lync audio system responding to the python queries. (Source code is here GitHub - meester-stoo/Homeassistant) (Yes the ip is “hardcoded” and I’m not concerned with people knowing my internal HTD address).

What I have been able to do is create the speakers as commandline switches with on/off and status (and they work well and can be automated too). However I’m having issues getting the other functionality to work. Such as changing the audio source or volume. what I’d like to do is have a dropdown list to select the various sources but any selection lists I’ve looked at only allow for calling a specific service. And I can’t call the script as a service from what I’ve seen (as the default homeassistant implementation doesn’t support imports and the other python packages don’t appear to provide a method of running a script natively. At least from what I’ve been able to fathom.

Is there someone that can perhaps give some guidance on how I can get this going?

Thank you,

2 Likes

I’d love for this to be a thing as well. I suggest emailing HTD to request they release their API or whatever it is that is needed to make this easy!

1 Like

So I see the code you linked to on GitHub, but how do I use it? Realize I am super new to all this, so maybe I just need to copy and paste it somehwhere? I have Home Assistant OS up and running and I have the HTD Lync 12 system. I would love even to just be able to detect if a zone is on in Home Assistant and either alert me or power it off (otherwise it gets left on overnight and all day long…) Would you be able to add some instructions to the GitHub page? This is the only thing I’ve found that is for the Lync system, all the other projects and code are for the older MCA-66 system. Thanks!

1 Like

Yeaaah, I’m kind of bad for github instructions…:stuck_out_tongue:

So here’s what I did and what you need to do:
First things first, download both files, edit the Lync12.py in a text editor (notepad++ or such). Look for line 31.

Replace the IP address there with the IP address of your lync gateway. (and although the default port for the gateway is 10006 you may have modified that or such) Modify line 32 if you need to.

Then upload both files to your homeassistant (I run a VM HA instance with the SSH add-on). I uploaded mine to a subfolder under config called scripts.

Now you need to create a whole slew of sensors and switches ( I still haven’t got the volume sliders or source inputs setup yet but that’s been me being lazy).

So First the Sensor (in sensors.yaml):
Duplicate as required

  - platform: command_line
    name: htd_zone1
    scan_interval: 45
    json_attributes:
      - dnd
      - idx
      - mute
      - name
      - power
      - source
      - source_name
      - volume
    command: "python3 /config/scripts/htd-lync12.py query zone 1"

Then the Switches (switch.yaml):

  - platform: command_line
    switches:
      htd_sw_zone1:
        command_on: 'python3 /config/scripts/htd-lync12.py power 1 on'
        command_off: 'python3 /config/scripts/htd-lync12.py power 1 off'
        friendly_name: "Kitchen"
        value_template: "{{ value_json.power }}"
        command_timeout: "15"
        command_state: "python3 /config/scripts/htd-lync12.py query zone 1"

This should create two entities, a basic on/off switch and a sensor that will be able to show what volume source and state.

image

image

As for automations well that I’m sure you don’t need my help on :slight_smile: Unless you do :thinking:

J

1 Like

Edit: I’m going to mess around with this some more and see if I can figure it out. Was just able to put that code directly in my config.yaml file and it said the config was valid.

Edit 2: Okay, got them to show up in entities, so that is progress.

Thanks for putting that together! I’m working through it right now.

I was able to get to “This should create two entities, a basic on/off switch and a sensor that will be able to show what volume source and state.”

No entities show up when I search for HTD in my entities list. Do I have to do something to have HA look at the files I just created? I feel like that step is missing. I trying adding

sensor: !include sensors.yaml
switch: !include switch.yaml

in my configuration.yaml file but when I checked the configuration I got an error that said it was invalid

"Error loading /config/configuration.yaml: mapping values are not allowed here
in “/config/switch.yaml”, line 2, column 13

I feel like I need to somehow tell HA that those new scripts are there.

1 Like

Ok I have the switch partially working. I can turn on a zone, but can’t turn it off. When I turn it off, the switch reverts to back on after a few seconds. When the zone is off and I use the switch to turn it on, the zone comes on right away! So I did something right.

How does the sensor look in Lovelace for you? Are you using a HACS custom card or something? Here is what my two cards look like:

Screen Shot 2021-12-18 at 1.47.21 PM

Also, you included some “State attributes (YAML, optional)”. What is this? I see those are just blank when I made the sensor. Wouldn’t those be variables? That is, power won’t always be true as the power won’t always be on. I guess I don’t get how those state attributes work, could you enlighten me please?

This is awesome that I’ve finally been able to make some progress on this after a year of wanting to get HTD into HA. Thanks again!

Edit: so sometimes just typing this out helps me think through it. I understand now that the State attributes go in the Lovelace card somehow. Can you post the yaml for your Lovelace cards? I think that would be helpful. Still don’t know why my switch will only turn on and not off. The sensor is pulling correct info (power, volume, source, etc) so it’s working in the background.

1 Like

So I’m not using a custom Card, I basically keep the sensor hidden and will most likely use it as an automation state later when I sit down and tackle some of the other things I want to do with them. (Things like incorporating a volume slider and source selector)

As for the powering on but not off. Do you have a Lync 12 or Lync 6? It’s possible that some of the index items are off in the program (I’d have to get my friend to check if that’s the case). I’ve uploaded my sensors and switch yamls to the git If you want to look, very basic.

To test you can go into the shell of your HA and manually run the script (python3 /config/scripts/htd-lync12.py power 1 off) Additionally if you run the script “as-is” a help text displays showing what the script can do and the syntax as well.

As for my lovelace, it is just like yours (the switch) except I customised the icon to be a speaker instead.

Ah, I see regarding the Lovelace cards. I have a Lync 12, so I think that is all good.

Thanks for uploading those files, it was really helpful for me to find silly mistakes and stuff. I was able to create the separate files for switch and sensor and move the stuff out of my main config file which is good. So satisfying for me to see the green “Configuration valid!” message after messing with this stuff - I have zero programming experience so it’s a steep hill to climb sometimes.

To test you can go into the shell of your HA and manually run the script (python3 /config/scripts/htd-lync12.py power 1 off) Additionally if you run the script “as-is” a help text displays showing what the script can do and the syntax as well.

Ok, I am able to open up the terminal and run that script and it worked! Same thing with power on. So maybe it is something with my switch. FOUND IT! So I didn’t put the python files in a /scripts/ folder, I made one called /HTD instead. So when changed it I wrote Htd with the lowercase d. It works! I guess the old adage “garbage in, garbage out” applies here.

Oh hot damn! When I made the card with multiple zones and put in a title, there is a bit switch at the top that powers everything on and off!

What is the scan interval and why is it not the same for all of the sensors?

Okay so my next project which I’ll have to start on a later date is setting up some sort of automation where if a zone is on for more than N hours or if it’s a certain time turn the zone off. I probably should do something with scenes as well.

This is so cool though. I have a major headache and need to go do something else, but this was very satisfying and I’m so glad I finally made some progress. Thanks so much for the time and support!

Glad you got it sorted out!

So regarding the timer. They’re different because sometimes (and it might just be my instance) the HTD gateway with kind of bork on receiving too many queries simultaneously so I space them out.

Another project I was looking into, the fellow had almost reversed the api but it required setting up a full “stack” as it were to host the application so it was kind of a non starter.

And don’t worry about being a newb. I’m still very much in that bucket and slowly work my way though getting smart logic into my home :slight_smile:

Oh one thing that I do is have the “work day” integration setup and have the house automatically turn on my “home office” speaker at the start of the work day and off at the end of it. Helps keep timing to “hey the work day’s done”.

Happy tinkering!

So a bit of a status update:

A buddy pointed me to the following page Input slider values to a python script for RGB LED - #14 by nnelg which actually helped me a lot to setup the sliders to work correctly.

So now I can actually update the volume within HA :slight_smile:

So you need to create some entries in a shell_command.yaml (if you don’t have it create is and don’t forget to add the include line in your configuration (shell_command: !include shell_command.yaml))

In there I added the following entry:

zone1_volume_slider:
   python3 /config/scripts/htd-lync12.py volume 1 {{volumevalue}}

Then I created a numeric helper

Then I created an automation

alias: HTD_Kitchen_Volume
description: Automation to handle the volume slider for the HTD Zone 1 (kitchen/Livingroom)
trigger:
  - platform: state
    entity_id: input_number.kitchen_livingroom_volume
condition: []
action:
  - service: shell_command.zone1_volume_slider
    data_template:
      volumevalue: '{{states.input_number.kitchen_livingroom_volume.state | int}}'
mode: single

After adding that so my lovelace card and testing it out by moving it around it successfully changed the volume (up and down).

The HTD only supports a max volume setting of 60 so I made sure my slider was set the same.
Now my speaker card looks like this:
image

Another side-note, which you’re probably aware of, changing the volume when the speaker is off powers it on, this isn’t the script it’s the way the HTD system works.

Aaaand another update.

Based on the previous post I’ve been able to get the source selection working as well.

So I created a drop down selector helper


And added another entry in the shell_command.yaml

set_zone_source:
  python3 /config/scripts/htd-lync12.py input {{zonevalue}} {{inputvalue}}

Then created an automation

alias: HTD_Zone1_Input
description: >-
  Automation to handle the Source selection for the HTD Zone 1 (Kitchen/Living
  Room)
trigger:
  - platform: state
    entity_id: input_select.htd_zone1_source
condition: []
action:
  - service: shell_command.set_zone_source
    data_template:
      zonevalue: 1
      inputvalue: >
        {% if states('input_select.htd_zone1_source') == "Kitchen Input" %} 1 {%
        elif states('input_select.htd_zone1_source') == "En-Suite Input" %} 2 {%
        elif states('input_select.htd_zone1_source') == "Craftroom Input" %} 3
        {% elif states('input_select.htd_zone1_source') == "Backyard Input/BT
        50EC" %} 4 {% elif states('input_select.htd_zone1_source') == "Basement
        Input/BT 50FC" %} 5 {% elif states('input_select.htd_zone1_source') ==
        "Garage Input" %} 6 {% elif states('input_select.htd_zone1_source') ==
        "Relaxing Playlist" %} 7 {% elif states('input_select.htd_zone1_source')
        == "Africa/Christmas Playlist" %} 8 {% elif
        states('input_select.htd_zone1_source') == "Jason's Favourite Playlist"
        %} 9 {% elif states('input_select.htd_zone1_source') == "Renee's
        Favourite Playlist" %} 10 {% elif
        states('input_select.htd_zone1_source') == "Alexxa Streaming" %} 11 {%
        elif states('input_select.htd_zone1_source') == "Built-in MP3 Player" %}
        12 {% endif %}
mode: single

I had to basically match out each selection in the list to the appropriate “source” ID in the HTD system. (I basically matched them top down in the HTD app and verified they actually matched).
Now the card looks like this:
image
And best of all it works.

If anyone wants to comment on the automation and template to help clean it up I’m all ears :slight_smile:

1 Like

Oh wow, that’s a lot of stuff. I currently am just running one source (a Raspberry Pi as an Apple AirPlay device) so I’m just pushing audio (and volume control) out from my phone via AirPlay on the Pi, so just a single source and static volume on HTD.

One thing I’m not getting is reliability in HA. For instance, HA showed all zones were off last night, but this morning one was still on. With that same zone that was on all night and not showing it, when I turn it on in HA, the slider goes back to off in a few seconds, but the zone turns on. Even if I wait for a minute, the sensor still won’t show that the speaker is turned on. But then later on this zone worked fine. The Logbook in HA isn’t super consistent either. Sometimes the switch change shows up, and sometimes the sensor change shows up. And it seems like the sensors are throwing stuff like this up, even though nothing has changed for that zone. Is that the scanning? Looks like this happens regardless of whether I am changing anything or not.

htd_zone1 changed to { "dnd": false, "idx": 1, "mute": false, "name": "Zone 1", "power": false, "source": 14, "source_name": "Source 14", "sources": [], "volume": 40 }

So it has to scan in order to pick up changes made from the HTD app, right? But if you hit the switch right after a scan, then the sensor misses that it changed until the next scan?

You ever have this issue?

So yes, I do encounter that issue occasionally. Although I don’t currently use the sensor portion presently so I can’t say I’ve noticed it much.

You can try modifying the
scan_interval: 45

value a bit to smaller values but if you’re running a pi it will probably start taxing the system with the frequent script executions (not taxing THAT much but still additional load on a “minimized” device).

The thing is that the switch itself (the command_line entry) automatically queries the state (I think it’s once a minute, provided you use the state query line like I did) regardless of the sensor so if you want you could potentially just remove the sensor altogether (unless you’re currently using it).

The reason I’m not using it is because I think I’d create an update loop if I query the sensor to populate my volume and source which then triggers the automation to set the volume and source, still got to mull that one over)

I’ve had the odd occasion where the script doesn’t return a value for the json entries but it usually clears up by the next refresh.

For your automation, do you expect a state as a condition? to ensure the system is off I would just set a time is XX then device → switch.htd_zonex → turn off and repeat the action for all the zones. And not worry about a check condition. Then it will force them off regardless.

Oh, I think I don’t understand it it then. I thought that the icon on the switch’s Lovelace card was linked to the sensor. When I commented out the '!includeline in theconfiguration.yaml` file and restarted, I still get the same behavior.

I think I copied everything exactly the way you did, so it should work the same. I wouldn’t know what to change anyway.

Found the issue! I am horrible at looking for things physically, and I guess that transfers over to code as well. Somehow this last line got duplicated in the switch.yaml file and it was for two different zones.

command_state: "python3 /config/HTD/htd-lync12.py query zone 10"
command_state: "python3 /config/HTD/htd-lync12.py query zone 9"

So that was causing the unexpected behavior. My guess is it was “inconsistent” as when zone 9 was on I would get different behavior as to when zone 9 was off.

Ha, I don’t even know what “do you expect a state as a condition” means! I’ll probably do it like i have my locks: at [time] set all locks to closed. Maybe with a scene? That’s what I did before. I do want to investigate node red at some point, perhaps this would be a good chance.

Edit: Also, any idea how to make a group of speakers in HA?

Oookay, I re-read the response and I realise now that you don’t run HA on a pi (that’s for your audio source).

Anyways…
Yeah, “proof-reading” is the bane of most HA issues, especially in the yaml configs (using tabs instead of spaces, not enough spaces, too many spaces etc :slight_smile: ) So always double check. As for a group of speakers, I’m not sure, but you can try adding an entry in the groups.yaml file as follows:

spkr_kitchen:
  name: Kitchen Speakers
  entities:
    - switch.speaker_zone1
    - switch.speaker_zone2

Obviously replace the entities with the entity names for your speakers :stuck_out_tongue:
then reload the groups.yaml in ha and see if you have a new entity called spkr_kitchen.
(Note I haven’t grouped any speakers yet)

Regarding my references to “expecting a state as a condition” I was referring to setting a condition on the automation that it would only fire if the speaker “switch” was on. for example.

I have one Pi that has HASS OS on it and one with Rasbian.

So the group thing worked. I was able to easily add it to my Lovelace card and even changed the icon to show multiple speakers.

I set up a super basic automation so that every night at midnight it’ll “activate” the scene that I saved with all the speakers off. What I need to do is figure out how to give me a notification if the speakers have been one for 3 hours or something. Or, better yet, somehow figure out how to tell HA if anyone is currently connected via AirPlay to Shair-port sync and if not, then ping me and let me know “Your speakers have been on for 10 minutes and aren’t being used.” or something like that. So much easier said than done though - I can’t even figure out how to move my shade groups from configuration.yaml to groups.yaml without it giving me an error. :stuck_out_tongue:

Okay so probably not to drag this thread out. I would suggest posting that as a new question in the forum as the main integration question has been sorted.

My thoughts would be having a wait action when a speaker turns on with a timeout of 3 hours (and continue on timeout) then when the wait expires send a notification. A choose action would probably work to allow a condition to test if the speaker is still on.

Best of luck :slight_smile:

So I just checked my error logs and it’s LOADED with errors from this HTD integration. Haven’t changed anything that I know of, everything is working as expected.

[Here is the fully error log.] (Home Assistant Error Logs with HTD integration · GitHub) You seen anything like this with your setup?

I do have that as well. Personally I ignore it but changing the polling interval (or disabling it and setting a polling interval through an automation) may help minimize it. It could be that the script isn’t getting a timely response from the controller and thus returning empty results.

this is awesome. i tried seeting it up. any reason it wont let me power on a zone?