Trouble using a string variable with uart.write

I’m having difficulty getting a variable to pass into a service call on ESPHome. I have made a static service call that works without any issue, sending a string to UART.

api:
  services:
    - service: send_voice_queryall
      then:
        - uart.write:  "$<QD>\r\n"

Next I have adjusted the call to use variable serial_command. I have tried both string and string without success (along with days of other tinkering). I always get an error when attempting to install with this code.

api:
  services:
    - service: send_serial_command_raw
      variables:
        serial_command: string
      then:
        - uart.write: !lambda 'return serial_command;'

and the error during install with string:

<unicode string>: In lambda function:
<unicode string>:35:14: error: could not convert 'serial_command' from 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} to 'std::vector<unsigned char>'

and with string:

<unicode string>: In lambda function:
<unicode string>:35:14: error: could not convert 'serial_command' from 'vector<std::__cxx11::basic_string<char>>' to 'vector<unsigned char>'

I have played with this for two days, and while I suspect this is a simple issue, I haven’t been able to google hard enough to solve it. I’ll add, the end goal here is simply to pass in a string during the service call similar to the static one shown in the first example. Any suggestions would be appreciated.

This write action may help you get closer. I think I was initially using a service call and switched to importing a text sensor (which I could populate from HA for testing).

I can’t recall if I had to do the special character handling when I was using it as a service.

The data type conversions may be of some help.

button:
#Run HA free text command
  - platform: template
    name: "Run HA Text Command"
    icon: mdi:format-text-rotation-none
    id: ha_scorbot_text_command
    on_press:
      - logger.log: Executing HA Free Text Scorbot Command
      - uart.write:
          id: uart_r
          #Need to handle \r conversion. Or '1M+30\r2M+20\r3M+100\r' ends up like '1M+30\\r2M+20\\r3M+100\\r'
          #Thanks @ssieb : https://discord.com/channels/429907082951524364/1091572034741489684/1091613097380298795
          data: !lambda |-
              std::string str = id(ha_scobot_text_command).state;
              std::size_t pos;
              while ((pos = str.find("\\r")) != std::string::npos) 
                {
                    str.replace(pos, 2, "\r");
                }
              return std::vector<uint8_t>(str.begin(), str.end()); 

I have this to read and write in my esphome yaml.

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

uart:
  - id: UART1
    baud_rate: 9600
    data_bits: 8
    stop_bits: 1
    parity: NONE
    rx_buffer_size: 512
    tx_pin:
      number: 17
      inverted: true
    rx_pin:
      number: 18
      inverted: true
    debug:
      direction: RX
      dummy_receiver: true
      after:
        bytes: 4
#        delimiter: "\r"
      sequence:
        - lambda: |-
            UARTDebug::log_string(direction, bytes);
            std::string str(bytes.begin(), bytes.end());
            id(rawString).publish_state(str.c_str());

text_sensor:
  - platform: template
    name: "Response"
    icon: mdi:audio-video
    id: "rawString"

The read is set to 4 bytes, but can be switched to a char or string instead by using the commented string line, so \n or \n\r and other versions can be used too.

Note that my rx and tx pins are inverted, which is required for some of the protocols, like RS232.
If you put a serial terminal on the tx pin and get gibberish, then try to change the inverted pins.

2 Likes

The lambda was the magic for me. Getting things in expected forms was where I was stuck and this small piece resolved what I was stuck with. MANY thanks!!