Webradio via MQTT Discovery op Home Assistant

NAIM Uniti Atom

Sinds een aantal jaren ben ik in het bezit van een NAIM Uniti Atom streaming versterker, een compact apparaat met een fantastische geluidskwaliteit.

Dit apparaat heeft geen 'normale' radio, maar gebruikt internet om radiozenders te streamen. Daarnaast heeft het nog een aantal andere digitale en analoge ingangen.
Ik kan dit apparaat besturen via een afstandsbediening of een app op mijn smartphone, maar natuurlijk zocht ik ook een manier om dit aan mijn domotica te koppelen.

Helaas bleek bij een zoektocht op internet dat door NAIM niet echt wordt gestimuleerd om dit te doen, de informatie die ik vond was vaag en beperkt. Wat ik wel ontdekte was dat de streamer via een URL zonder authenticatie was te benaderen, en dat hiermee alle instellingen en informatie was op te vragen.

Alles was in JSON formaat, dus dit stemde me hoopvol, ik had al wat ervaring met het omzetten van en naar JSON via diverse Python scripts.

Status opvragen

Even een voorbeeld: om de huidige status van de streamer op te vragen, kun je de het ip-adres van de streamer opgeven met de toevoeging 'nowplaying':

http://<ip-adres streamer>:15081/nowplaying:

{
  "version": "1.4.0",
  "changestamp": "0",
  "name": "Now Playing",
  "ussi": "nowplaying",
  "class": "object.nowplaying",
  "artwork": "https://media.focal-naim.com/app/images/stations/2822.png",
  "artworkSource": "https://media.focal-naim.com/app/images/stations/2822.png",
  "bitDepth": "16",
  "bitRate": "830637",
  "canResume": "1",
  "channels": "2",
  "codec": "FLAC",
  "contentTag": "naim.vtuner.24069",
  "country": "United States",
  "cpu": "2187",
  "error": "0",
  "favouriteUssi": "inputs/radio/djF8dnR1bmVyOlAxTnZZMmxoYkVaaVBXaDBkSEJ6T2k4dmQzZDNMbVpoWTJWaWIyOXJMbU52YlM5U1lXUnBiMUJoY21Ga2FYTmxKbE52WTJsaGJFbHVKbE52WTJsaGJGUjNQV2gwZEhCek9pOHZkM2QzTG5SM2FYUjBaWEl1WTI5dEwzSmhaR2x2Y0dGeVlXUnBjMlVtVTNSaGRHbHZia2xrUFRJNE1qSW1VM1J5WldGdFNXUTlNalF3TmprbVdIQmxjbWxKUkNaWWNHVnlhVTF4UlhoamFDWlljR1Z5YVUxeFVrc21XSEJsY21sTmNWVnliQ1pZY0dWeWFVNVFSR1ZzWVhrbWFYUmxiVUpwZEhKaGRHVTlNVEF3TUNacGRHVnRRbTl2YTIxaGNtczlhSFIwY0hNNkx5OXlZV1JwYjJWMUxtNWhhVzFoZFdScGJ5NWpiMjB2WVhCcEwybHlMMlZ0Y0hSNVAyVnRjSFI1SlRORUptbDBaVzFDYjI5cmJXRnlhMU5vYjNjbWFYUmxiVU52YlcxbGJuUW1hWFJsYlVkbGJuSmxQVVZqYkdWamRHbGpKVEl3Sm1sMFpXMUlWVkpNUFdoMGRIQnpPaTh2ZDNkM0xuSmhaR2x2Y0dGeVlXUnBjMlV1WTI5dEx5WnBkR1Z0VEc5allYUnBiMjQ5Vlc1cGRHVmtKVEl3VTNSaGRHVnpKbWwwWlcxTWIyZHZQV2gwZEhCek9pOHZjbUZrYVc5bGRTNXVZV2x0WVhWa2FXOHVZMjl0TDJGd2FTOXBiV2N2YzNSaGRHbHZiaTh5T0RJeUxuQnVaeVpwZEdWdFRtRnRaVDFTWVdScGJ5VXlNRkJoY21Ga2FYTmxKVEl3TFNVeU1FMWhhVzRsTWpCTmFYZ2xNakJJUkNacGRHVnRVbTkzUFRBbWFYUmxiVlI1Y0dVOVUzUmhkR2x2YmlacGRHVnRWWEpzUFdoMGRIQnpPaTh2Y21Ga2FXOWxkUzV1WVdsdFlYVmthVzh1WTI5dEwyRndhUzlwY2k5emRHRjBhVzl1YzNSeVpXRnRQMmxrSlRORU1qUXdOamtsTWpadFlXTmhKVE5FWTJFM1l6VXhNMlJrTXpCak5qTTJaVFV4Tm1RMllqSXdNMlU0WVRObU1HTXwyNDA2OQ==",
  "genre": "Eclectic ",
  "live": "1",
  "mimeType": "audio/unknown",
  "presetID": "36",
  "repeat": "0",
  "restrictPause": "128",
  "restrictPeekNext": "128",
  "restrictPeekPrev": "128",
  "restrictResume": "0",
  "restrictSeek": "128",
  "restrictSkipNext": "128",
  "restrictSkipPrev": "128",
  "restrictStop": "0",
  "sampleRate": "44100",
  "shuffle": "0",
  "socialFB": "https://www.facebook.com/RadioParadise",
  "socialUrl": "https://www.radioparadise.com/",
  "socialX": "https://www.twitter.com/radioparadise",
  "source": "inputs/radio",
  "sourceMultiroom": "inputs/none",
  "station": "Radio Paradise - Main Mix",
  "stationId": "djF8dnR1bmVyOlAxTnZZMmxoYkVaaVBXaDBkSEJ6T2k4dmQzZDNMbVpoWTJWaWIyOXJMbU52YlM5U1lXUnBiMUJoY21Ga2FYTmxKbE52WTJsaGJFbHVKbE52WTJsaGJGUjNQV2gwZEhCek9pOHZkM2QzTG5SM2FYUjBaWEl1WTI5dEwzSmhaR2x2Y0dGeVlXUnBjMlVtVTNSaGRHbHZia2xrUFRJNE1qSW1VM1J5WldGdFNXUTlNalF3TmprbVdIQmxjbWxKUkNaWWNHVnlhVTF4UlhoamFDWlljR1Z5YVUxeFVrc21XSEJsY21sTmNWVnliQ1pZY0dWeWFVNVFSR1ZzWVhrbWFYUmxiVUpwZEhKaGRHVTlNVEF3TUNacGRHVnRRbTl2YTIxaGNtczlhSFIwY0hNNkx5OXlZV1JwYjJWMUxtNWhhVzFoZFdScGJ5NWpiMjB2WVhCcEwybHlMMlZ0Y0hSNVAyVnRjSFI1SlRORUptbDBaVzFDYjI5cmJXRnlhMU5vYjNjbWFYUmxiVU52YlcxbGJuUW1hWFJsYlVkbGJuSmxQVVZqYkdWamRHbGpKVEl3Sm1sMFpXMUlWVkpNUFdoMGRIQnpPaTh2ZDNkM0xuSmhaR2x2Y0dGeVlXUnBjMlV1WTI5dEx5WnBkR1Z0VEc5allYUnBiMjQ5Vlc1cGRHVmtKVEl3VTNSaGRHVnpKbWwwWlcxTWIyZHZQV2gwZEhCek9pOHZjbUZrYVc5bGRTNXVZV2x0WVhWa2FXOHVZMjl0TDJGd2FTOXBiV2N2YzNSaGRHbHZiaTh5T0RJeUxuQnVaeVpwZEdWdFRtRnRaVDFTWVdScGJ5VXlNRkJoY21Ga2FYTmxKVEl3TFNVeU1FMWhhVzRsTWpCTmFYZ2xNakJJUkNacGRHVnRVbTkzUFRBbWFYUmxiVlI1Y0dVOVUzUmhkR2x2YmlacGRHVnRWWEpzUFdoMGRIQnpPaTh2Y21Ga2FXOWxkUzV1WVdsdFlYVmthVzh1WTI5dEwyRndhUzlwY2k5emRHRjBhVzl1YzNSeVpXRnRQMmxrSlRORU1qUXdOamtsTWpadFlXTmhKVE5FWTJFM1l6VXhNMlJrTXpCak5qTTJaVFV4Tm1RMllqSXdNMlU0WVRObU1HTXwyNDA2OQ==",
  "stationKey": "24069",
  "streamDomain": "",
  "streamMessage": "",
  "title": "Genesis - The Carpet Crawlers",
  "transportPosition": "631025",
  "transportState": "2" 

Dit geeft al een schat aan informatie, die ik dan ook kon uitlezen via Python:

#!/usr/bin/python3
# coding=utf-8

import requests, json

base_url='http://<ip-adres uniti>:15081'
SongData = {}

r = requests.get(base_url+'/nowplaying')
SongData["title"] = (r.json()['title'])

Instellingen wijzigen

Om instellingen te wijzigen, gebruik je andere URLs, zoals:

http://<ip-adres uniti>:15081/power

http://<ip-adres uniti>:15081/inputs

http://<ip-adres uniti>:15081/levels/room

http://<ip-adres uniti>:15081/favourites

Zo kun je bijvoorbeeld het volume opvragen door een 'HTTP GET':

r = requests.get(base_url+'/levels/room')
volume =  r.json()['volume']

En deze kun je wijzigen door de volgende 'put' actie in Python:

requests.put(base_url+'/levels/room?volume={value}'.format(value=volume))

Het vreemde is wel, dat sommige acties met een 'HTTP PUT' actie worden ingesteld, en andere met een 'HTTP GET':

requests.get(base_url+'/inputs/'+input+'?cmd=select')

Op deze manier kon ik de volgende zaken instellen:

  • volume
  • ingang
  • favoriet (bv. radiostation)
  • modus: aan of standby
Een van de grappige zaken was dat de waarden voor de modus bestonden uit 'on' en 'lona'. Wat 'lona' precies betekent weet ik niet…

Python Programma opbouw


Mijn programma werd dan als volgt opgebouwd:
  • Stuur de MQTT Discovery configs voor de volgende items:
    • status (de status van het programma)
    • power (de status van de streamer)
    • scene (de favorieten/radiostations)
    • sensors (cpu temperature sensor van de raspberry pi waarop het programma draait)
    • select (de geselecteerde favoriet)
    • select_inputs (de geselecteerde ingang)
    • sensor voor volume
    • instelling voor volume
    • button voor mute
    • button voor power
    • button voor play/pause
    • sensors voor 'songdata', zoals Artiest, Nummer, etc.
  • Stuur de huidige waarden voor de sensoren
  • Wacht op een commando voor het aanpassen van:
    • mute status
    • play/pause modus
    • power modus
    • favoriet/radiostation
    • volume
    • ingang
  • Als er een commando komt, voer dit uit
  • Blijf periodiek de waarden doorsturen

Resultaat in Home Assistant


In Home Assistant ziet dat er dan als volgt uit:


Issues

Een van de zaken die ik tegenkwam is het probleem dat er geen standaard manier is waarop de radiostations hun informatie sturen: meestal is er wel een plaatje en de naam van het radiostation, maar andere informatie, zoals het huidige nummer, wordt niet altijd doorgegeven. Ook is het formaat soms anders: in bovenstaand voorbeeld wordt door het radiostation bijvoorbeeld alleen de 'title' doorgegeven, geen andere info. Bij streamen vanuit een streaming service (Spotify, Tidal, etc.) wordt meestal wel de volledig info weergegeven: Artiest, Album, Titel.








Reacties

Populaire posts van deze blog

Deurbel

Een airco gebruiker als verwarming