Passer en dernière beta ou attendre?

Par contre je n’ai jamais fait cette manip…

Il faut faire « créer template » en haut à droite de mon équipement ?
image
Ensuite aller dans le menu template et j’aurai un bouton export ?
image

Voici le reste :

  • L’équipement est le CerboGX de chez Victron :
    CerboGX

  • La liste des commandes :
    Modbus-TCP

  • Le log mymodbus_daemon (en PJ car il y a pas mal de lignes, j’ai un peu de mal à parfaitement isoler les séquences).
    23:01:26 → mode évènement et suvegarde équipement.
    23h02:17 → lancement d’une lecture
    mymodbus_daemon_debug.log (87,3 Ko)

Je n’ai pas remis « mymodbus.log », dis-moi si tu as besoin d’une extraction fraîche.

@+

Exactement, mais c’est bon, j’ai ta config puisque tu as laissé la ligne qui va bien dans les logs.

En se concentrant sur ceci qui correspond à la première erreur dans le cycle de lecture et dont le résultat est identique sur les lectures suivantes avec l’adresse esclave à 0 :

[2024-10-20 23:02:45][DEBUG] : mod_VICTRON_id100: 'one_cycle_read' treatment cmd_id = 16028
[2024-10-20 23:02:45][DEBUG] : mod_VICTRON_id100: 'one_cycle_read'/843 Battery SoC (System): requesting read
[2024-10-20 23:02:45][DEBUG] : Adding transaction 15
[2024-10-20 23:02:45][DEBUG] : send: 0x0 0xf 0x0 0x0 0x0 0x6 0x0 0x3 0x3 0x4b 0x0 0x1
[2024-10-20 23:02:45][ERROR] : mod_VICTRON_id100/843 Battery SoC (System): return error during read request on slave id 0, address 843 -> None
[2024-10-20 23:02:45][DEBUG] : mod_VICTRON_id100: 'add_change' launched with payload = {'values::cycle_ok': {'value': 0, 'eqId': '2056'}}
[2024-10-20 23:02:45][DEBUG] : MyModbusd: Message received from MyModbusClient mod_VICTRON_id100: {'add_change': {'values::cycle_ok': {'value': 0, 'eqId': '2056'}}}
[2024-10-20 23:02:45][DEBUG] : recv: 0x0 0xf 0x0 0x0 0x0 0x5 0x0 0x3 0x2 0x0 0xa old_data:  addr=None
[2024-10-20 23:02:45][DEBUG] : Processing: 0x0 0xf 0x0 0x0 0x0 0x5 0x0 0x3 0x2 0x0 0xa
[2024-10-20 23:02:45][DEBUG] : Factory Response[ReadHoldingRegistersResponse': 3]
[2024-10-20 23:02:45][DEBUG] : Frame advanced, resetting header!!
[2024-10-20 23:02:45][DEBUG] : Getting transaction 15
[2024-10-20 23:02:45][DEBUG] : Send to jeedom: {'values': {'cycle_ok': {'value': 0, 'eqId': '2056'}}}
  • 2 premières lignes : traitement de la commande info avec l’id 16028, c-à-d la première commande avec l’adresse esclave à 0
  • 2 lignes suivantes : pymodbus envoi la requête de lecture
  • ligne 5 : pymodbus renvoie None : c’est ça qui est très étrange, surtout que depuis la version 3.7.3 de pymodbus, ça devrait être corrigé et ce n’est plus None qui doit être renvoyé
  • 2 lignes suivantes : mise à 0 de Cycle OK
  • 4 lignes suivantes : réception de la réponse par le buffer de pymodbus qui a pourtant retourné None juste avant… → valeur = 10, ça peut coller 10% de SoC hier soir à 23h02 ?

Chez au moins 2 utilisateurs de MyModbus qui utilisent l’adresse esclave 0 la version 3.7.3 de pymodbus a corrigé leur problème et j’ai pu le tester chez moi aussi. Chez toi c’est comme si ça n’avait eu aucun impact…

Le démon a été redémarré (pour prendre la nouvelle version de pymodbus en compte) ?
Tu as fait une modification dans le module pymodbus comme proposé par un utilisateur (je ne sais plus qui) ?

Basé sur un exemple d’utilisation de pymodbus, je te propose ce script python :

import logging
from enum import Enum
from math import log10
from time import sleep

from pymodbus import pymodbus_apply_logging_config

# --------------------------------------------------------------------------- #
# import the various client implementations
# --------------------------------------------------------------------------- #
from pymodbus.client import ModbusTcpClient
from pymodbus.exceptions import ModbusException
from pymodbus.pdu import ExceptionResponse
from pymodbus import FramerType


HOST = "172.16.50.151"
PORT = 502
CYCLES = 4


pymodbus_apply_logging_config(logging.ERROR)
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s %(message)s')
_logger = logging.getLogger(__file__)


def main() -> None:
    """Run client setup."""
    _logger.info("### Client starting")
    client: ModbusTcpClient = ModbusTcpClient(
        host=HOST,
        port=PORT,
        # Common optional parameters:
        framer=FramerType.SOCKET,
        timeout=5,
    )
    client.connect()
    _logger.info("### Client connected")
    sleep(1)
    _logger.info("### Client starting")
    for count in range(CYCLES):
        _logger.info(f"Running loop {count}")
        solar_calls(client)
        sleep(10)  # scan interval
    client.close()
    _logger.info("### End of Program")


def solar_calls(client: ModbusTcpClient) -> None:
    """Read registers."""
    error = False
        
    for addr, slave, format, factor, comment, unit in ( # data_type according to ModbusClientMixin.DATATYPE.value[0]
        (3724,   1, "h", 1, "3724 Power tracker5",               "W"),
        ( 843,   0, "H", 1, "843 Battery SoC (System) (id 0)",   "%"),
        ( 843, 100, "H", 1, "843 Battery SoC (System) (id 100)", "%"),
    ):
        if error:
            error = False
            client.close()
            sleep(0.1)
            client.connect()
            sleep(1)
        
        data_type = get_data_type(format)
        count = data_type.value[1]
        var_type = data_type.name

        _logger.info(f"*** Reading {comment} ({var_type})")
        
        try:
            rr = client.read_holding_registers(address=addr, count=count, slave=slave)
        except ModbusException as exc:
            _logger.error(f"Modbus exception: {exc!s}")
            error = True
            continue
        if rr.isError():
            _logger.error(f"Error")
            error = True
            continue
        if isinstance(rr, ExceptionResponse):
            _logger.error(f"Response exception: {rr!s}")
            error = True
            continue
        
        value = client.convert_from_registers(rr.registers, data_type) * factor
        if factor < 1:
            value = round(value, int(log10(factor) * -1))
        _logger.info(f"*** READ *** {comment} = {value} {unit}")


def get_data_type(format: str) -> Enum:
    """Return the ModbusTcpClient.DATATYPE according to the format"""
    for data_type in ModbusTcpClient.DATATYPE:
        if data_type.value[0] == format:
            return data_type


if __name__ == "__main__":
    main()

C’est un script à sauvegarder dans un fichier quelque part sur ta machine Jeedom (via l’éditeur de fichiers) de préférence sous ‹ tests › :

Il faudrait désactiver le plugin et lancer le script avec cette commande dans un terminal :

~www-data/html/plugins/mymodbus/resources/venv/bin/python3 ~www-data/html/tests/[Nom de ton script.py]

Le script peut ensuite être supprimé.

Avant de tester le script, passe les adresses esclave de 0 à 100.

GX Modbus-TCP Manual [Victron Energy]

Note that both Unit-ID 0 and Unit-ID 100 map to the same internal address. We recommend to use ID 100, since many Modbus-TCP clients and PLCs do not work with ID 0.

Exact !

On est certain que cette version est bien installée chez moi ? (Je n’arrive pas à vérifier …).

Il me semble que oui mais dans le doute je viens de refaire ça :

  • équipement en mode évènement (je l’avais remis en polling)
  • sauvegarde équipement
  • relance démon
  • lecture/rafraichir équipement

→ Pas de changement.

Non aucune modification effectuée.

Questions à propos du script :

  • Il ne « traite » que deux registres (3724 et 843) → c’est juste du debug ?
  • J’ai du mal à le lire → quelle est sa fonction (en deux mots, juste pour comprendre) ?
  • Donc je ne passe en « slave_100 » que ces 2 éléments 3724 et 843 pour test → OK ?

Bingo !

Je viens d’aller vérifier dans la configuration du Cerbo, le device qui pose souci est à 100 et non à 0 ! Donc j’ai modifié toutes les commandes de 0 → 100, tout remonte sans erreur :+1:

Par contre, c’était fonctionnel avec l’ancienne version de modbus, je ne comprends pas comment :thinking:

Il y a juste un dernier truc, j’ai l’impression que le refresh est un peu moins réactif avec cette nouvelle version. J’aimerais un refresh à la seconde, est-ce que cette config te parait cohérente avec le besoin ?

Oui

C’est un test de fonctionnement avec les cas id = 1, id = 0 et id = 100

Déjà tester une ou deux et si c’est concluant tout passer en id 100

ah ben voilà…

ancienne version de pymodbus aussi, je ne connais pas tous les détails des modifications entre la 2.5 et la 3.7 (il doit y en avoir quelques unes…)

Tant de choses à répondre… Je fais un résumé :

Sur le temps de cycle de cette version bêta : les lectures se font les unes après les autres sans pause liées au traitement puisque les appels sont faits de manière asynchrone. Le traitement des lectures se fait en tâche de fond. Donc difficile de faire plus rapide. Une mesure plus précise permettrait de comparer les performances.
MAIS l’utilisation des plages de registres diminue largement le temps de cycle. Il y a un chapitre dans la doc là-dessus, fais des essais.
De plus le temps de cycle est renseigné dans une commande ainsi que le polling effectif.

Un refresh à la seconde : ça dépend de ton équipement, du type de connexion, du nombre de requêtes. En utilisant les plages de registres tu diminues le nombre de requêtes. En Ethernet filaire c’est ce qu’il y a de plus rapide.

Ta config doit être en phase avec ton appareil, pas uniquement avec ton besoin.

Bien sûr, mais je pars d’un environnement connu, sur lequel la réactivité était parfaite.

Je viens de faire quelques tests sur une commande : 817 id100 (puissance instantanée).
En fait Il y a un truc qui ne colle pas :

  • le CerboGX rafraîchit la puissance sur son serveur web.
  • l’ancienne version de Mymodbus rafraîchissait pareil.
  • la nouvelle version de Mymodbus ne rafraîchit pas (comme si certains id100 coincent).

Dans un premier temps, je vais revérifier les différents paramètres, et regarder s’il y a d’autres registres impactés. A suivre…

Avec les log debug du démon on arrive à voir ce qu’il se passe en détail. Regarde si un moment te paraît suspect et poste les log de ce moment là.
Ton impression est peut-être faussée.
Ou alors il est encore possible d’améliorer cette version.
Dans tous les cas, songe à utiliser les plages de registres.

Il y a eu une mise a jour de firmware?

OK on fait ça…

C’est ce que j’ai cru à un moment mais pour le coup non. Je surveille le solaire xxx fois par jour (tout est affiché en partie basse du design sur la tablette murale). Avant, les valeurs de production (solaire, consommation onduleur, etc… ) se rafraîchissaient vraiment vite (1 à 2 secondes).

Là j’en ai qui ne se rafraîchissent plus ou peu. Il est probable qu’une fois que ce problème réglé, la réactivité reviendra. → Je vais investiguer pour avoir des éléments plus précis.

Tu veux dire être certain d’avoir migrer tous les slave id 0 en slave id 100.*
→ C’est bien ça ?

Oui le CerboGX a évolué, mais comme j’ai utilisé le nouveau firmware avec l’ancien Modbus, je peux confirmer que je n’ai pas vu de régression sur la fréquence du refresh.

Merci pour ton support :+1:

A suivre.

Non, regarde la Doc, tu verras de quoi je veux parler.
Certains fils en parlent aussi

Bonne nouvelle, tout est revenu à la normale !

Je résume si d’autres utilisateurs Victron étaient concernés :

1. Commandes en « slave_id » = 0 qui ne remontaient pas
→ Réglé en configurant tous ces « slave_id » à 100.

2. Soucis global de refresh des données
→ Réglé en passant le temps entre deux requêtes de 1 → 0.01
(nb : c’est la valeur par défaut lorsque l’on créé un nouvel équipement)

Pour info ma configuration fonctionnelle avec :

  • firmware Cerbo GX v3.42
  • version Mymodbus beta actuelle :
    image

image

Je ne regrette pas le temps passé :
→ pas de gap de version, donc facilité de passage en stable…

@Michel_F merci encore pour le support sans faille :+1:

1 « J'aime »