blueprint:
  name: "AWTRIX Nordpool"
  description: "Display Nordpool electricity prices on the Ulanzi Clock"
  domain: automation
  author: Kimmo
  input:
    awtrix:
      name: AWTRIX Device
      description: Select the Awtrix light device
      selector:
        device:
          integration: mqtt
          manufacturer: Blueforcer
          model: AWTRIX Light
          multiple: false
    nordpool:
      name: Nordpool sensor
      description: "Select a nordpool sensor that provides hourly electricity prices."
      selector:
        entity:
          filter:
          - domain:
            - sensor
          multiple: false
    hourly_attribute:
      name: Hourly attribute
      description: "Select an attribute in the above sensor containing the hourly prices in an array form."
      selector:
        text: {}
      default: today
    unit:
      name: Unit
      description: "Price unit to display."
      selector:
        text: {}
      default: c/kWh
    unit_multiplier:
      name: Multiplier
      description: "Multiplier to modify the raw price value. For example, use 100
        if the raw price value is in Eur and you want to display it in cents.
        Use 1 if you want the value to be unchanged."
      selector:
        number:
      default: 100
    color_matrix_json:
      name: Color Map
      description: "This will control how colors are mapped to a price range
        on the display. The color mapping is in JSON format."
      selector:
        text:
          multiline: true
      default: "{\n  \"0\": \"#00FF00\",\n  \"20\": \"#FFFF00\",\n  \"40\": \"#FF0000\"\n}"
    message_duration:
      name: Duration
      description: How long should the message remain on the screen (in seconds). *If
        you select `0` it will use the Global App Time*
      selector:
        number:
          min: 0.0
          max: 300.0
          unit_of_measurement: sec
          step: 1.0
          mode: slider
      default: 30
    icon:
      name: Icon
      description: "Enter the Icon Name or ID of the icon that you like to show."
      selector:
        text: {}
      default: 54077
mode: restart
variables:
  device_id: !input awtrix
  awtrix_light: "{{ iif( device_attr(device_id, 'name_by_user') != none, device_attr(device_id, 'name_by_user'), device_attr(device_id, 'name') ) }}"
  nordpool: !input nordpool
  hourly_attribute: !input hourly_attribute
  unit: !input unit
  unit_multiplier: !input unit_multiplier
  color_matrix_json: !input color_matrix_json
  message_duration: !input message_duration
  icon: !input icon
  nordpool_prices: '{{state_attr(nordpool,hourly_attribute)}}'
  current_price: '{{states(nordpool) | float}}'
  multiplied_price: '{{current_price | float * unit_multiplier }}'
  price_text: '{{ multiplied_price | round(1) ~ unit}}'
  color_dict: >-
    {% set b = color_matrix_json | from_json %}
    {%- set ns = namespace(tuples=[]) %}
    {%- for k,v in b | items -%}
      {%- set key = k|float -%}
      {%- set ns.tuples = ns.tuples + [(key,v)] %}
    {% endfor %}
    {{ dict.from_keys(ns.tuples) }}
  payload: |-
    {%- macro interpolate(dictionary, x) -%}
      {%- set x = x * unit_multiplier -%}
      {%- set sorted_keys = dictionary|dictsort -%}
      {%- set above = sorted_keys|selectattr('0', 'gt', x)|map(attribute='0')|list|first-%}
      {%- set below = sorted_keys|selectattr('0', 'lt', x)|map(attribute='0')|list|last -%}

      {#- Key matches x exactly -#}
      {%- if above is defined and dictionary[above] == x -%}
        {%- set value = dictionary[above] -%}
        {{ value }}
      {%- elif below is defined and dictionary[below] == x -%}
        {%- set value = dictionary[below]-%}
        {{ value }}

      {#- Interpolation between two values -#}
      {%- elif below is defined and above is defined -%}
        {%- set lower_value = dictionary[below] -%}
        {%- set upper_value = dictionary[above] -%}
        {%- set lower_rgb = lower_value[1:] -%}
        {%- set upper_rgb = upper_value[1:] -%}
        {%- set lower_r = lower_rgb[0:2]|int(base=16) -%}
        {%- set lower_g = lower_rgb[2:4]|int(base=16)-%}
        {%- set lower_b = lower_rgb[4:6]|int(base=16) -%}
        {%- set upper_r = upper_rgb[0:2]|int(base=16) -%}
        {%- set upper_g = upper_rgb[2:4]|int(base=16)-%}
        {%- set upper_b = upper_rgb[4:6]|int(base=16) -%}
        {%- set interpolation_factor = (x - below) / (above - below) -%}
        {%- set interpolated_r = ((1 - interpolation_factor) * lower_r + interpolation_factor * upper_r)|int -%}
        {%- set interpolated_g   = ((1 - interpolation_factor) * lower_g + interpolation_factor * upper_g)|int -%}
        {%- set interpolated_b = ((1 - interpolation_factor) * lower_b + interpolation_factor * upper_b)|int -%}
        {%- set interpolated_hex = '#' ~ '%02X' % interpolated_r ~ '%02X' % interpolated_g ~ '%02X' % interpolated_b -%}
        {{ interpolated_hex }}

      {#- Only below key available -#}
      {%- elif below is defined -%}
        {%- set value = dictionary[below] -%}
        {{ value }}

      {#- Only above key available -#}
      {%- elif above is defined -%}
        {%- set value = dictionary[above] -%}
        {{ value }}

      {#- No matching keys available -#}
      {%- else -%}\
        No matching key found.
      {%- endif -%}
    {%- endmacro -%}

    {#- Define a macro to draw out the price lines#}
    {%- macro draw_price_lines() %}
      {%- for hour in range(24) %}
      {"dp": [{{8+hour}},7,"{{interpolate(color_dict, nordpool_prices[hour]) }}"]}
      {%- if hour+1 != 24 %},{%endif%}
      {%- endfor %}
    {%- endmacro %}

    {"draw":[ {{draw_price_lines()}}
    ],
      "icon": '{{icon}}',
      "duration": '{{message_duration}}',
      "text": '{{price_text}}',
      "textCase": 2,
      "color": '{{interpolate(color_dict, current_price | float)}}',
      "lifetimeMode": 1
    }

trigger:
- platform: state
  entity_id: !input nordpool
  id: Changes
  enabled: true
condition: []
action:
  - service: mqtt.publish
    data:
      qos: 0
      retain: false
      topic: "{{awtrix_light}}/custom/nordpool"
      payload: '{{payload}}'