Uart send text from helper

This sends “input_text.test” instead of “Hello,world” ?

text_sensor:
  - platform: homeassistant
    id: text_tx
    entity_id: input_text.text_tx  # ha helper
    on_value:  # On Change 
      then:
        - uart.write: input_text.text_tx

and this errors out

text_sensor:
  - platform: homeassistant
    id: text_tx
    entity_id: input_text.text_tx  # ha helper
    on_value:  # On Change 
      then:
        - uart.write: !lambda  
                         return id(text_tx).state;

With what error?

Compiling /data/office-8x8/.pioenvs/office-8x8/src/main.cpp.o
/config/esphome/office-8x8.yaml: In lambda function:
/config/esphome/office-8x8.yaml:82:23: error: could not convert ‘text_tx->esphome::homeassistant::HomeassistantTextSensor::.esphome::text_sensor::TextSensor::state’ from ‘std::string {aka std::basic_string}’ to ‘std::vector’
- uart.write: !lambda
^
/config/esphome/office-8x8.yaml:83:3: warning: control reaches end of non-void function [-Wreturn-type]
return id(text_tx).state;
^
*** [/data/office-8x8/.pioenvs/office-8x8/src/main.cpp.o] Error 1
========================== [FAILED] Took 3.81 seconds ==========================

See if this helps:

So in your case think it goes like this:

  on_value:
    - uart.write: !lambda  
                      char buf[128];
                      sprintf(buf, id(text_tx).state);
                      std::string s = buf;
                      return std::vector<unsigned char>( s.begin(), s.end() );

I bet that would work if I didn’t get this error.

Compiling /data/office-8x8/.pioenvs/office-8x8/src/main.cpp.o
/config/esphome/office-8x8.yaml: In lambda function:
/config/esphome/office-8x8.yaml:82:49: error: cannot convert ‘std::string {aka std::basic_string}’ to ‘const char*’ for argument ‘2’ to ‘int sprintf(char*, const char*, …)’
- uart.write: !lambda
^
*** [/data/office-8x8/.pioenvs/office-8x8/src/main.cpp.o] Error 1
========================== [FAILED] Took 3.59 seconds ==========================

Did I space something wrong?

text_sensor:
  - platform: homeassistant
    name: "text_tx"
    id: text_tx
    entity_id: input_text.text_tx  # ha helper
    on_value:  # On Change 
      then:
        - uart.write: !lambda
                          char buf[128];
                          sprintf(buf, id(text_tx).state);
                          std::string s = buf;
                          return std::vector<unsigned char>( s.begin(), s.end() );

tom_l did this not give you the same error?

No, because I’m not using it.

I use a custom Home Assistant Service in ESPHome rather than a text sensor:

api:
  services:
    - service: write
      variables:
        command: string
      then:
        - uart.write:
            id: projector
            data: !lambda |-
              std::string str = command;
              std::vector<uint8_t> vec(str.begin(), str.end());
              return vec;

uart:
  tx_pin: GPIO12
  rx_pin: GPIO32
  baud_rate: 9600
  id: projector

To use it in Home Assistant:

  - service: esphome.projector_uart_write
    data:
      command: "KEY 20\r\n"

'projector_uart` is the ESP device name.

I’m giving what you got a try. Question? what is - service: under or what yaml file? in homeassistant: ?

You call services using automation actions or script sequences. Or for testing you can use Developer Tools / Services.

Here’s one of my scripts:

script:
  projector_menu:
    sequence:
    - service: esphome.projector_uart_write
      data:
        command: "KEY 03\r\n"

Was just going to reply that it worked and thank you !!!

In an Automation

- id: '1645952179094'
  alias: Test uart service call
  description: ''
  trigger:
  - platform: state
    entity_id: input_boolean.test_toggle
    from: 'off'
    to: 'on'
  condition: []
  action:
  - service: esphome.office_8x8_write
    data:
      command: S000,O,red,off,020

In the ESPHome

# Enable Home Assistant API
api:
  services:
    - service: write
      variables:
        command: string
      then:
        - uart.write:
            id: uart_bus
            data: !lambda |-
              std::string str = command;
              std::vector<uint8_t> vec(str.begin(), str.end());
              return vec;


uart:
  id: uart_bus
  tx_pin:  
    number: D0
    #inverted: true
  rx_pin:
    number: D1
    #inverted: true    
  baud_rate: 19200 #9600

  

Thank you again :slight_smile:

1 Like

@Joe3 and/or @tom_l , are you able to confirm if you’ve gotten this working via an input_text (or other method for setting via the front end)?

eg like this:

service: esphome.scorbot_quinled_write
data:
  command: "{{states.input_text.scorbot_command.state}}"

I’m trying to get some help over on Discord with issues with escape sequences. Cheers.

Edit: Solved by @ssieb on Discord. Thanks!

\r was being stuborn…

api:
  services:
    - service: write
      variables:
        command: string
      then:
        - uart.write:
            id: uart_r
            data: !lambda |-
              std::size_t pos;
              std::string str = command;
              while ((pos = str.find("\\r")) != std::string::npos)
                str.replace(pos, 2, "\r");
              std::vector<uint8_t> vec(str.begin(), str.end());
              return vec;   

Or another way I prefer:

In HA:

input_text:
  scorbot_command:
    name: Scorbot Command
    initial: "1M+100\r2M+100\r3M+100\r"

image

In Esphome:

text_sensor:
  - platform: homeassistant
    name: "HA Scorbot Command"
    entity_id: input_text.scorbot_command
    id: ha_scobot_text_command
    internal: false

button:
  - platform: template
    name: "Execute HA Command"
    id: ha_scorbot_command
    on_press:
      - logger.log: Execute HA Command 1
      - uart.write:
          id: uart_r
          data: !lambda |-
            std::size_t pos;
            std::string str = id(ha_scobot_text_command).state;
            while ((pos = str.find("\\r")) != std::string::npos)
              str.replace(pos, 2, "\r");
            std::vector<uint8_t> vec(str.begin(), str.end());
            return vec;   
      

I found a way to write a hex string from a template text component to uart. I use the function parse_hex from the ESPHome helpers class.

text:
  - platform: template
    name: "Template text"
    id: templ_text
    optimistic: true
    min_length: 0
    max_length: 100
    mode: text
    initial_value: "f1f10100017e"

button:
  - platform: template
    name: "Template button"
    on_press:
      - uart.write: !lambda |-
          auto str = id(templ_text).state;
          std::vector<uint8_t> out;
          auto ret = parse_hex(str, out, str.length() / 2);
          return out;

I could create a button in esphome for each command I have for my projector rather than creating a script in home assistant to send the data for each command. Then I would just use the button press service for each command. Same amount of entities, (buttons instead of scripts) but a little less complicated.

However there is other logic that needs too be incorporated to prevent button collisions while waiting for the projector to process the command so I doubt I’ll bother.

projector_menu:
  sequence:
  - condition: state
    entity_id: input_boolean.uart_busy # collision prevention
    state: 'off'
  - service: input_boolean.turn_on
    entity_id: input_boolean.uart_busy
  - service: esphome.projector_uart_write
    data:
      command: "KEY 03\r\n"
  - delay: 1
  - service: input_boolean.turn_off
    entity_id: input_boolean.uart_busy

The delay can be different for each command (40 sec for power_on!).