MCZ Maestro et Jeedom

Bonjour,

J’ai renseigné une mauvaise valeur, et maintenant, je ne peux plus m’en servir… Il me marque dans "etat du poêle : [« Code inconnu : »,« 38 »]

Savez-vous comment je peux faire pour le réinitialiser ?

J’ai débranché et rebrancher le poêle, sans résultat.

D’avance merci.

Si tu passes par le brocker mqtt, l’info est peut-etre en « retain » dans le topic SUBmcz du broker Mqtt.
Connectes-toi avec MQTT Explorer et supprime cette info.

Hello,

Grace au post de @EtienneME, j’ai réussi à faire fonctionner l’envoi / réception de commande depuis les serveurs MCZ (nécéssaire pour les poêles Brisach). Merci aussi à @Anthony pour ce programme bien utile !

Je peux bien entendu partager le code avec ceux qui auraient besoin, mais avant ca une petite question:
Il semblerait que le programme envoie une commande vers le WS toutes les secondes. Cela est un comportement normal ? Pas de risques d’être considéré comme un « spammeur » par les serveurs brisach ?

Merci d’avance,
Nicolas

Edit: Du coup, j’ai mis une récupération toutes les 15 secondes (envoi de la commande C|RecuperoInfo) mais envoi instantané pour les commandes du poele.
Ca fonctionne au top depuis maintenant 12h. A suivre sur la durée.
Le code n’est pas très propre, mais je peux le partager avec ceux qui auraient besoin !

Je pense que tu peux même monter à 30 secondes si c’est pour de la lecture. C’est super si tu as pu communiquer avec les serveurs Mcz, tu peux partager ton code, c’est toujours interressant et instructif :wink:

il y a une raz sur github ? que se passe-t-il

Hello,

Voici le code! Surement possible de l’améliorer, c’est de la bidouille ! J’ai passé la récup à 30 sec, c’est top.
Once again, merci à @Anthony et @EtienneME .

Ca marche bien chez moi, stable et rapide. En cas de déconnection du wifi, j’avais des soucis à la reco (le message « join » n’était pas envoyé). Ca devrait normalement être bon, à voir à la prochaine déco.

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

import paho.mqtt.client as mqtt
import time
import sys
import os
import json
import logging
import datetime
from logging.handlers import RotatingFileHandler
import websocket
try:
	import thread
except ImportError:
	import _thread as thread

logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(message)s')
file_handler = RotatingFileHandler('activity1.log', 'a', 1000000, 1)
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)

stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
logger.addHandler(stream_handler)

class PileFifo(object):
    def __init__(self,maxpile=None):
        self.pile=[]
        self.maxpile = maxpile

    def empile(self,element,idx=0):
        if (self.maxpile!=None) and (len(self.pile)==self.maxpile):
            raise ValueError ("erreur: tentative d'empiler dans une pile pleine")
        self.pile.insert(idx,element)
 
    def depile(self,idx=-1):
        if len(self.pile)==0:
            raise ValueError ("erreur: tentative de depiler une pile vide")
        if idx<-len(self.pile) or idx>=len(self.pile):
            raise ValueError ("erreur: element de pile à depiler n'existe pas")
        return self.pile.pop(idx)
 
    def element(self,idx=-1):
        if idx<-len(self.pile) or idx>=len(self.pile):
            raise ValueError ("erreur: element de pile à lire n'existe pas")
        return self.pile[idx]
 
    def copiepile(self,imin=0,imax=None):
        if imax==None:
            imax=len(self.pile)
        if imin<0 or imax>len(self.pile) or imin>=imax:
            raise ValueError ("erreur: mauvais indice(s) pour l'extraction par copiepile")
        return list(self.pile[imin:imax])
 
    def pilevide(self):
        return len(self.pile)==0
 
    def pilepleine(self):
        return self.maxpile!=None and len(self.pile)==self.maxpile
 
    def taille(self):
        return len(self.pile)

Message_MQTT=PileFifo()
Message_WS=PileFifo()

# SIO CONNECT TO MCZ MAESTRO
from pprint import pprint
import socketio

sio = socketio.Client(logger=True, engineio_logger=True)
MCZ_device_serial = "vorenumdeserie"
MCZ_device_MAC = "votremac"
MCZ_App_URL = "http://app.mcz.it:9000"

_INTERVALLE = 1
_TEMPS_SESSION = 60

# MQTT
from _config_ import _MQTT_ip
from _config_ import _MQTT_port
from _config_ import _MQTT_TOPIC_SUB
from _config_ import _MQTT_TOPIC_PUB

from _config_ import _MQTT_authentication
from _config_ import _MQTT_user
from _config_ import _MQTT_pass

MQTT_MAESTRO = {}

logger.info('Lancement du deamon')
logger.info('Anthony L. 2019')
logger.info('Niveau de LOG : DEBUG')


def on_connect_mqtt(client, userdata, flags, rc):
	logger.info("Connecté au broker MQTT avec le code : " + str(rc))

def on_message_mqtt(client, userdata, message):
	logger.info('Message MQTT reçu : ' + str(message.payload.decode()))
	cmd = message.payload.decode().split(",")
	if cmd[0] == "42":
		cmd[1]=(int(cmd[1])*2)
	Message_MQTT.empile("C|WriteParametri|"+cmd[0]+"|"+str(cmd[1]))
	logger.info('Contenu Pile Message_MQTT : ' + str(Message_MQTT.copiepile()))
	send()

def secTOdhms(nb_sec):
	qm,s=divmod(nb_sec,60)
	qh,m=divmod(qm,60)
	d,h=divmod(qh,24)
	return "%d:%d:%d:%d" %(d,h,m,s)

@sio.event
def connect():
	pprint("Connected")
	pprint("SID is : {}".format(sio.sid))
	sio.emit(
	    "join",
	    {
	        "serialNumber": MCZ_device_serial,
	        "macAddress": MCZ_device_MAC,
	        "type": "Android-App",
	    },
	)
	sio.emit(
	    "chiedo",
	    {
	        "serialNumber": MCZ_device_serial,
	        "macAddress": MCZ_device_MAC,
	        "tipoChiamata": 0,
	        "richiesta": "RecuperoParametri",
	    },
	)
	sio.emit(
	    "chiedo",
	    {
	        "serialNumber": MCZ_device_serial,
	        "macAddress": MCZ_device_MAC,
	        "tipoChiamata": 1,
	        "richiesta": "C|RecuperoInfo",
	    },
	)

@sio.event
def disconnect():
	pprint("Disconnected")

@sio.event
def rispondo(response):
	pprint("Received 'rispondo' message")
	datas = response["stringaRicevuta"].split("|")
	from _data_ import RecuperoInfo
	for i in range(0,len(datas)):
			for j in range(0,len(RecuperoInfo)):
				if i == RecuperoInfo[j][0]:
					if len(RecuperoInfo[j]) > 2:
						for k in range(0,len(RecuperoInfo[j][2])):
							if int(datas[i],16) == RecuperoInfo[j][2][k][0]:
								MQTT_MAESTRO[RecuperoInfo[j][1]] = RecuperoInfo[j][2][k][1]
								break
							else:
								MQTT_MAESTRO[RecuperoInfo[j][1]] = ('Code inconnu :', str(int(datas[i],16)))
					else:
						if i == 6 or i == 26 or i == 28:
							MQTT_MAESTRO[RecuperoInfo[j][1]] = float(int(datas[i], 16))/2
						
						elif i >= 37 and i <=42:
							MQTT_MAESTRO[RecuperoInfo[j][1]] = secTOdhms(int(datas[i],16))
						else:
							MQTT_MAESTRO[RecuperoInfo[j][1]] = int(datas[i],16)
	logger.info('Publication sur le topic MQTT ' + str(_MQTT_TOPIC_PUB) + ' le message suivant : ' + str(json.dumps(MQTT_MAESTRO)))
	client.publish(_MQTT_TOPIC_PUB, json.dumps(MQTT_MAESTRO),1)

sio.connect(MCZ_App_URL)

logger.info('Connection en cours au broker MQTT (IP:'+_MQTT_ip + ' PORT:'+str(_MQTT_port)+')')
client = mqtt.Client()
if _MQTT_authentication == True:
	client.username_pw_set(username=_MQTT_user,password=_MQTT_pass)
client.on_connect = on_connect_mqtt
client.on_message = on_message_mqtt
client.connect(_MQTT_ip, _MQTT_port)
client.loop_start()
logger.info('Souscription au topic ' + str(_MQTT_TOPIC_SUB) + ' avec un Qos=1')
client.subscribe(_MQTT_TOPIC_SUB, qos=1)


def receive(*args):
	while True:
		time.sleep(30)
		logger.info("Envoi de la commande pour rafraichir les donnees")
		sio.emit(
		    "chiedo",
		    {
		        "serialNumber": MCZ_device_serial,
		        "macAddress": MCZ_device_MAC,
		        "tipoChiamata": 1,
		        "richiesta": "C|RecuperoInfo",
		    },
		)
			

def send():
	def run(*args):
		
		time.sleep(_INTERVALLE)
		if Message_MQTT.pilevide():
			Message_MQTT.empile("C|RecuperoInfo")
		cmd = Message_MQTT.depile()
		logger.info("Envoi de la commande : " + str(cmd))
		sio.emit(
		    "chiedo",
		    {
		        "serialNumber": MCZ_device_serial,
		        "macAddress": MCZ_device_MAC,
		        "tipoChiamata": 1,
		        "richiesta": cmd,
		    },
		)
			
	thread.start_new_thread(run, ())



Bonjour,

Merci pour cette info.
Cependant, lorsque je lance le programme, je reçois le message d’erreur:
ModuleNotFoundError: No module named ‹ socketio ›
Pourriez-vous m’aider?
Merci d’avance

Bonjour est-ce quelqu’un a les codes pour faire tourner la vis sans fin 120secondes comme dans l appli maestro mcz merci.

Voici mon module de gestion de pellet.
Il permet de rentrer dans son stock des sacs de pellet à différent prix, du coup il calcul un cout unitaire moyen pondéré pour la sortie en consommation.
Il suffit de cliquer sur Sac Consomme lorsque l’on met un sac dans le poele, et on clique 2 fois lorsque l’on met 2 sacs. La prochaine évolution sera de mettre un ESP sur le poele avec un bouton poussoir, il suffira d’appuyer sur le bouton poussoir pour mettre à jour le stock…

Tu peux aussi le faire sur ecopellets.fr - Ressources et information concernant ecopellets Resources and Information. et le plugin script

Hello,

Il faut faire un pip install "python-socketio[client]" ou pip3 install "python-socketio[client]" suivant ta version de python pour installer socketio avec ses dépendances !

Bonjour,

Je souhaite commander mon poêle « MCZ Ego air 8 Up » avec le système Maestro.
Je débute dans Jeedom, actuellement je contrôle mon poêle avec un actionneur et thermostat d’ambiance externe (Delat Dore Tybox 5100).
Jeedom est installer sur une VM sur mon NAS synology DS218+ qui est connecter au réseau de la maison, le poêle et aussi connecter au réseau de la maison.

  • Est-ce qu’il y a besoin d’avoir un dongle usb Wifi obligatoirement pour ma configuration ? Si oui, quel model pour fonctionnier sur Débian Stretch ?

Merci

2 « J'aime »

Hello,

Deux solution:

  1. Soit tu te connectes directement sur le wifi du poele, dans ce cas il te faut en effet un dongle wifi sur ton nas, pour avoir une connexion sur ton réseau normal + une connexion sur le poele en direct.
    C’est la solution la plus fiable (= en cas de coupure internet ou des serveurs MCZ, jeedom continuera de communiquer avec le poele)
  2. Tu communiques avec le poele via les serveurs MCZ, dans ce cas tu n’as pas besoin de rajouter un dongle, il faut juste que ton jeedom soit connecté à internet.
    Avantage: c’est + simple. Inconvénient: en cas de coupure internet ou indisponibilité des serveurs mcz, jeedom ne pourra plus contrôler le poele.

De mon côté j’utilise la solution 2, mon poele brisach (technologie maestro) ne supportant pas une connexion en direct.
Ca doit faire maintenant 1 ou 2 mois, RAS

1 « J'aime »

Bonjour,

Merci pour ton code, je suis parti du principe que ça remplaçait le maestro.py.

ça marche chez moi pour envoyer, mais je ne reçois jamais d’update des serveurs, est-ce que j’ai raté quelque chose ?

J’en reçois uniquement quand j’envoie une commande, du coup rien ne se met à jour chez moi.

*2021-01-12 15:20:13,073 :: INFO :: Sending packet PING data None*
*2021-01-12 15:20:13,091 :: INFO :: Received packet PONG data None*
*2021-01-12 15:20:38,075 :: INFO :: Sending packet PING data None*
*2021-01-12 15:20:38,186 :: INFO :: Received packet PONG data None*
*2021-01-12 15:20:53,733 :: INFO :: Message MQTT reçu : 45,1*
*2021-01-12 15:20:53,733 :: INFO :: Contenu Pile Message_MQTT : ['C|WriteParametri|45|1']*
*2021-01-12 15:20:54,735 :: INFO :: Envoi de la commande : C|WriteParametri|45|1*
*2021-01-12 15:20:54,736 :: INFO :: Emitting event "chiedo" [/]*
*2021-01-12 15:20:54,737 :: INFO :: Sending packet MESSAGE data 2["chiedo",{"serialNumber":"XXXXXXXXXX","macAddress":"XXXXXXXXXXXXX","tipoChiamata":1,"richiesta":"C|WriteParametri|45|1"}]*
*2021-01-12 15:20:54,895 :: INFO :: Received packet MESSAGE data 2["rispondo",{"stringaRicevuta":"01|0b|06|06|06|006d|fc|00|00|00|00|04b0|04af|0117|013f|00|00|00|00|00|00|00a4|00|00|01|00|28|00|40|0b|010806|*
*14|0f|19|0c|01|07e5|0094caab|007f0d1d|0000dbd1|0000aa51|00005658|0003e951|01d6|0000|030f|00|00|00|01|00|00|fe|ff|ff|ff","socketChiamata":"W-60UrLzXMq5kBBp4TZC"}]*
*2021-01-12 15:20:54,896 :: INFO :: Received event "rispondo" [/]*
*2021-01-12 15:20:54,898 :: INFO :: Publication sur le topic MQTT PUBmcz le message suivant : {"Etat du po\u00eale": "Puissance 1", "Etat du ventilateur d'ambiance": "Automatique", "Etat du ventilateur canal*
*ise 1": " Automatique ", "Etat du ventilateur canalise 2": " Automatique ", "Temp\u00e9rature des fum\u00e9es": 109, "Temp\u00e9rature ambiante": 126.0, "Etat de la bougie": "Arr\u00eat", "ACTIVE - Set": 12*
*00, "RPM - Ventilateur fumm\u00e9es": 1199, "RPM - Vis sans fin - SET": 279, "RPM - Vis sans fin - LIVE": 319, "Etat du mode Active": 0, "ACTIVE - Live": 164, "Mode de r\u00e9gulation": "Manuelle", "Mode EC*
*O": 0, "Mode Silence": "Marche", "Mode Chronotermostato": "Arr\u00eat", "TEMP - Consigne": 20.0, "TEMP - Carte m\u00e8re": 32.0, "Puissance Active": "Puissance 1", "Heure du po\u00eale (0-23)": 15, "Minutes*
* du po\u00eale (0-29)": 25, "Jour du po\u00eale (1-31)": 12, "Mois du po\u00eale (1-12)": 1, "Ann\u00e9e du po\u00eale": 2021, "Heures de fonctionnement total (s)": "112:20:40:11", "Heures de fonctionnement*
* en puissance 1 (s)": "96:8:53:49", "Heures de fonctionnement en puissance 2 (s)": "0:15:37:53", "Heures de fonctionnement en puissance 3 (s)": "0:12:6:41", "Heures de fonctionnement en puissance 4 (s)": "0*
*:6:8:24", "Heures de fonctionnement en puissance 5 (s)": "2:23:12:17", "Heures avant entretien": 470, "Minutes avant extinction": 0, "Nombre d'allumages": 783, "Etat effets sonores": 1, "Mode": "Hiver"}*

Bonjour Pipolas,

Merci pour votre réponse.
Je suis pas très bon en informatique, est-ce que vous avez le descriptif pour l’installation et la configuration ?

J’ai créer un broker sous Jeedom sur le plugin JMQTT comme indiquer, je laisse les valeur par défaut. Puis je vais sur Débian pour lancer les commandes:

  • " git clone https://github.com/Anthony-55/maestro.git
    cd maestro " → OK tout ce passe bien.
  • " sudo bash install" j’ai une erreur « Etablissement d’une nouvelle connection au serveur websocket (IP: xxx.xxx.xxx.x Port: 81)
    [Errono 113] No route to host
    Session websocket fermée ».

Avez-vous une idée du problème ?

Merci

Merci

Salut,
Es-tu connecté en Wi-Fi direct sur le poêle ou via ton reseau interne ?
La solution fournie par Anthony ne fonctionne qu’avec une connection directe sur le poêle.
Si tu es sur ton reseau, c’est normal que l’adresse 192.168.120.1 ne répond pas.

Pour utiliser la solution avec les serveurs MCZ, il faut une autre version. Je ne sais pas si elle est disponible sur un autre repo git.

Salut,

Mon poêle est connecté à ma box internet en wifi, et je peux accéder à distance à l’application MCZ Maestro.
Si @pipolas peut m’aider pour trouver le bon repo git.

Car j’ai pas trop envie de mettre un dungle USB Wifi qui pourrai ne pas être compatible avec le synology DS218+ et la VM sous débian 10.

Je suis preneur de vos solutions, sachant que je contrôle mon poêle en Tout ou Rien sans gestion de puissance. Ca fonctionne correctement mais le plus gênant c’est l’arrêt répétitif du poêle qui peut dégrader la bougie.

merci

Salut,

C’est assez calme par ici :sleeping:

Du coup, de mon coté, j’essaye d’étoffer un peu le script pour arriver à faire une connexion via le site de MCZ à la place du wifi direct.
Avec en plus, la récupération d’autres paramètres (Chronothermostato, Eco, …), le formatage de certaines infos en numérique à la place de ‹ String ›, formatage de date et autre.
Dans les trames échangées, j’ai repéré ceci :

C|RecuperoParametri
C|RecuperoInfo
C|RecuperoGiornoChrono
C|RecuperoParametriExtra|11
C|RecuperoVersioneSW

A voir comment implémenter ça.
Dernière modification en vue : ne remonter que les données modifiées depuis la dernière publication.

Par contre, je ne suis pas à l’aise avec Python, cela risque donc de prendre un certain temps avant d’avoir une version fonctionnelle.

A+

Bonjour à tous,

Tout d’abord merci pour le travail. Je suis assez novice sur jeedom et la domotique en général.

Je pense avoir bien déroulé la procédure.

La découverte de mon broker créer bien un équipement PUBmcz.
Dans celui, je vois une ligne qui remonte les infos du poele (EGO 8M1 tout neuf).
Cette ligne recoit la commande suivante :
[2021-01-30 16:26:18][INFO] : Evènement sur la commande [Aucun][PUBmcz][PUBmcz] valeur : {« RPM - Vis sans fin - LIVE »: 472, « RPM - Ventilateur fumm\u00e9es »: 1494, « Heure du po\u00eale (0-23) »: 16, « Etat du ventilateur d’ambiance »: « Automatique », « Minutes du po\u00eale (0-29) »: 27, « TEMP - Carte m\u00e8re »: 35.5, « Heures de fonctionnement en puissance 1 (s) »: « 2:6:48:14 », « TEMP - Consigne »: 22.0, « Jour du po\u00eale (1-31) »: 30, « Heures de fonctionnement total (s) »: « 6:21:6:55 », « Etat du mode Active »: 1, « Mode Chronotermostato »: 1, « Minutes avant extinction »: 0, « ACTIVE - Live »: 160, « Etat effets sonores »: 1, « Temp\u00e9rature des fum\u00e9es »: 146, « Temp\u00e9rature ambiante »: 21.0, « Heures de fonctionnement en puissance 5 (s) »: « 1:12:6:38 », « Heures de fonctionnement en puissance 2 (s) »: « 0:6:5:50 », « Puissance Active »: « Puissance 5 », « Mode »: « Hiver », « Heures de fonctionnement en puissance 3 (s) »: « 0:10:58:42 », « Etat du po\u00eale »: « Puissance 5 », « Heures de fonctionnement en puissance 4 (s) »: « 0:13:5:0 », « Mode ECO »: 1, « RPM - Vis sans fin - SET »: 474, « Etat de la bougie »: 0, « Heures avant entretien »: 1834, « ACTIVE - Set »: 155, « Ann\u00e9e du po\u00eale »: 2021, « Nombre d’allumages »: 78, « Mode de r\u00e9gulation »: « Dynamique », « Mois du po\u00eale (1-12) »: 1}
Cependant quand je clique sur JSON, il créer des nouvelles commandes vides qui ne fonctionnent pas. Avez vous une idée ?
PS : je suis en jeedom : 4.1.18 et le plugin jMQTT est du 18 février 2020. / NUC 8i5beh / proxmox / 1 vm jeedom / 1 vm debian pour communiquer avec le poele)
Merci d’avance si quelqu’un sait comment aller plus loin.

Je serai partant aussi pour continuer à développer le plug in pour pouvoir utiliser toutes les fonctions du poele, notamment la partie chrono. Mais je suis comme toi, pas trés fort en Python…

En revanche j’ai fait l’analyse de fonctionnement et de comportement des strings chrono.

Voici mon analyse:

Lorsque l’on envoie la string suivante :
42[« chiedo »,{« serialNumber »:« XXXXXXXXXXX »,« macAddress »:« XXXXXXXX »,« tipoChiamata »:1,« richiesta »:« C|RecuperoGiornoChrono »}]
La réponse est : 04|ebc90002aaaaaaaaaaaaaaa0|00000aaaaa8000aaaaaaaaa0|000000aaa800aaaaaaaaaaa0|000002aaaaaa00002aaaaaa0|000002aaaa000002aaaaaaa0|700002aaaa8002aaaaaaaaa0|00000002aaaaa8000aaaaaa0|12|13|18",« socketChiamata »:« XXXXXXXXXXXX »}]

La trame se décompose en 7 partie (une pour chaque jour)
Dans l’exemple:
ebc90002aaaaaaaaaaaaaaa0 est égale à la réponse pour dimanche
00000aaaaa8000aaaaaaaaa0 est égale à la réponse pour lundi
000000aaa800aaaaaaaaaaa0 est égale à la réponse pour mardi
000002aaaaaa00002aaaaaa0 est égale à la réponse pour mercredi
000002aaaa000002aaaaaaa0 est égale à la réponse pour jeudi
700002aaaa8002aaaaaaaaa0 est égale à la réponse pour vendredi
00000002aaaaa8000aaaaaa0 est égale à la réponse pour samedi

Ensuite on peux voir que pour chaque réponse de chaque jour il y a 24 caractères correspondant à chaque heure. Vous me direz que dans l’appli le pas de réglage est par tranche de 30 minutes, il y a en fait une table de correspondance dont voici l’analyse.

Pour chaque pas de temps il y a 4 configurations possibles OFF, T1, T2, T3, et pour chaque pas de temps il y a 2 demi-heures, ce qui donne 16 combinaisons.

Ce qui donne les combinaisons suivante =
OFF,OFF = caractere 0
OFF,T1 = caractere 1
OFF,T2 = caractere 2
OFF,T3 = caractere 3
T1,OFF = caractere 4
T1,T1 = caractere 5
T1,T2 = caractere 6
T1,T3 = caractere 7
T2,OFF = caractere 8
T2,T1 = caractere 9
T2,T2 = caractere a
T2,T3 = caractere b
T3,OFF = caractere c
T3,T1 = caractere d
T3,T2 = caractere e
T3,T3 = caractere f

Est enfin pour envoyer un string de configuration:
42[« chiedo »,{« serialNumber »:« XXXXXXXXX »,« macAddress »:« XXXXXXXXX »,« tipoChiamata »:1,« richiesta »:« C|ScriviGiornoChrono|5|700002aaaa8002aaaaaaaaa0 »}]

L’exemple est pour la configuration du vendredi, le caractère |5| est pour le vendredi.
Ce qui donne pour:
Dimanche : |0|
Lundi : |1|
Mardi : |2|
Mercredi : |3|
Jeudi : |4|
Vendredi : |5|
Samedi : |6|

1 « J'aime »