Lovelace: Forked daapd card

Lovelace: forked daapd card

This card is very niche, I made it mostly to cover my own needs, but thought I would share it anyway, hopefully someone can find it useful!

A lovelace card for Home Assistant to control a forked daapd instance.

This card allow you to control your forked daapd instance through Home Assistant.
The following controls are available: master volume, play/pause, next/previous, on/off, output selection, individual output volume.

Prerequisite

  • Forked daapd built with websocket support.
  • Forked daapd setup as an media_player (mpd component) in Home Assistant

Install

Simple install

  • Copy forked-daapd-card.js into your config/www ”folder.
  • Add a reference to the forked-daapd-card.js inside your ui-lovelace.yaml.
resources:
  - url: /local/forked-daapd-card.js?v=0.0.1
    type: module

Install using git

  • Clone this repository into your config/www folder using git.
git clone https://github.com/kalkih/forked-daapd-card.git
  • Add a reference to the card in your ui-lovelace.yaml.
resources:
  - url: /local/forked-daapd-card/forked-daapd-card.js?v=0.0.1
    type: module

Updating

  • Locate your forked-daapd-card.js in config/www or wherever you ended up storing it.
  • Replace it with the latest version of forked-daapd-card.js.
  • Add the new version number to the end of the cards reference url in your ui-lovelace.yaml like below.
resources:
  - url: /local/forked-daapd-card.js?v=0.0.1
    type: module

If you went the git clone route, just run git pull from inside your config/www/forked-daapd-card/ directory, to get the latest version of the code. Then add the new version number to the end of the card reference url in your ui-lovelace.yaml like below.

resources:
  - url: /local/forked-daapd-card/forked-daapd-card.js?v=0.0.1
    type: module

Using the card

Options

Name Type Default Since Description
type string required v0.0.1 custom:forked-daapd-card.
entity string required v0.0.1 The entity_id of your forked-daapd media_player (mpd) in home assistant.
ip string required v0.0.1 Set the IP address of your forked-daapd server.
port number 3689 v0.0.1 Set the port of your forked-daapd server.
ws_port number 3688 v0.0.1 Set the websocket port of your forked-daapd server.
name string optional v0.0.1 Set a custom friendly_name which is displayed beside the icon.
icon string optional v0.0.1 set a custom icon from any of the available mdi icons.
outputs list optional v0.0.1 If you want to only show specific outputs, include the id of each one in the list.
  • You can find the outputs ids by accessing http://<forked-daapd-ip>:<port>/api/outputs

Example usage

Normal

- type: "custom:forked-daapd-card"
  entity: media_player.multiroom_audio
  ip: "192.168.1.5"
  name: Multiroom

Show only specified outputs

- type: "custom:forked-daapd-card"
  entity: media_player.multiroom_audio
  ip: "192.168.1.5"
  name: Multiroom
  outputs:
    - "225176710053082"
    - "962995053492"
    - "24918234768"

Getting errors?

Make sure you have javascript_version: latest in your configuration.yaml under frontend:.

Make sure you have the latest versions of forked-daapd-card.js.

If you have issues after updating the card, try clearing your browser cache.

License

This project is under the MIT license.

7 Likes

Thanks a lot Kalkih,
It’s working very goodbut i have one problem, i don’t understand how to get id’s from my google home speaker.
I don’t know what port i need to fill in:

http://<Google Home IP>:<port>/api/outputs

Can you please help.
Thanks.

Hey!

The address should be to your forked-daapd server, not your Google Home.

http://<forked-daapd-ip>:<port>/api/outputs

Example:

http://192.168.1.5:3689/api/outputs

You’ll get a list of all outputs indexed by your forked daapd server.

Well damn, now I have another project for myself, slapping your other media player card on top of this one

1 Like

This looks great and would be very useful for me! (I’ve been putting off hacking together something like this for a while now). I had a go at setting it up with my own forked-daapd server, unfortunately I don’t get any outputs listed with the below config (should it include all by default?).

  - type: "custom:forked-daapd-card"
    entity: media_player.mpd
    ip: "10.1.0.5"
    name: Multiroom

I’ve made sure I have Home Assistant listed as part of my trusted networks in forked-daapd.

image

The results of http://10.1.0.5:3689/api/outputs are:

{ "outputs": [ { "id": "132116594556980", "name": "Bedroom", "type": "AirPlay", "selected": true, "has_password": false, "requires_auth": false, "needs_auth_key": false, "volume": 37 }, { "id": "71243858016208", "name": "Living Room", "type": "AirPlay", "selected": false, "has_password": false, "requires_auth": true, "needs_auth_key": false, "volume": 45 }, { "id": "203920983312531", "name": "MusicPi", "type": "AirPlay", "selected": false, "has_password": false, "requires_auth": false, "needs_auth_key": false, "volume": 56 }, { "id": "82372667526045", "name": "MusicPi-Shed", "type": "AirPlay", "selected": false, "has_password": false, "requires_auth": false, "needs_auth_key": false, "volume": 100 }, { "id": "0", "name": "Computer", "type": "ALSA", "selected": false, "has_password": false, "requires_auth": false, "needs_auth_key": false, "volume": 50 } ] }

Any ideas?

It’d also be great if you could set up your repo to work with Custom Updater :slight_smile:

Did you build your forked daapd with websocket support? or if you use a websocket port other than 3688 specify it with the ws_port option.

Otherwise I would check the browsers developer console for clues, and let me know if anything shows up there. :slight_smile:

Yes, all outputs should indeed show up by default if no outputs list is provided!

Probably won’t update this card much, but sure, will add it in next release!

1 Like

Yep, I just rebuilt it with websocket support for this - still using the default ports.

Thanks for the tip about the console, I’m getting the below errors whenever I expand it, which looks to be something unhappy with using this behind HTTPS:

Aah, yeah that’s the issue, I think you could try building forked-daapd with ssl support if you haven’t already (build flag --with-ssl=openssl).

and change line 87 in forked-daapd-card.js:

this.ws = new WebSocket('ws://' + this.config.ip + ':' + this.config.ws_port, 'notify');

to

this.ws = new WebSocket('wss://' + this.config.ip + ':' + this.config.ws_port, 'notify');

and line 95:

const resp = await fetch('http://' + this.config.ip + ':' + this.config.port + '/api/outputs');

to

const resp = await fetch('https://' + this.config.ip + ':' + this.config.port + '/api/outputs');

I’m not sure if this works but please let me know if it does and I’ll add an SSL config option.

Thanks, I did try changing your js file manually before. I wasn’t aware of the forked-daapd ssl build option, so have rebuilt with that and had to increment the version number too. Different error now, but still nothing showing though.

This is how I built forked-daapd

 ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --with-libwebsockets --enable-chromecast --enable-spotify --with-ssl=openssl

I also tested it was working okay with HTTP internally before, but now the HTTP access shows this same error.

Seeing the same error as you in console for the card (and have not made the ssl changes above).
Does not show up the outputs even though they are there.

Using this docker image which is built with websockets on default port https://hub.docker.com/r/linuxserver/daapd/

forked-daapd-card.js?v=0.0.1:87 WebSocket connection to 'ws://192.168.1.4:3688/' failed: Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT

||_initSocket|@|forked-daapd-card.js?v=0.0.1:87|
| --- | --- | --- | --- |
||shouldUpdate|@|forked-daapd-card.js?v=0.0.1:81|
||_validate|@|updating-element.ts:515|
||_invalidate|@|updating-element.ts:498|

Hmm, I found that build flag from a quick google, maybe ssl isn’t supported or not working properly. Can you access your forked-daapd interface through https?
It’s possible that some headers are needed for the SSL connection.

The error message tells me that the browser isn’t able to connect to forked-daapd via WebSockets. If you are sure it’s built with WebSockets make sure that the WebSocket port is exposed and accessible from outside of the docker container.

You can test the daapd WebSocket connection from your terminal with the following command (obviously change ip and port to match your setup):

curl --include \
     --no-buffer \
     --header "Connection: Upgrade" \
     --header "Upgrade: websocket" \
     --header "Host: localhost:3688" \
     --header "Origin: http://localhost:3688" \
     --header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
     --header "Sec-WebSocket-Version: 13" \
     --header "Sec-WebSocket-Protocol: notify" \
     http://localhost:3688/ \
     --data "{ \"notify\": [ \"player\" ] }"

ok, yes, it appears that eventhough websockets is enabled and the docker container is in host mode, its refusing the connection.

[admin@dockerhost ~]$ curl --include      --no-buffer      --header "Connection: Upgrade"      --header "Upgrade: websocket"      --header "Host: 192.168.1.4:3688"      --header "Origin: http://192.168.1.4:3688"      --header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ=="      --header "Sec-WebSocket-Version: 13"      --header "Sec-WebSocket-Protocol: notify"      http://192.168.1.4:3688/      --data "{ \"notify\": [ \"player\" ] }"
curl: (7) Failed connect to 192.168.1.4:3688; Connection refused

forked-daapd.conf has 3688 as websocket port
And netstat shows its listening on ports 3689 and 3688

[admin@dockerhost ~]$ netstat -tulpn | grep :3689
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:3689            0.0.0.0:*               LISTEN      5965/forked-daapd
[admin@dockerhost ~]$ netstat -tulpn | grep :3688
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:3688            0.0.0.0:*               LISTEN      5965/forked-daapd
udp6       0      0 :::36889                :::*                                -
[admin@dockerhost ~]$

This is driving me nuts!

Docker log showing websocket enabled

[s6-init] making user provided files available at /var/run/s6/etc...exited 0.

[s6-init] ensuring user provided files have correct perms...exited 0.


[fix-attrs.d] applying ownership & permissions fixes...


[fix-attrs.d] done.


[cont-init.d] executing container initialization scripts...


[cont-init.d] 10-adduser: executing... 




-------------------------------------


          _         ()


         | |  ___   _    __


         | | / __| | |  /  \ 


         | | \__ \ | | | () |


         |_| |___/ |_|  \__/






Brought to you by linuxserver.io


We gratefully accept donations at:


https://www.linuxserver.io/donate/


-------------------------------------


GID/UID


-------------------------------------




User uid:    1000


User gid:    1000


-------------------------------------




[cont-init.d] 10-adduser: exited 0.


[cont-init.d] 30-dbus: executing... 


[cont-init.d] 30-dbus: exited 0.


[cont-init.d] 40-config: executing... 


[cont-init.d] 40-config: exited 0.


[cont-init.d] done.


[services.d] starting services


[services.d] done.


Failed to set ownership on logfile: Operation not permitted


[  LOG]     main: Forked Media Server Version 26.4 taking off


[  LOG]     main: Built with:


[  LOG]     main: - ffmpeg


[  LOG]     main: - iTunes XML


[  LOG]     main: - LastFM


[  LOG]     main: - Chromecast


[  LOG]     main: - MPD


[  LOG]     main: - Device verification


[  LOG]     main: - Websockets


[  LOG]     main: - ALSA


[  LOG]     main: - Webinterface


[  LOG]     main: mDNS init


[  LOG]     mdns: Avahi state change: Client connecting


[  LOG]       db: Configured to use database file '/config/dbase_and_logs/songs3.db'


[  LOG]       db: Now vacuuming database, this may take some time...


[  LOG]       db: Database OK with 6844 active files and 7 active playlists


[  LOG]     mdns: Failed to create service browser: Bad state


[  LOG]     raop: Could not add mDNS browser for AirPlay devices


[  LOG]     mdns: Failed to create service browser: Bad state


[  LOG]     cast: Could not add mDNS browser for Chromecast devices


[  LOG]     mdns: Failed to create service browser: Bad state


[FATAL]   remote: Could not browse for Remote services


[FATAL]     main: Remote pairing service failed to start


[  LOG]     main: MPD deinit


[  LOG]     main: HTTPd deinit


Found user 'avahi' (UID 86) and group 'avahi' (GID 86).


Successfully dropped root privileges.


avahi-daemon 0.7 starting up.


WARNING: No NSS support for mDNS detected, consider installing nss-mdns!


Loading service file /etc/avahi/services/sftp-ssh.service.


Loading service file /etc/avahi/services/ssh.service.

Looks like maybe it’s an old option as I can’t find any current documentation around it. There’s no mention of it in the forked-daapd config and I can’t access the API json pages over HTTPS so doesn’t look promising doing it this way. As it’s trying to access an internal IP externally, it might require pulling the data/controls through a custom component rather than trying to display them directly through the browser? Unless there’s some way to route the requests to come from Home Assistant internally, rather than the user’s browser?

I’m not that comfortable with docker but are you running the netstat command outside of the docker container?
You could try to manually expose the port maybe?

Yeah, unfortunately that might be the case.

As you said, running all communication through a forked daapd component would be much preferred and would also solve the issues you are having.
This card is not a perfect solution and is kinda “cheating”, the browser should not directly handle communication with devices, that should go through the backend components.

yes, running it on the host outside the container.
Have tried the non host route exposing ports, will give it a go again.

Let me know how it goes :+1:

Hi, great looking plugin!

I am also having ssl problems when accessing home assistant through https and outside the lan.

Do you think it is possible with your plugin? I tried using a nginx proxy for the websockets but did not figure it out.

Thanks