Initial commit
This commit is contained in:
18
Dockerfile
Executable file
18
Dockerfile
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
# Utilisez une image de base Python officielle
|
||||||
|
FROM python:3.9-slim
|
||||||
|
|
||||||
|
# Définissez le répertoire de travail dans le conteneur
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Copiez le fichier des exigences dans le conteneur
|
||||||
|
COPY requirements.txt ./
|
||||||
|
|
||||||
|
# Installez les dépendances
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# Copier seulement le fichier main.py et config.yaml dans le conteneur
|
||||||
|
COPY ./src/main.py /usr/src/app/main.py
|
||||||
|
COPY ./config/config.yaml /usr/src/app/config.yaml
|
||||||
|
|
||||||
|
# Commande pour exécuter l'application
|
||||||
|
CMD ["python", "./main.py"]
|
||||||
467
config/config.yaml
Executable file
467
config/config.yaml
Executable file
@@ -0,0 +1,467 @@
|
|||||||
|
# Digital Outputs
|
||||||
|
# Function: Read Coil Status (FC=01)
|
||||||
|
# Address Range: 00001-00158
|
||||||
|
|
||||||
|
# Digital Inputs
|
||||||
|
# Function: Read Input Status (FC=02)
|
||||||
|
# Address Range: 10001-10086
|
||||||
|
|
||||||
|
# Actual Values
|
||||||
|
# Function: Read Input Registers(FC=04)
|
||||||
|
# Address Range: 30001-30272
|
||||||
|
# input_type : input
|
||||||
|
|
||||||
|
# Parameters
|
||||||
|
# Function: Read Holding Registers(FC=03)
|
||||||
|
# Address Range: 40001-41094
|
||||||
|
# input_type: holding
|
||||||
|
|
||||||
|
|
||||||
|
mqtt:
|
||||||
|
host: "10.0.0.3"
|
||||||
|
port: 1883
|
||||||
|
user: ""
|
||||||
|
password: ""
|
||||||
|
topic_prefix: "froling/S3Turbo"
|
||||||
|
|
||||||
|
homeassistant:
|
||||||
|
autodiscovery: True
|
||||||
|
discovery_prefix: "homeassistant" # Préfixe par défaut pour l'autodiscovery
|
||||||
|
node_id: "froling" # Remplacer par l'identifiant unique du dispositif
|
||||||
|
|
||||||
|
modbus:
|
||||||
|
host: "10.0.0.12"
|
||||||
|
port: 502
|
||||||
|
unit_id: 2
|
||||||
|
timeout: 30
|
||||||
|
|
||||||
|
refresh_rate: 10 # Fréquence d'actualisation en secondes
|
||||||
|
|
||||||
|
device:
|
||||||
|
identifiers: "FrolingS3" # Remplacer par l'identifiant unique du dispositif
|
||||||
|
manufacturer: "Froling" # Remplacer par le fabricant du dispositif
|
||||||
|
model: "S3" # Remplacer par le modèle du dispositif
|
||||||
|
name: "Froling S3" # Remplacer par le nom du dispositif
|
||||||
|
sw_version: "1.0" # Remplacer par la version du logiciel du dispositif, si applicable
|
||||||
|
# configuration_url: "http://example.com" # Remplacer par l'URL de configuration ou de documentation du dispositif
|
||||||
|
|
||||||
|
|
||||||
|
# Ajout des paramètres pour l'état de l'installation et l'état de la chaudière
|
||||||
|
value_maps:
|
||||||
|
SystemStatus:
|
||||||
|
0: "Charge continue"
|
||||||
|
1: "Eau chaude sanitaire"
|
||||||
|
2: "Automatique"
|
||||||
|
3: "Fonctionnement au bois de chauffage"
|
||||||
|
4: "Nettoyage"
|
||||||
|
5: "Éteint"
|
||||||
|
6: "Chauffage supplémentaire"
|
||||||
|
7: "Ramoneur"
|
||||||
|
8: "Nettoyage2"
|
||||||
|
FurnaceStatus:
|
||||||
|
0: "DÉFAUT"
|
||||||
|
1: "Chaudière éteinte"
|
||||||
|
2: "Montée en température"
|
||||||
|
3: "Chauffage"
|
||||||
|
4: "Maintien du feu"
|
||||||
|
5: "Feu éteint"
|
||||||
|
6: "Porte ouverte"
|
||||||
|
7: "Préparation"
|
||||||
|
8: "Préchauffage"
|
||||||
|
9: "Allumage"
|
||||||
|
10: "Attente d'arrêt"
|
||||||
|
11: "Attente d'arrêt1"
|
||||||
|
12: "Arrêt_Alimentation1"
|
||||||
|
13: "Arrêt_Attente2"
|
||||||
|
14: "Arrêt_Alimentation2"
|
||||||
|
15: "Nettoyage"
|
||||||
|
16: "Attente_2h"
|
||||||
|
17: "Aspiration_Chauffage"
|
||||||
|
18: "Défaut_d'allumage"
|
||||||
|
19: "Prêt_à_l'emploi"
|
||||||
|
|
||||||
|
entities:
|
||||||
|
- name: "Etats systeme"
|
||||||
|
unique_id: "etats_systeme_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
#device_class: "enum"
|
||||||
|
#state_class: "measurement"
|
||||||
|
icon: "mdi:radiator"
|
||||||
|
unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/ETATS_SYSTEME/state"
|
||||||
|
value_template: "{{ value_json.etats_systeme_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 34001
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 1
|
||||||
|
value_map: "SystemStatus"
|
||||||
|
signed: false
|
||||||
|
- name: "Etat Chaudiere"
|
||||||
|
unique_id: "etats_chaudiere_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
#device_class: "enum"
|
||||||
|
#state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler-alert"
|
||||||
|
unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/ETATS_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value_json.etats_chaudiere_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 34002
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: "FurnaceStatus"
|
||||||
|
signed: false
|
||||||
|
- name: "T° Chaudiere"
|
||||||
|
unique_id: "temperature_chaudiere_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:hydraulic-oil-temperature"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value_json.temperature_chaudiere_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30001
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Fumee"
|
||||||
|
unique_id: "temperature_fumee_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:smoke"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_FUMEE/state"
|
||||||
|
value_template: "{{ value_json.temperature_fumee_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30002
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Board"
|
||||||
|
unique_id: "temperature_board_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:thermometer-lines"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_BOARD/state"
|
||||||
|
value_template: "{{ value_json.temperature_board_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30003
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "O2 residuel"
|
||||||
|
unique_id: "o2_residuel_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/O2_RESIDUEL/state"
|
||||||
|
value_template: "{{ value_json.o2_residuel_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30004
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Exterieur"
|
||||||
|
unique_id: "temp_exterieur_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:home-thermometer-outline"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMP_EXTERIEUR/state"
|
||||||
|
value_template: "{{ value_json.temp_exterieur_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30005
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: true
|
||||||
|
- name: "Porte chaudiere"
|
||||||
|
unique_id: "porte_chaudiere_sensor"
|
||||||
|
type: "binary_sensor"
|
||||||
|
device_class: "door"
|
||||||
|
payload_on: "1"
|
||||||
|
payload_off: "0"
|
||||||
|
#state_class: "measurement"
|
||||||
|
icon: "mdi:door-open"
|
||||||
|
#unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/PORTE_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "input_status"
|
||||||
|
address: 10001
|
||||||
|
offset: 10001
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
|
||||||
|
|
||||||
|
- name: "Air primaire"
|
||||||
|
unique_id: "air_primaire_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-filter"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/AIR_PRIMAIRE/state"
|
||||||
|
value_template: "{{ value_json.air_primaire_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30006
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Air Secondaire"
|
||||||
|
unique_id: "air_secondaire_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "Battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-filter"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/AIR_SECONDAIRE/state"
|
||||||
|
value_template: "{{ value_json.air_secondaire_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30007
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Vitesse ventilateur"
|
||||||
|
unique_id: "vitesse_ventilateur_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "None"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-conditioner"
|
||||||
|
unit_of_measurement: "RPM"
|
||||||
|
state_topic: "froling/S3Turbo/VITESSE_VENTILATEUR/state"
|
||||||
|
value_template: "{{ value_json.vitesse_ventilateur_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30008
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Commande tirage"
|
||||||
|
unique_id: "commande_tirage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "None"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent-box"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/COMMANDE_TIRAGE/state"
|
||||||
|
value_template: "{{ value_json.commande_tirage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30016
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Consigne T° fumée"
|
||||||
|
unique_id: "consigne_temperature_fumee_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:temperature-celsius"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/CONSIGNE_TEMPERATURE_FUMEE/state"
|
||||||
|
value_template: "{{ value_json.consigne_temperature_fumee_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30020
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Consigne T° chauffage"
|
||||||
|
unique_id: "consigne_temperature_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:temperature-celsius"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/CONSIGNE_TEMPERATURE_CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.consigne_temperature_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30023
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure fonctionnement"
|
||||||
|
unique_id: "heure_fonctionnement_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE FONCTIONNEMENT/state"
|
||||||
|
value_template: "{{ value_json.heure_fonctionnement_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30099
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure de maintien de feu"
|
||||||
|
unique_id: "heure_maintien_de_feu_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE MAINTIEN DE FEU/state"
|
||||||
|
value_template: "{{ value_json.heure_maintien_de_feu_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30116
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure chauffage"
|
||||||
|
unique_id: "heure_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.heure_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30222
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Tampon Haut"
|
||||||
|
unique_id: "tampon_haut_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TAMPON_HAUT/state"
|
||||||
|
value_template: "{{ value_json.tampon_haut_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30119
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Tampon Bas"
|
||||||
|
unique_id: "tampon_bas_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TAMPON_BAS/state"
|
||||||
|
value_template: "{{ value_json.tampon_bas_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30121
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° depart chauffage"
|
||||||
|
unique_id: "temperature_depart_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:thermometer"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_DEPART_CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.temperature_depart_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30022
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Charge tampon"
|
||||||
|
unique_id: "charge_tampon_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent-circle-outline"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/CHARGE TAMPON/state"
|
||||||
|
value_template: "{{ value_json.charge_tampon_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30226
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
# Digital Outputs
|
||||||
|
# Function: Read Coil Status (FC=01)
|
||||||
|
- name: pompe circuit chauffage"
|
||||||
|
unique_id: "pompe_circuit_chauffage"
|
||||||
|
type: "binary_sensor"
|
||||||
|
device_class: "running"
|
||||||
|
icon: "mdi:pump"
|
||||||
|
state_topic: "froling/S3Turbo/pump_chauffage/state"
|
||||||
|
value_template: "{{ value_json.charge_tampon_sensor }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 30226
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
# Digital Outputs
|
||||||
|
# Function: Read Coil Status (FC=01)
|
||||||
|
- name: pompe circuit_chauffage
|
||||||
|
unique_id: "pompe_circuit_chauffage"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pump"
|
||||||
|
state_topic: "froling/S3Turbo/pump_chauffage/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 0
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: cc_melangeur_ouvert
|
||||||
|
unique_id: "cc_melangeur_ouvert"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pipe-valve"
|
||||||
|
state_topic: "froling/S3Turbo/cc_melangeur_ouvert/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 2
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: cc_melangeur_ferme
|
||||||
|
unique_id: "cc_melangeur_ferme"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pipe-valve"
|
||||||
|
state_topic: "froling/S3Turbo/cc_melangeur_ferme/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 3
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
|
||||||
10
docker-compose.yml
Executable file
10
docker-compose.yml
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
container_name: froling_modbus2mqtt
|
||||||
|
build: .
|
||||||
|
volumes:
|
||||||
|
- ./src:/usr/src/app
|
||||||
|
- ./config:/usr/src/app/config
|
||||||
|
restart: unless-stopped
|
||||||
3
exclude.txt
Executable file
3
exclude.txt
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
modbus2mqtt/env/
|
||||||
|
modbus2mqttsrc/__pycache__/
|
||||||
|
modbus2mqtt/*.log
|
||||||
2
readme.txt
Executable file
2
readme.txt
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
pour creer l'archive du dossier, se mettre dans le dossier parent et lancer la commande suivante :
|
||||||
|
tar -czvf froling_modbus2mqtt.tar.gz --exclude-from='modbus2mqtt/exclude.txt' -C modbus2mqtt .
|
||||||
4
requirements.txt
Executable file
4
requirements.txt
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
paho-mqtt==1.6.1
|
||||||
|
pymodbus==3.5.4
|
||||||
|
pyModbusTCP==0.2.0
|
||||||
|
PyYAML==6.0.1
|
||||||
435
src/config.yaml
Executable file
435
src/config.yaml
Executable file
@@ -0,0 +1,435 @@
|
|||||||
|
mqtt:
|
||||||
|
host: "10.0.0.3"
|
||||||
|
port: 1883
|
||||||
|
user: ""
|
||||||
|
password: ""
|
||||||
|
topic_prefix: "froling/S3Turbo"
|
||||||
|
|
||||||
|
homeassistant:
|
||||||
|
autodiscovery: True
|
||||||
|
discovery_prefix: "homeassistant" # Préfixe par défaut pour l'autodiscovery
|
||||||
|
node_id: "froling" # Remplacer par l'identifiant unique du dispositif
|
||||||
|
|
||||||
|
modbus:
|
||||||
|
host: "10.0.0.12"
|
||||||
|
port: 502
|
||||||
|
unit_id: 2
|
||||||
|
timeout: 30
|
||||||
|
|
||||||
|
refresh_rate: 10 # Fréquence d'actualisation en secondes
|
||||||
|
|
||||||
|
device:
|
||||||
|
identifiers: "FrolingS3" # Remplacer par l'identifiant unique du dispositif
|
||||||
|
manufacturer: "Froling" # Remplacer par le fabricant du dispositif
|
||||||
|
model: "S3" # Remplacer par le modèle du dispositif
|
||||||
|
name: "Froling S3" # Remplacer par le nom du dispositif
|
||||||
|
sw_version: "1.0" # Remplacer par la version du logiciel du dispositif, si applicable
|
||||||
|
# configuration_url: "http://example.com" # Remplacer par l'URL de configuration ou de documentation du dispositif
|
||||||
|
|
||||||
|
|
||||||
|
# Ajout des paramètres pour l'état de l'installation et l'état de la chaudière
|
||||||
|
value_maps:
|
||||||
|
SystemStatus:
|
||||||
|
0: "Charge continue"
|
||||||
|
1: "Eau chaude sanitaire"
|
||||||
|
2: "Automatique"
|
||||||
|
3: "Fonctionnement au bois de chauffage"
|
||||||
|
4: "Nettoyage"
|
||||||
|
5: "Éteint"
|
||||||
|
6: "Chauffage supplémentaire"
|
||||||
|
7: "Ramoneur"
|
||||||
|
8: "Nettoyage2"
|
||||||
|
FurnaceStatus:
|
||||||
|
0: "DÉFAUT"
|
||||||
|
1: "Chaudière éteinte"
|
||||||
|
2: "Montée en température"
|
||||||
|
3: "Chauffage"
|
||||||
|
4: "Maintien du feu"
|
||||||
|
5: "Feu éteint"
|
||||||
|
6: "Porte ouverte"
|
||||||
|
7: "Préparation"
|
||||||
|
8: "Préchauffage"
|
||||||
|
9: "Allumage"
|
||||||
|
10: "Attente d'arrêt"
|
||||||
|
11: "Attente d'arrêt1"
|
||||||
|
12: "Arrêt_Alimentation1"
|
||||||
|
13: "Arrêt_Attente2"
|
||||||
|
14: "Arrêt_Alimentation2"
|
||||||
|
15: "Nettoyage"
|
||||||
|
16: "Attente_2h"
|
||||||
|
17: "Aspiration_Chauffage"
|
||||||
|
18: "Défaut_d'allumage"
|
||||||
|
19: "Prêt_à_l'emploi"
|
||||||
|
|
||||||
|
entities:
|
||||||
|
- name: "Etats systeme"
|
||||||
|
unique_id: "etats_systeme_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "enum"
|
||||||
|
# state_class: "measurement"
|
||||||
|
icon: "mdi:radiator"
|
||||||
|
unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/ETATS_SYSTEME/state"
|
||||||
|
value_template: "{{ value_json.etats_systeme_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 34001
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 1
|
||||||
|
value_map: "SystemStatus"
|
||||||
|
signed: false
|
||||||
|
- name: "Etat Chaudiere"
|
||||||
|
unique_id: "etats_chaudiere_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "enum"
|
||||||
|
# state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler-alert"
|
||||||
|
unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/ETATS_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value_json.etats_chaudiere_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 34002
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: "FurnaceStatus"
|
||||||
|
signed: false
|
||||||
|
- name: "T° Chaudiere"
|
||||||
|
unique_id: "temperature_chaudiere_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:hydraulic-oil-temperature"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value_json.temperature_chaudiere_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30001
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Fumee"
|
||||||
|
unique_id: "temperature_fumee_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:smoke"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_FUMEE/state"
|
||||||
|
value_template: "{{ value_json.temperature_fumee_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30002
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Board"
|
||||||
|
unique_id: "temperature_board_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:thermometer-lines"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_BOARD/state"
|
||||||
|
value_template: "{{ value_json.temperature_board_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30003
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "O2 residuel"
|
||||||
|
unique_id: "o2_residuel_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/O2_RESIDUEL/state"
|
||||||
|
value_template: "{{ value_json.o2_residuel_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30004
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Exterieur"
|
||||||
|
unique_id: "temp_exterieur_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:home-thermometer-outline"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMP_EXTERIEUR/state"
|
||||||
|
value_template: "{{ value_json.temp_exterieur_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30005
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: true
|
||||||
|
- name: "Porte chaudiere"
|
||||||
|
unique_id: "porte_chaudiere_sensor"
|
||||||
|
type: "binary_sensor"
|
||||||
|
device_class: "door"
|
||||||
|
payload_on: "1"
|
||||||
|
payload_off: "0"
|
||||||
|
#state_class: "measurement"
|
||||||
|
icon: "mdi:door-open"
|
||||||
|
#unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/PORTE_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "input_status"
|
||||||
|
address: 10001
|
||||||
|
offset: 10001
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
|
||||||
|
|
||||||
|
- name: "Air primaire"
|
||||||
|
unique_id: "air_primaire_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-filter"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/AIR_PRIMAIRE/state"
|
||||||
|
value_template: "{{ value_json.air_primaire_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30006
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Air Secondaire"
|
||||||
|
unique_id: "air_secondaire_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "Battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-filter"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/AIR_SECONDAIRE/state"
|
||||||
|
value_template: "{{ value_json.air_secondaire_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30007
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Vitesse ventilateur"
|
||||||
|
unique_id: "vitesse_ventilateur_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "None"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-conditioner"
|
||||||
|
unit_of_measurement: "RPM"
|
||||||
|
state_topic: "froling/S3Turbo/VITESSE_VENTILATEUR/state"
|
||||||
|
value_template: "{{ value_json.vitesse_ventilateur_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30008
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Commande tirage"
|
||||||
|
unique_id: "commande_tirage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "None"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent-box"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/COMMANDE_TIRAGE/state"
|
||||||
|
value_template: "{{ value_json.commande_tirage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30016
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Consigne T° fumée"
|
||||||
|
unique_id: "consigne_temperature_fumee_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:temperature-celsius"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/CONSIGNE_TEMPERATURE_FUMEE/state"
|
||||||
|
value_template: "{{ value_json.consigne_temperature_fumee_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30020
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Consigne T° chauffage"
|
||||||
|
unique_id: "consigne_temperature_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:temperature-celsius"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/CONSIGNE_TEMPERATURE_CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.consigne_temperature_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30023
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure fonctionnement"
|
||||||
|
unique_id: "heure_fonctionnement_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE FONCTIONNEMENT/state"
|
||||||
|
value_template: "{{ value_json.heure_fonctionnement_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30099
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure de maintien de feu"
|
||||||
|
unique_id: "heure_maintien_de_feu_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE MAINTIEN DE FEU/state"
|
||||||
|
value_template: "{{ value_json.heure_maintien_de_feu_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30116
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure chauffage"
|
||||||
|
unique_id: "heure_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.heure_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30222
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Tampon Haut"
|
||||||
|
unique_id: "tampon_haut_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TAMPON_HAUT/state"
|
||||||
|
value_template: "{{ value_json.tampon_haut_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30119
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Tampon Bas"
|
||||||
|
unique_id: "tampon_bas_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TAMPON_BAS/state"
|
||||||
|
value_template: "{{ value_json.tampon_bas_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30121
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° depart chauffage"
|
||||||
|
unique_id: "temperature_depart_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:thermometer"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_DEPART_CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.temperature_depart_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30022
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Charge tampon"
|
||||||
|
unique_id: "charge_tampon_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent-circle-outline"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/CHARGE TAMPON/state"
|
||||||
|
value_template: "{{ value_json.charge_tampon_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30226
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
# Digital Outputs
|
||||||
|
# Function: Read Coil Status (FC=01)
|
||||||
|
- name: pompe circuit_chauffage
|
||||||
|
unique_id: "pompe_circuit_chauffage"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pump"
|
||||||
|
state_topic: "froling/S3Turbo/pump_chauffage/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 0
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: cc_melangeur_ouvert
|
||||||
|
unique_id: "cc_melangeur_ouvert"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pipe-valve"
|
||||||
|
state_topic: "froling/S3Turbo/cc_melangeur_ouvert/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 2
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: cc_melangeur_ferme
|
||||||
|
unique_id: "cc_melangeur_ferme"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pipe-valve"
|
||||||
|
state_topic: "froling/S3Turbo/cc_melangeur_ferme/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 3
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
435
src/config/config.yaml
Executable file
435
src/config/config.yaml
Executable file
@@ -0,0 +1,435 @@
|
|||||||
|
mqtt:
|
||||||
|
host: "10.0.0.3"
|
||||||
|
port: 1883
|
||||||
|
user: ""
|
||||||
|
password: ""
|
||||||
|
topic_prefix: "froling/S3Turbo"
|
||||||
|
|
||||||
|
homeassistant:
|
||||||
|
autodiscovery: True
|
||||||
|
discovery_prefix: "homeassistant" # Préfixe par défaut pour l'autodiscovery
|
||||||
|
node_id: "froling" # Remplacer par l'identifiant unique du dispositif
|
||||||
|
|
||||||
|
modbus:
|
||||||
|
host: "10.0.0.12"
|
||||||
|
port: 502
|
||||||
|
unit_id: 2
|
||||||
|
timeout: 30
|
||||||
|
|
||||||
|
refresh_rate: 10 # Fréquence d'actualisation en secondes
|
||||||
|
|
||||||
|
device:
|
||||||
|
identifiers: "FrolingS3" # Remplacer par l'identifiant unique du dispositif
|
||||||
|
manufacturer: "Froling" # Remplacer par le fabricant du dispositif
|
||||||
|
model: "S3" # Remplacer par le modèle du dispositif
|
||||||
|
name: "Froling S3" # Remplacer par le nom du dispositif
|
||||||
|
sw_version: "1.0" # Remplacer par la version du logiciel du dispositif, si applicable
|
||||||
|
# configuration_url: "http://example.com" # Remplacer par l'URL de configuration ou de documentation du dispositif
|
||||||
|
|
||||||
|
|
||||||
|
# Ajout des paramètres pour l'état de l'installation et l'état de la chaudière
|
||||||
|
value_maps:
|
||||||
|
SystemStatus:
|
||||||
|
0: "Charge continue"
|
||||||
|
1: "Eau chaude sanitaire"
|
||||||
|
2: "Automatique"
|
||||||
|
3: "Fonctionnement au bois de chauffage"
|
||||||
|
4: "Nettoyage"
|
||||||
|
5: "Éteint"
|
||||||
|
6: "Chauffage supplémentaire"
|
||||||
|
7: "Ramoneur"
|
||||||
|
8: "Nettoyage2"
|
||||||
|
FurnaceStatus:
|
||||||
|
0: "DÉFAUT"
|
||||||
|
1: "Chaudière éteinte"
|
||||||
|
2: "Montée en température"
|
||||||
|
3: "Chauffage"
|
||||||
|
4: "Maintien du feu"
|
||||||
|
5: "Feu éteint"
|
||||||
|
6: "Porte ouverte"
|
||||||
|
7: "Préparation"
|
||||||
|
8: "Préchauffage"
|
||||||
|
9: "Allumage"
|
||||||
|
10: "Attente d'arrêt"
|
||||||
|
11: "Attente d'arrêt1"
|
||||||
|
12: "Arrêt_Alimentation1"
|
||||||
|
13: "Arrêt_Attente2"
|
||||||
|
14: "Arrêt_Alimentation2"
|
||||||
|
15: "Nettoyage"
|
||||||
|
16: "Attente_2h"
|
||||||
|
17: "Aspiration_Chauffage"
|
||||||
|
18: "Défaut_d'allumage"
|
||||||
|
19: "Prêt_à_l'emploi"
|
||||||
|
|
||||||
|
entities:
|
||||||
|
- name: "Etats systeme"
|
||||||
|
unique_id: "etats_systeme_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "enum"
|
||||||
|
# state_class: "measurement"
|
||||||
|
icon: "mdi:radiator"
|
||||||
|
unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/ETATS_SYSTEME/state"
|
||||||
|
value_template: "{{ value_json.etats_systeme_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 34001
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 1
|
||||||
|
value_map: "SystemStatus"
|
||||||
|
signed: false
|
||||||
|
- name: "Etat Chaudiere"
|
||||||
|
unique_id: "etats_chaudiere_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "enum"
|
||||||
|
# state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler-alert"
|
||||||
|
unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/ETATS_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value_json.etats_chaudiere_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 34002
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: "FurnaceStatus"
|
||||||
|
signed: false
|
||||||
|
- name: "T° Chaudiere"
|
||||||
|
unique_id: "temperature_chaudiere_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:hydraulic-oil-temperature"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value_json.temperature_chaudiere_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30001
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Fumee"
|
||||||
|
unique_id: "temperature_fumee_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:smoke"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_FUMEE/state"
|
||||||
|
value_template: "{{ value_json.temperature_fumee_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30002
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Board"
|
||||||
|
unique_id: "temperature_board_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:thermometer-lines"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_BOARD/state"
|
||||||
|
value_template: "{{ value_json.temperature_board_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30003
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "O2 residuel"
|
||||||
|
unique_id: "o2_residuel_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/O2_RESIDUEL/state"
|
||||||
|
value_template: "{{ value_json.o2_residuel_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30004
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° Exterieur"
|
||||||
|
unique_id: "temp_exterieur_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:home-thermometer-outline"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMP_EXTERIEUR/state"
|
||||||
|
value_template: "{{ value_json.temp_exterieur_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30005
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: true
|
||||||
|
- name: "Porte chaudiere"
|
||||||
|
unique_id: "porte_chaudiere_sensor"
|
||||||
|
type: "binary_sensor"
|
||||||
|
device_class: "door"
|
||||||
|
payload_on: "1"
|
||||||
|
payload_off: "0"
|
||||||
|
#state_class: "measurement"
|
||||||
|
icon: "mdi:door-open"
|
||||||
|
#unit_of_measurement: ""
|
||||||
|
state_topic: "froling/S3Turbo/PORTE_CHAUDIERE/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "input_status"
|
||||||
|
address: 10001
|
||||||
|
offset: 10001
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
|
||||||
|
|
||||||
|
- name: "Air primaire"
|
||||||
|
unique_id: "air_primaire_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-filter"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/AIR_PRIMAIRE/state"
|
||||||
|
value_template: "{{ value_json.air_primaire_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30006
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Air Secondaire"
|
||||||
|
unique_id: "air_secondaire_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "Battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-filter"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/AIR_SECONDAIRE/state"
|
||||||
|
value_template: "{{ value_json.air_secondaire_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30007
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Vitesse ventilateur"
|
||||||
|
unique_id: "vitesse_ventilateur_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "None"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:air-conditioner"
|
||||||
|
unit_of_measurement: "RPM"
|
||||||
|
state_topic: "froling/S3Turbo/VITESSE_VENTILATEUR/state"
|
||||||
|
value_template: "{{ value_json.vitesse_ventilateur_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30008
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Commande tirage"
|
||||||
|
unique_id: "commande_tirage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
# device_class: "None"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent-box"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/COMMANDE_TIRAGE/state"
|
||||||
|
value_template: "{{ value_json.commande_tirage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30016
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Consigne T° fumée"
|
||||||
|
unique_id: "consigne_temperature_fumee_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:temperature-celsius"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/CONSIGNE_TEMPERATURE_FUMEE/state"
|
||||||
|
value_template: "{{ value_json.consigne_temperature_fumee_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30020
|
||||||
|
offset: 30001
|
||||||
|
scale: 1
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Consigne T° chauffage"
|
||||||
|
unique_id: "consigne_temperature_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:temperature-celsius"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/CONSIGNE_TEMPERATURE_CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.consigne_temperature_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30023
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure fonctionnement"
|
||||||
|
unique_id: "heure_fonctionnement_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE FONCTIONNEMENT/state"
|
||||||
|
value_template: "{{ value_json.heure_fonctionnement_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30099
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure de maintien de feu"
|
||||||
|
unique_id: "heure_maintien_de_feu_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE MAINTIEN DE FEU/state"
|
||||||
|
value_template: "{{ value_json.heure_maintien_de_feu_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30116
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Heure chauffage"
|
||||||
|
unique_id: "heure_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "duration"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:clock-time-eight-outline"
|
||||||
|
unit_of_measurement: "h"
|
||||||
|
state_topic: "froling/S3Turbo/HEURE CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.heure_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30222
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Tampon Haut"
|
||||||
|
unique_id: "tampon_haut_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TAMPON_HAUT/state"
|
||||||
|
value_template: "{{ value_json.tampon_haut_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30119
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Tampon Bas"
|
||||||
|
unique_id: "tampon_bas_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:water-boiler"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TAMPON_BAS/state"
|
||||||
|
value_template: "{{ value_json.tampon_bas_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30121
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "T° depart chauffage"
|
||||||
|
unique_id: "temperature_depart_chauffage_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:thermometer"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
state_topic: "froling/S3Turbo/TEMPERATURE_DEPART_CHAUFFAGE/state"
|
||||||
|
value_template: "{{ value_json.temperature_depart_chauffage_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30022
|
||||||
|
offset: 30001
|
||||||
|
scale: 0.5
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: "Charge tampon"
|
||||||
|
unique_id: "charge_tampon_sensor"
|
||||||
|
type: "sensor"
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: "mdi:percent-circle-outline"
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
state_topic: "froling/S3Turbo/CHARGE TAMPON/state"
|
||||||
|
value_template: "{{ value_json.charge_tampon_sensor }}"
|
||||||
|
input_type: "input_register"
|
||||||
|
address: 30226
|
||||||
|
offset: 30001
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
# Digital Outputs
|
||||||
|
# Function: Read Coil Status (FC=01)
|
||||||
|
- name: pompe circuit_chauffage
|
||||||
|
unique_id: "pompe_circuit_chauffage"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pump"
|
||||||
|
state_topic: "froling/S3Turbo/pump_chauffage/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 0
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: cc_melangeur_ouvert
|
||||||
|
unique_id: "cc_melangeur_ouvert"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pipe-valve"
|
||||||
|
state_topic: "froling/S3Turbo/cc_melangeur_ouvert/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 2
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
- name: cc_melangeur_ferme
|
||||||
|
unique_id: "cc_melangeur_ferme"
|
||||||
|
type: "binary_sensor"
|
||||||
|
icon: "mdi:pipe-valve"
|
||||||
|
state_topic: "froling/S3Turbo/cc_melangeur_ferme/state"
|
||||||
|
value_template: "{{ value }}"
|
||||||
|
input_type: "coil"
|
||||||
|
address: 3
|
||||||
|
offset: 0
|
||||||
|
precision: 0
|
||||||
|
value_map: null
|
||||||
|
signed: false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
278
src/main.py
Executable file
278
src/main.py
Executable file
@@ -0,0 +1,278 @@
|
|||||||
|
import os
|
||||||
|
import time
|
||||||
|
import yaml
|
||||||
|
import json
|
||||||
|
import paho.mqtt.client as mqtt
|
||||||
|
from pyModbusTCP.client import ModbusClient
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Types de registres Modbus et fonctions associées :
|
||||||
|
|
||||||
|
1. Coils (Bobines) : sortie digital - light - relay
|
||||||
|
- Fonction Modbus : 01 (FC01)
|
||||||
|
- Lecture : read_coils()
|
||||||
|
- Écriture : write_single_coil() ou write_multiple_coils()
|
||||||
|
- Plage d'adresses typique : 00001-09999
|
||||||
|
|
||||||
|
2. Discrete Inputs (Entrées Discrètes) : entrée digital - binary_sensor - switch
|
||||||
|
- Fonction Modbus : 02 (FC02)
|
||||||
|
- Lecture : read_discrete_inputs()
|
||||||
|
- Écriture : Non applicable (lecture seule)
|
||||||
|
- Plage d'adresses typique : 10001-19999
|
||||||
|
|
||||||
|
3. Input Registers (Registres d'Entrée) : valeur actuelle - sensor
|
||||||
|
- Fonction Modbus : 04 (FC04)
|
||||||
|
- Lecture : read_input_registers()
|
||||||
|
- Écriture : Non applicable (lecture seule)
|
||||||
|
- Plage d'adresses typique : 30001-39999
|
||||||
|
|
||||||
|
4. Holding Registers (Registres de Maintien) : parameters
|
||||||
|
- Fonction Modbus : 03 (FC03)
|
||||||
|
- Lecture : read_holding_registers()
|
||||||
|
- Écriture : write_single_register() ou write_multiple_registers()
|
||||||
|
- Plage d'adresses typique : 40001-49999
|
||||||
|
|
||||||
|
Note : Les adresses Modbus sont souvent spécifiées avec leur 'offset' - c'est-à-dire que l'adresse réelle utilisée dans le protocole est l'adresse spécifiée moins un. Par exemple, l'adresse 40001 serait l'adresse 0 dans le message Modbus.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def load_config():
|
||||||
|
# Obtenez le chemin du dossier actuel où se trouve main.py
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
# Construisez le chemin vers config.yaml
|
||||||
|
config_path = os.path.join(current_dir, 'config.yaml') # Suppression du sous-dossier 'config'
|
||||||
|
with open(config_path, 'r') as file:
|
||||||
|
config = yaml.safe_load(file)
|
||||||
|
return config
|
||||||
|
|
||||||
|
# Ajout de la fonction de publication des messages de découverte
|
||||||
|
def publish_discovery_messages(client, config):
|
||||||
|
base_topic = config['homeassistant']['discovery_prefix']
|
||||||
|
node_id = config['homeassistant']['node_id']
|
||||||
|
device_info = config['device']
|
||||||
|
|
||||||
|
for entity in config['entities']:
|
||||||
|
component = entity['type'] # 'sensor', 'binary_sensor', etc.
|
||||||
|
object_id = entity['unique_id']
|
||||||
|
discovery_topic = f"{base_topic}/{component}/{node_id}/{object_id}/config"
|
||||||
|
message = {
|
||||||
|
"availability_topic": f"{config['mqtt']['topic_prefix']}/availability",
|
||||||
|
"icon": entity.get('icon', ''),
|
||||||
|
"unique_id": entity['unique_id'],
|
||||||
|
"device": device_info,
|
||||||
|
"name": entity['name'],
|
||||||
|
"state_topic": f"{config['mqtt']['topic_prefix']}/{entity['name']}/state",
|
||||||
|
#"value_template": "{{ value }}", # Ajouter une value_template si nécessaire
|
||||||
|
#"device_class": entity.get('device_class', ''),
|
||||||
|
#"unit_of_measurement": entity.get('unit_of_measurement', '')# La valeur par défaut est '°C
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
if "unit_of_measurement" in entity: message["unit_of_measurement"] = entity["unit_of_measurement"]
|
||||||
|
if "state_class" in entity: message["state_class"] = entity["state_class"]
|
||||||
|
if "device_class" in entity: message["device_class"] = entity["device_class"]
|
||||||
|
|
||||||
|
if component == "binary_sensor":
|
||||||
|
message.update({
|
||||||
|
"payload_on": entity.get('payload_on', '1'), # La valeur par défaut est 'ON'
|
||||||
|
"payload_off": entity.get('payload_off', '0'), # La valeur par défaut est 'OFF'
|
||||||
|
"value_template": entity.get('value_template', "{{ value_json.value }}"), # Ajouter une value_template si nécessaire
|
||||||
|
})
|
||||||
|
client.publish(discovery_topic, json.dumps(message), qos=1, retain=True)
|
||||||
|
|
||||||
|
def publish_availability(client, status, config):
|
||||||
|
availability_topic = f"{config['mqtt']['topic_prefix']}/availability"
|
||||||
|
client.publish(availability_topic, status, qos=1, retain=True)
|
||||||
|
|
||||||
|
def convert_to_signed(value):
|
||||||
|
NEGATIVE_THRESHOLD = 32000 # Seuil pour déterminer les valeurs négatives
|
||||||
|
MAX_VALUE = 32767
|
||||||
|
|
||||||
|
if value >= NEGATIVE_THRESHOLD:
|
||||||
|
# Interpréter comme une température négative
|
||||||
|
return -(MAX_VALUE - value + 1)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def on_connect(client, userdata, flags, rc):
|
||||||
|
if rc == 0:
|
||||||
|
print("Connected to MQTT Broker!")
|
||||||
|
publish_availability(client, 'online', userdata)
|
||||||
|
# Si l'autodiscovery est activé, publiez les messages de découverte
|
||||||
|
if userdata['homeassistant']['autodiscovery']:
|
||||||
|
publish_discovery_messages(client, userdata)
|
||||||
|
else:
|
||||||
|
print("Failed to connect, return code %d\n", rc)
|
||||||
|
|
||||||
|
def on_publish(client, userdata, result):
|
||||||
|
print(f"Data published to MQTT. Result: {result}")
|
||||||
|
|
||||||
|
|
||||||
|
def connect_modbus(host, port, unit_id, timeout):
|
||||||
|
"""
|
||||||
|
Connect to the Modbus server.
|
||||||
|
"""
|
||||||
|
client = ModbusClient()
|
||||||
|
client.host = host # Set the host
|
||||||
|
client.port = port # Set the port
|
||||||
|
client.unit_id = unit_id
|
||||||
|
client.timeout = timeout
|
||||||
|
connection = client.open()
|
||||||
|
|
||||||
|
if connection:
|
||||||
|
print(f"Connected to Modbus server at {host}:{port}")
|
||||||
|
else:
|
||||||
|
print(f"Failed to connect to Modbus server at {host}:{port}")
|
||||||
|
|
||||||
|
return client
|
||||||
|
|
||||||
|
def read_modbus_registers(client, input_type, address, offset, scale=1, precision=0, count=1):
|
||||||
|
"""
|
||||||
|
Read registers from the Modbus server.
|
||||||
|
|
||||||
|
:param client: the Modbus client instance
|
||||||
|
:param input_type: the type of the register (input_register, holding_register)
|
||||||
|
:param address: the address of the register to read
|
||||||
|
:param offset: the offset to apply to the address
|
||||||
|
:param scale: the scaling factor to apply to the read values
|
||||||
|
:param precision: the number of decimal places to round the scaled values
|
||||||
|
:param count: the number of registers to read
|
||||||
|
:param value_map: a dictionary mapping register values to human-readable strings
|
||||||
|
:return: the scaled and rounded value of the registers or None if an error occurs
|
||||||
|
"""
|
||||||
|
print(f"Address from call: {address}, Offset from call: {offset}")
|
||||||
|
# Calculate the real address by subtracting the offset
|
||||||
|
real_address = address - offset
|
||||||
|
print(f"Preparing to read Modbus registers with initial address: {address}, "
|
||||||
|
f"offset: {offset}, resulting in real address: {real_address}")
|
||||||
|
try:
|
||||||
|
regs = None
|
||||||
|
if input_type == 'input_register':
|
||||||
|
# Use FC04 to read input registers
|
||||||
|
print(f"Reading {count} input register(s) starting at initial address {address} "
|
||||||
|
f"(real address {real_address}, offset {offset}) using FC04")
|
||||||
|
regs = client.read_input_registers(real_address, count)
|
||||||
|
elif input_type == 'holding_register':
|
||||||
|
# Use FC03 to read holding registers
|
||||||
|
print(f"Reading {count} holding register(s) starting at initial address {address} "
|
||||||
|
f"(real address {real_address}, offset {offset}) using FC03")
|
||||||
|
regs = client.read_holding_registers(real_address, count)
|
||||||
|
elif input_type == 'input_status':
|
||||||
|
# Use FC02 to read discrete inputs
|
||||||
|
print(f"Reading {count} input status(es) starting at initial address {address} "
|
||||||
|
f"(real address {real_address}, offset {offset}) using FC02")
|
||||||
|
regs = client.read_discrete_inputs(real_address, count)
|
||||||
|
elif input_type == 'coil':
|
||||||
|
# Use FC01 to read coils
|
||||||
|
print(f"Reading {count} coil(s) starting at initial address {address} "
|
||||||
|
f"(real address {real_address}, offset {offset}) using FC01")
|
||||||
|
regs = client.read_coils(real_address, count)
|
||||||
|
else:
|
||||||
|
print(f"Invalid input type: {input_type}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if regs is not None:
|
||||||
|
|
||||||
|
# Apply scaling and rounding to the read values
|
||||||
|
scaled_and_rounded_regs = [round(reg * scale, precision) for reg in regs]
|
||||||
|
print(f"Read successful: {scaled_and_rounded_regs}")
|
||||||
|
return scaled_and_rounded_regs
|
||||||
|
else:
|
||||||
|
print(f"Read error at initial address {address} (real address {real_address}, offset {offset})")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Modbus read error at initial address {address} (real address {real_address}, offset {offset}): {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
config = load_config()
|
||||||
|
|
||||||
|
refresh_rate = config['refresh_rate'] # Obtenez la fréquence d'actualisation depuis la configuration
|
||||||
|
|
||||||
|
# Configuration MQTT
|
||||||
|
mqtt_config = config['mqtt']
|
||||||
|
mqtt_client = mqtt.Client()
|
||||||
|
mqtt_client.user_data_set(config) # Passer la configuration comme userdata
|
||||||
|
mqtt_client.on_connect = on_connect
|
||||||
|
mqtt_client.on_publish = on_publish
|
||||||
|
if mqtt_config['user'] and mqtt_config['password']:
|
||||||
|
mqtt_client.username_pw_set(mqtt_config['user'], mqtt_config['password'])
|
||||||
|
mqtt_client.connect(mqtt_config['host'], mqtt_config['port'], 60)
|
||||||
|
mqtt_client.loop_start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
modbus_client = None
|
||||||
|
try:
|
||||||
|
# etape de connexion Modbus
|
||||||
|
# Affichage de la configuration pour la vérification
|
||||||
|
|
||||||
|
# print("MQTT Configuration:")
|
||||||
|
# print(config['mqtt'])
|
||||||
|
# print("\nModbus Configuration:")
|
||||||
|
# print(config['modbus'])
|
||||||
|
# print("\nHome Assistant Configuration:")
|
||||||
|
# print(config['homeassistant'])
|
||||||
|
# print("\nRefresh Rate:")
|
||||||
|
# print(config['refresh_rate'])
|
||||||
|
# print("\nDevice:")
|
||||||
|
# for device in config['device']:
|
||||||
|
# print(device)
|
||||||
|
# print("\nEntities:")
|
||||||
|
# for entity in config['entities']:
|
||||||
|
# print(entity)
|
||||||
|
|
||||||
|
|
||||||
|
# Étape de connexion Modbus
|
||||||
|
modbus_client = connect_modbus(config['modbus']['host'],
|
||||||
|
config['modbus']['port'],
|
||||||
|
config['modbus']['unit_id'],
|
||||||
|
config['modbus']['timeout'])
|
||||||
|
if modbus_client:
|
||||||
|
# Lecture des registres Modbus pour chaque entité
|
||||||
|
for entity in config['entities']:
|
||||||
|
input_type = entity['input_type']
|
||||||
|
address = entity['address']
|
||||||
|
offset = entity['offset'] # Utilisation de l'offset de l'entité
|
||||||
|
scale = entity.get('scale', 1)
|
||||||
|
precision = entity.get('precision', 0) # Utilisation de get pour une valeur par défaut si non présente
|
||||||
|
count = 1 # Supposons que count est toujours 1 pour simplifier, à ajuster si nécessaire
|
||||||
|
|
||||||
|
# Affichage de l'entité et de l'offset avant la lecture
|
||||||
|
print(f"Reading entity: {entity['name']} with offset: {offset}")
|
||||||
|
# Lecture des registres avec l'offset correct
|
||||||
|
regs = read_modbus_registers(modbus_client, input_type, address, offset, scale, precision, count)
|
||||||
|
if regs is not None:
|
||||||
|
|
||||||
|
value = regs[0] # Prend la première valeur si plusieurs registres sont lus
|
||||||
|
if entity.get('signed', False):
|
||||||
|
value = convert_to_signed(value)
|
||||||
|
print(f"Valeur convertie en signée: {value}")
|
||||||
|
|
||||||
|
# Publier la valeur lue sur le topic MQTT approprié
|
||||||
|
topic = f"{config['mqtt']['topic_prefix']}/{entity['name']}/state"
|
||||||
|
mqtt_client.publish(topic, value)
|
||||||
|
print(f"Published value for {entity['name']}: {value}")
|
||||||
|
else:
|
||||||
|
print(f"Failed to read value for {entity['name']}")
|
||||||
|
|
||||||
|
# Assurez-vous de fermer la connexion Modbus lorsque vous avez terminé
|
||||||
|
modbus_client.close()
|
||||||
|
else:
|
||||||
|
print("Failed to connect to the Modbus server.")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
publish_availability(mqtt_client, 'offline', config)
|
||||||
|
finally:
|
||||||
|
if modbus_client:
|
||||||
|
modbus_client.close()
|
||||||
|
|
||||||
|
# Attendez la fréquence d'actualisation avant de recommencer
|
||||||
|
print(f"Waiting for {refresh_rate} seconds before the next update.")
|
||||||
|
time.sleep(refresh_rate)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user