Changing LVGL colours using lambda

I am trying my hand and LVGL for a new display project. I am converting some old code, so I have a whole bunch of lambda already I am trying to re-use.

My question is about named colours for widgets. In a widget you can use named colours like:

        - arc:
            id: dir_indicator
            x: 10
            y: 10
            start_angle: 0
            end_angle: 360
            arc_width: 3
            adjustable: false 
            height: 12
            width: 12
            arc_color: LIGHTBLUE

Then what I want to do is change that colour in an on_value: block for a sensor.

I tried using the named colours in the lambda assigns, but of course they are not defined. I could just do my if statements in yaml, but what I have currently is:

globals:
  - id: rose_indicator_color
    type: lv_color_t

text_sensor:

  - platform: homeassistant
    entity_id: sensor.wind_speed
    id: wind_speed
    on_value: 
      then:
        - lambda: |-
            float speed = atof(id(wind_speed).state.c_str());
            if (speed<=11) { id(rose_indicator_color) = lv_palette_lighten(LV_PALETTE_BLUE, 3); }
              else {
            if (speed>11 && speed<=30) { id(rose_indicator_color) = lv_palette_main(LV_PALETTE_GREEN); }
              else {
            if (speed>30 && speed<=60) { id(rose_indicator_color) = lv_palette_main(LV_PALETTE_ORANGE); }
              else {
            if (speed>60) { id(rose_indicator_color) = lv_palette_main(LV_PALETTE_RED); }
              } } }
        - lvgl.widget.update:
            id: dir_indicator
            arc_color: !lambda return id(rose_indicator_color);

Is there a better way to do this? This seems a bit ugly and I was hoping I was missing something…

Can’t you move the conditions directly to arc_color lambda?

Then what triggers them to update? I am having problems with the learning curve here. :slight_smile: The small arc is the indicator for wind direction which changes often. Apart from the colour and the x/y values, the arc parameters never change and aren’t linked to any sensor.

For lambda display code the code is executed every time the display engine refreshes the display. I didn’t think LVGL did that - but happy to be corrected. I thought LVGL widgets were static unless updated specifically by lvl.widget.update or by user interaction…

I have never even held LVGL display on my hand…
What I meant, to move the first on_value: lambda with conditions directly to arc_color update lambda underneath. So you don’t need to use globals.
I’m not sure if I understood the problem here though…

Ah - I get it - yes that would save a couple of lines - thanks.

Still doesn’t solve my problem with colour names as I’ll have to use the same functions but it’s halfway there. :smiley:

Wouldn’t it be easier to use hex colors like
0xAAD8E6

1 Like

Worth a try - yes.

This how I change label color based on a change in the sensor value.

sensor: 
  - platform: wifi_signal
    name: ${disp_name} WiFi Status
    update_interval: 10s
  - platform: homeassistant
    id: blood_sugar
    entity_id: sensor.blood_sugar_2
    accuracy_decimals: 0
    unit_of_measurement: mg/dL
    internal: true
    on_value:
      - lvgl.label.update:
          id: bg_level
          text:
            format: "%.0f"
            args: [x]
          text_color: !lambda |-
            if (x < 55 || x >= 260.0) return lv_color_hex(0xFF0000);
            if ((x >= 55.0 && x < 70.0) || (x >= 180.0 && x < 260.0)) return lv_color_hex(0xFFFF00);
            if (x >= 70.0 && x < 180.0) return lv_color_hex(0x00FF00);
            return lv_color_hex(0xFF00FF);

3 Likes

Thanks guys - I don’t think I can get away from using the functions but both your suggestions make for much neater yaml:

  - platform: homeassistant
    entity_id: sensor.wind_speed
    id: wind_speed
    on_value: 
      then:
        - lvgl.widget.update:
            id: dir_indicator
            arc_color: !lambda |-
              float speed = atof(id(wind_speed).state.c_str());
              if (speed<=11) return lv_palette_lighten(LV_PALETTE_BLUE, 3); 
              if (speed>11 && speed<=30) return lv_palette_main(LV_PALETTE_GREEN); 
              if (speed>30 && speed<=60) return lv_palette_main(LV_PALETTE_ORANGE); 
              return lv_palette_main(LV_PALETTE_RED); 
1 Like