Skip to content

Module SunSpec

Le protocole SunSpec est un standard industriel pour la communication avec les équipements solaires (onduleurs, compteurs, batteries). Le module modbus inclut un support natif pour SunSpec, permettant la détection automatique et la lecture des données normalisées.

Vue d'ensemble

SunSpec définit des "modèles" standardisés pour différents types d'équipements :

  • Modèle 1 : Informations communes (fabricant, modèle, numéro de série)
  • Modèles 101-103 : Onduleurs monophasé/split/triphasé
  • Modèles 111-113 : Onduleurs avec valeurs flottantes étendues
  • Modèles 124-126 : Stockage et batteries
  • Modèles 201-204 : Compteurs électriques

Prérequis

Le module SunSpec utilise le module modbus existant. Assurez-vous d'avoir configuré votre connexion Modbus correctement.

iot:
  modules:
    modbus:
      - name: modbus1
        transmissionmode: TCP
        controller: tcp://192.168.1.100:502
        slaveid: 1

API Lua

modbus.sunspecDetect()

Détecte automatiquement l'adresse de base SunSpec en testant les adresses standard (40000, 50000, 0).

  • Paramètres : Aucun
  • Retour :
  • base_address (int) : L'adresse de base SunSpec si trouvée
  • nil, error : En cas d'échec
local modbus = require("modbus1")

modbus.connect()

local base_addr, err = modbus.sunspecDetect()
if not base_addr then
    print("Erreur de détection SunSpec : " .. err)
    return
end

print("Adresse de base SunSpec trouvée : " .. base_addr)

modbus.disconnect()

modbus.sunspecScan(baseAddr)

Scanne les modèles SunSpec disponibles à l'adresse de base spécifiée.

  • Paramètres :
  • baseAddr (int) : L'adresse de base SunSpec
  • Retour :
  • models (table) : Liste des modèles trouvés avec leurs métadonnées
  • nil, error : En cas d'échec

Chaque modèle retourné contient :

Champ Type Description
id int Identifiant du modèle SunSpec
length int Longueur en registres
base_addr int Adresse de début du modèle
name string Nom technique du modèle
label string Libellé du modèle
desc string Description du modèle
local modbus = require("modbus1")

modbus.connect()

local base_addr, _ = modbus.sunspecDetect()
local models, err = modbus.sunspecScan(base_addr)

if not models then
    print("Erreur de scan : " .. err)
    return
end

for i, model in ipairs(models) do
    print(string.format("Modèle %d: %s (%s)", model.id, model.name, model.label))
end

modbus.disconnect()

modbus.sunspecReadModel(modelId, baseAddr)

Lit les données d'un modèle SunSpec spécifique.

  • Paramètres :
  • modelId (int) : L'identifiant du modèle à lire
  • baseAddr (int) : L'adresse de base SunSpec
  • Retour :
  • data (table) : Données du modèle avec les noms de points comme clés
  • nil, error : En cas d'échec
local modbus = require("modbus1")

modbus.connect()

local base_addr, _ = modbus.sunspecDetect()

-- Lire le modèle Common (1)
local common, err = modbus.sunspecReadModel(1, base_addr)
if common then
    print("Fabricant : " .. (common.Mn or "N/A"))
    print("Modèle : " .. (common.Md or "N/A"))
    print("Numéro de série : " .. (common.SN or "N/A"))
end

-- Lire un modèle onduleur (101)
local inverter, err = modbus.sunspecReadModel(101, base_addr)
if inverter then
    print("Puissance AC : " .. (inverter.W or 0) .. " W")
    print("Courant AC : " .. (inverter.A or 0) .. " A")
    print("Tension AC : " .. (inverter.PhVphA or 0) .. " V")
end

modbus.disconnect()

modbus.sunspecReadAll(baseAddr)

Lit tous les modèles SunSpec disponibles en une seule opération.

  • Paramètres :
  • baseAddr (int) : L'adresse de base SunSpec
  • Retour :
  • all_data (table) : Table imbriquée avec model_N comme clés
  • nil, error : En cas d'échec
local modbus = require("modbus1")

modbus.connect()

local base_addr, _ = modbus.sunspecDetect()
local all_data, err = modbus.sunspecReadAll(base_addr)

if all_data then
    -- Accéder aux données du modèle Common
    if all_data.model_1 then
        print("Fabricant : " .. (all_data.model_1.Mn or "N/A"))
    end

    -- Accéder aux données de l'onduleur
    if all_data.model_101 then
        print("Puissance : " .. (all_data.model_101.W or 0) .. " W")
    end
end

modbus.disconnect()

Modèles supportés

ID Nom Description
1 Common Informations fabricant, modèle, version (requis)
101 Inverter Single Phase Onduleur monophasé
102 Inverter Split Phase Onduleur biphasé
103 Inverter Three Phase Onduleur triphasé
111 Inverter Single Phase Float Onduleur monophasé (valeurs float)
112 Inverter Split Phase Float Onduleur biphasé (valeurs float)
113 Inverter Three Phase Float Onduleur triphasé (valeurs float)
124 Storage Stockage/batterie
125 Storage Extended Stockage étendu
126 Storage Control Contrôle du stockage
201 Meter Single Phase Compteur monophasé
202 Meter Split Phase Compteur biphasé
203 Meter Three Phase Wye Compteur triphasé (étoile)
204 Meter Three Phase Delta Compteur triphasé (triangle)

Facteurs d'échelle (Scale Factors)

SunSpec utilise des facteurs d'échelle (sunssf) pour optimiser l'utilisation des registres. Le module applique automatiquement ces facteurs.

Exemple : Un registre de tension contenant 2400 avec un facteur d'échelle de -1 retournera 240.0 V.

Les facteurs d'échelle sont lus avant les valeurs et appliqués automatiquement selon la formule :

valeur_réelle = valeur_brute × 10^facteur_échelle

Exemple complet

Script complet pour la collecte de données d'un onduleur SunSpec :

local modbus = require("modbus1")
local alemca = require("alemca")
local json = require("json")

-- Connexion Modbus
local ok, err = modbus.connect()
if not ok then
    printError("Connexion échouée : " .. err)
    return
end

-- Détection SunSpec
local base_addr, err = modbus.sunspecDetect()
if not base_addr then
    printError("Appareil non compatible SunSpec : " .. err)
    modbus.disconnect()
    return
end

printInfo("Base SunSpec : " .. base_addr)

-- Scan des modèles disponibles
local models, err = modbus.sunspecScan(base_addr)
if models then
    printInfo("Modèles disponibles :")
    for _, m in ipairs(models) do
        printInfo("  - " .. m.id .. ": " .. m.label)
    end
end

-- Lecture des données
local data = {}

-- Modèle Common
local common, _ = modbus.sunspecReadModel(1, base_addr)
if common then
    data.manufacturer = common.Mn
    data.model = common.Md
    data.serial = common.SN
    data.version = common.Vr
end

-- Modèle Onduleur (101, 102 ou 103)
for _, model_id in ipairs({101, 102, 103}) do
    local inverter, _ = modbus.sunspecReadModel(model_id, base_addr)
    if inverter then
        data.power_ac = inverter.W
        data.current_ac = inverter.A
        data.voltage_ac = inverter.PhVphA
        data.frequency = inverter.Hz
        data.energy_total = inverter.WH
        data.status = inverter.St
        break
    end
end

modbus.disconnect()

-- Envoi des métriques
if data.power_ac then
    local metrics = {
        {name = "power_ac", value = data.power_ac, unit = "W"},
        {name = "current_ac", value = data.current_ac, unit = "A"},
        {name = "voltage_ac", value = data.voltage_ac, unit = "V"},
        {name = "energy_total", value = data.energy_total, unit = "Wh"}
    }

    alemca.writeMetrics(metrics)
    printInfo("Métriques envoyées : " .. json.encode(data))
end

Points de données courants

Modèle 1 (Common)

Point Type Description
Mn string Fabricant
Md string Modèle
SN string Numéro de série
Vr string Version firmware

Modèles 101-103 (Onduleurs)

Point Type Unité Description
A float A Courant AC total
AphA float A Courant phase A
AphB float A Courant phase B
AphC float A Courant phase C
PhVphA float V Tension phase A
PhVphB float V Tension phase B
PhVphC float V Tension phase C
W float W Puissance AC
Hz float Hz Fréquence
VA float VA Puissance apparente
VAr float var Puissance réactive
PF float % Facteur de puissance
WH float Wh Énergie totale produite
St int - État de fonctionnement

Modèles 201-204 (Compteurs)

Point Type Unité Description
A float A Courant moyen
PhV float V Tension moyenne
W float W Puissance active totale
VA float VA Puissance apparente totale
VAR float var Puissance réactive totale
PF float % Facteur de puissance
TotWhExp float Wh Énergie exportée totale
TotWhImp float Wh Énergie importée totale

Erreurs courantes

Erreur Cause Solution
SunSpec detection failed Signature SunSpec non trouvée Vérifier que l'appareil supporte SunSpec
Model N not found Modèle non disponible sur l'appareil Utiliser sunspecScan pour voir les modèles disponibles
Connection failed Problème de connexion Modbus Vérifier la configuration réseau et les paramètres Modbus

Voir aussi