Juke Audio Juke-8 (Development)

I just bought a Juke Audio Juke-8 (https://jukeaudio.com/) and asked them if there was an API.

There is, and jumping in the deep end to make this work with HA

What it is

An 8 zone amplifier from 4 sources. Each source can map to one or more zones, and each zone is a stereo independent amp with volume control.

Application

  • 8 rooms with stereo speakers wire to the amp
  • room audio can be played from the 4 sources
  • Room A can be playing from iPhone 1
  • Room B&C Can be playing from iPhone 2
  • Room D&E&F can be playing from AppleTV

Integration Goal

Have entities
Speaker_RoomA(-H)

  • On/Off
  • Source 1-4
  • Volume

If anyone has done this, please save me. If not, I will post progress.

3 Likes

How long did it take you to get a response on the API doc? I asked a few days ago.

The information I received from JUKE was

Toggling zones:
Path: …/zone_toggle.php
Method: POST
Parameters:

  • index: zone number minus 1
  • id (optional): Typically None, but for multi-juke systems, can replace this with the mac id of the juke of interest
  • power: power toggle for the zone. “on” will get flipped to “off” and “off” will get flipped to “on”
  • source: source to play to the zone specified in the ‘id’ field

Changing volume:
Path: …/commit_zone_volumes.php
Method: POST
Parameters:

  • data: a json string which consists of a list of dictionaries containing the following fields:
    • index: zone number minus 1
    • new_volume: volume to set to (0-100)
    • id (optional): Typically None, but for multi-juke systems, can replace this with the mac id of the Juke of interest

Sample:
To clear zone 1:
requests.post(‘http://juke.local/zone_toggle.php’, data={‘index’:0, ‘id’:‘None’, ‘power’:‘on’})

To set zone 2 to source 3:
requests.post(‘http://juke.local/zone_toggle.php’, data={‘index’:1, ‘id’:‘None’, ‘power’:‘off’, ‘source’:3})

To set zone 2 volume to 100%:
requests.post(‘http://juke.local/commit_zone_volume.php’, data=“[{‘index’:1, ‘new_volume’:100, ‘id’:‘None’})]”

Based on the above and help from many here, in the file configuration.yaml add


rest_command: !include rest.yaml

File rest.yaml


  # IP address for the Juke is needed, this configuration uses 10.10.10.13 
  # Setting outputs to source 1

   # name juke_{the source}_{output numner}_{off if it to be off}
  juke_s1_o1:
   # url of juke with zone_toggle.pho as the page
   url: http://10.10.10.13/zone_toggle.php
   # post to change
   method: post
   # format of the post
   content_type: "application/x-www-form-urlencoded"
   # Path: .../zone_toggle.php 
   # Method: POST 
   # Parameters: 
   # - index: zone number minus 1 
   # - id (optional): Typically None, but for multi-juke systems, 
   #   can replace this with the mac id of the juke of interest 
   # - power: power toggle for the zone. "on" will get flipped to "off" 
   #   and "off" will get flipped to "on" 
   # - source: source to play to the zone specified in the 'id' field 
   payload: 'index=0&id=None&power=off&source=1'

  juke_s1_o2:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=1&id=None&power=off&source=1'

  juke_s1_o3:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=2&id=None&power=off&source=1'

  juke_s1_o4:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=3&id=None&power=off&source=1'

  juke_s1_o5:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=4&id=None&power=off&source=1'

  juke_s1_o6:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=5&id=None&power=off&source=1'   

  juke_s1_o7:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=6&id=None&power=off&source=1'

  juke_s1_o8:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=7&id=None&power=off&source=1'

  # Setting outputs to source 2

   # name juke_{the source}_{output numner}_{off if it to be off}
  juke_s2_o1:
   # url of juke with zone_toggle.pho as the page
   url: http://10.10.10.13/zone_toggle.php
   # post to change
   method: post
   # format of the post
   content_type: "application/x-www-form-urlencoded"
   # Path: .../zone_toggle.php 
   # Method: POST 
   # Parameters: 
   # - index: zone number minus 1 
   # - id (optional): Typically None, but for multi-juke systems, 
   #   can replace this with the mac id of the juke of interest 
   # - power: power toggle for the zone. "on" will get flipped to "off" 
   #   and "off" will get flipped to "on" 
   # - source: source to play to the zone specified in the 'id' field 
   payload: 'index=0&id=None&power=off&source=2'

  juke_s2_o2:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=1&id=None&power=off&source=2'

  juke_s2_o3:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=2&id=None&power=off&source=2'

  juke_s2_o4:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=3&id=None&power=off&source=2'

  juke_s2_o5:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=4&id=None&power=off&source=2'

  juke_s2_o6:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=5&id=None&power=off&source=2'   

  juke_s2_o7:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=6&id=None&power=off&source=2'

  juke_s2_o8:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=7&id=None&power=off&source=2'

  # Setting outputs to source 3

   # name juke_{the source}_{output numner}_{off if it to be off}
  juke_s3_o1:
   # url of juke with zone_toggle.pho as the page
   url: http://10.10.10.13/zone_toggle.php
   # post to change
   method: post
   # format of the post
   content_type: "application/x-www-form-urlencoded"
   # Path: .../zone_toggle.php 
   # Method: POST 
   # Parameters: 
   # - index: zone number minus 1 
   # - id (optional): Typically None, but for multi-juke systems, 
   #   can replace this with the mac id of the juke of interest 
   # - power: power toggle for the zone. "on" will get flipped to "off" 
   #   and "off" will get flipped to "on" 
   # - source: source to play to the zone specified in the 'id' field 
   payload: 'index=0&id=None&power=off&source=3'

  juke_s3_o2:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=1&id=None&power=off&source=3'

  juke_s3_o3:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=2&id=None&power=off&source=3'

  juke_s3_o4:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=3&id=None&power=off&source=3'

  juke_s3_o5:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=4&id=None&power=off&source=3'

  juke_s3_o6:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=5&id=None&power=off&source=3'   

  juke_s3_o7:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=6&id=None&power=off&source=3'

  juke_s3_o8:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=7&id=None&power=off&source=3'

# Setting Output to source 4

# name juke_{the source}_{output numner}_{off if it to be off}
  juke_s4_o1:
   # url of juke with zone_toggle.pho as the page
   url: http://10.10.10.13/zone_toggle.php
   # post to change
   method: post
   # format of the post
   content_type: "application/x-www-form-urlencoded"
   # Path: .../zone_toggle.php 
   # Method: POST 
   # Parameters: 
   # - index: zone number minus 1 
   # - id (optional): Typically None, but for multi-juke systems, 
   #   can replace this with the mac id of the juke of interest 
   # - power: power toggle for the zone. "on" will get flipped to "off" 
   #   and "off" will get flipped to "on" 
   # - source: source to play to the zone specified in the 'id' field 
   payload: 'index=0&id=None&power=off&source=4'

  juke_s4_o2:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=1&id=None&power=off&source=4'

  juke_s4_o3:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=2&id=None&power=off&source=4'

  juke_s4_o4:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=3&id=None&power=off&source=4'

  juke_s4_o5:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=4&id=None&power=off&source=4'

  juke_s4_o6:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=5&id=None&power=off&source=4'   

  juke_s4_o7:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=6&id=None&power=off&source=4'

  juke_s4_o8:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=7&id=None&power=off&source=4'

  # Setting outputs to off

   # name juke_{the source}_{output numner}_{off if it to be off}
   # off will turn it off no matter the source, universal off
  juke_s1_o1_off:
   # url of juke with zone_toggle.pho as the page
   url: http://10.10.10.13/zone_toggle.php
   # post to change
   method: post
   # format of the post
   content_type: "application/x-www-form-urlencoded"
   # Path: .../zone_toggle.php 
   # Method: POST 
   # Parameters: 
   # - index: zone number minus 1 
   # - id (optional): Typically None, but for multi-juke systems, 
   #   can replace this with the mac id of the juke of interest 
   # - power: power toggle for the zone. "on" will get flipped to "off" 
   #   and "off" will get flipped to "on" 
   # - source: source to play to the zone specified in the 'id' field 
   payload: 'index=0&id=None&power=on&source=1'

  juke_o2_off:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=1&id=None&power=on&source=1'

  juke_o3_off:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=2&id=None&power=on&source=1'

  juke_o4_off:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=3&id=None&power=on&source=1'

  juke_o5_off:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=4&id=None&power=on&source=1'

  juke_o6_off:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=5&id=None&power=on&source=1'   

  juke_o7_off:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=6&id=None&power=on&source=1'

  juke_o8_off:
   url: http://10.10.10.13/zone_toggle.php
   method: post
   content_type: "application/x-www-form-urlencoded"
   payload: 'index=7&id=None&power=on&source=1'


then the part I got working, but do not understand

Now to automate the speakers. I wanted the JUKE AUDIO to set a configuration of speakers every time a specific media player played. I could not call the entities directly from a single automation. ( Please comment if you can explain )

You need one automation to track the media player, then another to react to the first.

Tracking Automation in automations.yaml (I built it in the GUI) and what is not clear below is that the target is the second automation. I the GUI it shows Home-Audio-Zone-Set as the target the configuration file uses the entity_id that was created when I started to hack this into existence.


- id: '1651508519857' # Home Audio Helper - track the media state
  alias: Home Audio Helper - track the media state
  description: This will track the state of the media player, then trigger the automation
    to turn on the JUKE Zones
  trigger:
  - platform: state
    entity_id: media_player.itunes
    to: playing
  condition: []
  action:
  - service: automation.trigger
    data: {}
    target:
      entity_id: automation.new_automation_2
  mode: single

The second automation to actually move the speakers to the right configuration in automations.yaml is

- id: '1651490678798' # Home-Audio-Zone-Set
  alias: Home-Audio-Zone-Set
  description: ''
  trigger: []
  condition: []
  action:
  # Kitchen
  - service: rest_command.juke_s4_o1
    data: {}
  # Dining Room
  - service: rest_command.juke_s4_o2
    data: {}
  # Office
  - service: rest_command.juke_o3_off
    data: {}
  # Basement
  - service: rest_command.juke_s3_o4
    data: {}
  # Front Porch
  - service: rest_command.juke_o5_off
    data: {}
  # Sunroom       
  - service: rest_command.juke_s4_o6
    data: {}
  # Back Deck
  - service: rest_command.juke_o7_off
    data: {}
1 Like

the next steps to the above would be to make an actual integration or some variables instead of discrete commands for each state.

that being said, once I got it working, the thrill is gone, and not sure when I might circle back.

Hope all this helps.

1 Like

I am trying to find a good multi room amp for my house. Have you been happy with the Juke-8 and have you gotten it well integrated into HA by now?

Following up, any updates on this or others with additional experience or input to share?

Amplipi has HA support and it has been rock solid. Pretty happy with the installation I did and it’s been very reliable.

Not sure how old the firmware is, but I was looking over firmware release notes and in 3.3.0 they have a note about accessing their swagger io RESTful service documentation. Very cool! nice to see this Juke! I presume the endpoints given to kcossabo (almost a year ago) are either legacy or user friendly endpoints. They have endpoints to fully control the device and is perfect for a full HA integration, unfortunately I wont have the bandwidth to write such integration for it.

The Developers over at JUKE wanted me to try the new REST API, but I have not had time. The old works, and well it is working.

I may get my head above water and play, but right now I have not played with he REST API

its pretty straightforward and works well. Here are the 3 that I use in my current configuration.

juke_post_input_restart:
  url: http://192.168.50.15/api/v1/inputs/{{ id }}/restart
  username: Admin
  password: Admin
  headers:
    accept: application/json
  method: POST
  content_type: application/x-www-form-urlencoded
juke_put_input_type:
  url: http://192.168.50.15/api/v1/inputs/{{ id }}/type
  username: Admin
  password: Admin
  headers:
    accept: application/json
  method: PUT
  content_type: application/x-www-form-urlencoded
  payload: type={{ type }}
juke_put_input_zones:
  url: http://192.168.50.15/api/v1/inputs/{{ id }}/zones
  username: Admin
  password: Admin
  headers:
    accept: application/json
  method: PUT
  content_type: application/json
  payload: "{{ zones }}"
juke_put_zone_volume:
  url: http://192.168.50.15/api/v1/zones/{{ id }}/volume
  username: Admin
  password: Admin
  headers:
    accept: application/json
  method: PUT
  content_type: application/x-www-form-urlencoded
  payload: volume={{ volume }}
juke_put_zone_input:
  url: http://192.168.50.15/api/v1/zones/{{ id }}/input
  username: Admin
  password: Admin
  headers:
    accept: application/json
  method: PUT
  content_type: application/json
  payload: "{{ input }}" #[] ['1']
juke_zone_toggle:
  url: http://192.168.50.15/zone_toggle.php
  method: POST
  content_type: "application/x-www-form-urlencoded"
  payload: "source={{ source }}&id={{ id }}&index={{ index }}&action={{ action }}"

I am stuck on getting the input ids

Using the built in API tool

curl -X GET "https://juke.local/api/v1/inputs/" -H "accept: application/json"

the response is;

{
  "input_ids": [
    "4"
  ]
}

I would expect an array of the names, like the ZONEs

{
  "zone_ids": [
    "B0B9A1-5C8-Z0",
    "B0B9A1-5C8-Z1",
    "B0B9A1-5C8-Z2",
    "B0B9A1-5C8-Z3",
    "B0B9A1-5C8-Z4",
    "B0B9A1-5C8-Z5",
    "B0B9A1-5C8-Z6",
    "B0B9A1-5C8-Z7"
  ]
}

I’m just an end-user but would love to see this working so I can add to home app via homebridge.

curl -X GET "https://juke.local/api/v1/inputs/" -H "accept: application/json"

This will give you

{
  "input_ids": [
    "1",
    "2",
    "3",
    "4"
  ]
}

The input id’s are not the same type of id’s as zone id’s, you are getting the right id’s. You can see in the swagger. https://juke.local/api/apidocs/#/inputs/get_api_v1_inputs_

I opened a ticket with JUKE, mine only returns

{
  "input_ids": [
    "4"
  ]
}

Welcome.

@seesoe is using the new API, I will switch when I work the bugs.

Right now though the JUKE Amp is working well with the old calls I posted above.

Home Assistant is very wordy, and I am still working through right process to do this, but now have an automation that when I want to listed to whole house audio;

  • set the outputs I want to the input I want on the JUKE
  • then set a Raspberry Pi with OwnTone to play a specific play list (off of my NAS) to the Airplay2 input on the Juke Amp

The automation so far is

- id: '1682867875027'
  alias: juke_house
  # this automation Apr 30, 2023 - turns on OnwTone sets the output to JUKE, and then sets Juke to all the right outputs.
  description: turn the Juke Amp inputs for normal home audio listening
  trigger: []
  condition: []
  action:
  - service: rest_command.juke_s4_o1
    data: {}
  - service: rest_command.juke_s4_o2
    data: {}
  - service: rest_command.juke_s4_o6
    data: {}
  - service: rest_command.juke_o3_off
    data: {}
  - service: rest_command.juke_o4_off
    data: {}
  - service: rest_command.juke_o5_off
    data: {}
  - service: rest_command.juke_o7_off
    data: {}
  - service: rest_command.juke_o8_off
    data: {}
  - service: media_player.turn_on
    data: {}
    target:
      entity_id: media_player.forked_daapd_output_juke2
  - service: media_player.select_source
    data:
      source: May2022 (playlist)
    target:
      entity_id: media_player.forked_daapd_server
  - service: media_player.shuffle_set
    data:
      shuffle: true
    target:
      entity_id: media_player.forked_daapd_server
  - service: media_player.media_play
    data: {}
    target:
      entity_id: media_player.forked_daapd_server
  mode: single

It is a bug, waiting for next release

Thanks for everyones work on this. I’d love to be able to use HA to yell through the speakers at my kids in other rooms of the house lol but not sure I’d be able to with my Juke…

Hey friends. I created a basic HACS integration for my Juke. You can add a custom repository in HACS using this repo: pkarimov/jukeaudio_ha: Custom Home Assistant integration for Juke Audio (github.com). It exposes each zone as a media player entity on which you can set the source and the volume.

Let me know if you hit issues or have any feedback or wishes. Work in progress :slight_smile:

1 Like

This is great, thanks for sharing Paul!! I’ve checked your repo, but not sure if I was able to find the answer to my question; apologies, I’m new to HA. Leveraging your integration, would it be possible to create an automation to play a voice announcement on all zones based on a trigger from another device, and then resume the music in those zones (if any was playing)?

For example, if my door sensor changes to “open” while music is playing in zones 1 and 2, the automation would pause the music, make an announcement that the door was opened in all zones, and then resume playback of the music in zones 1 and 2 shortly after the announcement. Would that be possible? Thanks in advance for your help. :slight_smile: Just seriously looking at buying a Juke, but need to know if it/your integration will support my use case before pulling the trigger. :slight_smile:

My integration can help there but it can’t do all of this on its own. What it can do is set the zones where you want to play the announcement to the input from which the announcement will come (from the inputs supported by the Juke) and then set them back to whatever input (if any) was playing music there before. You still need other components to be able to actually pause current music, play the announcement, and then resume music.