ESPHome (Win11) OSError: no library called "cairo-2" was found

Bonjour,
J’ai un problème de compilation avec ESPhome ( 2025.7.2 ) sous windows 11 ( python 3.13 ).
dans mon code du esp32, j’utilise des icônes.

Code ESP32
substitutions:
  name: m5stickc-plus2
  friendly_name: M5StickC PLUS2

esphome:
  name: ${name}
  name_add_mac_suffix: false
  friendly_name: ${friendly_name}
  platformio_options:
    upload_speed: 115200
  on_boot: 
    - priority: 600
      then: 
        - output.turn_on: output_high
    - then:
      # read the RTC time once when the system boots
      - pcf8563.read_time: my_time
      - text_sensor.template.publish:
          id: template_text
          state: !lambda |-
              char str[17];
              time_t currTime = id(my_time).now().timestamp;
              strftime(str, sizeof(str), "%H:%M:%S %d/%m/%y", localtime(&currTime));
              return  { str };
    - then:
      - light.turn_on:
          id: display_bl
          brightness: 75%
  on_shutdown:
    - priority: 600
      then:
        - output.turn_off: output_high

esp32:
  board: m5stick-c
  framework:
    type: esp-idf   
  flash_size: 8MB

external_components:
   - source: github://pr#9021
     components: adc

psram:

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "VRxG3uCKeoR0szZUk7VksVHSjLb/XGhu5+briCNGNdg="

ota:
  - platform: esphome
    password: "f38d2cbb6bd7d5baf9c294c6d0939a73"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: 192.168.1.107
    gateway: !secret wifi_gtw
    subnet: !secret wifi_sub
    dns1: !secret wifi_dns1

script:
  - id: buzzer_cycle
    mode: single
    then:
      - output.turn_on: buzzer
      - output.ledc.set_frequency:
          id: buzzer
          frequency: "1000Hz"
      - output.set_level:
          id: buzzer
          level: "50%"
      - delay: 2s
      - output.turn_off: buzzer

# Battery voltage measured through ADC1_CH2. PLUS2 has a voltage divider,
# so reading needs to be multiplied by 2
sensor:
  - platform: adc
    pin: GPIO38
    attenuation: 12db
    update_interval: 60s
    name: "Battery Voltage"
    filters:
      - multiply: 2.0
    on_value_range:
      - below: 3.2
        then:
          - script.execute: buzzer_cycle

  - platform: sht3xd
    i2c_id: i2c_external
    temperature:
      name: Temperature
      id: temp_state
      filters:
        - offset: -1.5
    humidity:
      name: Humidity
      id: hum_state
      filters:
        - offset: 8.0
    address: 0x44
    update_interval: 60s

  - platform: qmp6988
    i2c_id: i2c_external
    pressure:
      name: Pression
      id: pression_state
      filters:
        - offset: 8.2    #7.2  
    address: 0x70
    update_interval: 60s
    iir_filter: 2x

  - platform: homeassistant
    id: battery_percent
    entity_id: sensor.m5stick_plus2_battery_pourcent

  - platform: wifi_signal
    id: wifi_signal_db
    update_interval: 60s
    entity_category: "diagnostic"
    internal: true

  - platform: copy
    source_id: wifi_signal_db
    name: WiFi Signal
    id: wifi_signal_pct
    filters:
      - lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
    unit_of_measurement: "%"
    entity_category: "diagnostic"
    device_class: ""

  - platform: uptime
    id: uptime_sec
    update_interval: 60s
    internal: true

switch:
  - platform: restart
    name: Restart
    entity_category: "diagnostic"

binary_sensor:
  # Turn on display backlight TFT LCD while Button A is click. Turn on red led while Button A is double_click
  - platform: gpio
    pin:
      number: GPIO37
      inverted: true
    name: Button A
    on_multi_click:
      - timing:
          - ON for 40ms to 400ms
          - OFF for at least 330ms
        then:
          - light.toggle: display_bl
      - timing:
          - ON for 40ms to 400ms
          - OFF for 40ms to 300ms
          - ON for 40ms to 400ms
          - OFF for at least 330ms
        then:
          - light.toggle: led1

  # Play 1000Hz tone through buzzer while Button B is pressed
  - platform: gpio
    pin:
      number: GPIO39
      inverted: true
    name: Button B
    on_press:
      then:
        - output.turn_on: buzzer
        - output.ledc.set_frequency:
            id: buzzer
            frequency: "1000Hz"
        - output.set_level:
            id: buzzer
            level: "50%"

    on_release:
      then:
        - output.turn_off: buzzer

  - platform: gpio
    pin:
      number: GPIO35
      inverted: true
    name: Button C

  - platform: status
    name: Statut
    entity_category: "diagnostic"

light:
  # Red led
  - platform: monochromatic
    output:  builtin_led
    name: Led
    id: led1
  # Backlight TFT LCD
  - platform: monochromatic
    output:  backlight
    name: Backlight
    id: display_bl
    restore_mode: ALWAYS_ON

time:
  - platform: pcf8563
    i2c_id: i2c_internal
    id: my_time
    address: 0x51
    update_interval: never

  - platform: homeassistant
    on_time_sync:
      then:
        - pcf8563.write_time: my_time
        - text_sensor.template.publish:
            id: template_text
            state: !lambda |-
              char str[17];
              time_t currTime = id(my_time).now().timestamp;
              strftime(str, sizeof(str), "%H:%M:%S %d/%m/%y", localtime(&currTime));
              return  { str };

text_sensor:
  - platform: template
    name: "RTC Sensor"
    id: template_text

  - platform: template
    id: plus_uptime
    name: Uptime
    lambda: |-
      int seconds = (id(uptime_sec).state);
      int days = seconds / (24 * 3600);
      seconds = seconds % (24 * 3600); 
      int hours = seconds / 3600;
      seconds = seconds % 3600;
      int minutes = seconds /  60;
      seconds = seconds % 60;
      if ( days ) {
        return { (to_string(days) +"d " + to_string(hours) +"h " + to_string(minutes) +"m "+ to_string(seconds) +"s ").c_str() };
      } else if ( hours ) {
        return { (to_string(hours) +"h " + to_string(minutes) +"m "+ to_string(seconds) +"s ").c_str() };
      } else if ( minutes ) {
        return { (to_string(minutes) +"m "+ to_string(seconds) +"s ").c_str() };
      } else {
        return { (to_string(seconds) +"s ").c_str() };
      }
    icon: mdi:clock-start
    update_interval: 60s
    entity_category: "diagnostic"


output:
  # Red led
  - platform: ledc
    pin: 19
    inverted: false
    id: builtin_led
  # Buzzer
  - platform: ledc
    pin:
      number: 2
      ignore_strapping_warning: true
    inverted: true
    id: buzzer
  # Backlight TFT LCD
  - platform: ledc
    pin: 27
    inverted: false
    id: backlight
  # Battery switch
  - platform: gpio
    id: output_high
    pin:
      number: GPIO4
      mode:
        output: true  


spi:
  clk_pin: GPIO13
  mosi_pin: GPIO15

# Built-in I2C Bus. Bus_external is for devices connected via the HAT pins. Not sure which interface is used for devices connected via the Grove port
i2c:
  - id: i2c_internal
    sda: GPIO21
    scl: GPIO22
    scan: false
  - id: i2c_external
    sda: GPIO0
    scl: GPIO26
    scan: false

font:
  - file: "gfonts://Roboto"
    id: roboto
    size: 22

image:
  - file: mdi:weather-pouring
    id: pouring
    type: BINARY  
    resize: 70x70
  - file: mdi:weather-partly-cloudy
    id: partly_cloudy
    type: BINARY
    resize: 70x70
  - file: mdi:weather-sunny
    id: sunny
    type: BINARY
    resize: 70x70
  - file: mdi:close
    id: croix
    type: BINARY
    resize: 70x70
  - file: mdi:battery-high
    id: battery
    type: BINARY
    resize: 30x30
  - file: mdi:wifi
    id: wifi_icon
    type: BINARY
    resize: 30x30

color:
  - id: my_white
    red: 100%
    green: 100%
    blue: 100%
  - id: my_blue
    red: 0%
    green: 0%
    blue: 100%
  - id: my_red
    red: 100%
    green: 0%
    blue: 0%
  - id: my_green
    red: 0%
    green: 100%
    blue: 0%
  - id: my_yellow
    red: 100%
    green: 100%
    blue: 0%
  - id: my_orange
    red: 100%
    green: 50%
    blue: 0%

# 1.14 inch, 135*240 Colorful TFT LCD, ST7789v2
display:
  - platform: ili9xxx
    model: st7789v
    cs_pin: GPIO5
    dc_pin: GPIO14
    reset_pin: GPIO12
    rotation: 90
    dimensions:
      height: 240
      width: 135
      offset_height: 40
      offset_width: 52
    # Required or the colors are all inverted, and Black screen is White
    invert_colors: true
    lambda: |-
      it.strftime(30, 2, id(roboto), id(my_blue), "%H:%M:%S %d/%m/%y", id(my_time).now());     
      if ((id(pression_state).state >= 960) && (id(pression_state).state < 990)) {it.image(14, 30, id(pouring), id(my_red));}
      else if ((id(pression_state).state >= 990) && (id(pression_state).state < 1020)) {it.image(14, 30, id(partly_cloudy), id(my_yellow));}
      else if ((id(pression_state).state >= 1020) && (id(pression_state).state < 1060)) {it.image(14, 30, id(sunny), id(my_green));}
      else {it.image(14, 30, id(croix), id(my_red));}
      it.printf(94, 40, id(roboto), id(my_green), "%.0fhpa", id(pression_state).state);
      it.printf(94, 66, id(roboto), id(my_blue), "%.1f°C", id(temp_state).state);
      it.printf(173, 66, id(roboto), id(my_blue), "%.0f%%", id(hum_state).state);
      if (id(battery_percent).state < 11) { it.image(20, 102, id(battery), id(my_red));}
      else {it.image(20, 102, id(battery), id(my_green));}
      it.printf(54, 106, id(roboto), id(my_white), "%.0f%%", id(battery_percent).state);
      if ((id(wifi_signal_pct).state >= 1) && (id(wifi_signal_pct).state < 25)) {it.image(123, 102, id(wifi_icon), id(my_red));}
      else if ((id(wifi_signal_pct).state >= 25) && (id(wifi_signal_pct).state < 50)) {it.image(123, 102, id(wifi_icon), id(my_orange));}
      else if ((id(wifi_signal_pct).state >= 50) && (id(wifi_signal_pct).state < 75)) {it.image(123, 102, id(wifi_icon), id(my_yellow));}
      else {it.image(123, 102, id(wifi_icon), id(my_green));}
      it.printf(161, 106, id(roboto), id(my_white), "%.0f%%", id(wifi_signal_pct).state);

Voici l’erreur que j’obtiens en testant la config :

OSError: no library called "cairo-2" was found
no library called "cairo" was found
no library called "libcairo-2" was found
cannot load library 'libcairo.so.2': error 0x7e.  Additionally, ctypes.util.find_library() did not manage to locate a library called 'libcairo.so.2'
cannot load library 'libcairo.2.dylib': error 0x7e.  Additionally, ctypes.util.find_library() did not manage to locate a library called 'libcairo.2.dylib'
cannot load library 'libcairo-2.dll': error 0x7e.  Additionally, ctypes.util.find_library() did not manage to locate a library called 'libcairo-2.dll'

j’ai essayer pip3 install cairosvg, mais toujours pareil.
Es ce que quelqu’un aurais une solution ?

Salut

Tu as plusieurs pistes là
https://stackoverflow.com/questions/73637315/oserror-no-library-called-cairo-2-was-found-from-custom-widgets-import-proje

J’ai essayé la solution :

pip install pipwin

pipwin install cairocffi

À l’installation de pipwin install cairocffi, j’ai c’est erreur :

    raise RuntimeError(
        'Your python version made changes to the bytecode')
RuntimeError: Your python version made changes to the bytecode

J’ai trouvé, il fallait installer GTK. Mais dans le lien de @Pulpy-Luke , il parlait de la version gtk2-runtime-2.24.10-2012-10-10-ash.exe qui est une version 32bits et ça ne fonctionnait pas.
Puis en lisant les commentaires, un utilisatuer a donné une autre solution et d’installer GTK3 64bits:

https://stackoverflow.com/questions/28211418/python-oserror-cannot-load-library-libcairo-so-2/77634528#77634528

le lien de download de GTK3 64bits :

Et là, magie !!! :grin:
image

1 « J'aime »

Ce sujet a été automatiquement fermé après 2 jours. Aucune réponse n’est permise dorénavant.