How to display this custom integration?

Hello everyone

I’m trying to make a custom integration for my HDMI matrix switcher. It’s an 8x8 so a lot of input and outputs.

The matrix has switching via TCP hex commands and the following code works.

switch:
  - platform: command_line
    switches:
      hdmi_in1_out6:
        command_on: echo -e "\xa5\x5b\x02\x03\x01\x00\x06\x00\x00\x00\x00\x00\xf4" | nc 192.168.0.3 8000
        friendly_name: Input 1 to Output 6
      hdmi_in2_out6:
        command_on: echo -e "\xa5\x5b\x02\x03\x02\x00\x06\x00\x00\x00\x00\x00\xf3" | nc 192.168.0.3 8000
        friendly_name: Input 2 to Output 6

My question is, there must be an easier way to write this in the config? It’s going to take me a while to put all the swtiches in manually unless there is a simple way to put them in?
The matrix has the following document.

Input 1 to Output 1 -\xa5\x5b\x02\x03\x01\x00\x01\x00\x00\x00\x00\x00\xf9
Input 1 to Output 2 -\xa5\x5b\x02\x03\x01\x00\x02\x00\x00\x00\x00\x00\xf8	
Input 1 to Output 3 -\xa5\x5b\x02\x03\x01\x00\x03\x00\x00\x00\x00\x00\xf7
Input 1 to Output 4 -\xa5\x5b\x02\x03\x01\x00\x04\x00\x00\x00\x00\x00\xf6
Input 1 to Output 5 -\xa5\x5b\x02\x03\x01\x00\x05\x00\x00\x00\x00\x00\xf5
Input 1 to Output 6 -\xa5\x5b\x02\x03\x01\x00\x06\x00\x00\x00\x00\x00\xf4     
Input 1 to Output 7 -\xa5\x5b\x02\x03\x01\x00\x07\x00\x00\x00\x00\x00\xf3
Input 1 to Output 8 -\xa5\x5b\x02\x03\x01\x00\x08\x00\x00\x00\x00\x00\xf2

This is just one output so you can see how big the final code would be.

What is the best way to go about this please?

Regards
Mathew

You might be able to template the command if you can figure out which of these bytes is the input and which is the output:

Input 1 to Output 1 -\xa5\x5b\x02\x03\x01\x00\x01\x00\x00\x00\x00\x00\xf9
Input 1 to Output 2 -\xa5\x5b\x02\x03\x01\x00\x02\x00\x00\x00\x00\x00\xf8	
Input 1 to Output 3 -\xa5\x5b\x02\x03\x01\x00\x03\x00\x00\x00\x00\x00\xf7
Input 1 to Output 4 -\xa5\x5b\x02\x03\x01\x00\x04\x00\x00\x00\x00\x00\xf6
Input 1 to Output 5 -\xa5\x5b\x02\x03\x01\x00\x05\x00\x00\x00\x00\x00\xf5
Input 1 to Output 6 -\xa5\x5b\x02\x03\x01\x00\x06\x00\x00\x00\x00\x00\xf4     
Input 1 to Output 7 -\xa5\x5b\x02\x03\x01\x00\x07\x00\x00\x00\x00\x00\xf3
Input 1 to Output 8 -\xa5\x5b\x02\x03\x01\x00\x08\x00\x00\x00\x00\x00\xf2
                                                ^                       ^
                                                |                       |
                                              input?                 10 - output?

Do you have an example of Input 2 to each output?

The template would look something like:

shell_command:
  matrix_switch: >
    echo -e {{ '\xa5\x5b\x02\x03\x01\x00\x0' ~ states('input_number.input')int(1) ~ '\x00\x00\x00\x00\x00\xf' ~ (10 - states('input_number.output')|int(8)) }} | nc 192.168.0.3 8000

For the frontend you would display the input numbers for input and output then a button that calls the shell command as the tap action.

This would also lend itself well to automation. Set the input numbers, call the shell command.

1 Like

Hi Tom

Thanks for your help.
Here is the coding for input 2. Ignore that it’s not formatted correctly yet, i have not had time to change it to the backslash version yet.

Input 2 to Output 1 - 0xa5 0x5b 0x02 0x03 0x02 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0xf8
Input 2 to Output 2 - 0xa5 0x5b 0x02 0x03 0x02 0x00 0x02 0x00 0x00 0x00 0x00 0x00 0xf7
Input 2 to Output 3 - 0xa5 0x5b 0x02 0x03 0x02 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0xf6
Input 2 to Output 4 - 0xa5 0x5b 0x02 0x03 0x02 0x00 0x04 0x00 0x00 0x00 0x00 0x00 0xf5
Input 2 to Output 5 - 0xa5 0x5b 0x02 0x03 0x02 0x00 0x05 0x00 0x00 0x00 0x00 0x00 0xf4
Input 2 to Output 6 - 0xa5 0x5b 0x02 0x03 0x02 0x00 0x06 0x00 0x00 0x00 0x00 0x00 0xf3
Input 2 to Output 7 - 0xa5 0x5b 0x02 0x03 0x02 0x00 0x07 0x00 0x00 0x00 0x00 0x00 0xf2
Input 2 to Output 8 - 0xa5 0x5b 0x02 0x03 0x02 0x00 0x08 0x00 0x00 0x00 0x00 0x00 0xf1

You are right that it seem the only two numbers change in the whole command. the middle 01-08 and the end f1-8

Thanks for the template, i will give that a go later.

Regarding the front end, It wouldn’t be used much as i plan to make use of this mainly in automation scripts but what card would you use for this or are you saying a complete custom one?

Cheers!

A core entities card with these entities:

input_number.input
input_number.output

And a button in the entities card that executes shell_command.matrix_switch as the tap action.

You would set the input number, set the output number then press the button to send the commad to the matrix switch

Yeah but now I have more data I see I Identified the wrong columns and there are three that change.

Input 1 to Output 1 -\xa5\x5b\x02\x03\x01\x00\x01\x00\x00\x00\x00\x00\xf9
Input 1 to Output 2 -\xa5\x5b\x02\x03\x01\x00\x02\x00\x00\x00\x00\x00\xf8	
Input 1 to Output 3 -\xa5\x5b\x02\x03\x01\x00\x03\x00\x00\x00\x00\x00\xf7
Input 1 to Output 4 -\xa5\x5b\x02\x03\x01\x00\x04\x00\x00\x00\x00\x00\xf6
Input 1 to Output 5 -\xa5\x5b\x02\x03\x01\x00\x05\x00\x00\x00\x00\x00\xf5
Input 1 to Output 6 -\xa5\x5b\x02\x03\x01\x00\x06\x00\x00\x00\x00\x00\xf4     
Input 1 to Output 7 -\xa5\x5b\x02\x03\x01\x00\x07\x00\x00\x00\x00\x00\xf3
Input 1 to Output 8 -\xa5\x5b\x02\x03\x01\x00\x08\x00\x00\x00\x00\x00\xf2
                                        ^       ^                       ^
                                        |       |                       |
                                    input       output                 see *below

* I’ll need to see at least another input set to decipher that last byte. Can you post the table for input 7?

I’m thinking it’s a pretty simple checksum but without one more set of data it’s hard to pin down for sure.

Don’t use it. It’s not quite right yet. Need more data.

1 Like

Hi Tom

Many thanks for your help, it’s much appreciated!
I’m starting to understand where you are going with this now.

Here is the data for input 7

Input 7 to Output 1 -\xa5\x5b\x02\x03\x07\x00\x01\x00\x00\x00\x00\x00\xf3
Input 7 to Output 2 -\xa5\x5b\x02\x03\x07\x00\x02\x00\x00\x00\x00\x00\xf2
Input 7 to Output 3 -\xa5\x5b\x02\x03\x07\x00\x03\x00\x00\x00\x00\x00\xf1
Input 7 to Output 4 -\xa5\x5b\x02\x03\x07\x00\x04\x00\x00\x00\x00\x00\xf0
Input 7 to Output 5 -\xa5\x5b\x02\x03\x07\x00\x05\x00\x00\x00\x00\x00\xef
Input 7 to Output 6 -\xa5\x5b\x02\x03\x07\x00\x06\x00\x00\x00\x00\x00\xee		
Input 7 to Output 7 -\xa5\x5b\x02\x03\x07\x00\x07\x00\x00\x00\x00\x00\xed
Input 7 to Output 8 -\xa5\x5b\x02\x03\x07\x00\x08\x00\x00\x00\x00\x00\xec[Processing: 4x4-8x8 2K4K IP stringst (HEX) 2.txt...]()

If you want to see the whole document, download the driver tool from this page and in the documents is a text file containing all the hex codes which might help. Software configuration tool for MHUB 2K and MHUB 4K (2014-2016) | HDANYWHERE (HDA) Worldwide Support Site

Cheers
Mathew

Put this in the developer tools template editor and change the value of the input and output in the first two lines:

{% set input = 3 %}
{% set output = 8 %}
{# only change the above two numbers, change nothing below #}

{% set cheksum = '\\x' ~ '%0x' % (0xfb - input - output) %}

{{ '\\xa5\\x5b\\x02\\x03\\x0' ~ input ~ '\\x00\\x0' ~ output ~ '\\x00\\x00\\x00\\x00\\x00' ~ cheksum }}

Confirm you are getting the expected resultant byte string for each input and output combination you try.

If it works then it’s a small step to add input numbers to this to allow automation and frontend control.

shell_command:
  matrix_switch: >
    {% set input = states('input_number.matrix_switch_input')|int(8) %}
    {% set output = states('input_number.matrix_switch_output')|int(8) %}
    {% set cheksum = '\\x' ~ '%0x' % (0xfb - input - output) %}
    echo -e {{ '\\xa5\\x5b\\x02\\x03\\x0' ~ input ~ '\\x00\\x0' ~ output ~ '\\x00\\x00\\x00\\x00\\x00' ~ cheksum }} | nc 192.168.0.3 8000

Note: I have set the default values to 8 in and 8 out if something goes wrong with the input numbers (unlikely). If for some reason you notice this does occur we could also add an if statement to skip sending the command, but I don’t think it is necessary. We could also add input validation to ensure the number is 1-8 when used in an automation. Again, as long as you are careful with your automations I don’t think it is necessary.

You have to create the input numbers as well, obviously:

input number:
  matrix_switch_input:
    name: "Matrix Switch Input"
    min: 1
    max: 8
    step: 1
    icon: "mdi:import"

  matrix_switch_output:
    name: "Matrix Switch Output"
    min: 1
    max: 8
    step: 1
    icon: "mdi:export"

Use it in a card:

type: entities
title: Matrix Switch
entities:
  - entity: input_number.matrix_switch_input
  - entity: input_number.matrix_switch_output
  - type: button
    icon: mdi:dots-grid
    name: Set input to output
    action_name: Execute
    tap_action:
      action: call-service
      confirmation:
        text: Are you sure you want to set the input and output?
      service: shell_command.matrix_switch

Use it in an automation by passing variables to a script:

Automation:

action:
  - service: script.set_matrix_switch
    data:
      input: 7  # you can template this if you wish but ensure the resultant number is 1-8
      output: 3 # you can template this if you wish but ensure the resultant number is 1-8

Script:

set_matrix_switch:
  sequence:
    - service: input_number.set_value
      target: 
        entity_id: input_number.matrix_switch_input
      data:
        value: "{{ input }}"
    - service: input_number.set_value
      target: 
        entity_id: input_number.matrix_switch_output
      data:
        value: "{{ output }}"
    - service: shell_command.matrix_switch
1 Like

In the template editor i checked a selection of the hex codes and they all seem to work fine.

I added the shell command along with the input number script into the configuration.ymal, however it would not save due to the input number: “Integration ‘input’ not found”.
I changed this to input_number and it saves ok.

I then added the code to the front end and tried a command. However it doesnt do anything and comes up with the following error.

Logger: homeassistant.components.shell_command
Source: helpers/template.py:411
Integration: Shell Command (documentation, issues)
First occurred: 14:32:59 (1 occurrences)
Last logged: 14:32:59

Error rendering command template: UndefinedError: 'input' is undefined
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 409, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 1842, in _render_with_context
    return template.render(**kwargs)
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.9/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
jinja2.exceptions.UndefinedError: 'input' is undefined

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 51, in async_service_handler
    rendered_args = args_compiled.async_render(
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 411, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: UndefinedError: 'input' is undefined

It’s very close!

Cheers
Mathew

Paste all the code you are using. Including the frontend card.

Also, did you create the input numbers?

By creating the input numbers i assume you mean putting that code in the configuration.yaml?

Here is the code i am using

shell_command:
  matrix_switch: >
    {% set input = states('input_number.matrix_switch_input')|int(8) %}
    {% set output = states('input_number.matrix_switch_output')|int(8) %}
    {% set cheksum = '\\x' ~ '%0x' % (0xfb - input - output) %}
    echo -e {{ '\\xa5\\x5b\\x02\\x03\\x0' ~ input ~ '\\x00\\x0' ~ output ~ '\\x00\\x00\\x00\\x00\\x00' ~ cheksum }} | nc 192.168.0.3 8000

input_number:
  matrix_switch_input:
    name: "Matrix Switch Input"
    min: 1
    max: 8
    step: 1
    icon: "mdi:import"

  matrix_switch_output:
    name: "Matrix Switch Output"
    min: 1
    max: 8
    step: 1
    icon: "mdi:export"

The front end card. It’s the same as yours.

type: entities
title: Matrix Switch
entities:
  - entity: input_number.matrix_switch_input
  - entity: input_number.matrix_switch_output
  - type: button
    icon: mdi:dots-grid
    name: Set input to output
    action_name: Execute
    tap_action:
      action: call-service
      confirmation:
        text: Are you sure you want to set the input and output?
      service: shell_command.matrix_switch

Delete this:

input_number:
  matrix_switch_input:
    name: "Matrix Switch Input"
    min: 1
    max: 8
    step: 1
    icon: "mdi:import"

  matrix_switch_output:
    name: "Matrix Switch Output"
    min: 1
    max: 8
    step: 1
    icon: "mdi:export"

And create the input number helpers from the GUI instead.

I have created the helpers via the GUI and get this error which i think is the same.

Logger: homeassistant.components.shell_command
Source: helpers/template.py:423
Integration: Shell Command (documentation, issues)
First occurred: 21:58:20 (1 occurrences)
Last logged: 21:58:20

Error rendering command template: UndefinedError: 'input' is undefined
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 421, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 1906, in _render_with_context
    return template.render(**kwargs)
  File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
jinja2.exceptions.UndefinedError: 'input' is undefined

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 51, in async_service_handler
    rendered_args = args_compiled.async_render(
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 423, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: UndefinedError: 'input' is undefined

Have i set this up correctly?

Try it like this:

shell_command:
  matrix_switch: >
    {% set input = states('input_number.matrix_switch_input')|int(8) %}
    {% set output = states('input_number.matrix_switch_output')|int(8) %}
    {% set cheksum = '\\x' ~ '%0x' % (0xfb - input - output) %}
    echo -e \\xa5\\x5b\\x02\\x03\\x0{{input}}\\x00\\x0{{output}}\\x00\\x00\\x00\\x00\\x00{{cheksum}} | nc 192.168.0.3 8000

Changed the configuration.yaml to that and same error i think.

Logger: homeassistant.components.shell_command
Source: helpers/template.py:423
Integration: Shell Command (documentation, issues)
First occurred: 19:31:33 (1 occurrences)
Last logged: 19:31:33

Error rendering command template: UndefinedError: 'input' is undefined
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 421, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 1906, in _render_with_context
    return template.render(**kwargs)
  File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
jinja2.exceptions.UndefinedError: 'input' is undefined

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 51, in async_service_handler
    rendered_args = args_compiled.async_render(
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 423, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: UndefinedError: 'input' is undefined

Might have to call in some help, I can’t see what I am doing wrong. This template renders fine in the template editor even without creating the input numbers (because it has defaults):

shell_command:
  matrix_switch: >
    {% set input = states('input_number.matrix_switch_input')|int(8) %}
    {% set output = states('input_number.matrix_switch_output')|int(8) %}
    {% set cheksum = '\\x' ~ '%0x' % (0xfb - input - output) %}
    echo -e \\xa5\\x5b\\x02\\x03\\x0{{input}}\\x00\\x0{{output}}\\x00\\x00\\x00\\x00\\x00{{cheksum}} | nc 192.168.0.3 8000

@petro , @123 , @rccoleman

You have a pipe in it, and shell_commands don’t like that.

When using templates, shell_command runs in a more secure environment which doesn’t allow any shell helpers like automatically expanding the home dir ~ or using pipe symbols to run multiple commands.

I recommend calling a shell script instead, where you can do whatever you want.

1 Like

That would just make the command not work when called though, rather than causing this error UndefinedError: 'input' is undefined ?

:man_shrugging: You could try

shell_command:
  matrix_switch: >
    {% set input = states('input_number.matrix_switch_input')|int(8) %}
    {% set output = states('input_number.matrix_switch_output')|int(8) %}
    {% set vs = 165, 91, 2, 3, input, 0, output, 0, 0, 0, 0, 0, 251 - input - output %}
    {{ 'echo -e ' ~ ('\\\\x%02x' * vs | count) % vs ~ ' | nc 192.168.0.3 8000' }}

Same error sadly

Logger: homeassistant.components.shell_command
Source: helpers/template.py:423
Integration: Shell Command (documentation, issues)
First occurred: 08:53:11 (1 occurrences)
Last logged: 08:53:11

Error rendering command template: UndefinedError: 'input' is undefined
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 421, in async_render
    render_result = _render_with_context(self.template, compiled, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 1906, in _render_with_context
    return template.render(**kwargs)
  File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<template>", line 1, in top-level template code
jinja2.exceptions.UndefinedError: 'input' is undefined

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/shell_command/__init__.py", line 51, in async_service_handler
    rendered_args = args_compiled.async_render(
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 423, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: UndefinedError: 'input' is undefined

Was the way i created the input numbers correct in my picture above? I just want to make sure it’s not me causing this issue.

I appreciate all the help everyone!

I did a bit of experimenting. It appears shell commands don’t support multiline templates.

This works:

matrix_switch: "echo -e \\xa5\\x5b\\x02\\x03\\x0{{states('input_number.matrix_switch_input')|int(8)}}\\x00\\x0{{states('input_number.matrix_switch_output')|int(8)}}\\x00\\x00\\x00\\x00\\x00{{'\\\\x' ~ '%0x' % (0xfb - states('input_number.matrix_switch_input')|int(8) - states('input_number.matrix_switch_output')|int(8))}} | nc 192.168.0.3 8000"

Any by “works” I mean it does not generate errors. Whether or not it actually controls the switch remains to be seen.

That does get rid of the error but sadly it does not switch anything :frowning: