Easy UART Parsing ESPHome Component

Your packet is expected to be F2 F2 01 03 03 39 07 47 7E. Would you like to test it like this?

#  F2 F2 01 03 03 39 07 47 7E
#Offset   0  1  2  3  4
sensor:
  - platform: uartex
    name: Test Sensor
    state_number:
      offset: 2
      length: 2

Thank you very much for your feedback. Basically, the sensor seems to work straight away, even if I don’t yet understand how.

[18:47:59][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[18:47:59][D][uart_debug:176]: >>> 0,7,126
[18:47:59][D][sensor:094]: 'Position': Sending state 829.00000  with 0 decimals of accuracy
[18:47:59][D][uart_debug:176]: <<< 242,242,37,2,3,61,103,126,242
[18:47:59][D][uart_debug:176]: <<< 242,38,2,2,129,171,126,242,242
[18:47:59][D][sensor:094]: 'Position': Sending state 641.00000  with 0 decimals of accuracy
[18:47:59][D][uart_debug:176]: <<< 39,2,2,129,172,126,242,242,40
[18:47:59][D][uart_debug:176]: <<< 2,0,0,42,126,242,242,1,3
[18:47:59][D][sensor:094]: 'Position': Sending state 1284.00000  with 0 decimals of accuracy
[18:47:59][D][uart_debug:176]: <<< 5,4,7,20,126

As you can see, the test sensor responds three times, although only the last result would be of interest to me. Can the first two hits be ignored?

It’s about making my height-adjustable desk smart using ESPHome and replacing the Bluetooth dongle supplied. I read out the control commands myself using the dongle. So unfortunately I can’t say anything about the protocol.

What I have noticed so far is that every command has to be sent twice to achieve a result.

Instead of 0, 7, 126 I would have expected 07 00 07, the part between F1F1 & 7E.

It doesn’t quite look like ASCII code, at least not every character makes sense (imho).

If you only want to use protocols in the format like
F2 F2 01 03 05 04 07 14 7E
F2 F2 01 03 03 39 07 47 7E
you can try the following approach.

#  F2 F2 01 03 03 39 07 47 7E
#  F2 F2 01 03 05 04 07 14 7E
#Offset   0  1  2  3  4
sensor:
  - platform: uartex
    name: "Position"
    state: [0x01, 0x03]
    state_number:
      offset: 2
      length: 2

Unfortunately, this does not (yet) work. The sensor no longer responds. Do you have any other ideas?

sensor:
  - platform: uartex
    name: "Position"
    state: [0x01, 0x03] 
    update_interval: 10s
    command_update:
      data: [0x07, 0x00, 0x07, 0x7E, 0xF1, 0xF1, 0x07, 0x00, 0x07]
    state_number:
      offset: 2
      length: 2
07:09:09][D][uart_debug:176]: >>> 241,241,7,0,7,126,241,241,7
[07:09:09][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[07:09:09][D][uart_debug:176]: >>> 0,7,126
[07:09:09][D][uart_debug:176]: <<< 242,242,37,2,3,61,103,126,242
[07:09:09][D][uart_debug:176]: <<< 242,38,2,2,129,171,126,242,242
[07:09:09][D][uart_debug:176]: <<< 39,2,2,129,172,126,242,242,40
[07:09:09][D][uart_debug:176]: <<< 2,0,0,42,126,242,242,1,3
[07:09:09][D][uart_debug:176]: <<< 5,4,7,20,126

Here again as HEX output with correct delimiter for the log.

[07:51:421 [D] [uart_debug: 114]: >>>

F1, F1,07,00,07,7E

[07:51:421 [D] [uart_debug: 1141: >>>

F1, F1,07,00,07,7E

[07:51:421 [D] [uartex:208]: Write array->

F1F10700077EF1F10700077E(12)

107:51:421 [D] [uart_debug: 114]: <<

F2, F2,25,02,03, 3D, 67,7E

107:51:421 [D] luart_debug: 1141: <<

F2, F2, 26,02, 02,81, AB, 7E

107:51:421 [D] [uart_debug: 114]: <<

F2, F2, 27,02,02,81, AC, 7E 107:51:421 [D] luart_debug: 114]: << F2, F2, 28,02,00,00, 2A, 7E

107:51:421 [D] [uart_debug: 114]: <<

F2, F2,01,03, 05, 04,07,14,7E

Try adding log and error sensors, and bump up the timeout.
Let me know the results for the log and error sensors.

uartex:
  rx_timeout: 100ms

  version:
    disabled: False
  error:
    disabled: False
  log:
    disabled: False

Basically, the state pattern seems to work. In between, I get a valid result back from the sensor. However, I cannot provoke this and cannot recognize any reason when it works and when it does not.

From feeling I would say after rebooting or flashing a new version the chance to get a result is higher.

[20:54:28][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[20:54:28][D][text_sensor:064]: 'Log': Sending state '[W]F1F10700077EF1F10700077E(12)'
[20:54:28][D][uart_debug:114]: <<< F2,F2,25,02,03,3D,67,7E
[20:54:28][D][uart_debug:114]: <<< F2,F2,26,02,02,81,AB,7E
[20:54:28][D][uart_debug:114]: <<< F2,F2,27,02,02,81,AC,7E
[20:54:28][D][text_sensor:064]: 'Log': Sending state '[R]F2F227020281AC7E(8)'
[20:54:28][D][uart_debug:114]: <<< F2,F2,28,02,00,00,2A,7E
[20:54:28][D][text_sensor:064]: 'Log': Sending state '[R]F2F2280200002A7E(8)'
[20:54:28][D][uart_debug:114]: <<< F2,F2,01,03,05,04,07,14,7E
[20:54:38][D][uart_debug:114]: >>> F1,F1,07,00,07,7E
[20:54:38][D][uart_debug:114]: >>> F1,F1,07,00,07,7E
[20:54:38][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[20:54:38][D][text_sensor:064]: 'Log': Sending state '[W]F1F10700077EF1F10700077E(12)'
[20:54:38][D][uart_debug:114]: <<< F2,F2,25,02,03,3D,67,7E
[20:54:38][D][uart_debug:114]: <<< F2,F2,26,02,02,81,AB,7E
[20:54:38][D][uart_debug:114]: <<< F2,F2,27,02,02,81,AC,7E
[20:54:38][D][text_sensor:064]: 'Log': Sending state '[R]F2F227020281AC7E(8)'
[20:54:38][D][uart_debug:114]: <<< F2,F2,28,02,00,00,2A,7E
[20:54:38][D][text_sensor:064]: 'Log': Sending state '[R]F2F2280200002A7E(8)'
[20:54:38][D][uart_debug:114]: <<< F2,F2,01,03,05,04,07,14,7E

Did the sensor with the error show any specific issues? Could you share the YAML configuration you are using? I’d like to try testing it under the same conditions.
Also, I’m wondering if you still get the same result after disabling the UART debug logging.

Many thanks for your efforts so far. I have not been able to find an error so far. Deactivating the UART debug has also had no effect. Here is the YAML file:

esphome:
  name: buero-schreibtisch
  friendly_name: Buero-Schreibtisch

esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxx"

ota:
  - platform: esphome
    password: "xxx"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Buero-Schreibtisch"
    password: "bqoVrbWYuiGv"

captive_portal:

uart:
  id: schreibtisch_uart
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600
  # debug:
  #     direction: BOTH
  #     dummy_receiver: true
  #     after:
  #       delimiter: [0x7E]
  #     sequence:     
  #       # - lambda: UARTDebug::log_int(direction, bytes, ',');
  #       - lambda: UARTDebug::log_hex(direction, bytes, ',');


button:
  - platform: template
    name: "Stehposition"
    on_press:
      - uart.write:
          id: schreibtisch_uart
          data: [0xF1, 0xF1, 0x1B, 0x02, 0x05, 0x05, 0x27, 0x7E, 0xF1, 0xF1, 0x1B, 0x02, 0x05, 0x05, 0x27, 0x7E]
  - platform: template
    name: "Sitzposition"
    on_press:
      - uart.write:
          id: schreibtisch_uart
          data: [0xF1, 0xF1, 0x1B, 0x02, 0x03, 0x39, 0x59, 0x7E, 0xF1, 0xF1, 0x1B, 0x02, 0x03, 0x39, 0x59, 0x7E]
  - platform: template
    name: "Hƶhe abfragen"
    on_press:
      - uart.write:
          id: schreibtisch_uart
          data: [0xF1, 0xF1, 0x07, 0x00, 0x07, 0x7E, 0xF1, 0xF1, 0x07, 0x00, 0x07, 0x7E]



external_components:
  - source: github://eigger/espcomponents@latest
    components: [ uartex ]
    refresh: always


uartex:
  rx_timeout: 2000ms
  tx_delay: 50ms
  tx_timeout: 500ms
  tx_retry_cnt: 3

  rx_header: [0xF2, 0xF2]
  rx_footer: [0x7E]
  # tx_header: [0xF1, 0xF1]
  # tx_footer: [0x7E]

  version:
    disabled: False
  error: 
    disabled: False
  log:
    disabled: False



sensor:
  - platform: uartex
    name: "Position"
    state: [0x01, 0x03] 
    update_interval: 10s
    command_update:
      data: [0xF1, 0xF1, 0x07, 0x00, 0x07, 0x7E, 0xF1, 0xF1, 0x07, 0x00, 0x07, 0x7E]
    state_number:
      offset: 2
      length: 2

When I checked, it seemed to be due to UART debug. If the dummy_receiver option in UART debug is enabled, the data that should be received by UARTEX is already taken by UART, making it difficult to receive the data properly.

This is the log when the dummy_receiver is disabled. The data is parsed correctly.

[10:44:16][D][uart_debug:114]: >>> F1,F1,07,00,07,7E
[10:44:16][D][uart_debug:114]: >>> F1,F1,07,00,07,7E
[10:44:16][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[10:44:16][D][text_sensor:064]: 'Log': Sending state '[W]F1F10700077EF1F10700077E(12)'
[10:44:16][D][uart_debug:114]: <<< F2,F2,25,02,03,3D,67,7E
[10:44:16][D][text_sensor:064]: 'Log': Sending state '[R]F2F22502033D677E(8)'
[10:44:16][D][uart_debug:114]: <<< F2,F2,26,02,02,81,AB,7E
[10:44:16][D][text_sensor:064]: 'Log': Sending state '[R]F2F226020281AB7E(8)'
[10:44:16][D][uart_debug:114]: <<< F2,F2,27,02,02,81,AC,7E
[10:44:16][D][text_sensor:064]: 'Log': Sending state '[R]F2F227020281AC7E(8)'
[10:44:16][D][uart_debug:114]: <<< F2,F2,28,02,00,00,2A,7E
[10:44:16][D][text_sensor:064]: 'Log': Sending state '[R]F2F2280200002A7E(8)'
[10:44:16][D][uart_debug:114]: <<< F2,F2,01,03,05,04,07,14,7E
[10:44:16][D][text_sensor:064]: 'Log': Sending state '[R]F2F20103050407147E(9)'

I have already observed this. If I then also comment out the state pattern in the sensor, I get a sensor value in every update interval.

[06:59:29][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[06:59:29][D][text_sensor:064]: 'Log': Sending state '[W]F1F10700077EF1F10700077E(12)'
[06:59:29][D][text_sensor:064]: 'Log': Sending state '[R]F2F22502033D677E(8)'
[06:59:29][D][text_sensor:064]: 'Log': Sending state '[R]F2F226020281AB7E(8)'
[06:59:29][D][text_sensor:064]: 'Log': Sending state '[R]F2F227020281AC7E(8)'
[06:59:29][D][text_sensor:064]: 'Log': Sending state '[R]F2F2280200002A7E(8)'
[06:59:29][D][text_sensor:064]: 'Log': Sending state '[R]F2F20103050307137E(9)'

[07:05:17][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[07:05:17][D][text_sensor:064]: 'Log': Sending state '[W]F1F10700077EF1F10700077E(12)'
[07:05:17][D][text_sensor:064]: 'Log': Sending state '[R]F2F22502033D677E(8)'
[07:05:17][D][sensor:094]: 'Position': Sending state 829.00000  with 0 decimals of accuracy
[07:05:17][D][text_sensor:064]: 'Log': Sending state '[R]F2F226020281AB7E(8)'
[07:05:17][D][sensor:094]: 'Position': Sending state 641.00000  with 0 decimals of accuracy
[07:05:17][D][text_sensor:064]: 'Log': Sending state '[R]F2F227020281AC7E(8)'
[07:05:17][D][text_sensor:064]: 'Log': Sending state '[R]F2F2280200002A7E(8)'
[07:05:17][D][sensor:094]: 'Position': Sending state 0.00000  with 0 decimals of accuracy
[07:05:17][D][text_sensor:064]: 'Log': Sending state '[R]F2F20103050307137E(9)'
[07:05:17][D][sensor:094]: 'Position': Sending state 1283.00000  with 0 decimals of accuracy

Not sure if this is exactly what you’re looking for, but if you apply the state pattern and disable dummy_receiver, you should be able to get the position value you want.

After booting the ESP, i.e. if no sensor value exists and the state pattern is active, the commands are sent but the return values are not evaluated.

[06:54:45][C][api:141]:   Address: buero-schreibtisch.local:6053
[06:54:45][C][api:143]:   Using noise encryption: YES
[06:54:49][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[06:54:50][D][esp32.preferences:114]: Saving 1 preferences to flash...
[06:54:50][D][esp32.preferences:143]: Saving 1 preferences to flash: 1 cached, 0 written, 0 failed
[06:54:59][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[06:55:09][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)

The situation is different if the state pattern is commented out. In this case, every return is interpreted. But perhaps I have made a mistake in the way the sensor works.

[06:57:55][C][api:141]:   Address: buero-schreibtisch.local:6053
[06:57:55][C][api:143]:   Using noise encryption: YES
[06:57:59][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[06:57:59][D][sensor:094]: 'Position': Sending state 829.00000  with 0 decimals of accuracy
[06:57:59][D][sensor:094]: 'Position': Sending state 641.00000  with 0 decimals of accuracy
[06:57:59][D][sensor:094]: 'Position': Sending state 1284.00000  with 0 decimals of accuracy

The command probably queries the table settings. Four results are returned, the last of which is the currently set height.

data: [0xF1, 0xF1, 0x07, 0x00, 0x07, 0x7E, 0xF1, 0xF1, 0x07, 0x00, 0x07, 0x7E]

If I move the table up or down, the height is displayed individually. The sensor responds to this return without any problems as I would expect.

If you only need the last value, try the following option.

uartex:
  rx_length: 9

I still don’t really understand why the state isn’t working.

I had already tried this, but it leads to the following output:

[09:11:50][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[09:11:50][W][component:239]: Component uartex took a long time for an operation (114 ms).
[09:11:50][W][component:240]: Components should block for at most 30 ms.

Are you testing while changing the position? If the value remains the same, even if the data is parsed, it won’t be updated or logged. To verify proper parsing, enable the log sensor and check the logs.
If there is no state pattern, the value is updated every time, so the log will continuously show changes. However, if a state pattern is set, only the position value is updated, and if there is no actual movement, no change will be recorded in the log. Please enable the state pattern and log sensor to check if the value updates correctly and parsing works according to position changes.
If the state pattern works correctly, you don’t need to use rx_length.

test log

[16:59:01][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[16:59:01][D][text_sensor:064]: 'Log': Sending state '[W]F1F10700077EF1F10700077E(12)'
[16:59:01][D][text_sensor:064]: 'Log': Sending state '[R]F2F22502033D677E(8)'
[16:59:01][D][text_sensor:064]: 'Log': Sending state '[R]F2F226020281AB7E(8)'
[16:59:01][D][text_sensor:064]: 'Log': Sending state '[R]F2F227020281AC7E(8)'
[16:59:01][D][text_sensor:064]: 'Log': Sending state '[R]F2F2280200002A7E(8)'
[16:59:01][D][text_sensor:064]: 'Log': Sending state '[R]F2F20103050807147E(9)'
[16:59:01][D][sensor:094]: 'Position': Sending state 1288.00000  with 0 decimals of accuracy
[16:59:11][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[16:59:11][D][text_sensor:064]: 'Log': Sending state '[W]F1F10700077EF1F10700077E(12)'
[16:59:11][D][text_sensor:064]: 'Log': Sending state '[R]F2F22502033D677E(8)'
[16:59:11][D][text_sensor:064]: 'Log': Sending state '[R]F2F226020281AB7E(8)'
[16:59:11][D][text_sensor:064]: 'Log': Sending state '[R]F2F227020281AC7E(8)'
[16:59:11][D][text_sensor:064]: 'Log': Sending state '[R]F2F2280200002A7E(8)'
[16:59:11][D][text_sensor:064]: 'Log': Sending state '[R]F2F20103050607147E(9)'
[16:59:11][D][sensor:094]: 'Position': Sending state 1286.00000  with 0 decimals of accuracy
[16:59:21][D][uartex:208]: Write array-> F1F10700077EF1F10700077E(12)
[16:59:21][D][text_sensor:064]: 'Log': Sending state '[W]F1F10700077EF1F10700077E(12)'
[16:59:21][D][text_sensor:064]: 'Log': Sending state '[R]F2F22502033D677E(8)'
[16:59:21][D][text_sensor:064]: 'Log': Sending state '[R]F2F226020281AB7E(8)'
[16:59:21][D][text_sensor:064]: 'Log': Sending state '[R]F2F227020281AC7E(8)'
[16:59:21][D][text_sensor:064]: 'Log': Sending state '[R]F2F2280200002A7E(8)'
[16:59:21][D][text_sensor:064]: 'Log': Sending state '[R]F2F20103050107147E(9)'
[16:59:21][D][sensor:094]: 'Position': Sending state 1281.00000  with 0 decimals of accuracy

Then this is probably the solution to the problem. I assumed that the sensor value is updated each time the appropriate byte structure is received. Thank you very much.

I’m glad the issue has been resolved. I understand it now as well.

Hi Eigger
Thank you for making an amazing component

I’m looking for some assistance.

Im currently trying to interface to a Vent Axia Sentinel Kinteic MVHR, and this component look like it is the one for the Job.

An example data packet it will send out is the folowing

{0x02, 0x00, 0x00, 0x08, 0x07, 0x15, 'N', 'o', 'r', 'm', 'a', 'l', ' ', 'A', 'i', 'r', 'f', 'l', 'o', 'w', ' ', ' ', 0x16, '3', '5', ' ', '%', ' ', ' ', 'A', 'u', 't', 'o', ' ', ' ', ' ', ' ', ' ', ' ', 0xF7, 0xD8}

or

02 00 00 0C 07 15 54 65 78 74 20 4D 65 73 73 61 67 65 20 4C 31 20 16 54 65 78 74 20 4D 65 73 73 61 67 65 20 4C 31 20 F5 31 

the last 2 bytes are the ckecksum, and can be calulated with
uint16_t crc = 0xFFFF
and then loop through every byte and subtract it from the CRC value.

2 Questions in this regard:
how do i setup the CRC in this component to output to 2 Bytes as the checksum? answer: rx_checksum2
How can I include the Header in the custom CRC calculations?

Edit: I can’t get the crc calculation to add to the expected value. Any ideas what im ding wrong? Expected CRC is 0xF7D8

  rx_checksum2: !lambda |-
    uint16_t crc = 0xFFFF - 0x02;
    for (int i = 0; i < len; i++)
    {
      crc -= data[i];
    }
    return { (uint8_t)(crc >> 8), (uint8_t)(crc & 0xFF) };

Message from the logs:
[D][text_sensor:064]: 'Log': Sending state '[R]0200000807154E6F726D616C20416972666C6F772020163335202520204175746F202020202020F7D8(41)'