Bonjour,
j’ai préparé quelque chose, voilà une procédure pour tester sachant que ça risque fortement de ne pas fonctionner puisque le script n’a jamais été testé.
1. Créer le script
Dans Réglages / Système / Editeur de fichiers, créer un fichier dans le répertoire tests avec cette icone :
Renommer ce fichier fc23.py
Double cliquer sur ce fichier et coller le script suivant :
#!/usr/bin/env python3
import logging
import argparse
from pymodbus import pymodbus_apply_logging_config
from pymodbus.client import ModbusSerialClient
from pymodbus.exceptions import ModbusException
from pymodbus.pdu import ExceptionResponse
from pymodbus import FramerType
pymodbus_apply_logging_config(logging.ERROR)
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(levelname)s %(message)s')
_logger = logging.getLogger(__file__)
def parse_args():
parser = argparse.ArgumentParser(description="Script de test de la fonctionnalité de lecture/écriture avec FC23")
parser.add_argument("--port", type=str, default="/dev/serial0", help="Interface série à utiliser")
parser.add_argument("--address", type=int, default=1, help="Device ID. Numéro de l'esclave")
parser.add_argument("--idb", type=str, default="0217C1", help="Bus ID IDB (18 bit dans 3 octets)")
parser.add_argument("--idal", type=str, default="0E", help="Bus ID IDAL (5 bit dans 1 octet)")
parser.add_argument("--tabNr", type=int, default=0, help="Tab number")
parser.add_argument("--index", type=int, default=1, help="Index")
return parser.parse_args()
def main() -> None:
args = parse_args()
_logger.info("### Début du programme")
assert 0 <= args.address <= 247, "L'adresse doit être entre 0 et 247"
assert len(args.idb) == 6, "IDB doit être long de 6 caractères pour représenter 3 octets"
assert len(args.idal) == 2, "IDAL doit être long de 2 caractères pour représenter 1 octet"
assert 0 <= args.tabNr <= 4, "Tab number doit être entre 0 et 4"
assert 0 <= args.index <= 255, "Index doit être entre 0 et 255"
# Construction des registres à envoyer
registers = idx2reg(args.idal, args.idb)
registers.append(args.tabNr)
registers.append(args.index)
# valeur à utiliser d'une manière ou d'une autre
value = 0
write_value = ModbusSerialClient.convert_to_registers(value, ModbusSerialClient.DATATYPE.FLOAT32)
registers.extend(write_value) # valeur à écrire
_logger.info("### Connexion au client")
client = ModbusSerialClient(
port=args.port,
parity="E",
framer=FramerType.RTU,
timeout=5,
)
client.connect()
_logger.info("### Client connecté")
error = False
try:
# write_address => 0: read, 1: write d'après la documentation
rr = client.readwrite_registers(read_address=0, read_count=0, write_address=0, values=registers, slave=args.address)
except ModbusException as exc:
_logger.error(f"Exception Modbus : {exc!s}")
error = True
if not error and rr.isError():
_logger.error(f"Erreur")
error = True
if not error and isinstance(rr, ExceptionResponse):
_logger.error(f"Response exception : {rr!s}")
error = True
if not error:
_logger.info(f"Réponse: {rr.registers}")
value = client.convert_from_registers(rr.registers[-4], client.DATATYPE.FLOAT32)
_logger.info(f"Valeur lue: {value}")
else:
_logger.error("Une erreur est survenue")
client.close()
_logger.info("### Fin du programme")
def idx2reg(idal, idb) -> list[int]:
registers = bytearray()
registers.extend(bytes.fromhex(idal))
registers.extend(bytes.fromhex(idb))
ret = []
for i in range(0, len(registers), 2):
ret.append(int.from_bytes(registers[i:i+2], byteorder='big', signed=False))
return ret
if __name__ == "__main__":
main()
Cliquer sur le bouton Sauvegarder & Fermer :
2. Préparer le terrain
Ouvrir une session terminal (ssh ou console locale sur la VM) et se placer dans le répertoire tests et rendre le script exécutable :
cd ~www-data/html/tests
chmod +x fc23.py
2.1. Installer pymodbus
Pour éviter de perturber le système avec d’éventuelles dépendances supplémentaires à gérer on va faire ça dans un venv isolé. Dans le shell :
python3 -m venv modbus
Cette commande va créer un venv nommé modbus. Dans l’éditeurs de fichiers, si tu réactualises l’affichage, tu verras qu’un répertoire modbus est créé.
Pour activer ce venv :
source modbus/bin/activate
Maintenant on peut installer pymodbus et les dépendances pour les liaisons série dont tu as besoin dans le venv actif :
pip install pymodbus[serial]
3. Exécuter le script
Le script prend les paramètres suivants :
- port : le port série à utiliser
/dev/ttyUSB1
par exemple - address : device ID tel que défini dans la documentation chapitre 3 :
1
par exemple - idb : la valeur idb telle que définie dans la doc (en héxadécimal mais sans
0x
devant) mais sur 2 caractères impérativement :0E
par exemple (pour reprendre l’exemple de la doc) - idal : la valeur idal telle que définie dans la doc (en héxadécimal mais sans
0x
devant) mais sur 6 caractères impérativement :0217C1
par exemple (pour reprendre l’exemple de la doc) - tabNr : la valeur tabNr telle que définie dans la doc :
0
pour monitoring - index : la valeur index telle que définie dans la doc :
1
pour reprendre l’exemple de la doc
Test avec la commande suivante. C’est à toi de renseigner les bons paramètres :
./fc23.py --port /dev/ttyUSB1 --address 1 --idb 0E --idal 0217C1 --tabNr 0 --index 1
Et à partir de là je ne peux plus tester chez moi, à toi de me dire ce qu’il se passe.
Si tout va bien tu vas avoir des log de retour dont une ligne avec Valeur lue : xxx
. Si tu as ça du premier coup, je serai très étonné, un script ne fonctionne jamais du premier coup.
→ A toi de jouer !