SpeakerCraft MZC Control

First off let me apologize if this is not the correct location for this question, it seemed like the best option to me.
I have a SpeakerCraft MZC-66 System that I refurbished the amp cards on and learned how to program and set up. This is a pretty decent multi-zone distributed audio setup (think before the time of Sonos) and I have a SpeakerCraft MODE ERS-1.0 Kit that allows me to control it from an app or a web page. I just upgraded my phone and the app is no longer available, bummer, but I can still use the web page. I’m wanting to be able to put this in my Home Assistant setup BUT the code in the ERS-1.0 does a check for user agent so when I try to iframe it, it doesn’t work. I’m also using NGINX too if it matters.

Is there anyone out there that has a similar setup and has gotten something working? Ideally, I’d like to be able to pull some of the data from this device and not use re-display it’s clunky interface, but redesign my own.

Thoughts?

TLDR version:

Summary of current status of this thread.

This thread is complex as it discusses a number of different approach to Speakercraft integration.

The currently progressing options are;

GitHub

GitHub - mattsaxon/HASS-SpeakercraftMediaPlayer: Speakercraft Platform for…

Speakercraft Platform for Home Assistant. Contribute to mattsaxon/HASS-SpeakercraftMediaPlayer development by creating an account on GitHub.

The code uses a direct serial connection from HA to Speakercraft MZC. It is under active development.

GitHub

GitHub - sjeffrey101/homeassistant_speakercraft: Media player custom…

Media player custom component which works with MQTT. I designed this to specifically work with a ESP32 which i used to control a speakercraft amp. - GitHub - sjeffrey101/homeassistant_speakercraft…

This code uses an MQTT connection from HA to the MZC via an ESP32 providing the remote serial connection. It is working, but not under active development. It is hoped to include the remote capabilities into the first approach in the future.

Neither of these component shows up as an “integration”, you install the component via HACS and edit configuration.yaml.

If you have issues with either of these specific integrations, please post direct to the GitHub issues pages as community pages are not ideal for complex threaded conversations

In addition to these 2 components, there are 2 discontinued approaches;

  1. A NodeRed prototype implementation - this has been discontinued in favour of the direct approach
  2. A REST API approach using an MZC add-on - this has also been discarded in favour of the MQTT approach

So here is what I could figure out so far (if there is anyone out there that cares).

In my rest_commands.yaml file I added these lines which can be used to send the commands to the MODE ERS

  line_1_select:
    url: http://192.168.1.254/SelLine0.htm
  line_2_select:
    url: http://192.168.1.254/SelLine1.htm
  line_3_select:
    url: http://192.168.1.254/SelLine2.htm
  line_4_select:
    url: http://192.168.1.254/SelLine3.htm
  line_5_select:
    url: http://192.168.1.254/SelLine4.htm
  line_6_select:
    url: http://192.168.1.254/SelLine5.htm

  menu:
    url: http://192.168.1.254/SelMenuBk.htm
    
  vol_up:
    url: http://192.168.1.254/SelVolUp.htm
  vol_down:
    url: http://192.168.1.254/SelVolDn.htm
  mute:
    url: http://192.168.1.254/SelMute1.htm

  power_on:
    url: http://192.168.1.254/SelPwr1.htm
  power_off:
    url: http://192.168.1.254/SelPwr0.htm

  play:
    url: http://192.168.1.254/SelPlyTr.htm
  pause:
    url: http://192.168.1.254/Pause.htm
    
  next_track:
    url: http://192.168.1.254/SelNxtTr.htm
  prev_track:
    url: http://192.168.1.254/SelPrvTr.htm

Then I added these to the scripts.yaml:

mzc_line_1_select:
#  alias: MCZ Line 1
  sequence:
    - service: rest_command.line_0_select

mzc_line_2_select:
#  alias: MCZ Line 2
  sequence:
    - service: rest_command.line_1_select

mzc_line_3_select:
#  alias: MCZ Line 3
  sequence:
    - service: rest_command.line_2_select

mzc_line_4_select:
#  alias: MCZ Line 4
  sequence:
    - service: rest_command.line_3_select

mzc_line_5_select:
#  alias: MCZ Line 5
  sequence:
    - service: rest_command.line_4_select

mzc_line_6_select:
#  alias: MCZ Line 6
  sequence:
    - service: rest_command.line_5_select


mzc_menu:
#  alias: MZC Menu
  sequence:
    - service: rest_command.menu
    
mzc_vol_up:
#  alias: MZC Volume Up
  sequence:
    - service: rest_command.vol_up

mzc_vol_down:
#  alias: MZC Volume Down
  sequence:
    - service: rest_command.vol_down

mzc_mute:
#  alias: MZC Mute
  sequence:
    - service: rest_command.mute


mzc_power_on:
#  alias: MZC Power On
  sequence:
    - service: rest_command.power_on

mzc_power_off:
#  alias: MZC Power Off
  sequence:
    - service: rest_command.power_off

mzc_play:
#  alias: MZC Play
  sequence:
    - service: rest_command.play

mzc_pause:
#  alias: MZC Pause
  sequence: 
    - service: rest_command.pause

    
mzc_next_track:
#  alias: MZC Next Track
  sequence:
    - service: rest_command.next_track

mzc_prev_track:
#  alias: MZC Previous Track
  sequence:
    - service: rest_command.prev_track

Finally I made a card that uses these commands:

title: MZC
icon: mdi:speaker
cards:

 - type: vertical-stack
   cards:
   
    - type: picture
      image: /local/speakercraft_BW.png
  
    - type: horizontal-stack
      cards:
      #Kitchen
       - type: entity-button
         icon: mdi:stove
         entity: script.mzc_line_1_select
         name: "Kitchen"
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_line_1_select
            
      #Deck
       - type: entity-button
         icon: mdi:beer
         entity: script.mzc_line_2_select
         name: "Deck"
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_line_2_select

      #Patio
       - type: entity-button
         icon: mdi:shovel
         entity: script.mzc_line_4_select
         name: "Patio"
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_line_4_select

      #Front
       - type: entity-button
         icon: mdi:car-side
         entity: script.mzc_line_6_select
         name: "Front"
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_line_6_select


    - type: horizontal-stack
      cards:
      #Menu
       - type: entity-button
         entity: script.mzc_menu
         icon: mdi:menu
         name: "Menu"
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_menu
            
      #Receiver
       - type: entity-button
         icon: mdi:television-classic
         entity: script.mzc_line_1_select
         name: 'TV'
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_line_1_select

      #Ipod
       - type: entity-button
         icon: mdi:ipod
         entity: script.mzc_line_3_select
         name: 'iPod 1'
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_line_3_select

      #Ipod2
       - type: entity-button
         icon: mdi:ipod
         entity: script.mzc_line_5_select
         name: 'iPod 2'
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_line_5_select

    - type: horizontal-stack
      cards:
      #Skip Back
       - type: entity-button
         entity: script.mzc_prev_track
         icon: mdi:skip-previous
         name: " "
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_prev_track
              
      # Play/Pause
       - type: entity-button
         entity: script.mzc_play
         icon: mdi:play-pause
         name: " "
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_play


      # Skip Forward
       - type: entity-button
         entity: script.mzc_next_track
         icon: mdi:skip-next
         name: " "
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_next_track
        
    - type: horizontal-stack
      cards:
      # Vol Down
       - type: entity-button
         entity: script.mzc_vol_down
         icon: mdi:volume-minus
         name: " "
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_vol_down

      #Mute
       - type: entity-button
         entity: script.mzc_mute
         icon: mdi:volume-off
         name: " "
         tap_action:
           action: call-service
           service: script.turn_on
           service_data:
             entity_id: script.mzc_mute

      #Vol Up
       - type: entity-button
         entity: script.mzc_vol_up
         icon: mdi:volume-plus
         name: " "
         tap_action:
           action: call-service
           service: script.mzc_vol_up

    - type: entities
      entities:
        - type: weblink
          name: MZC Audio
          url: http://192.168.1.254/
          icon: mdi:speaker

The issue I can’t seem to figure out is that for this to work, I need to have accessed the regular website first and then it will control for that zone only. It seems like it has some kind of cashed version of what was accessed last. This is pretty good for now but a little hard to explain to my wife on why she has to do some things some ways.

The next step would be to pull the information from the frames of the ERS web page and have them displayed inside home assistant. iframe won’t work for me since it’s http only.

Hi. Did you have any more luck with this?

I’ve just picked up an mzc-64 on ebay for £30 to play around with, with the goal of not using any of the dated wall pads to control it

Did you get the ERS as well for the web control? What about the programming software? I was never really able to the web part dialed in how I wanted to. It seems like there is a session that needs to be started before any of my web commands would work.

One thing you could do is to hack into one of the keypads and use something like an ESP32 to simulate the button presses. But you’ll need the software to program the MAC as well. You can find it with some creative googling.

How did you get on with this? I have a MZC-66 and was thinking of using RS232 via the 3.5mm Control Jack that is used to configure the system via EZ Tools. I seem to have all the tools and documentation to support this, has anyone considered this approach?

Hi, I have a prototype working using NodeRed and RS232 communications if anyone is interested.

I never really got back to working on this. It works ok if I first view in browser but still to hit and miss for the family. I don’t use NodeRed now (was concerned about the security rating) but I’d be interested in your project.

OK, I can export the NodeRed config here if you’d like.

It’s specific to my config, but I think you’d be able to amend it fairly easily for yours.

There’s 2 issues at the moment that I’m looking at and I believe they are both related to an issue in NodeRed Serial Port that needs to support software flow control. See issue I raised today Software Flow Control to be added to nodered-node-serialport - Feature Requests - Node-RED Forum

However in the meantime I have a workaround for this which makes it fairly usable. Tinkering needs to happen at each home assistant hardware restart.

Your nodered install needs this in the configuration

npm_packages:
  - node-red-node-serialport

You will also need something like this in your configuration.yaml

  - platform: serial
    serial_port: /dev/ttyUSB0
    name: speakercraft
    baudrate: 57600
    xonxoff: true

this pertains to the hack I refer to previously. This turns on flow control for NodeRed (believe it or not). Whilst you will get an error when both NodeRed flow is running and this sensor is running, this will ‘trick’ node red into behaving ‘better’. This is why home assistant needs restarting after nodered starts, so this setting takes precedence over the NodeRed serial port which doesn’t have xonxoff setting which enables software flow control. Note there are other hardware modules for the MZC that don’t need software flow control, I don’t know if you have this, but I don’t.

Obviously this is not ideal and I’m working to fix this

NodeRed flow is here https://github.com/mattsaxon/node-red-serial-speakercraft/blob/b95674eb98b33b8869651685f2a8b2bd403265c8/speakercraftflow.json

So the hardware for this is the box your HA instance is on then? I’m on a Pi 3B+ not a regular PC. I’m wondering if there is a way to use something like an ESP to issue the commands?

Yes, that the way I run it, I have a Pi3B+ also, which sits next to the Speakercraft amp and also runs Node Red Add-on.

I’m sure it would be possible to do what you describe, but haven’t had the need.

Hi, just spotted this thread.

ive been running an ESP32 as a speakcraft to MQTT broker. It listens on the serial port (control port) for status updates then sends all the status’ to mqtt. It also responds to commands and sends them to speaker craft in the command window.

Ive quickly uploaded my code to githum incase you want to look and amend. first time using github, hhopefuly its ok. Also i coded it quite a while ago so memory is a little foggy now.

but this hasnt failed at all for probably a couple of years.

Here on github

let me know if its any help.

1 Like

Can you link to the ESP32 serial port adapter you used? This is exactly the solution I’ve been looking for.

Thanks for sharing the info. I’ve done a bunch of things with ESPHOME but haven’t loaded anything manually since I discovered that. I just got my ESP32 from the Bezos’ family store so I’ll have a nice project to play with over Christmas. If I figure some stuff out, I’ll try to post some detailed instructions to help other out as well.

i got one of these

pihut

Also got this off ebay

serial

then i think i had to use a gender bender.

im sure it would be easy to make a cable, with level shifter.

yeah i use esphome alot. but i think i’d of had to do a custom component in C. But i know python and had already done most the code, as i had written custom python component for HA, which worked ok, but used ALOT of CPU as the serial is very busy. so i decided to use a ESP to buffer only the messages needed.

This is great info! I ordered an ESP32 and RS232 adapter. I have a MZC66 so I may need to alter the python code but this looks very promising.

I checked out the GitHub code (thanks for sharing) and the links to the hardware. I’ve had to remake the Speakercraft cables before as they seem to die easily so I was under the impression that I’d just make the 4 contact plug and then wire that into the ESP32 and use the SPI Bus, but it looks like you are using the actual RS232 Serial board. Sorry for the extreme ignorance here, but do you have any schematics for the setup? I can’t figure it out from the code. If I can get this running, I’d be more than happy to do a full tutorial writeup for anyone who comes after me.

should work fine with MZC66 without code editing. just wont report the extra 2 channels.

i think it needs to go through a TTL to RS-232 adapter. As RS232 (serial) can be -25 to 25v whereas ttl is either 0v or 3.3v. So attaching direct to the esp32 might kill it. It might be possible using a level shifter… circuir, i think thats what the adapter i use basically is. i may be wrong.

uart = machine.UART(2, tx=17, rx=16, baudrate=57600)

looks like i use pins 16, 17. to the adapter.

does that help. If not i’ll pop into the loft and take a look/photos.