Module modbus
Le module modbus permet d'interagir avec des appareils Modbus via TCP/RTU.
Import
Pour importer :
Configuration YAML
Le module modbus nécessite une configuration spécifique pour fonctionner. Cette configuration est définie dans le fichier de configuration de l'agent.
Pour la configuration voici un exemple de toutes les options possibles :
iot:
modules:
modbus: # module modbus
- name: modbus1 # nom du module
transmissionmode: RTU # mode de transmission (auto, TCP, RTUoverTCP, ASCIIoverTCP, RTU, ASCII, file)
controller: file:///dev/ttyUSB0 # contrôleur (file, tcp)
baudrate: 9600 # baudrate
databits: 8 # databits
parity: N # parity (N, E, O)
stopbits: 1 # stopbits
slaveid: 1 # slaveid
timeout: 5 # timeout en secondes
debug: false # permet d'activer le mode debug
rs485: # configuration rs485
enabled: false # activer rs485
delay_rts_before_send: 2 # délai avant l'envoi
delay_rts_after_send: 2 # délai après l'envoi
rts_high_during_send: false # rts haut pendant l'envoi
rts_high_after_send: false # rts haut après l'envoi
rx_during_tx: false # rx pendant tx
- name: modbus2 # nom du module
transmissionmode: TCP # mode de transmission
controller: tcp://127.0.0.1:502 # contrôleur
slaveid: 1 # slaveid
Détails de la configuration
- name : Nom du module. Il doit être unique et ne pas contenir d'espaces ou de caractères spéciaux.
- transmissionmode : Mode de transmission. Il peut s'agir de
auto,TCP,RTUoverTCP,ASCIIoverTCP,RTU,ASCII, oufile. - controller : Contrôleur. Il peut s'agir d'un fichier (ex.
/dev/ttyUSB0,file:///dev/ttyUSB0) ou d'une adresse TCP (ex.tcp://127.0.0.1:502). - baudrate : Baudrate pour la communication série (ex.
9600). - databits : Nombre de bits de données (ex.
8). - parity : Parité pour la communication série. Il peut s'agir de
N(aucune),E(pair), ouO(impair). - stopbits : Nombre de bits d'arrêt (ex.
1). - slaveid : ID de l'esclave Modbus (ex.
1). - timeout : Délai d'attente pour les opérations Modbus, en secondes (ex.
5). - debug : Permet d'activer le mode debug pour le module Modbus (ex.
false). - rs485 : Configuration pour le mode RS485.
- enabled : Activer le mode RS485 (ex.
false). - delay_rts_before_send : Délai avant l'envoi, en millisecondes (ex.
2). - delay_rts_after_send : Délai après l'envoi, en millisecondes (ex.
2). - rts_high_during_send : RTS haut pendant l'envoi (ex.
false). - rts_high_after_send : RTS haut après l'envoi (ex.
false). - rx_during_tx : RX pendant TX (ex.
false).
API Lua
Liste des fonctions
| Fonction | Signature Lua | Rôle | Retour (succès) | Retour (échec) |
|---|---|---|---|---|
connect |
bool, err = modbus.connect() |
Établit une connexion Modbus. | true, nil |
nil, "msg" |
disconnect |
bool, err = modbus.disconnect() |
Ferme la connexion Modbus. | true, nil |
nil, "msg" |
readCoils |
tbl, err = modbus.readCoils(address, quantity) |
Lit les coils (bits). | table, nil |
nil, "msg" |
writeSingleCoil |
bool, err = modbus.writeSingleCoil(address, value) |
Écrit un coil unique. | true, nil |
nil, "msg" |
writeMultipleCoils |
bool, err = modbus.writeMultipleCoils(address, values) |
Écrit plusieurs coils. | true, nil |
nil, "msg" |
readDiscreteInputs |
tbl, err = modbus.readDiscreteInputs(addr, byteorder[, resultType]) |
Lit les entrées discrètes. | table, nil |
nil, "msg" |
readHoldingRegisters |
tbl, err = modbus.readHoldingRegisters(addr, byteorder[, resultType, qty]) |
Lit les registres de maintien. | table, nil |
nil, "msg" |
writeSingleRegister |
bool, err = modbus.writeSingleRegister(address, value) |
Écrit un registre unique. | true, nil |
nil, "msg" |
writeMultipleRegisters |
bool, err = modbus.writeMultipleRegisters(addr, byteorder, qty, val[, type]) |
Écrit plusieurs registres. | true, nil |
nil, "msg" |
readInputRegisters |
tbl, err = modbus.readInputRegisters(addr, byteorder[, resultType, qty]) |
Lit les registres d'entrée. | table, nil |
nil, "msg" |
setSlaveId |
modbus.setSlaveId(slaveId) |
Change l'ID esclave. | nil |
– |
sunspecDetect |
addr, err = modbus.sunspecDetect() |
Détecte l'adresse SunSpec. | number, nil |
nil, "msg" |
sunspecScan |
models, err = modbus.sunspecScan(base_addr) |
Scanne les modèles SunSpec. | table, nil |
nil, "msg" |
sunspecReadModel |
data, units, err = modbus.sunspecReadModel(id, base_addr) |
Lit un modèle SunSpec. | table, table, nil |
nil, nil, "msg" |
sunspecReadAll |
data, units, err = modbus.sunspecReadAll(base_addr) |
Lit tous les modèles SunSpec. | table, table, nil |
nil, nil, "msg" |
| Champs | modbus.name, modbus.type |
Métadonnées du module. | – | – |
modbus.connect()
Établit une connexion avec l'appareil Modbus.
- Paramètres : Aucun
- Retour :
truesi la connexion est réussie.- En cas d'échec, retourne
nilsuivi d'un message d'erreur.
local modbus = require("modbus1")
local status, err = modbus.connect()
if not status then
print("Erreur lors de la connexion Modbus : " .. err)
return
end
modbus.disconnect()
Ferme la connexion avec l'appareil Modbus.
- Paramètres : Aucun
- Retour :
truesi la déconnexion est réussie.- En cas d'échec, retourne
nilsuivi d'un message d'erreur.
local status, err = modbus.disconnect()
if not status then
print("Erreur lors de la déconnexion Modbus : " .. err)
return
end
modbus.readCoils(address, quantity)
Lit les coils (bobines) depuis l'appareil Modbus à l'adresse spécifiée.
- Paramètres :
address(int) : L'adresse de départ des coils à lire.-
quantity(int) : Le nombre de coils à lire. -
Retour :
- Un tableau Lua contenant les valeurs booléennes (
true/false) des coils lus. nilsuivi d'un message d'erreur en cas d'échec.
local modbus = require("modbus1")
local address = 0 -- adresse de départ
local quantity = 8 -- nombre de coils à lire
local coils, err = modbus.readCoils(address, quantity)
if not coils then
print("Erreur lors de la lecture des coils : " .. err)
else
for i, v in ipairs(coils) do
print("Coil " .. (address + i - 1) .. ": " .. tostring(v))
end
end
modbus.writeSingleCoil(address, value)
Écrit une valeur unique dans un coil à l'adresse spécifiée.
- Paramètres :
address(int) : L'adresse du coil à écrire.-
value(bool) : La valeur à écrire (trueoufalse). -
Retour :
truesi l'écriture est réussie.- En cas d'échec, retourne
nilsuivi d'un message d'erreur.
local modbus = require("modbus1")
local address = 0 -- adresse du coil
local value = true -- valeur à écrire
local status, err = modbus.writeSingleCoil(address, value)
if not status then
print("Erreur lors de l'écriture du coil : " .. err)
else
print("Coil " .. address .. " écrit avec succès.")
end
modbus.writeMultipleCoils(address, values)
Écrit plusieurs valeurs dans des coils à l'adresse spécifiée.
- Paramètres :
address(int) : L'adresse à partir de laquelle commencer l'écriture.-
values(string) : Une chaîne représentant les valeurs ('1'ou'0'). -
Retour :
truesi l'écriture est réussie.- En cas d'échec, retourne
nilsuivi d'un message d'erreur.
local modbus = require("modbus1")
local address = 0 -- adresse de départ
local values = "1100" -- valeurs à écrire (ex. '1100')
local status, err = modbus.writeMultipleCoils(address, values)
if not status then
print("Erreur lors de l'écriture des coils : " .. err)
else
print("Coils écrits avec succès à partir de l'adresse " .. address .. ".")
end
modbus.readDiscreteInputs(address, byteorder[, resultType])
Lit les entrées discrètes depuis l'appareil Modbus à l'adresse spécifiée.
- Paramètres :
address(int) : L'adresse à partir de laquelle commencer la lecture.byteorder(string) : L'ordre des octets.-
resultType(string, optionnel) : Le type de résultat attendu (par défautint16). -
Retour :
- Un tableau Lua contenant les résultats ou
nilsuivi d'un message d'erreur en cas d'échec.
local modbus = require("modbus1")
local address = 0 -- adresse de départ
local byteorder = "big" -- ordre des octets
local resultType = "int16" -- type de résultat (optionnel)
local inputs, err = modbus.readDiscreteInputs(address, byteorder, resultType)
if not inputs then
print("Erreur lors de la lecture des entrées discrètes : " .. err)
else
for i, v in ipairs(inputs) do
print("Input " .. (address + i - 1) .. ": " .. v)
end
end
modbus.readHoldingRegisters(address, byteorder[, resultType, quantity])
Lit les registres de maintien (holding registers) depuis l'appareil Modbus.
- Paramètres :
address(int) : L'adresse du premier registre à lire.byteorder(string) : L'ordre des octets.resultType(string, optionnel) : Le type de résultat attendu (par défautint16).-
quantity(int, optionnel) : Le nombre de registres à lire (défaut : déterminé parresultType). -
Retour :
- Un tableau Lua contenant les résultats ou
nilsuivi d'un message d'erreur en cas d'échec.
local modbus = require("modbus1")
local address = 0 -- adresse de départ
local byteorder = "big" -- ordre des octets
local resultType = "int16" -- type de résultat (optionnel)
local quantity = 10 -- nombre de registres à lire (optionnel)
local registers, err = modbus.readHoldingRegisters(address, byteorder, resultType, quantity)
if not registers then
print("Erreur lors de la lecture des registres de maintien : " .. err)
else
for i, v in ipairs(registers) do
print("Register " .. (address + i - 1) .. ": " .. v)
end
end
modbus.writeSingleRegister(address, value)
Écrit une valeur unique dans un registre à l'adresse spécifiée.
- Paramètres :
address(int) : L'adresse du registre à écrire.-
value(int) : La valeur à écrire. -
Retour :
truesi l'écriture est réussie.- En cas d'échec, retourne
nilsuivi d'un message d'erreur.
local modbus = require("modbus1")
local address = 0 -- adresse du registre
local value = 12345 -- valeur à écrire
local status, err = modbus.writeSingleRegister(address, value)
if not status then
print("Erreur lors de l'écriture du registre : " .. err)
else
print("Register " .. address .. " écrit avec succès.")
end
modbus.writeMultipleRegisters(address, byteorder, quantity, value[, valueType])
Écrit plusieurs registres dans l'appareil Modbus.
- Paramètres :
address(int) : L'adresse à partir de laquelle commencer l'écriture.byteorder(string) : L'ordre des octets.quantity(int) : Le nombre de registres à écrire.value(variable) : La valeur à écrire.-
valueType(string, optionnel) : Le type de la valeur (défaut :int16). -
Retour :
truesi l'écriture est réussie.- En cas d'échec, retourne
nilsuivi d'un message d'erreur.
local modbus = require("modbus1")
local address = 0 -- adresse de départ
local byteorder = "big" -- ordre des octets
local quantity = 2 -- nombre de registres à écrire
local value = 12345 -- valeur à écrire
local valueType = "int16" -- type de valeur (optionnel)
local status, err = modbus.writeMultipleRegisters(address, byteorder, quantity, value, valueType)
if not status then
print("Erreur lors de l'écriture des registres : " .. err)
else
print("Registres écrits avec succès à partir de l'adresse " .. address .. ".")
end
modbus.readInputRegisters(address, byteorder[, resultType, quantity])
Lit les registres d'entrée (input registers) depuis l'appareil Modbus.
- Paramètres :
address(int) : L'adresse du premier registre à lire.byteorder(string) : L'ordre des octets.resultType(string, optionnel) : Le type de résultat attendu (par défautint16).-
quantity(int, optionnel) : Le nombre de registres à lire (défaut : déterminé parresultType). -
Retour :
- Un tableau Lua contenant les résultats ou
nilsuivi d'un message d'erreur en cas d'échec.
local modbus = require("modbus1")
local address = 0 -- adresse de départ
local byteorder = "big" -- ordre des octets
local resultType = "int16" -- type de résultat (optionnel)
local quantity = 10 -- nombre de registres à lire (optionnel)
local registers, err = modbus.readInputRegisters(address, byteorder, resultType, quantity)
if not registers then
print("Erreur lors de la lecture des registres d'entrée : " .. err)
else
for i, v in ipairs(registers) do
print("Input Register " .. (address + i - 1) .. ": " .. v)
end
end
modbus.setSlaveId(slaveId)
Change l'ID de l'esclave pour la connexion Modbus.
- Paramètres :
-
slaveId(int) : Le nouvel ID de l'esclave. -
Retour :
truesi l'ID de l'esclave est défini avec succès.- En cas d'échec, retourne
nilsuivi d'un message d'erreur.
local modbus = require("modbus1")
local newSlaveId = 2 -- nouvel ID de l'esclave
local status, err = modbus.setSlaveId(newSlaveId)
if not status then
print("Erreur lors de la définition de l'ID de l'esclave : " .. err)
else
print("ID de l'esclave défini avec succès à " .. newSlaveId .. ".")
end
Support SunSpec
Le module Modbus intègre le support du protocole SunSpec pour la communication avec les onduleurs solaires et compteurs d'énergie. SunSpec est un standard industriel qui définit des modèles de données normalisés accessibles via Modbus.
modbus.sunspecDetect()
Détecte automatiquement l'adresse de base SunSpec sur l'appareil connecté. La fonction recherche la signature "SunS" aux adresses standard (40000, 50000, 0).
- Paramètres : Aucun
- Retour :
- L'adresse de base SunSpec (number).
nilet un message d'erreur si la signature n'est pas trouvée.
local modbus = require("modbus1")
modbus.connect()
local base_addr, err = modbus.sunspecDetect()
if not base_addr then
print("Erreur de détection SunSpec : " .. err)
else
print("Signature SunSpec trouvée à l'adresse " .. base_addr)
end
modbus.disconnect()
modbus.sunspecScan(base_addr)
Scanne les modèles SunSpec disponibles à partir de l'adresse de base spécifiée.
- Paramètres :
-
base_addr(int) : Adresse de base SunSpec (obtenue viasunspecDetect()). -
Retour :
- Une table Lua contenant les modèles découverts.
nilet un message d'erreur en cas d'échec.
Chaque modèle dans la table contient :
- id : Identifiant du modèle SunSpec
- length : Longueur du modèle en registres
- base_addr : Adresse de début du modèle
- name : Nom du modèle (si disponible)
- label : Label descriptif (si disponible)
- desc : Description du modèle (si disponible)
local modbus = require("modbus1")
modbus.connect()
local base_addr, err = modbus.sunspecDetect()
if not base_addr then
print("Erreur : " .. err)
modbus.disconnect()
return
end
local models, err = modbus.sunspecScan(base_addr)
if not models then
print("Erreur lors du scan SunSpec : " .. err)
else
for _, model in ipairs(models) do
print("Modèle " .. model.id .. " (" .. (model.label or "inconnu") .. ") à l'adresse " .. model.base_addr)
end
end
modbus.disconnect()
modbus.sunspecReadModel(model_id, base_addr)
Lit les données d'un modèle SunSpec spécifique.
- Paramètres :
model_id(int) : L'identifiant du modèle SunSpec à lire.-
base_addr(int) : Adresse de base SunSpec. -
Retour :
data: Table Lua contenant les valeurs du modèle avec les facteurs d'échelle appliqués.units: Table Lua contenant les unités pour chaque champ (ex.{W = "W", A = "A"}).nil, nil, erren cas d'échec.
local modbus = require("modbus1")
modbus.connect()
local base_addr, err = modbus.sunspecDetect()
if not base_addr then
print("Erreur : " .. err)
modbus.disconnect()
return
end
-- Lecture du modèle 103 (onduleur triphasé)
local data, units, err = modbus.sunspecReadModel(103, base_addr)
if not data then
print("Erreur lors de la lecture SunSpec : " .. err)
else
print("Puissance AC : " .. data.W .. " " .. (units.W or ""))
print("Tension phase A : " .. data.PhVphA .. " " .. (units.PhVphA or ""))
print("Courant total : " .. data.A .. " " .. (units.A or ""))
end
modbus.disconnect()
modbus.sunspecReadAll(base_addr)
Lit tous les modèles SunSpec disponibles à l'adresse de base spécifiée.
- Paramètres :
-
base_addr(int) : Adresse de base SunSpec. -
Retour :
data: Table Lua avec les données de chaque modèle, indexée parmodel_N(ex.model_1,model_103).units: Table Lua avec les unités de chaque modèle, même indexation.nil, nil, erren cas d'échec.
local modbus = require("modbus1")
local json = require("json")
modbus.connect()
local base_addr, err = modbus.sunspecDetect()
if not base_addr then
print("Erreur : " .. err)
modbus.disconnect()
return
end
local data, units, err = modbus.sunspecReadAll(base_addr)
if not data then
print("Erreur : " .. err)
else
-- Accès aux données du modèle Common (1)
if data.model_1 then
print("Fabricant : " .. (data.model_1.Mn or ""))
print("Modèle : " .. (data.model_1.Md or ""))
end
-- Accès aux données de l'onduleur (103)
if data.model_103 then
print("Puissance : " .. data.model_103.W .. " " .. (units.model_103.W or ""))
end
end
modbus.disconnect()
Modèles SunSpec courants
| Model ID | Description | Usage |
|---|---|---|
| 1 | Common Model | Identification de l'appareil (fabricant, modèle, série) |
| 101 | Inverter (Single Phase) | Onduleur monophasé |
| 102 | Inverter (Split Phase) | Onduleur split-phase |
| 103 | Inverter (Three Phase) | Onduleur triphasé |
| 111-113 | Extended Inverter | Onduleurs avec valeurs float |
| 124-126 | Storage | Batteries et stockage |
| 201-204 | Meter | Compteurs d'énergie |
Facteurs d'échelle
Les facteurs d'échelle SunSpec (type sunssf) sont automatiquement appliqués aux valeurs retournées. Par exemple, si un registre de tension contient 2400 avec un facteur d'échelle de -1, la valeur retournée sera 240.0 V.
Les valeurs "not implemented" (marqueurs SunSpec 0x8000, 0x80000000, NaN) sont automatiquement filtrées et n'apparaissent pas dans les données retournées.
Champs Lua associés
modbus.name: Retourne le nom de l'instanceModbus.modbus.type: Retourne le type du module (ici,modbus1).