Inovelli LED Strip (LZW45) Custom Effects Script

This allows you to program up to 4 custom transitions for the Inovelli LED Strip instead of using the pixel effects or the quick strip effects.

Here’s the script

lzw45_custom_effect:
  alias: LZW45 Custom Effect
  description: Sets the custom effects for the Inovelli LZW45 LED Strip
  mode: restart
  fields:
    service: 
      description:
        (required) The name of the service. 
          OpenZwave (Beta) -> 'ozw.set_config_parameter'
          OpenZwave (1.4) -> 'zwave.set_config_parameter'
          Zwave JS -> 'zwave_js.set_config_parameter'
      example: ozw.set_config_parameter
    lzw45: 
      description: (required) The entity_id for the lzw45 LED Strip.
      example: light.lzw45_light_strip_level
    colors:
      description: (required) A list of colors, (1 to 4 colors).  Color choices are off, 2700k, 4500k, 6500k, red, orange, yellow, yellow-green, green, spring-green, cyan, azure, blue, violet, magenta, and random.
      example: "[ 'red', 'orange', 'yellow', 'off' ]"
    effects:
      description: (required) A list of colors (1 to 4 effects).  Color choices are fade, fade-blend, flash, chase, and chase-blend.
      example: "[ 'fade', 'fade-blend', 'fade', 'chase' ]"
    brightness_pcts:
      description: (optional) A list of brightness percents, 0 - 99.  Defaults to 99 if omitted.
      example: "[ 99, 99, 99, 99 ]"
    duration_units:
      description: (required) The units of the duration.  Choices are 100ms, seconds, minutes, hours.
      example: 100ms
    durations:
      description: (required) A list of durations (1-60).
      example: "[ 10, 10, 10, 10 ]"
    finish_behavior:
      description: (optional) The behavior when the effect reaches the max number of iterations.  Choices are off, previous-color, last-color-in-program.  Default is previous-color.
      example: previous-color
    iterations:
      description: (optional) The number of times the custom effect repeats (1-254).  255 is forever.  Default is 255.
      example: 255
  variables:
    service: >
      {{ service | default('ozw.set_config_parameter') }}
    node_id: >
      {%- if lzw45 is not defined %}
        0
      {%- else %}
        {%- set node_id = state_attr(lzw45, 'node_id') %}
        {{ node_id if node_id else 0 }}
      {%- endif %}
    transitions: >
      {%- set ns = namespace(counts=[]) %}
      {%- for item in [ colors, effects, brightness_pcts, durations ] %}
        {%- set ns.counts = ns.counts + [ item | length ] %}
      {%- endfor %}
      {{ ns.counts | min }}
    levels: >
      {%- set levels = brightness_pcts | default([]) %}
      {%- if not levels %}
        {{ [ 99 ] * transitions }}
      {%- else %}
        {%- set ns = namespace(levels = []) %}
        {%- for i in range(transitions) %}
          {%- set pct = levels[i] | int %}
          {%- set pct = pct if pct >= 0 else 0 %}
          {%- set pct = pct if pct <= 99 else 99 %}
          {%- set ns.levels = ns.levels + [ pct ] %}
        {%- endfor %}
        {{ ns.levels }}
      {%- endif %}
    parameter22: >
      {%- macro byte(color, effect) %}
        {%- set colors = [
          'off',
          '2700k',
          '4500k',
          '6500k',
          'red',
          'orange',
          'yellow',
          'yellow green',
          'green',
          'spring green',
          'cyan',
          'azure',
          'blue',
          'violet',
          'magenta',
          'random'
        ] %}
        {% set effects = [
          'fade', 
          'fade-blend', 
          'flash', 
          'chase', 
          'chase-blend'
        ] %}
        {%- if color in colors and effect in effects %}
          {%- set ci = colors.index(color) %}
          {%- set ei = effects.index(effect) %}
          {{- '{0:05b}{1:03b}'.format(ci, ei) }}
        {%- else %}
          {{- '00000000' }}
        {%- endif %}
      {%- endmacro %}
      {%- set ns = namespace(bytes=[]) %}
      {%- for i in range(transitions) %}
        {%- set ns.bytes = ns.bytes + [ byte(colors[i], effects[i]) | int('', 2) * 2**(i * 8) ] %}
      {%- endfor %}
      {{ ns.bytes | sum }}
    parameter23: >
      {%- set ns = namespace(bytes=[]) %}
      {%- for i in range(transitions) %}
        {%- set ns.bytes = ns.bytes + [ '{0:08b}'.format(levels[i]) | int('', 2) * 2**(i * 8) ] %}
      {%- endfor %}
      {{ ns.bytes | sum }}
    parameter24: >
      {%- set ns = namespace(bytes=[]) %}
      {%- for i in range(transitions) %}
        {%- set duration = durations[i] | int %}
        {%- set duration = duration if duration >= 1 else 1 %}
        {%- set duration = duration if duration <= 60 else 60 %}
        {%- set ns.bytes = ns.bytes + [ '{0:08b}'.format(duration) | int('', 2) * 2**(i * 8) ] %}
      {%- endfor %}
      {{ ns.bytes | sum }}
    parameter30: >
      {%- set iterations = iterations | default(255) | int %}
      {%- set iterations = iterations if iterations >= 0 else 0 %}
      {%- set byte1 = iterations if iterations <= 255 else 255 %}
      {%- set behaviors = [ 'off', 'previous-color', 'last-color-in-program' ] %}
      {%- set units = ['100ms', 'seconds', 'minutes', 'hours'] %}
      {%- set byte2 = behaviors.index(behavior) if behavior in behaviors else 1 %}
      {%- set byte3 = units.index(duration_units) if duration_units in units else 0 %}
      {{ '{0:08b}{1:08b}{2:08b}'.format(byte3, byte2, byte1) | int('', 2) }}
  sequence:
  - condition: template
    value_template: "{{ node_id != 0 and transitions > 0 }}"
  - service: "{{ service }}"
    data:
      node_id: "{{ node_id }}"
      parameter: 22
      value: "{{ parameter22 }}"
  - service: "{{ service }}"
    data:
      node_id: "{{ node_id }}"
      parameter: 23
      value: "{{ parameter23 }}"
  - service: "{{ service }}"
    data:
      node_id: "{{ node_id }}"
      parameter: 24
      value: "{{ parameter24 }}"
  - service: "{{ service }}"
    data:
      node_id: "{{ node_id }}"
      parameter: 30
      value: "{{ parameter30 }}"

Feel free to ask questions about the script.

This is an example service call that blends red -> orange -> yellow -> orange every second indefinitely.

service: script.lzw45_custom_effect
data:
  service: ozw.set_config_parameter
  lzw45: light.lzw45_light_strip_level
  colors:
    - red
    - orange
    - yellow
    - orange
  effects:
    - fade-blend
    - fade-blend
    - fade-blend
    - fade-blend
  brightness_pcts:
    - 99
    - 99
    - 99
    - 99
  duration_units: 100ms
  durations:
    - 10
    - 10
    - 10
    - 10
  finish_behavior: previous-color
  iterations: 255
3 Likes

Hi! I just got my Inovelli LZW45 LED Strip today and am trying to give this script a try, but I have no idea what I am doing. I keep getting:

2021-09-23 18:46:30 ERROR (MainThread) [homeassistant.config] Invalid config for [script]: [service] is an invalid option for [script]. Check: script->service. (See /home/homeassistant/.homeassistant/configuration.yaml, line 15).

    14	group: !include groups.yaml
    15	automation: !include automations.yaml
    16	script: !include scripts.yaml
    17	scene: !include scenes.yaml

but line 15 is a reference to automations.yaml which is seemingly empty (contains []).
However, line 16 is a reference to scripts.yaml - which is where I put the zwave-js script and service from the original post.

I guess I just do not actually know where to put this second service part? or how to use it much less…

You must have put the word script inside scripts.yaml. You don’t need it, it’s already defined in configuration.yaml

1 Like

@petro using ZWave JS, i cant quite figure out why this script wont work for me, yet the other 2 are perfect when testing via Dev Tools>Services. has anything changed with the script since your most recent post? thanks.

1 Like