LVGL bar widget indicator color is not updated

I have created a battery symbol, where the outline is made up of simple lines, the variable SOC ‘contents’ is a bar and then there is an additional label on the right hand side with the SOC value in %.
Then I have defined a minimum SOC value where the color of the whole thing shall change from green to red.
Everything works as expected with the exception of the bar indicator color. This seems to stay at the original value and does not change.

        # symbol for battery low warning
        - obj:
            id: battery_symbol_obj
            x: 420
            y: 2
            width: 60
            height: 24
            bg_color: 0
            pad_all: 0
            outline_width: 0
            outline_color: 0
            border_width: 0
            border_color: 0
            border_side: NONE
            outline_pad: 0
            radius: 0
#            hidden: ${Hide_Battery_Symbol}
            hidden: false
            widgets:
              - line:
                  id: battery_symbol
                  points:
                    - 12, 2
                    - 18, 2
                    - 17, 2
                    - 17, 4
                    - 17, 3
                    - 20, 3
                    - 19, 3
                    - 19, 20
                    - 19, 19
                    - 10, 19
                    - 11, 19
                    - 11, 2
                    - 11, 3
                    - 14, 3
                  line_width: 2
                  line_rounded: false
                  line_color: !lambda |-
                    if( id(battery_soc_value) <= id(min_soc_value) ) {
                      return lv_color_hex(0xff0000); // red
                      } else {
                      return lv_color_hex(0x00ff00); // green
                    }
              - bar:
                  id: battery_bar
                  x: 12
                  y: 3
                  height: 15
                  width: 6
                  radius: 0
                  min_value: 0
                  max_value: 100
                  bg_color: 0
                  indicator:
                    bg_color:  !lambda |-
                      if( id(battery_soc_value) <= id(min_soc_value) ) {
                        return lv_color_hex(0xff0000); // red
                        } else {
                        return lv_color_hex(0x00ff00); // green
                      }
                    radius: 0
                  value: !lambda return id(battery_soc_value);
              - label:
                  id: battery_soc_label
                  x: 25
                  y: 3
                  text_font: MONTSERRAT_14
                  text_align: CENTER
                  width: 35
                  text_color: !lambda |-
                    if( id(battery_soc_value) <= id(min_soc_value) ) {
                      return lv_color_hex(0xff0000); // red
                      } else {
                      return lv_color_hex(0x00ff00); // green
                    }
                  text: !lambda |-
                    return (to_string(static_cast<int>(id(battery_soc_value)))+"%").c_str();



sensor:
  - platform: adc
    pin: 5
    name: "Battery SOC"
    unit_of_measurement: "%"
    state_class: measurement
    device_class: battery
    accuracy_decimals: 2       # ???
    attenuation: 12db          # input voltage range: 150mV --- 2450mV
    samples: 16                # samples taken per update interval
    filters:
      - multiply: 1.72
      - sliding_window_moving_average:
          window_size: 15      # average over 15 values
      - calibrate_linear:      # linearise voltage->SOC dependency
          method: exact
          datapoints:
            - 3.00 ->   0.0    # <=3.00V = battery empty (0.0%)
            - 3.36 ->   5.0
            - 3.41 ->  10.0
            - 3.48 ->  20.0
            - 3.52 ->  30.0
            - 3.56 ->  40.0
            - 3.61 ->  50.0
            - 3.70 ->  60.0
            - 3.79 ->  70.0
            - 3.89 ->  80.0
            - 4.00 ->  90.0
            - 4.05 -> 100.0    # >=4.05V = battery full (100.0%)
      - clamp:
          min_value: 0.0
          max_value: 100.0
    update_interval: 4s        # new value after 4s*15(=window size) = 60s!
    on_value:
      - lambda: id(battery_soc_value) = x;
      - lvgl.widget.refresh: battery_soc_label
      - lvgl.widget.refresh: battery_symbol
      - lvgl.widget.refresh: battery_bar

I thought that ‘lvgl.widget.refresh: battery_bar’ should also effect the bar indicator color. Is there anything I am missing?

Jörg.

Not sure why it’s not working as is, but just use lvgl.bar.update to update the color and value. Then you can use x directly instead of having to store it in a global.

Same with the label. Having lambdas in the initial config isn’t best practice, since they get evaluated at startup before stuff they are referencing may be valid.

To set the text, instead of the lambda, use the format option, something like:

    lvgl.label.update:
      id: battery_soc_label
      text:
        format: "%.0f%%"
        args: [x]

That’s cleaner, easier to read and gives you more control over formatting.

1 Like

Thank you very much for these hints!
I turned to use global variables because I need the values in many different places, but good to know this is not best practice.

I will try to apply this to my code!

Jörg.