Control MCZ Maestro pellet stove via HACore trough MQTT

Hi All,

Because of some limitations with Homekit I recently switched from Homebridge to Home Assistant Core.

As I’m trying to transfer all my smart devices to HACore I’m a bit stuck with my stove which sends and receives MQTT signals.

The MQTT data that I’m receiving is the following:

Bericht 8 ontvangen op PUBmcz om 21:55:
{
    "RPM - Vis sans fin - LIVE": 0,
    "RPM - Ventilateur fummées": 0,
    "Heure du poêle (0-23)": 21,
    "Etat du ventilateur d'ambiance": "Niveau 5",
    "Minutes du poêle (0-29)": 58,
    "TEMP - Carte mère": 30,
    "Heures de fonctionnement en puissance 1 (s)": "1:17:39:31",
    "TEMP - Consigne": 22,
    "Jour du poêle (1-31)": 23,
    "Heures de fonctionnement total (s)": "11:5:49:37",
    "Etat du mode Active": 1,
    "Mode Chronotermostato": 0,
    "Minutes avant extinction": 0,
    "ACTIVE - Live": 100,
    "Etat effets sonores": 1,
    "Température des fumées": 25,
    "Température ambiante": 15,
    "Heures de fonctionnement en puissance 5 (s)": "4:2:26:14",
    "Heures de fonctionnement en puissance 2 (s)": "1:3:18:44",
    "Puissance Active": "Puissance 3",
    "Mode": "Hiver",
    "Heures de fonctionnement en puissance 3 (s)": "1:23:48:16",
    "Etat du poêle": "Eteint",
    "Heures de fonctionnement en puissance 4 (s)": "0:20:26:50",
    "Mode ECO": 0,
    "RPM - Vis sans fin - SET": 0,
    "Etat de la bougie": 0,
    "Heures avant entretien": 1730,
    "ACTIVE - Set": 192,
    "Année du poêle": 2020,
    "Nombre d'allumages": 53,
    "Mode de régulation": "Manuelle",
    "Mois du poêle (1-12)": 10
}

Most of the stove’s codes are linked with numbers (full list below):

#coding: utf-8

'''
Tables des correspondances

        Le rang 0 correspond à la position de l'information dans la trame MAESTRO
        Le rang 1 correspond a l'intitulé publié sur le broker
        Le rang 2 (optionnel) permet de remplacer le code de la trame par une information texte correspondante

'''
RecuperoInfo=[
        [1,"Etat du poêle",[
                                                [0, "Eteint"],
                                                [1, "Controle du poele froid / chaud"],
                                                [2, "Clean Froid"],
                                                [3, "Load Froid"],
                                                [4, "Start 1 Froid"],
                                                [5, "Start 2 Froid"],
                                                [6, "Clean Chaud"],
                                                [7, "Load Chaud"],
                                                [8, "Start 1 chaud"],
                                                [9, "Start 2 chaud"],
                                                [10, "Stabilisation"],
                                                [11, "Puissance 1"],
                                                [12, "Puissance 2"],
                                                [13, "Puissance 3"],
                                                [14, "Puissance 4"],
                                                [15, "Puissance 5"],
                                                [30, "Mode diagnostique"],
                                                [31, "Marche"],
                                                [40, "Extinction"],
                                                [41, "Refroidissement en cours"],
                                                [42, "Nettoyage basse p."],
                                                [43, "Nettoyage haute p."],
                                                [44, "Débloquage vis sans fin"],
                                                [45, "AUTO ECO"],
                                                [46, "Standby"],
                                                [48, "Diagnostique"],
                                                [49, "CHARG. VIS SANS FIN"],
                                                [50, "Erreur A01 - Allumage raté"],
                                                [51, "Erreur A02 - Pas de flamme"],
                                                [52, "Erreur A03 - Surchauffe du réservoir"],
                                                [53, "Erreur A04 - Température des fumées trop haute"],
                                                [54, "Erreur A05 - Obstruction conduit - Vent"],
                                                [55, "Erreur A06 - Mauvais tirage"],
                                                [56, "Erreur A09 - Défaillance sonde de fumées"],
                                                [57, "Erreur A11 - Défaillance motoréducteur"],
                                                [58, "Erreur A13 - Température carte mère trop haute"],
                                                [59, "Erreur A14 - Défaut Active"],
                                                [60, "Erreur A18 - Température d'eau trop haute"],
                                                [61, "Erreur A19 - Défaut sonde température eau"],
                                                [62, "Erreur A20 - Défaut sonde auxiliaire"],
                                                [63, "Erreur A21 - Alarme pressostat"],
                                                [64, "Erreur A22 - Défaut sonde ambiante"],
                                                [65, "Erreur A23 - Défaut fermeture brasero"],
                                                [66, "Erreur A12 - Panne controleur motoréducteur"],
                                                [67, "Erreur A17 - Bourrage vis sans fin"],
                                                [69, "Attente Alarmes securité"],
                                                ]],
        [2,"Etat du ventilateur d'ambiance",[
                                                                                [0, "Désactivé"],
                                                                                [1, "Niveau 1"],
                                                                                [2, "Niveau 2"],
                                                                                [3, "Niveau 3"],
                                                                                [4, "Niveau 4"],
                                                                                [5, "Niveau 5"],
                                                                                [6, "Automatique"],
                                                                                ]],
        [5,"Température des fumées"],
        [6,"Température ambiante"],
        [10,"Etat de la bougie"],
        [11,"ACTIVE - Set"],
        [12,"RPM - Ventilateur fummées"],
        [13,"RPM - Vis sans fin - SET"],
        [14,"RPM - Vis sans fin - LIVE"],
        [20,"Etat du mode Active"],  #0: Désactivé, 1: Activé
        [21,"ACTIVE - Live"],
        [22,"Mode de régulation",[
                                                                [0, "Manuelle"],
                                                                [1, "Dynamique"],
                                                                ]],
        [23,"Mode ECO"],
        [25,"Mode Chronotermostato"],
        [26,"TEMP - Consigne"],
        [28,"TEMP - Carte mère"],
        [29,"Puissance Active",[
                                                     [11, "Puissance 1"],
                                                        [12, "Puissance 2"],
                                                        [13, "Puissance 3"],
                                                        [14, "Puissance 4"],
                                                        [15, "Puissance 5"],
                                                        ]],
        [32,"Heure du poêle (0-23)"],
        [33,"Minutes du poêle (0-29)"],
        [34,"Jour du poêle (1-31)"],
        [35,"Mois du poêle (1-12)"],
        [36,"Année du poêle"],
        [37,"Heures de fonctionnement total (s)"],
        [38,"Heures de fonctionnement en puissance 1 (s)"],
        [39,"Heures de fonctionnement en puissance 2 (s)"],
        [40,"Heures de fonctionnement en puissance 3 (s)"],
        [41,"Heures de fonctionnement en puissance 4 (s)"],
        [42,"Heures de fonctionnement en puissance 5 (s)"],
        [43,"Heures avant entretien"],
        [44,"Minutes avant extinction"],
        [45,"Nombre d'allumages"],
        [49,"Etat effets sonores"],
        [51,"Mode",[
                                [0, "Hiver"],
                                [1, "Eté"],
                                ]],
        ]

I used to be able to control this stove via the Homebridge-MQTT plugin via this configuration (it wasn’t perfect but it worked):

        {
            "accessory": "mqttthing",
            "type": "thermostat",
            "name": "MCZ VIVO 90",
            "logmqtt": true,
            "url": "mqtt://192.168.1.211:1883",
            "topics": {
                "getCurrentTemperature": {
                    "topic": "PUBmcz",
                    "apply": "return JSON.parse(message)['Température ambiante'].toFixed(1);"
                },
                "setTargetHeatingCoolingState": {
                    "topic": "SUBmcz",
                    "apply": "return message == 'HEAT' ? '34,1' : '34,40';"
                },
                "setTargetTemperature": {
                    "topic": "SUBmcz",
                    "apply": "return \"42,\"+message;"
                }
            }
        },

Now is the question:

How do I translate this into something working in HACore?

What I want to do:
2 states: On/Off
Temperature control

I don’t really need to do anything more as the stove itself regulates pellets and ventilation by it’s own built-in thermostat.

Thanks in advance!

1 Like

Anyone here that might be able to help me?

I tried first by adding a sensor to display the current temperature but this also didn’t work:

sensor:
  - platform: mqtt
    name: Veranda
    state_topic: "PUBmcz"
    unit_of_measurement: '°C'
    value_template: "{{ value_json.Température ambiante }}"

HA config checker doesn’t give an error, it restarts perfectly. However there’s no sensor added anywhere so I can’t check if it worked or not… As nothing is showing up I guess it didn’t obviously…

Any help would be greatly appreciated!

In the meantime I found out that the following works to get the data into a sensor:

  - platform: mqtt
    name: MCZ
    state_topic: "PUBmcz"
    unit_of_measurement: '°C'
    value_template: "{{ value_json['Température ambiante'] | round(1) }}"

Now I have to try and get it working as a thermostat via climate.
This seems way more complex so still need some help if anyone would be so kind!

Hello,

I’m trying to do the same thing as you :slight_smile:

To get the Température plus others info here’s my code that works. It’s embedded into a poele.yaml file into the sensors directory. I’m trying now to send commands to the stove, with limited success.

  - platform: mqtt
    name: "Mode"
    state_topic: "PUBmcz"
    value_template: "{{ value_json.Mode }}"

  - platform: mqtt
    name: "Etat du poele"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Etat du poêle'] }}"
    
  - platform: mqtt
    name: "Ventilateur Ambiance"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Etat du ventilateur d\\'ambiance'] }}"

  - platform: mqtt
    name: "Temperature Fumees"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Température des fumées'] }}"
    
  - platform: mqtt
    name: "Ventilateur Fumees"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['RPM - Ventilateur fummées'] }}"

  - platform: mqtt
    name: "Vis Sans Fin"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['RPM - Vis sans fin - LIVE'] }}" 

  - platform: mqtt
    name: "Mode Chronotermostato"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Mode Chronotermostato'] }}" 

  - platform: mqtt
    name: "Température - Carte mère"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['TEMP - Carte mère'] }}"
    
  - platform: mqtt
    name: "Puissance Active"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Puissance Active'] }}"

  - platform: mqtt
    name: "Minutes avant extinction"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Minutes avant extinction'] }}"
    
  - platform: mqtt
    name: "Ventilateur 1"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Etat du ventilateur canalise 1'] }}"

  - platform: mqtt
    name: "Ventilateur 2"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Etat du ventilateur canalise 2'] }}"    
    
  - platform: mqtt
    name: "Mode Silence"
    state_topic: "PUBmcz"
    value_template: "{{ value_json['Mode Silence'] }}"

Great! Could you be so kind to keep me updated when you’ve found out how it might work?

Here’s a way to create a switch to control the stove. It might not be the best way, but it works:

switch:
  - platform: mqtt
    unique_id: poeleonoff
    name: "Marche / Arret Poele"
    command_topic: "SUBmcz"
    payload_on: "34,1"
    payload_off: "34,40"
    state_on: "ON"
    state_off: "OFF"
    optimistic: false
    qos: 0
    retain: true

Cool! Thanks!
The only thing that’s left is to find out how to send the desired temperature to the stove.
After that we should have all the required elements to put it into a nice generic_thermostat… :slight_smile:

I think I’ll have some time today to search a bit more on that!

Hello,

If it helps, here is my configuration to control my MCZ stove:

switch:
  - platform: mqtt
    unique_id: MCZ_POWER
    name: "MCZ Power"
    command_topic: "SUBmcz"
    qos: 0
    retain: true
    payload_on: "{\"Command\":\"Power\", \"Value\":\"1\"}"
    payload_off: "{\"Command\":\"Power\", \"Value\":\"0\"}"
    state_topic: "PUBmcz"
    state_on: "ON"
    state_off: "OFF"
    value_template: >-
      {% if value_json.Stove_State == 0 %}
        OFF
      {% elif value_json.Stove_State == 1 %}
        ON
      {% elif value_json.Stove_State == 2 %}
        ON
      {% elif value_json.Stove_State == 3 %}
        ON
      {% elif value_json.Stove_State == 4 %}
        ON
      {% elif value_json.Stove_State == 5 %}
        ON
      {% elif value_json.Stove_State == 6 %}
        ON
      {% elif value_json.Stove_State == 7 %}
        ON
      {% elif value_json.Stove_State == 8 %}
        ON
      {% elif value_json.Stove_State == 9 %}
        ON
      {% elif value_json.Stove_State == 10 %}
        ON
      {% elif value_json.Stove_State == 11 %}
        ON
      {% elif value_json.Stove_State == 12 %}
        ON
      {% elif value_json.Stove_State == 13 %}
        ON
      {% elif value_json.Stove_State == 14 %}
        ON
      {% elif value_json.Stove_State == 15 %}
        ON
      {% elif value_json.Stove_State == 31 %}
        ON
      {% elif value_json.Stove_State == 40 %}
        OFF
      {% elif value_json.Stove_State == 46 %}
        OFF
      {% endif %}

sensor:
   - platform: mqtt
    name: "Temperature Ambiante MCZ"
    state_topic: "PUBmcz"
    unit_of_measurement: '°C'
    value_template: "{{ value_json.Ambient_Temperature | is_defined }}"
    
  - platform: mqtt
    name: "Temperature fumé MCZ"
    state_topic: "PUBmcz"
    unit_of_measurement: '°C'
    value_template: "{{ value_json.Fume_Temperature | is_defined }}"
    
  - platform: mqtt
    name: "Statut MCZ brut"
    state_topic: "PUBmcz"
    value_template: "{{ value_json.Stove_State | is_defined }}"
    
  - platform: template
    sensors:
      statut_mcz:
        friendly_name: "Statut MCZ"
        value_template: >-
          {% if is_state('sensor.statut_mcz_brut', '0') %}
            Inactif
          {% elif is_state('sensor.statut_mcz_brut', '1') %}
            Contrôle chaud froid
          {% elif is_state('sensor.statut_mcz_brut', '2') %}
            Nettoyage froid
          {% elif is_state('sensor.statut_mcz_brut', '3') %}
            Chargement froid
          {% elif is_state('sensor.statut_mcz_brut', '4') %}
            Démarrage 1 froid
          {% elif is_state('sensor.statut_mcz_brut', '5') %}
            Démarrage 2 froid
          {% elif is_state('sensor.statut_mcz_brut', '6') %}
            Nettoyage chaud
          {% elif is_state('sensor.statut_mcz_brut', '7') %}
            Chargement chaud
          {% elif is_state('sensor.statut_mcz_brut', '8') %}
            Démarrage 1 chaud
          {% elif is_state('sensor.statut_mcz_brut', '9') %}
            Démarrage 2 chaud
          {% elif is_state('sensor.statut_mcz_brut', '10') %}
            Stabilisation
          {% elif is_state('sensor.statut_mcz_brut', '11') %}
            Puissance 1
          {% elif is_state('sensor.statut_mcz_brut', '12') %}
            Puissance 2
          {% elif is_state('sensor.statut_mcz_brut', '13') %}
            Puissance 3
          {% elif is_state('sensor.statut_mcz_brut', '14') %}
            Puissance 4
          {% elif is_state('sensor.statut_mcz_brut', '15') %}
            Puissance 5
          {% elif is_state('sensor.statut_mcz_brut', '30') %}
            Mode diagnostique
          {% elif is_state('sensor.statut_mcz_brut', '31') %}
            Allumé
          {% elif is_state('sensor.statut_mcz_brut', '40') %}
            Extinction
          {% elif is_state('sensor.statut_mcz_brut', '41') %}
            Refroidissement
          {% elif is_state('sensor.statut_mcz_brut', '42') %}
            Low Cleaning
          {% elif is_state('sensor.statut_mcz_brut', '43') %}
            High Cleaning
          {% elif is_state('sensor.statut_mcz_brut', '44') %}
            UNLOCKING SCREW
          {% elif is_state('sensor.statut_mcz_brut', '45') %}
            AUTO ECO
          {% elif is_state('sensor.statut_mcz_brut', '46') %}
            Inactif
          {% elif is_state('sensor.statut_mcz_brut', '48') %}
            Diagnostics
          {% elif is_state('sensor.statut_mcz_brut', '49') %}
            LOADING AUGER
          {% elif is_state('sensor.statut_mcz_brut', '50') %}
            Error A01 - Ignition failed
          {% elif is_state('sensor.statut_mcz_brut', '51') %}
            Error A02 - No flame
          {% elif is_state('sensor.statut_mcz_brut', '52') %}
            Error A03 - Tank overheating
          {% elif is_state('sensor.statut_mcz_brut', '53') %}
            Error A04 - Flue gas temperature too high
          {% elif is_state('sensor.statut_mcz_brut', '54') %}
            Error A05 - Duct obstruction - Wind
          {% elif is_state('sensor.statut_mcz_brut', '55') %}
            Error A06 - Bad printing
          {% elif is_state('sensor.statut_mcz_brut', '56') %}
            Error A09 - SMOKE PROBE
          {% elif is_state('sensor.statut_mcz_brut', '57') %}
            Error A11 - GEAR MOTOR
          {% elif is_state('sensor.statut_mcz_brut', '58') %}
            Error A13 - MOTHERBOARD TEMPERATURE
          {% elif is_state('sensor.statut_mcz_brut', '59') %}
            Error A14 - DEFECT ACTIVE
          {% elif is_state('sensor.statut_mcz_brut', '60') %}
            Error A18 - WATER TEMP ALARM
          {% elif is_state('sensor.statut_mcz_brut', '61') %}
            Error A19 - FAULTY WATER PROBE
          {% elif is_state('sensor.statut_mcz_brut', '62') %}
            Error A20 - FAILURE OF AUXILIARY PROBE
          {% elif is_state('sensor.statut_mcz_brut', '63') %}
            Error A21 - PRESSURE SWITCH ALARM
          {% elif is_state('sensor.statut_mcz_brut', '64') %}
            Error A22 - ROOM PROBE FAULT
          {% elif is_state('sensor.statut_mcz_brut', '65') %}
            Error A23 - BRAZIER CLOSING FAULT
          {% elif is_state('sensor.statut_mcz_brut', '66') %}
            Error A12 - MOTOR REDUCER CONTROLLER FAILUR
          {% elif is_state('sensor.statut_mcz_brut', '67') %}
            Error A17 - ENDLESS SCREW JAM
          {% elif is_state('sensor.statut_mcz_brut', '69') %}
            WAITING FOR SECURITY ALARMS
          {% else %}
            Inactif
          {% endif %}

climate:
  - platform: generic_thermostat
    name: Poele salon
    heater: switch.mcz_power
    target_sensor: sensor.temperature_ambiante_mcz
    min_temp: 10
    max_temp: 32
    target_temp: 21
    cold_tolerance: 2
    hot_tolerance: 0.5
    initial_hvac_mode: "heat"
    away_temp: 18
    precision: 0.5

Thanks for sharing @NadeoGolf!
A quick question:

As I only need basic controls for the stove, would it then be possible to just leave out all the value_template parts? I guess it will be easier to just copy everything but I don’t want to implement code I won’t ever use.

Thanks again man!

the value_template part is useful if you start the stove with the MCZ application for any reason. Without it, the switch does not change in HA.

the code without the value_template part:

switch:
  - platform: mqtt
    unique_id: MCZ_POWER
    name: "MCZ Power"
    command_topic: "SUBmcz"
    qos: 0
    retain: true
    payload_on: "{\"Command\":\"Power\", \"Value\":\"1\"}"
    payload_off: "{\"Command\":\"Power\", \"Value\":\"0\"}"

Hi @NadeoGolf

I tweaked the code a bit to suit my needs:

# Switches
switch:
  - platform: mqtt
    unique_id: MCZ_POWER
    name: "MCZ Power"
    command_topic: "SUBmcz"
    qos: 0
    retain: true
    payload_on: "34,1"
    payload_off: "34,40"
    state_on: "ON"
    state_off: "OFF"

# Temperatuursensors
sensor:
  - platform: mqtt
    name: "Temperatuur Veranda"
    state_topic: "PUBmcz"
    unit_of_measurement: '°C'
    value_template: "{{ value_json['Température ambiante'] | is_defined }}"

#Thermostaat per ruimte
climate:
  - platform: generic_thermostat
    name: Kachel Veranda
    heater: switch.mcz_power
    target_sensor: sensor.temperatuur_veranda
    min_temp: 15
    max_temp: 25
    target_temp: 21
    cold_tolerance: 2
    hot_tolerance: 1
    initial_hvac_mode: "off"
    precision: 0.5

Right now I can see the temperature and turn the stove on and off…
However I can’t change the desired temperature.
When browsing trough your code I can’t immediately find anything that refers to how you change that.
Or am I missing something?

This is normal, my stove is set to manual.
It is HA which turns it on and off according to the target _sensor.
Without value_template and state_topic, state_on and state_off is useless for the switch.

But, I dont understand your payload_on and payload_off, why 34,1 and 34,40?
I tested, it does nothing.

Hi @NadeoGolf

As the stove can work with it’s own thermostat I don’t see the advantage of using HA to do that.
I just want to send the desired temperature to the stove so it can do what it’s made for.

As for the payloads, I’m still using the original maestro script, which is in French and uses numeric codes to represent the different modes. As it does exactly the same I don’t see the need to reinstall that part of the process…

So for example to change the temperature, I just need to send 42,21 over MQTT to request 21°C .

I wanted to do that too but I didn’t succeed. So I set the stove to manual. So I won’t be able to help you with this

I guess we can solve this by using an automation which is triggered by a changed state in the desired temperature.
The automation can trigger a script which sends the mqtt payload to the stove…
I hope to be able to fiddle around a bit later this afternoon…

I’m curious to see that. :slightly_smiling_face:

@NadeoGolf Got it :slight_smile:

- id: '1605023600910'
  alias: Temperatuur Kachel Veranda
  description: ''
  trigger:
  - platform: state
    entity_id: climate.kachel_veranda
    attribute: temperature
  condition: []
  action:
  - service: mqtt.publish
    data:
      topic: SUBmcz
      retain: 'false'
      payload: 42,{{states.climate.kachel_veranda.attributes.temperature}}
  mode: single

Solution for other people looking for this as well:

configuration.yaml

# Switches
switch:
  - platform: mqtt
    unique_id: MCZ_POWER
    name: "MCZ Power"
    command_topic: "SUBmcz"
    qos: 0
    retain: true
    payload_on: "34,1"
    payload_off: "34,40"
    state_on: "ON"
    state_off: "OFF"

# Temperatuursensors
sensor:
  - platform: mqtt
    name: "Temperatuur Veranda"
    state_topic: "PUBmcz"
    unit_of_measurement: '°C'
    value_template: "{{ value_json['Température ambiante'] | is_defined }}"

#Thermostaat per ruimte
climate:
  - platform: generic_thermostat
    name: Kachel Veranda
    heater: switch.mcz_power
    target_sensor: sensor.temperatuur_veranda
    min_temp: 15
    max_temp: 25
    target_temp: 21
    cold_tolerance: 2
    hot_tolerance: 1
    initial_hvac_mode: "off"
    precision: 1

automations.yaml

- id: '1605023600910'
  alias: Temperatuur Kachel Veranda
  description: ''
  trigger:
  - platform: state
    entity_id: climate.kachel_veranda
    attribute: temperature
  condition: []
  action:
  - service: mqtt.publish
    data:
      topic: SUBmcz
      retain: 'false'
      payload: 42,{{states.climate.kachel_veranda.attributes.temperature}}
  mode: single

Great, that’s good news :grinning:

But you send start and stop commands to the stove with the HA thermostat and with the one integrated into the stove.

Do you use ECO mode?

@NadeoGolf

I’m using the stove in comfort mode.
I’m solely using the ha thermostat as an interface as it fits the image of the rest of my thermostats.
So as you can see in my config I only switch on/off the stove and provide a desired temperature trough the HA thermostat.
Everything else is done by the stove itself as it works fine as is.
To complete it I’m reading the ambient temperature from the stove’s WiFi sensor so it completes the HA thermostat.