Setting a color from HA for it.print?

Hi all

I’ve finally gotten my matrix led to work, thanks to the new function pixelmapper for that in ESPHome, THANKYOU for that!
I’ve toyed with ESPHomeMatrixLED/matrixleddemo.yaml at 69a054d0a0de2f855e3a9d1271437b87313ed3d4 · rnauber/ESPHomeMatrixLED · GitHub for quite a while, but had given up, until this function in ESPHome came up.
So now I actually have a scrolling 32x8 display, soooo cool :slight_smile:
I would however very much like to set the color of the scrolling text from HA, and I have no idea how to accomplish that.
Looking in rnauber’s code it’s set statically.

My code looks like this so far:

substitutions:
  device_name: Matrix1
  espname: matrix1
  xscrollpadding: "4" # in pix

esphome:
  name: '${espname}'
  platform: esp8266
  board: esp8285

wifi:
  ssid: !secret wifissid
  password: !secret wifipw
  reboot_timeout: 60min
  manual_ip:
    static_ip: 10.11.13.149
    gateway: 10.11.13.1
    subnet: 255.255.255.0
#  use_address: 10.11.12.201
  fast_connect: true
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${device_name} Hotspot"
    password: !secret appw

logger:
  baud_rate: 0

api:
  password: !secret apipw

ota:
  password: !secret otapw
captive_portal:

time:
  - platform: homeassistant
    id: homeassistant_time

sensor:
  - platform: wifi_signal
    name: '${device_name} wifi signal'
    update_interval: 60s
    accuracy_decimals: 0
  - platform: uptime
    name: '${device_name} uptime'
    unit_of_measurement: days
    update_interval: 300s
    accuracy_decimals: 1
    filters:
      - multiply: 0.000011574

text_sensor:
  - platform: version
    name: "${device_name} ESPHome Version"
  - platform: wifi_info
    ip_address:
      name: "${device_name} ip"
    ssid:
      name: "${device_name} ssid"
  - platform: mqtt_subscribe
    name: "Text"
    id: extratext
    topic: "${espname}/text"

mqtt:
  id: mqtt_client
  broker: !secret mqtt_broker
  username: !secret mqtt_user 
  password: !secret mqtt_password

font:
  - id: tinyfont
    file: "DejaVuSans-Bold.ttf"
    size: 9
    glyphs: '♡ÆØÅæøå!"%()+,-_.:*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'

light:
    platform: fastled_clockless
    chipset: WS2812B
    pin: GPIO2
    num_leds: 256
    rgb_order: GRB
    name: "${device_name}"
    id: led_matrix_32x8
    default_transition_length: 0s
    color_correct: [50%, 50%, 50%]
    restore_mode: ALWAYS_ON

display:
  - platform: addressable_light
    id: led_matrix_32x8_display
    addressable_light_id: led_matrix_32x8
    width: 32
    height: 8
    pixel_mapper: |-
      if (x % 2 == 0) {
        return (x * 8) + y;
      }
      return (x * 8) + (7 - y);
    rotation: 0°
    update_interval: 200ms
    lambda: |-
          static uint16_t xpos = 0;
          const char * text = id(extratext).state.c_str();
          int x_start, y_start;
          int width, height;
          
          it.get_text_bounds(0, 0, text, id(tinyfont), 
              TextAlign::TOP_LEFT, &x_start, &y_start, &width, &height); 
              
          it.print(-(xpos % (width + $xscrollpadding)), -2, 
            id(tinyfont), Color(0xFF1010), 
            TextAlign::TOP_LEFT, text); 
          xpos++;

With this I can send a text string to it via MQTT, and I can turn it on and off.
The color setting for the light entity is unfortunately not used. If I change the color it is shortly flashed on the display, and then it continues the text scrolling in the fixed color (currently red).
Is there a way I can use the color set (or have it set through a colorwheel on ha somehow), and transfer it to the it.print command?
I want to set this up for my “studio” so I can warn others of recording taking place :slight_smile: And it would be great to be able to set the color.through an automatiion or something like that.

1 Like

So, I found this on reddit to extract colors from a light:

id(red) = (id(bigclock).remote_values.get_red()*255);
id(green) = (id(bigclock).remote_values.get_green()*255);
id(blue) = (id(bigclock).remote_values.get_blue()*255);

So to test that out, I made a group of sensors:

  - platform: template
    name: red
    id: red
    lambda: |-
      return (id(led_matrix_32x8).remote_values.get_red()*255);

But that just returns 255 no matter what the color is set to?
I of course don’t need them as sensors, but that’s just for testing.

I tried defining the color ‘outside’ the it.print, and that works ok

color:
  - id: red
    red: 100%
    green: 0%
    blue: 0%
...
          it.print(-(xpos % (width + $xscrollpadding)), -2, 
            id(tinyfont), Color(id(red)), 
            TextAlign::TOP_LEFT, text);

So I guess it should be doable, but it could of course be me just going about it all silly :slight_smile:

Hey fribse,
not sure if you could solve it in the meantime but I had the same request as I was trying to make a little display for my dad that shows the temperature status for a boiler. My not-so-elegant workaround was as follows:

I defined my colours in the Display segment (see below as “auto temp”) and made the R G B values sensors. These are then connected to my MQTT Broker and get injected via Node Red.

display:
  - platform: ssd1351_spi
    model: "SSD1351 128x128"
    reset_pin: 16
    cs_pin: 13
    dc_pin: 19
    lambda: |-
      auto temp = Color(id(temp_red).state, id(temp_green).state, id(temp_blue).state);
      it.filled_circle(it.get_width() / 2, 12, 45, temp);

The sensors are simple MQTT_subscribe elements:

sensor:
  - platform: mqtt_subscribe
    name: "Temp Red"
    id: temp_red
    topic: studio/boiler/display/red
  - platform: mqtt_subscribe
    name: "Temp Green"
    id: temp_green
    topic: studio/boiler/display/green
  - platform: mqtt_subscribe
    name: "Temp Blue"
    id: temp_blue
    topic: studio/boiler/display/blue

I still feel there must be a better way to do this… but hey, for now this works!

Cheers,
Seb

Trying to get the same thing done. for some reason the compiler is not liking
auto temp = Color(id(temp_red).state, id(temp_green).state, id(temp_blue).state);
Ideally, I would like to define some colors, I only really need 3 or 4 colors. Define them like @fribse did above:

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

Then setup a color mqtt message to pick from one of them. Not sure if this is possible.

Hi @serimi89
I whish I had any experience with C++ coding, because this is so close.
I would like to be able to just set a color in HA (with a regular colorwheel), and then have it picked up in the it.print.
I tried different variations of this:

Color((id(rgbvalue).state).split(“,”)[0],(id(rgbvalue).state).split(“,”)[1],(id(rgbvalue).state).split(“,”)[2]);

But I can’t make it work :slight_smile: And it’s simply because of my lack of knowledge in C++ I guess.
I then thought about the Light MQTT platform.
If I could split up the RGB value there, into three different topics, then it would be great, and I could just use your example.
But how do I create a template that sends the three variables red, green and blue into different topics?
So far I’ve gotten to this:

- platform: mqtt
  command_topic: "sign/matrix1"
  red_template: '{{ value_json(Color[0:2] | int(base=16) }}'
  green_template: '{{ value_json(Color[2:4] | int(base=16) }}'
  blue_template: '{{ value_json(Color[4:6] | int(base=16) }}'

That will seperate the rgbvalue into seperate values.
Then I need it to send out the values as seperate topics.

Hi!

Did you try NeoPixelBus Light with matrix?
I not able to find decision how to change brightness.

No, haven’t tried that.

Great news here.
@ssieb has been a real gem here, and used a LOT of time on me, thankyou very very much, and he got everything working.

So now there are two settings that’s in HA.
A helper, in this case called
input_text.matrix1_scrolling_text
That holds the text to be shown on the matrix sign
And then the ESPHome code is going to make a single light that holds colour and brightness.
This is the code

substitutions:
  device_name: Matrix1
  espname: matrix1
  xscrollpadding: "8" # in pix
  device_description: "10.11.13.149 Matrix display that shows scrolling text published on MQTT"
  
esphome:
  name: '${espname}'
  comment: '${device_description}'
  platform: esp8266
  board: esp8285
  on_boot:
    - light.turn_off: matrixcolor

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  reboot_timeout: 60min
  manual_ip:
    static_ip: 10.11.13.149
    gateway: 10.11.13.1
    subnet: 255.255.255.0
  ap:
    ssid: "${device_name} Hotspot"
    password: !secret appw

logger:
  baud_rate: 0

api:
  password: !secret apipw

ota:
  password: !secret otapw

time:
  - platform: homeassistant
    id: homeassistant_time

sensor:
  - platform: wifi_signal
    name: '${device_name} wifi signal'
    update_interval: 60s
    accuracy_decimals: 0
  - platform: uptime
    name: '${device_name} uptime'
    unit_of_measurement: days
    update_interval: 300s
    accuracy_decimals: 1
    filters:
      - multiply: 0.000011574

text_sensor:
  - platform: version
    name: "${device_name} ESPHome Version"
  - platform: wifi_info
    ip_address:
      name: "${device_name} ip"
    ssid:
      name: "${device_name} ssid"
  - platform: homeassistant
    entity_id: input_text.matrix1_scrolling_text
    id: scrolltext

font:
  - id: tinyfont
    file: "DejaVuSans-Bold.ttf"
    size: 9
    glyphs: '♡ÆØÅæøå!"%()+,-_.:*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz'
    
light:
  - platform: neopixelbus
    type: GRB
    variant: WS2812X
    pin: GPIO2
    num_leds: 256
    id: matrix
    default_transition_length: 0s
    color_correct: [50%, 50%, 50%]
    internal: true
  - platform: rgb
    name: "Scrolling Sign"
    id: matrixcolor
    red: output_red
    green: output_green
    blue: output_blue
    on_turn_on:
      - switch.turn_on: matrixpower
      - light.turn_on: matrix
    on_turn_off:
      - switch.turn_off: matrixpower
      - light.turn_off: matrix

# Turns the relay for the LED's on / off, saves power by not having them supplied when the sign is off
switch:
  - platform: gpio
    pin: GPIO5
    id: matrixpower
    internal: true

# Used for extraction of colours from the RGB light, to be used in it.print
output:
  - platform: template
    id: output_red
    type: float
    write_action:
      lambda: ;
  - platform: template
    id: output_green
    type: float
    write_action:
      lambda: ;
  - platform: template
    id: output_blue
    type: float
    write_action:
      lambda: ;

display:
  - platform: addressable_light
    id: matrix_display
    addressable_light_id: matrix
    width: 32
    height: 8
    pixel_mapper: |-
      if (x % 2 == 0) {
        return (x * 8) + y;
      }
      return (x * 8) + (7 - y);
    rotation: 0°             # Which way is the text scrolled
    update_interval: 200ms   # Scroll speed
    lambda: |-
          static uint16_t xpos = 0;
          const char * text = id(scrolltext).state.c_str();
          int x_start, y_start;
          int width, height;
          
          it.get_text_bounds(0, 0, text, id(tinyfont), 
              TextAlign::TOP_LEFT, &x_start, &y_start, &width, &height); 

          auto values = id(matrixcolor).current_values;
          float brightness = values.get_brightness();

          Color color(values.get_red() * brightness * 255, values.get_green() * brightness * 255, values.get_blue() * brightness * 255);

          it.print(-(xpos % (width + $xscrollpadding)), -2, 
            id(tinyfont), color, 
            TextAlign::TOP_LEFT, text); 
          xpos++;

I can’t take ANY credit for this, the code is borrowed, stolen and given to me :laughing: