Module WIFI climatisation AIRTON

c’est bon j’ai résolu le problème du chargement du script : il fallait le renommer en autoexec.be

au niveau du script autoexec.be il doit y avoir possibilité de l’alléger car ouinouin de github avait intégrer des fonction qui ne sont pas forcement utile à tout le monde comme le fait de récupèrer les valeurs d’une sonde extérieur , ajouter une hysterisis …

mais mes connaissance en codage sont malheureusement très légère et j’ai passé une journée entière faire des petites modifs de son code pour enfin reussir à faire marcher ma clim

et ça serait genial si un bon codeur arrive à le porter sur ESPHOME

De rien pour le partage :wink:

Voici la traduction du fichier autoexec.be vers ESPHOME selon ChatGPT (version abonné).
Je n’ai pas le temps de tester en ce moment cependant cela peut servir de base aux connaisseurs.

Configuration ESPHome
esphome:
  name: airton_ac   # Nom du dispositif ESPHome
  platform: ESP32   # Plateforme matérielle utilisée
  board: esp32dev   # Type de carte ESP32

# Configuration WiFi
wifi:
  ssid: "votre_ssid"  # Remplacez par le nom de votre réseau WiFi
  password: "votre_mot_de_passe"  # Remplacez par le mot de passe de votre réseau
  manual_ip:  # Optionnel : Configurer une IP statique pour votre ESP32
    static_ip: 192.168.1.100
    gateway: 192.168.1.1
    subnet: 255.255.255.0

# Configuration MQTT pour communiquer avec Home Assistant
mqtt:
  broker: "192.168.1.2"  # Adresse IP de votre serveur MQTT (souvent Home Assistant)
  username: "mqtt_user"  # Nom d'utilisateur pour MQTT
  password: "mqtt_password"  # Mot de passe pour MQTT
  discovery: true  # Activer la découverte automatique pour Home Assistant
  discovery_prefix: "homeassistant"  # Préfixe pour les topics MQTT

# Configuration du logger pour débogage
logger:

# UART (Communication Série) pour le climatiseur
uart:
  tx_pin: GPIO26  # Broche TX (transmission)
  rx_pin: GPIO32  # Broche RX (réception)
  baud_rate: 9600  # Vitesse de communication série (bauds)
  stop_bits: 1  # Nombre de bits de stop

# Variables globales pour stocker l'état et les paramètres du climatiseur
globals:
  - id: ac_mode
    type: std::string  # Type : chaîne de caractères
    restore_value: true  # Restaurer la valeur après redémarrage
    initial_value: "off"  # Mode initial : éteint
  - id: fan_speed
    type: std::string
    restore_value: true
    initial_value: "auto"  # Vitesse initiale du ventilateur : automatique
  - id: temperature_setpoint
    type: float  # Type : nombre à virgule flottante
    restore_value: true
    initial_value: 20.0  # Consigne initiale de température : 20°C
  - id: last_thermostat_state
    type: int
    restore_value: true
    initial_value: 0  # État initial du thermostat

# Définition des capteurs pour afficher des données
sensor:
  - platform: template  # Capteur basé sur un modèle (valeur définie dans le code)
    name: "AC Internal Temperature"  # Nom affiché dans Home Assistant
    id: ac_internal_temp  # Identifiant interne
    unit_of_measurement: "°C"  # Unité : degrés Celsius
    accuracy_decimals: 1  # Nombre de décimales affichées

  - platform: template
    name: "AC Temperature Setpoint"
    id: ac_temp_setpoint
    unit_of_measurement: "°C"
    accuracy_decimals: 1

# Text Sensors pour afficher les modes du climatiseur
text_sensor:
  - platform: template
    name: "AC Mode"  # Capteur texte pour le mode de l'AC (auto, cool, etc.)
    id: ac_mode_sensor

  - platform: template
    name: "Fan Speed"  # Capteur texte pour la vitesse du ventilateur
    id: fan_speed_sensor

# Composant personnalisé pour gérer la communication UART
custom_component:
  - lambda: |-
      // Initialise le composant personnalisé pour communiquer avec l'AC
      auto ac_uart = new AirtonAC(id(ac_internal_temp), id(ac_temp_setpoint), id(ac_mode_sensor), id(fan_speed_sensor));
      return {ac_uart};

# Script pour envoyer des commandes à l'AC
script:
  - id: send_ac_command  # Identifiant du script
    then:
      - lambda: |-
          // Forge une trame basée sur les paramètres actuels et l'envoie via UART
          auto frame = id(ac_mode) == "off" ? AirtonAC::forge_frame_off() : AirtonAC::forge_frame(id(ac_mode), id(fan_speed), id(ac_temp_setpoint));
          ESP_LOGD("custom", "Sending frame: %s", frame.c_str());  // Affiche la trame dans les logs
          uart::UARTComponent::write(frame);

# Services exposés à Home Assistant pour contrôler le climatiseur
api:
  services:
    - service: set_ac_mode
      variables:
        mode: string  # Variable pour le mode (exemple : "cool")
      then:
        - globals.set:
            id: ac_mode
            value: !lambda 'return mode;'  # Met à jour la variable globale
        - script.execute: send_ac_command  # Envoie la commande à l'AC

    - service: set_fan_speed
      variables:
        speed: string  # Variable pour la vitesse du ventilateur (exemple : "high")
      then:
        - globals.set:
            id: fan_speed
            value: !lambda 'return speed;'
        - script.execute: send_ac_command

    - service: set_temperature_setpoint
      variables:
        setpoint: float  # Variable pour la consigne de température
      then:
        - globals.set:
            id: temperature_setpoint
            value: !lambda 'return setpoint;'
        - script.execute: send_ac_command

Fichier `airton_ac.h` pour le composant personnalisé

Ajoutez ce fichier dans le même répertoire que votre configuration YAML (généralement config/).

#include "esphome.h"

// Classe pour gérer la communication avec le climatiseur Airton
class AirtonAC : public Component, public UARTDevice {
 public:
  // Constructeur : Initialise les capteurs liés au composant
  AirtonAC(Sensor *internal_temp, Sensor *temp_setpoint, TextSensor *ac_mode, TextSensor *fan_speed)
      : internal_temp_(internal_temp), temp_setpoint_(temp_setpoint), ac_mode_(ac_mode), fan_speed_(fan_speed) {}

  // Boucle principale exécutée en continu
  void loop() override {
    if (available() > 0) {  // Vérifie si des données sont disponibles sur le port série
      std::vector<uint8_t> buffer;
      while (available()) {
        buffer.push_back(read());  // Lit les données disponibles
      }
      if (validate_crc(buffer)) {  // Valide le CRC de la trame
        parse_frame(buffer);  // Analyse et traite la trame reçue
      } else {
        ESP_LOGW("airton", "Invalid CRC");  // Log en cas de CRC invalide
      }
    }
  }

  // Forge une trame de commande pour l'AC
  static std::string forge_frame(const std::string &mode, const std::string &fan_speed, float temp_setpoint) {
    std::vector<uint8_t> frame = {0x7A, 0x7A, 0x21, 0xD5, 0x18, 0x00, 0x00, 0xA1, 0x00, 0x00, 0x00};
    uint8_t mode_value = mode_to_byte(mode);
    uint8_t fan_value = fan_to_byte(fan_speed);
    uint8_t temp_value = static_cast<uint8_t>(temp_setpoint) - 16;

    // Modifie les registres pour inclure les paramètres
    frame[12] = mode_value | fan_value;
    frame[13] = temp_value;

    // Calcule et ajoute le CRC à la fin de la trame
    uint16_t crc = calculate_crc(frame);
    frame.push_back(crc & 0xFF);
    frame.push_back((crc >> 8) & 0xFF);

    return bytes_to_hex(frame);  // Retourne la trame sous forme hexadécimale
  }

  // Génère une trame pour éteindre le climatiseur
  static std::string forge_frame_off() {
    return forge_frame("off", "auto", 16.0);
  }

 private:
  Sensor *internal_temp_;  // Capteur pour la température interne
  Sensor *temp_setpoint_;  // Capteur pour la consigne de température
  TextSensor *ac_mode_;  // Capteur pour le mode AC
  TextSensor *fan_speed_;  // Capteur pour la vitesse du ventilateur

  // Calcule le CRC de la trame
  static uint16_t calculate_crc(const std::vector<uint8_t> &data) {
    uint16_t crc = 0xFFFF;
    for (uint8_t byte : data) {
      crc ^= byte;
      for (int i = 0; i < 8; i++) {
        if (crc & 1) {
          crc = (crc >> 1) ^ 0xA001;
        } else {
          crc >>= 1;
        }
      }
    }
    return crc;
  }

  // Valide le CRC d'une trame
  static bool validate_crc(const std::vector<uint8_t> &data) {
    if (data.size() < 3) return false;
    uint16_t calculated_crc = calculate_crc({data.begin(), data.end() - 2});
    uint16_t received_crc = data[data.size() - 2] | (data[data.size() - 1] << 8);
    return calculated_crc == received_crc;
  }

  // Convertit un mode en valeur binaire
  static uint8_t mode_to_byte(const std::string &mode) {
    if (mode == "auto") return 0x00;
    if (mode == "cool") return 0x01;
    if (mode == "dry") return 0x02;
    if (mode == "fan_only") return 0x03;
    if (mode == "heat") return 0x04;
    if (mode == "off") return 0x08;
    return 0x00;  // Valeur par défaut
  }

  // Convertit une vitesse de ventilateur en valeur binaire
  static uint8_t fan_to_byte(const std::string &fan_speed) {
    if (fan_speed == "auto") return 0x00;
    if (fan_speed == "low") return 0x10;
    if (fan_speed == "medium") return 0x30;
    if (fan_speed == "high") return 0x50;
    return 0x00;  // Valeur par défaut
  }

  // Analyse une trame reçue et publie les valeurs dans les capteurs
  void parse_frame(const std::vector<uint8_t> &frame) {
    float internal_temp = frame[10] + frame[11] / 10.0;  // Température interne
    this->internal_temp_->publish_state(internal_temp);

    int temp_setpoint = frame[14] + 16;  // Consigne de température
    this->temp_setpoint_->publish_state(temp_setpoint);

    std::string mode = byte_to_mode(frame[13] & 0x07);  // Mode AC
    this->ac_mode_->publish_state(mode);

    std::string fan_speed = byte_to_fan((frame[13] & 0x70) >> 4);  // Vitesse ventilateur
    this->fan_speed_->publish_state(fan_speed);
  }

  // Convertit une valeur binaire en mode AC
  static std::string byte_to_mode(uint8_t byte) {
    switch (byte) {
      case 0x00:
        return "auto";
      case 0x01:
        return "cool";
      case 0x02:
        return "dry";
      case 0x03:
        return "fan_only";
      case 0x04:
        return "heat";
      case 0x08:
        return "off";
      default:
        return "unknown";
    }
  }

  // Convertit une valeur binaire en vitesse de ventilateur
  static std::string byte_to_fan(uint8_t byte) {
    switch (byte) {
      case 0x00:
        return "auto";
      case 0x10:
        return "low";
      case 0x30:
        return "medium";
      case 0x50:
        return "high";
      default:
        return "unknown";
    }
  }
};

Merci mais avant de chercher a convertir autoexec.be vers ESPHOME
il faut l’épurer au maximum retirer toutes les choses qui ne serviront pas forcement comme le choix d’une sonde externe / ajout d’une hystérise / ajour d’un offset

Je vais essayer cette semaine de retirer un max de chose non essentielle pour ensuite avoir une base saine pour la conversion

1 « J'aime »

Salut et bonne année !

@maverick80, as tu eu le temps d’avancer un peu sur le fichier pendant les fêtes ?

ah super intéressant !
Quelqu’un a essayé avec ESPHome ?

Négatif pour ma part, comme j’ai un module de la marque fonctionnel je n’ai pas pris le temps d’essayer et je pense que j’attendrais qu’une solution fonctionnelle soit trouvé via un ESP32. Je revendrais ce jour là mon module :joy:

Bonjour. Nouveau sur ce site, voilà : J’ai acheté sur « Bon Coin » un module Wi-Fi sans contrôler la comptabilité avec mon (très bon unité intérieure 409731) model 3.5kw. Mais voilà le module Wi-Fi 409945, n’est pas compatible (si qq est intéressé). Donc, la leçon pour moi (et peut-être d’autres) Vérifiez bien le type de module Wi-Fi avant de commander. Celui qui (me) convient est bien 409729 ! Bien sûr le vendeur refuse de me le reprendre parce que je n’ai pas été attentif à la référence (je comprend), mais il doit savoir (pro) avec quel model il est associé … à bon entendeur …

Bonjour à tous, clim raccordée aujourd’hui donc je vais regarder l’ESP32. J’ai que des C6 et des H2 (compatible Zigbee) donc si je peux j’essaierai de le faire fonctionner dessus.

Du nouveau ou je part du post de @Maverick80 du 2 novembre ?
Merci pour vos recherche en tout cas, très gros point de départ =)

Bonjour,

Je viens de m’équipé d’une clim airton et j’ai bien évidemment pas pris le module wifi a 100 balles. :smiley:
J’ai connecté un esp32 + max3485 sur le port série de l’unité intérieure et commencé a debug le port uart avec esphome.
Le contenu des trames est différent de ce que j’ai pu lire dans le code de ouinouin.

Le header de trame n’est pas A7A7 mais BDBD et le reste des données ne semble pas matché non plus.

ex :
[16:25:26][D][uart_debug:114]: <<< 57,FF,C7,F9,FF,4F,FF,FF,FF,F7,37,FF,D5,77,7B,9D,9D,95,9D,9F,35,19,A1,A1,45,3B,FF,FF,B3,BD,BD

J’ai passsé un peu de temps pour identifier la données correspond à la consigne, mais j’ai pas vraiment le temps pour le moment de me retaper toute le reverse engineering de la comm série.

dans la trame ci dessus, c’est le hi bit du 4eme bit qui correspond : 9, qui correspond a 19°C
table de traduction du bit en température :
F-16
E-16.5
D-17
C-17.5
B-18
A-18.5
9-19
8-19.5
7-20

Je sais pas si j’ai raté quelque chose mais il semblerait qu’airton ai fait evoluer son protocole de communication, non ?

1 « J'aime »

Top !

Merci du partage.

Helo, un petit message pour vous informer que mon soucis a été résolu, et l’intégration esphome / ha est sur de bon rail.

La gestion de la pac, en automatique, via un thermostat en esphome, c’est le jour et la nuit comparé à la gestion bourinne de base intégré à l’unité. :smiley:

1 « J'aime »

Au top !
Du coup ça veut dire qu’on va bientôt pouvoir se passer du module officiel, c’est cool si tu arrives à faire ça via ESPhome, merci pour ton travail !

C’est clair !
J’ai beau avoir un module wifi, si je pouvais me passer totalement de cette daube de truc en Tuya je prend !

2 « J'aime »

Question pour ceux qui ont le module wifi tuya. Est-ce que l’unité interieur « bippe » quand vous envoyez des commandes via la passerelle ? en tout cas via la télécommande c’est juste infernal…
Faut me laisser un peu de temps pour tester / paufiner la chose. Je posterai les sources sur github pour ceux qui sont à l’aise pour monter un esp, flasher et cabler.
Pour les moins habiles, il est possible que je monte une série d’unité plug and play pour concurrencer le module tuya. :smiley:

Oui la mienne bip pareille que si l’ordre était envoyé par la télécommande.
A priori sur certaines unités on peu désactiver le bip et dans ce cas c’est possible via la télécommande… si la télécommande ne comporte pas cette option, alors le bip ne peut pas être désactivé (sauf à le débrancher physiquement, ce que certains font…)

ok merci du retour. Ma télécommande n’a pas l’option « mute »… mais j’ai trouvé un bit dans la trame qui permet de couper le bip pour les commande envoyés via le serial.
Il y a pas de raison pour que ce fonctionne pas pour toutes les unités qui utilise, à minima, le acw02.
C’est que du bonus :smiley:

j’ai déjà essayé d’envoyer la commande via le DPS qui correspond à la fonction, ça n’a aucun effet.

byte 18 : premiere commande, ca bip, la seconde ca bip plus !
Perso, j’aurai trouvé ca ingérable un pilotage automatique avec des bip permanent. :wink:

1 « J'aime »

Super !
Bon maintenant faut que tu nous en dise plus sur tout ça ! Je suis chaud pour essayer.

Bonjour à tous,

Je suis un peut l exclus je suis sous jeedom mais je suis le fil.

Bravo pour le dev

Je viens d acquérir 2 clim A+++ idem j ai pas pris le module wifi.