lubeda / EspHoMaTriXv2

A simple DIY status display with a 8x32 RGB LED matrix, implemented with esphome.io and Home Assistant.
MIT License
269 stars 25 forks source link

How to set night_mode_screens with included packages #224

Closed popy2k14 closed 4 months ago

popy2k14 commented 4 months ago

Question

I have a setup like this:

substitutions:
  sub_night_modes_screens: "[2,16]"

#include ulanzi_tc001 yaml
packages:
  device_base: !include common/devices/ulanzi_tc001v2.yaml  

than in ulanzi_tc001v2.yaml :

ehmtxv2:
  ...
  night_mode_screens: $sub_night_modes_screens
  ...

Error on build:

  Unknown value '[2,16]', valid options are '1', '2', '3', '4', '5', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26'.
  night_mode_screens: [2,16]

It seems the conversion from the string substitution fails. When using:

ehmtxv2:
  ...
  night_mode_screens: [2,16]
  ...

it works.

Any ideas how i can substitute the night screens?

Additional information

Logs

see above

andrewjswan commented 4 months ago

sub_night_modes_screens: "[2,16]"

Maybe:

sub_night_modes_screens: [2,16]

?

popy2k14 commented 4 months ago

Alread tried and sadly not working. I think it's because substitutions are strings.

popy2k14 commented 4 months ago

@andrewjswan @lubeda any other hint's how i can change the config (with an included package) so that i can give different night mode screens into the package?

andrewjswan commented 4 months ago

any other hint's how

!secret .... ?

popy2k14 commented 4 months ago

How? Sorry but i dont get it. I have two device yamls (see above) which everyone includes the device_base where the ehmtx lives.

Also tried with vars, like described here: https://github.com/esphome/esphome/pull/3602 But the issue is it has to be a list and will always interpreted as one variable like "[2,16]".

Is any other method like map?

Sorry for being a little bit off topic here, but maybe this will also help others setup the component in the future.

andrewjswan commented 4 months ago

Sorry, but i dont know :(

popy2k14 commented 4 months ago

No problem :-) i am currently trying any way i find on the net :-)

popy2k14 commented 4 months ago

Found a solution with packages. Before, nothing worked. Tried substituions, vars, anchors, ...

Just using a second package for different night modes work. Packages will be combined when have the same keys, like ehmtxv2 -> night_mode_screens. So here is my solution:

device1 yaml:

substitutions:
  name: "pixel-clock-wz"
  night_mode_brightness: "50"
  aab_min: "40"
  night_mode_r: "205"

esphome:
  name: $name 
  friendly_name: "Pixel Clock WZ"

#include ulanzi_tc001 yaml
packages:
  night_modes: !include common/devices/ulanzi_tc001v2_night_modes_wz.yaml 
  device_base: !include common/devices/ulanzi_tc001v2.yaml

device2 yaml (just other substitutions & othe night_mode_screens package):

substitutions:
  name: "pixel-clock-sz"
  night_mode_brightness: "20"
  aab_min: "30"
  night_mode_r: "235"

esphome:
  name: $name 
  friendly_name: "Pixel Clock SZ"

#include ulanzi_tc001 yaml
packages:
  #device_base: !include common/devices/ulanzi_tc001.yaml
  night_modes: !include common/devices/ulanzi_tc001v2_night_modes_sz.yaml 
  device_base: !include common/devices/ulanzi_tc001v2.yaml

ulanzi_tc001v2.yaml has the main yaml part:

substitutions:
  # Pin definition from https://github.com/aptonline/PixelIt_Ulanzi 
  battery_pin: GPIO34 
  ldr_pin: GPIO35 
  matrix_pin: GPIO32 
  left_button_pin: GPIO26 
  mid_button_pin: GPIO27 
  right_button_pin: GPIO14 
  scl_pin: GPIO22 
  sda_pin: GPIO21

external_components:
  - source:
      type: git
      url: https://github.com/lubeda/EspHoMaTriXv2
      ref: 2024.4.1
    refresh: 1min
    components: [ehmtxv2]    

esphome:
  comment: "Ulanzi TC001"
  project:
    name: "Ulanzi.EHMTXv2"
    version: "2.0.0"
  on_boot:
    then:
      - ds1307.read_time:

esp32:
  board: esp32dev

#include device_base yaml
packages:
  device_base: !include /config/esphome/common/device_base.yaml

font:
  # Font included in this folder
  # - file: mateine.ttf
  #   size: 16
  #   id: default_font
  #   glyphs:  |
  #     !?"%()+*=,-_.:°0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnÖÄÜöäüopqrstuvwxyz@<>ߧ€/
  # Matrix Clock Fonts
  # Grab these from https://github.com/trip5/Matrix-Fonts
  # See https://github.com/lubeda/EspHoMaTriXv2#font
  # Store in a "fonts" subfolder of your ESPHome config folder or change paths below
  - file: fonts/MatrixLight8.bdf
    id: special_font
    glyphs:  |
      ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz°
  #- file: fonts/MatrixChunky6.bdf
  #  id: special_font
  #  glyphs:  |
  #    ! "#$%&'()*+,-./0123456789:APMTapmt
  - file: fonts/Calcium.ttf
    id: default_font
    size: 16
    glyphs:  |
      !?"%‰()+*=,-_.:°µ²³0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnÖÄÜöäüopqrstuvwxyz€$@<>/

globals:
  # aab = auto-adjustable brightness
  - id: aab_enabled
    type: "bool"
    restore_value: true
    initial_value: "true"
  - id: aab_add
    type: int
    initial_value: '10'
  - id: aab_max
    type: int
    initial_value: '220'
  - id: display_enabled
    type: "bool"
    restore_value: true
    initial_value: "true"
  - id: night_mode_enabled
    type: "bool"
    restore_value: true
    initial_value: "false"
  - id: is_running
    type: "bool"
    initial_value: "false"

ehmtxv2:
  id: rgb8x32
  icons2html: true
  matrix_component: ehmtx_display
  time_component: ehmtx_time
  time_format: "%H:%M"
  date_format: "%d.%m"
  show_seconds: false
  brightness: 0  #0-255
  # Uncomment below if using the mateine font
  default_font_id: default_font
  special_font_id: special_font
  default_font_yoffset: 8
  special_font_yoffset: 8
  # Comment out below if using mateine font
  #default_font_id: default_font
  #default_font_yoffset: 8
  #special_font_id: special_font
  #special_font_yoffset: 6
  # until here

  # black boot logo with red dot
  boot_logo: "[32768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]"

  clock_interval: 20      # show the clock at least each x seconds
  show_dow: false         # draw the day indicator on the bottom of the screen, defaults to true
  #show_date: true         # show the date for show_screen - show_clock seconds otherwise only shows the clock for show_screen seconds, defaults to true
  week_start_monday: true # default monday is first day of week, false = sunday
  #night_mode_screens: [2,16]       #will be set in files ulanzi_tc001v2_night_modes_xx.yaml
  icons:
    - id: ha
      lameid: 7956
    - id: tempc
      lameid: 2422
    - id: plug
      lameid: 403
    - id: humidity
      lameid: 51764
    - id: co2
      lameid: 30662
    - id: weather_clear_night
      lameid: 53383
    - id: weather_cloudy
      lameid: 53384
    - id: weather_fog
      lameid: 12196  
    - id: weather_hail
      lameid: 53385  
    - id: weather_lightning
      lameid: 50231  
    - id: weather_lightning_rainy
      lameid: 49299  
    - id: weather_partlycloudy
      lameid: 53802  
    - id: weather_pouring
      lameid: 49300  
    - id: weather_rainy
      lameid: 2284  
    - id: weather_snowy
      lameid: 2289  
    - id: weather_snowy_rainy
      lameid: 49301  
    - id: weather_sunny
      lameid: 1246
    - id: weather_windy
      lameid: 17076  
    - id: weather_windy_variant
      lameid: 15618  
    - id: weather_exceptional
      lameid: 5464    
    - id: washing_machine_ready
      lameid: 26673
    - id: dryer_ready
      lameid: 48497
    - id: dishwasher_ready
      lameid: 47488
    - id: door_ringing
      lameid: 24800
    - id: fire
      lameid: 24873
    - id: water
      lameid: 24116
    - id: speaker
      lameid: 59332
    - id: mute
      lameid: 31722
  on_empty_queue:
    then:
      lambda: |-
        //set flag that we are running and from now on the switch changes lambda take effect
        id(is_running) = true;

        //restore display state
        if (id(display_enabled)) {
            ESP_LOGI("on_empty_queue", "set display on!");
            //id(displaycontrol).turn_on();
            id(rgb8x32)->set_display_on();
        } else {
            ESP_LOGI("on_empty_queue", "set display off!");
            //id(displaycontrol).turn_off();
            id(rgb8x32)->set_display_off();
        }

        //restore night mode (this adds the clock_screen)
        if (id(night_mode_enabled)) {
            ESP_LOGI("on_empty_queue", "set night mode on!");        
            id(rgb8x32)->set_night_mode_on();
        } else {
            ESP_LOGI("on_empty_queue", "set night mode off!");        
            id(rgb8x32)->set_night_mode_off();
        }

        //add date screen
        id(rgb8x32)->date_screen(1440,5);
  on_start_running:
     then:
       lambda: |-
        //set flag that we are running and from now on the switch changes lambda take effect
        id(is_running) = true;

        //restore display state
        if (id(display_enabled)) {
            ESP_LOGI("on_empty_queue", "set display on!");
            //id(displaycontrol).turn_on();
            id(rgb8x32)->set_display_on();
        } else {
            ESP_LOGI("on_empty_queue", "set display off!");
            //id(displaycontrol).turn_off();
            id(rgb8x32)->set_display_off();
        }

        //restore night mode (this adds the clock_screen)
        if (id(night_mode_enabled)) {
            ESP_LOGI("on_empty_queue", "set night mode on!");        
            id(rgb8x32)->set_night_mode_on();
        } else {
            ESP_LOGI("on_empty_queue", "set night mode off!");        
            id(rgb8x32)->set_night_mode_off();
        }

        //add date screen
        id(rgb8x32)->date_screen(1440,5);
  on_next_screen:
    - homeassistant.event:
        event: esphome.new_screen
        data_template:
          iconname: !lambda "return icon.c_str();"
          text: !lambda "return text.c_str();"
  on_night_mode:
    then:
      lambda: |-
        if (state) {
            id(aab_enabled) = false;
            id(rgb8x32)->clock_screen(1440,10,true,$night_mode_r,0,0);
            id(rgb8x32)->set_brightness($night_mode_brightness);

        } else {
            id(aab_enabled) = true;
            id(rgb8x32)->clock_screen(1440,10,true,255,255,255);
        }

#workaround that clock doesnt disappear after lifetime
interval:
  - interval: 720min
    then:
      lambda: |-
        //restore night mode (this adds the clock_screen)
        if (id(night_mode_enabled)) {
            ESP_LOGI("interval", "set night mode on!");        
            id(rgb8x32)->set_night_mode_on();
        } else {
            ESP_LOGI("interval", "set night mode off!");        
            id(rgb8x32)->set_night_mode_off();
        }

        //add date screen
        id(rgb8x32)->date_screen(1440,5);

# workaround for compiling errors on esphome 2023.07: https://github.com/lubeda/EspHoMaTriXv2/issues/62#issuecomment-1643052894
animation:
  - id: animation_black
    file: icons/black_1x1_EspHoMaTriX.gif

binary_sensor:
  - platform: status
    name: "Status"
  - platform: gpio
    pin:
      number: $left_button_pin
      inverted: true
    name: "Left button"
    on_press:
      then:
        - number.decrement: screen_brightness
  - platform: gpio
    pin: 
      inverted: true
      number: $mid_button_pin
      mode: INPUT_PULLUP
    name: "Middle button"
    on_press:
      then:
        - switch.toggle: displaycontrol
  - platform: gpio
    pin: 
      number: $right_button_pin
      inverted: true
    name: "Right button"
    on_press:
      then:
        - number.increment: screen_brightness
# example to switch to next screen
#        lambda: |-
#          id(rgb8x32)->skip_screen();

# Enable Home Assistant API
api:
  services:
    - service: brightness_set
      variables:
        brightness: int
      then:
        lambda: |-
          id(rgb8x32)->set_brightness(brightness);
    - service: skip_screen
      then:
        lambda: |-
          id(rgb8x32)->skip_screen();
#disabled, we dont need the buzzer
#    - service: tuneplay
#      variables:
#        tune: string
#      then:
#        - rtttl.play:
#            rtttl: !lambda 'return tune;'

number:
  - platform: template
    name: "Brightness"
    id: screen_brightness
    min_value: 0
    max_value: 255
    update_interval: 10s
    step: 1
    lambda: |-
      return id(rgb8x32)->get_brightness();
    set_action:
      lambda: |-
        id(rgb8x32)->set_brightness(x);

switch:
  - platform: template
    name: "Display"
    id: displaycontrol
    icon: "mdi:power"
    restore_mode: ALWAYS_ON
    lambda: |-
      return id(rgb8x32)->show_display;
    turn_on_action:
      lambda: |-
        //just execute when is_running, otherwise we would manipulate display_enabled on an not so good point in time
        if(id(is_running) == true)
        {
            id(rgb8x32)->set_display_on();
            id(display_enabled) = true;
        }
    turn_off_action:
      lambda: |-
        //just execute when is_running, otherwise we would manipulate display_enabled on an not so good point in time
        if(id(is_running) == true)
        {
            id(rgb8x32)->set_display_off();
            id(display_enabled) = false;
        }
  - platform: template
    name: "Auto-Adjust Brightness"
    id: switch_autobrightness
    icon: mdi:brightness-auto
    restore_mode: ALWAYS_ON
    lambda: |-
      return(id(aab_enabled));
    turn_on_action:
      lambda: |-
        id(aab_enabled) = true;
    turn_off_action:
      lambda: |-
        id(aab_enabled) = false;
  - platform: template
    name: "Night mode"
    id: switch_night_mode
    icon: mdi:sleep
    restore_mode: ALWAYS_ON
    lambda: |-
        return id(rgb8x32)->night_mode;
    turn_on_action:
      lambda: |-
        //just execute when is_running, otherwise we would manipulate night_mode_enabled on an not so good point in time
        if(id(is_running) == true)
        {      
            id(rgb8x32)->set_night_mode_on();
            id(night_mode_enabled) = true;
        }
    turn_off_action:
      lambda: |-
        //just execute when is_running, otherwise we would manipulate night_mode_enabled on an not so good point in time
        if(id(is_running) == true)
        {      
            id(rgb8x32)->set_night_mode_off();
            id(night_mode_enabled) = false;
        }

sensor:
  - platform: sht3xd
    temperature:
      name: "Temperature"
    humidity:
      name: "Humidity"
    update_interval: 60s
  - platform: adc
    id: light_sensor
    name: "Illuminance"
    pin: $ldr_pin
    device_class: illuminance    
    update_interval: 10s
    attenuation: auto
    unit_of_measurement: lx
    accuracy_decimals: 0
    filters:
      - lambda: |-
          return (x / 10000.0) * 2000000.0 - 15 ;
    on_value:
      then:
        - lambda: |-
            if ( id(aab_enabled) ) {
              int n = x / 4 + id(aab_add); // new_value
              if (n > id(aab_max)) n = id(aab_max);
              if (n < $aab_min) n = $aab_min;
              int c = id(rgb8x32)->get_brightness(); // current value
              c = c>0?c:1 ; 
              int d = (n - c) * 100 / c; // diff in %
              if ( abs(d) > 2 ) id(rgb8x32)->set_brightness(n);
            }

#disabled, we dont need the buzzer     
#output:
#  - platform: ledc
#    pin: $buzzer_pin
#    id: rtttl_out

#rtttl:
#  output: rtttl_out

#The hardware design of the ulanzi isn't perfect. If your ulanzi makes a crazy beeping noise after removinf the rtttl-component you may use this setting to make it silent again.
output:
  - platform: gpio
    pin: GPIO15
    id: crazy_hardware_workaround

i2c:
  sda: $sda_pin
  scl: $scl_pin
  scan: true
  id: i2cbus

light:
  - platform: neopixelbus
    id: ehmtx_light
    type: GRB
    internal: true
    variant: WS2812
    pin: $matrix_pin
    num_leds: 256
    color_correct: [30%, 30%, 30%]
    gamma_correct: 2.0
    name: "Light"
    restore_mode: ALWAYS_OFF

time:
  - platform: homeassistant
    on_time_sync:
      then:
        ds1307.write_time:
  - platform: ds1307
    update_interval: never
    id: ehmtx_time

display:
  - platform: addressable_light
    id: ehmtx_display
    addressable_light_id: ehmtx_light
    width: 32
    height: 8
    pixel_mapper: |-
      if (y % 2 == 0) {
        return (y * 32) + x;
      }
      return (y * 32) + (31 - x);
    rotation: 0°
    update_interval: 16ms
    auto_clear_enabled: true
    lambda: |-
      id(rgb8x32)->tick();
      id(rgb8x32)->draw();

device_base.yaml (used also in every other device)

# WiFi connection
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: ap_${name}
    password: !secret ap_password
    ap_timeout: 1min

# Unavailable for esp-idf https://github.com/esphome/feature-requests/issues/1649
captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret api_password

# Enable over-the-air updates
ota:
  password: !secret ota_password
  id: my_ota

# Unavailable for esp-idf https://github.com/esphome/feature-requests/issues/1649
# Enable Web server
web_server:
  port: 80
  auth:
    username: admin
    password: !secret web_server_password

#not needed
#http_request:
#  useragent: esphome/${name}
#  timeout: 2s

# Sync time with Home Assistant
time:
  - platform: homeassistant
    id: homeassistant_time

sensor:
  - <<: !include sensor/uptime.config.yaml
  - <<: !include sensor/wifi_signal.config.yaml

text_sensor:
  - <<: !include text_sensor/version.config.yaml
  - <<: !include text_sensor/wifi_info.config.yaml

button:
  - <<: !include button/restart.config.yaml

And finally the device specific package with different night_mode_screens:

ulanzi_tc001v2_night_modes_wz.yaml:

ehmtxv2:
  night_mode_screens: [2,5,16]

ulanzi_tc001v2_night_modes_sz.yaml:

ehmtxv2:
  night_mode_screens: [2,16]

Hope this helps someone :-)

popy2k14 commented 4 months ago

closing for now