Réfrigérateur Tesla

=============================================================================
Bonjour ,

J'ai acheté un réfrigérateur / congélateur pour ma Tesla Y . La chaleur étant de plus en plus longue cela est fort utile pour les déplacement et même aller chercher des glaces !

Ce frigo de 35 litres s'installe dans le sous coffre arrière ( taille exact de la réservation )

Il fait du 10 à -15° C

Il se pilote en Bluetooth avec l'application Tesla Fridge .

Je voulais l'intégré dans HA .

J'ai donc fait un montage à base d'ESP32 avec EspHome

attention spoiler : cela ne fonctionne qu'à domicile car l'esp est sur le wifi de la maison , donc la Tesla dois être chez moi .

Pour l'extérieur j'utilise l'application

Et à savoir qu'1 seule instance Bluetooth est possible , donc soit l'application soit l'esp ;

Ce projet est peut être valable avec d'autre frigo ou glacière portable qui utilisent une application Bluetooth .

Le mode ECO est pour du standard , le mode MAX permet de descendre rapidement dans les valeurs négative .

Sur ce frigo il y a un mode de protection de la batterie , si la valeur de la tension de la batterie secondaire est trop basse , alors il s'arrête ( Mode L , M , ou H )

Le fichier EspHome , il faut modifier l'adresse MAC (ble_client :mac_adresse) en fonction de votre device ( le trouver avec NFR connect sur tel par exemple )

Suivant le modèle/marque les UUID seront peut être aussi différent .

esphome:
  name: tesla-fridge
  friendly_name: Tesla Fridge

esp32:
  board: esp32dev
  framework:
    type: esp-idf
    advanced:
      minimum_chip_revision: "3.1"
      sram1_as_iram: true

logger:
  level: INFO

api:
  encryption:
    key: "........................"

ota:
  - platform: esphome

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  min_auth_mode: WPA2

  manual_ip:
    static_ip: 192.168.0.161
    gateway: 192.168.0.1
    subnet: 255.255.255.0

  ap:
    ssid: "Tesla Frigo"
    password: ".............."

captive_portal:

globals:
  - id: tesla_ble_connected
    type: bool
    restore_value: no
    initial_value: "false"

  - id: tesla_requested_setpoint
    type: int
    restore_value: no
    initial_value: "0"

  - id: tesla_mode_command
    type: int
    restore_value: no
    initial_value: "3"

  - id: tesla_battery_level_command
    type: int
    restore_value: no
    initial_value: "0"

esp32_ble_tracker:
  scan_parameters:
    active: true
    continuous: true
    interval: 320ms
    window: 300ms

ble_client:
  - mac_address: xx:xx:xx:xx:xx:xx
    id: fridge
    auto_connect: true

    on_connect:
      then:
        - lambda: |-
            id(tesla_ble_connected) = true;
        - logger.log:
            level: INFO
            format: "Tesla Frigo connecté en BLE"

    on_disconnect:
      then:
        - lambda: |-
            id(tesla_ble_connected) = false;
        - logger.log:
            level: WARN
            format: "Tesla Frigo déconnecté du BLE"

binary_sensor:
  - platform: status
    name: "Statut ESP"
  - platform: template
    id: tesla_ble_status
    name: "Frigo Communication Bluetooth"
    device_class: connectivity
    lambda: |-
      return id(tesla_ble_connected);

sensor:
  - platform: template
    id: tesla_temperature_actuelle
    name: "Frigo Température actuelle"
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
    accuracy_decimals: 0
    update_interval: never

  - platform: template
    id: tesla_consigne
    name: "Frigo Consigne reçue"
    unit_of_measurement: "°C"
    device_class: temperature
    accuracy_decimals: 0
    update_interval: never

number:
  - platform: template
    id: tesla_reglage_consigne
    name: "Frigo Régler la consigne"
    icon: "mdi:thermometer"
    unit_of_measurement: "°C"
    min_value: -15
    max_value: 10
    step: 1
    optimistic: false
    update_interval: never

    set_action:
      then:
        - lambda: |-
            id(tesla_requested_setpoint) = static_cast<int>(lroundf(x));

        - if:
            condition:
              lambda: |-
                return id(tesla_ble_connected);
            then:
              - ble_client.ble_write:
                  id: fridge
                  service_uuid: "00001920-0000-1000-8000-00805F9B34FB"
                  characteristic_uuid: "00000000-0000-0000-0000-000000ABCD12"
                  value: !lambda |-
                    const int8_t target =
                      static_cast<int8_t>(id(tesla_requested_setpoint));

                    std::vector<uint8_t> frame = {
                      0x68, 0x0A, 0x03,
                      static_cast<uint8_t>(target),
                      0x00, 0x00,
                      0xF1, 0x6B, 0xD8, 0x7D, 0x2E, 0x78,
                      0x00, 0x16
                    };

                    uint8_t checksum = 0;
                    for (size_t i = 0; i <= 11; i++) {
                      checksum = static_cast<uint8_t>(checksum + frame[i]);
                    }
                    frame[12] = checksum;
                    return frame;
            else:
              - logger.log:
                  level: WARN
                  format: "Consigne non envoyée : frigo BLE non connecté"

select:
  - platform: template
    id: tesla_mode_refroidissement
    name: "Frigo Mode refroidissement"
    icon: "mdi:snowflake"
    optimistic: false
    options:
      - "MAX"
      - "ECO"

    set_action:
      then:
        - lambda: |-
            id(tesla_mode_command) = (x == "ECO") ? 0x04 : 0x03;

        - ble_client.ble_write:
            id: fridge
            service_uuid: "00001920-0000-1000-8000-00805F9B34FB"
            characteristic_uuid: "00000000-0000-0000-0000-000000ABCD12"
            value: !lambda |-
              const uint8_t mode =
                static_cast<uint8_t>(id(tesla_mode_command));

              std::vector<uint8_t> frame = {
                0x68, 0x08, 0x05, mode,
                0xF7, 0x6D, 0xDE, 0x7B, 0x28, 0x7E,
                0x00, 0x16
              };

              uint8_t checksum = 0;
              for (size_t i = 0; i <= 9; i++) {
                checksum = static_cast<uint8_t>(checksum + frame[i]);
              }
              frame[10] = checksum;
              return frame;

  - platform: template
    id: tesla_protection_batterie
    name: "Frigo Protection batterie"
    icon: "mdi:car-battery"
    optimistic: false
    options:
      - "L"
      - "M"
      - "H"

    set_action:
      then:
        - lambda: |-
            if (x == "H") {
              id(tesla_battery_level_command) = 0x02;
            } else if (x == "M") {
              id(tesla_battery_level_command) = 0x01;
            } else {
              id(tesla_battery_level_command) = 0x00;
            }

        - ble_client.ble_write:
            id: fridge
            service_uuid: "00001920-0000-1000-8000-00805F9B34FB"
            characteristic_uuid: "00000000-0000-0000-0000-000000ABCD12"
            value: !lambda |-
              const uint8_t level = static_cast<uint8_t>(
                id(tesla_battery_level_command)
              );

              std::vector<uint8_t> frame = {
                0x68, 0x08, 0x04, level,
                0xF6, 0x6C, 0xDF, 0x7A, 0x29, 0x7F,
                0x00, 0x16
              };

              uint8_t checksum = 0;
              for (size_t i = 0; i <= 9; i++) {
                checksum = static_cast<uint8_t>(checksum + frame[i]);
              }
              frame[10] = checksum;
              return frame;

text_sensor:
  - platform: ble_client
    id: tesla_notify
    name: "Frigo Notification"
    internal: true
    ble_client_id: fridge
    service_uuid: "00001920-0000-1000-8000-00805F9B34FB"
    characteristic_uuid: "00000000-0000-0000-0000-000000CDAB12"
    notify: true
    update_interval: never

    on_notify:
      then:
        - lambda: |-
            const uint8_t *d =
              reinterpret_cast<const uint8_t *>(x.data());

            if (x.size() != 13 || d[0] != 0x68 ||
                d[2] != 0x02 || d[12] != 0x16) {
              return;
            }

            uint8_t checksum = 0;
            for (size_t i = 0; i <= 10; i++) {
              checksum = static_cast<uint8_t>(checksum + d[i]);
            }
            if (checksum != d[11]) {
              return;
            }

            const int temperature =
              static_cast<int>(static_cast<int8_t>(d[4]));
            const int consigne =
              static_cast<int>(static_cast<int8_t>(d[7]));

            id(tesla_temperature_actuelle)->publish_state(temperature);
            id(tesla_consigne)->publish_state(consigne);
            id(tesla_reglage_consigne)->publish_state(consigne);

            if (d[6] == 0x00) {
              id(tesla_protection_batterie)->publish_state("L");
              id(tesla_battery_level_command) = 0x00;
            } else if (d[6] == 0x01) {
              id(tesla_protection_batterie)->publish_state("M");
              id(tesla_battery_level_command) = 0x01;
            } else if (d[6] == 0x02) {
              id(tesla_protection_batterie)->publish_state("H");
              id(tesla_battery_level_command) = 0x02;
            }

            if (d[10] == 0x03) {
              id(tesla_mode_refroidissement)->publish_state("MAX");
              id(tesla_mode_command) = 0x03;
            } else if (d[10] == 0x04) {
              id(tesla_mode_refroidissement)->publish_state("ECO");
              id(tesla_mode_command) = 0x04;
            }

  - platform: ble_client
    id: tesla_read
    name: "Frigo Lecture "
    internal: true
    ble_client_id: fridge
    service_uuid: "00001920-0000-1000-8000-00805F9B34FB"
    characteristic_uuid: "0000AB12-0000-1000-8000-00805F9B34FB"
    notify: false
    update_interval: 5s

    on_value:
      then:
        - lambda: |-
            const uint8_t *d =
              reinterpret_cast<const uint8_t *>(x.data());

            if (x.size() != 13 || d[0] != 0x68 ||
                d[2] != 0x01 || d[12] != 0x16) {
              return;
            }

            uint8_t checksum = 0;
            for (size_t i = 0; i <= 10; i++) {
              checksum = static_cast<uint8_t>(checksum + d[i]);
            }
            if (checksum != d[11]) {
              return;
            }

            const int temperature =
              static_cast<int>(static_cast<int8_t>(d[4]));
            const int consigne =
              static_cast<int>(static_cast<int8_t>(d[7]));

            id(tesla_temperature_actuelle)->publish_state(temperature);
            id(tesla_consigne)->publish_state(consigne);
            id(tesla_reglage_consigne)->publish_state(consigne);

            if (d[6] == 0x00) {
              id(tesla_protection_batterie)->publish_state("L");
              id(tesla_battery_level_command) = 0x00;
            } else if (d[6] == 0x01) {
              id(tesla_protection_batterie)->publish_state("M");
              id(tesla_battery_level_command) = 0x01;
            } else if (d[6] == 0x02) {
              id(tesla_protection_batterie)->publish_state("H");
              id(tesla_battery_level_command) = 0x02;
            }

            if (d[10] == 0x03) {
              id(tesla_mode_refroidissement)->publish_state("MAX");
              id(tesla_mode_command) = 0x03;
            } else if (d[10] == 0x04) {
              id(tesla_mode_refroidissement)->publish_state("ECO");
              id(tesla_mode_command) = 0x04;
            }

Sur l'afficheur il y a d'autres donné que je n'ai pas ajouté ou chercher : tension , défauts

et

Le marche/arrêt complet , pour le marche une simple pression et il s'allume

alors que l'arrêt il faut une pression longue d'au moins 5 à 6 secondes .

Cela peux être résolu temporairement par le programme de la Tesla qui coupe l'alimentation des accessoires .

1 « J'aime »