ee:2E:00:40:DE …
offset 1 packet is 0x00
Based on your packet values, since the value at offset 1 is 0x00, false is correct
ee:2E:00:40:DE …
offset 1 packet is 0x00
Based on your packet values, since the value at offset 1 is 0x00, false is correct
Hi @eigger
Thank you for your work !
I try to use your external component in order to drive my projector.
I can switch it on/off, but i have an “Timeout error” when I read the status :
[09:21:39][D][uartex:205]: Write array-> 071400050034000011005E(11)
[09:21:39][D][uartex:224]: Flush.
[09:21:39][D][text_sensor:064]: 'Log': Sending state '[W]071400050034000011005E(11)'
[09:21:39][D][uart_debug:114]: >>> 07:14:00:05:00:34:00:00:11:00:5E
[09:21:39][W][uartex:334]: [Read] Timeout error: 051400030000000017(9)
[09:21:39][D][text_sensor:064]: 'Log': Sending state '[R]051400030000000017(9)'
[09:21:39][D][uart_debug:114]: <<< 05:14:00:03:00:00:00:00:17
I don’t realy understand the timeout setting and error, could you help me ?
Regards,
Nicolas.
If the RX footer or RX checksum is missing, a timeout error will occur. This is because, without the RX footer or RX checksum, there is no criterion for determining packet completion.
Even if a timeout error occurs, the packet is processed normally. Does your packet have no termination rule?
rx_checksum: !lambda |-
uint8_t crc = 0;
for (int i = 0; i < len; i++)
{
crc += data[i];
}
crc -= data[0];
return crc;
Thank you for your answer and the explanation,
I now understand.
And, no, I don’t have termination rules.
In the doc, I have 3 possible states :
OFF : Sequence : 0x05 0x14 0x00 0x03 0x00 0x00 0x00 0x00 0x17
ON : Sequence : 0x05 0x14 0x00 0x03 0x00 0x00 0x00 0x01 0x18
STB : Sequence : 0x03 0x14 0x00 0x00 0x00 0x14
I will try to write a checksum.
Hi Thanks for this great looking component - it will really help. I am having some trouble understanding how to use it for the following situation.
I have to send this sequence of bytes “0xAA, 0xDD, 0x00, 0x06, 0x09, 0xD6” to a device (with no check sum) and then it returns 45 bytes of data in a format like this:
0xAA, 0xDD, a fixed header
0xXX, 0xXX, MSB then LSB of integer measurement value_1
0xYY, 0xYY, MSB then LSB of integer measurement value_2
0xZZ,0xZZ , MSB then LSB of integer measurement value_3
and so on …
The device does not send any other data.
Can you give me an example of how to set your component up to do this. Thanks.
You can try like this
uartex:
rx_timeout: 100ms
tx_delay: 50ms
tx_timeout: 500ms
tx_retry_cnt: 3
rx_header: [0xAA, 0xDD]
# If the received data includes a checksum or footer character, add them.
# rx_checksum or rx_footer
sensor:
- platform: uartex
name: "XX Data"
state:
data: [0x00] # Read All
mask: [0x00]
state_number:
offset: 0
length: 2
precision: 0
update_interval: 10s
command_update:
data: [0xAA, 0xDD, 0x00, 0x06, 0x09, 0xD6]
- platform: uartex
name: "YY Data"
state:
data: [0x00] # Read All
mask: [0x00]
state_number:
offset: 2
length: 2
precision: 0
- platform: uartex
name: "ZZ Data"
state:
data: [0x00] # Read All
mask: [0x00]
state_number:
offset: 4
length: 2
precision: 0
Thanks so much for your help!
I get this in the logger:
…
[09:49:39][D][uartex:205]: Write array-> AADD000609D6(6)
[09:49:39][D][uartex:224]: Flush.
[09:49:39][D][text_sensor:064]: ‘Log’: Sending state ‘[W]AADD000609D6(6)’
[09:49:39][W][component:237]: Component uartex took a long time for an operation (113 ms).
[09:49:39][W][component:238]: Components should block for at most 30 ms.
[09:49:39][W][component:237]: Component uartex took a long time for an operation (100 ms).
[09:49:39][W][component:238]: Components should block for at most 30 ms.
[09:49:39][D][uart_debug:114]: >>> AA:DD:00:06:09:D6
[09:49:39][W][uartex:334]: [Read] Timeout error: AADD062F900166000000020000000001260126012A018501850185000000000000000E2212017600800080803280EB(47)
[09:49:39][D][text_sensor:064]: ‘Log’: Sending state ‘[R]AADD062F900166000000020000000001260126012A018501850185000000000000000E2212017600800080803280EB(47)’
[09:49:39][W][component:237]: Component uartex took a long time for an operation (132 ms).
[09:49:39][W][component:238]: Components should block for at most 30 ms.
[09:49:39][D][uart_debug:114]: <<< AA:DD:06:2F:90:01:66:00:00:00:02:00:00:00:00:01:26:01:26:01:2A:01:85:01:85:01:85:00:00:00:00:00:00:00:0E:22:12:01:76:00:80:00:80:80:32:80:EB
[09:49:39][W][component:237]: Component uartex took a long time for an operation (100 ms).
[09:49:39][W][component:238]: Components should block for at most 30 ms.
…
And all the sensors are “Undefined”
I am not clear how to debug this.
Can you like to upload the firmware again? The issue with the sensor values not updating has been fixed. Previously, only the lambda method allowed sensor values to be updated.
Does the received data not have an end-of-message character or a checksum?
Yes refreshing from GitHub has fixed the sensor values.
I am still getting lots of:
[11:18:08][W][component:237]: Component uartex took a long time for an operation (101 ms).
[11:18:08][W][component:238]: Components should block for at most 30 ms.
I have a checksum at the end of the block of data.
I am not clear how your component works, it might help me track down the problem. How does your component identify when all of the block of data has been received?
My data is a fixed length, has no end-of-message character but has a checksum. The checksum is calculated by summing all of the bytes (uint32_t) in the message and masking the result to fit in one byte (& 0xFF)
If there is no end-of-message character or checksum, the received data is used after waiting for the rx_timeout duration. This causes a 100ms delay.
Does your checksum include the header and sum all values together?
Yes it includes the header and goes like this:
uint8_t i = 0;
uint8_t command[46] = {header and data ... ,0x00}; # header and data is 45 bytes long
uint32_t cs = 0;
for (i = 0; i < 45; I++)
{
cs += command[I];
}
command[46] = cs & 0xFF;
So (I am guessing a bit) it this how your component works: it keeps computing the check sum then when it gets a match in the data stream or an end-of-message character it will then use the data? Otherwise it has to wait for the time out. Is that correct?
Thanks.
Yes, that’s exactly how it works. You can add the add-checksum as rx_checksum: add, but something doesn’t add up when calculating the packet. When you sum all the values from AADD…3280 and mask them with 0xFF, you get 0xAB, yet the actual packet shows 0xEB.
OK so I added rx_checksum: add and now I get some data. (Sorry I sent you the wrong log file before - this one is correct - I checked the CRC at the end and it adds up correctly)
But I am still getting lots of “took too long” warnings.
[15:33:48][VV][scheduler:226]: Running interval 'update' with interval=10000 last_execution=7081 (now=17178)
[15:33:48][D][uartex:205]: Write array-> CAFD000609D6(6)
[15:33:48][VV][uart.arduino_esp32:194]: Flushing...
[15:33:48][D][uartex:224]: Flush.
[15:33:48][V][text_sensor:013]: 'Log': Received new state [W]CAFD000609D6(6)
[15:33:48][D][text_sensor:064]: 'Log': Sending state '[W]CAFD000609D6(6)'
[15:33:48][VV][api.service:174]: send_text_sensor_state_response: TextSensorStateResponse {
key: 545371381
state: '[W]CAFD000609D6(6)'
missing_state: NO
}
[15:33:48][W][component:237]: Component uartex took a long time for an operation (138 ms).
[15:33:48][W][component:238]: Components should block for at most 30 ms.
[15:33:48][W][component:237]: Component uartex took a long time for an operation (101 ms).
[15:33:48][W][component:238]: Components should block for at most 30 ms.
[15:33:48][D][uart_debug:114]: >>> CA:FD:00:06:09:D6
[15:33:48][V][text_sensor:013]: 'Log': Received new state [R]CAFD062F900168000000030000000001270127012A01850185018500000000000000012A2B02BE00000000003280CD(47)
[15:33:48][D][text_sensor:064]: 'Log': Sending state '[R]CAFD062F900168000000030000000001270127012A01850185018500000000000000012A2B02BE00000000003280CD(47)'
[15:33:48][VV][api.service:174]: send_text_sensor_state_response: TextSensorStateResponse {
key: 545371381
state: '[R]CAFD062F900168000000030000000001270127012A01850185018500000000000000012A2B02BE00000000003280CD(47)'
missing_state: NO
}
[15:33:48][V][sensor:043]: 'Local Input Voltage': Received new state 360.000000
[15:33:48][VV][sensor.filter:014]: Filter(0x3ffb3a28)::input(360.000000)
[15:33:48][VV][sensor.filter:021]: Filter(0x3ffb3a28)::output(12.774194) -> SENSOR
[15:33:48][D][sensor:094]: 'Local Input Voltage': Sending state 12.77419 V with 2 decimals of accuracy
[15:33:48][VV][api.service:140]: send_sensor_state_response: SensorStateResponse {
key: 887182904
state: 12.7742
missing_state: NO
}
[15:33:48][V][sensor:043]: 'Local Output voltage': Received new state 3.000000
[15:33:48][VV][sensor.filter:014]: Filter(0x3ffb4998)::input(3.000000)
[15:33:48][VV][sensor.filter:021]: Filter(0x3ffb4998)::output(0.106452) -> SENSOR
[15:33:48][D][sensor:094]: 'Local Output voltage': Sending state 0.10645 V with 2 decimals of accuracy
[15:33:48][VV][api.service:140]: send_sensor_state_response: SensorStateResponse {
key: 4169800201
state: 0.106452
missing_state: NO
}
[15:33:48][VV][uartex:101]: Receive data-> CAFD062F900168000000030000000001270127012A01850185018500000000000000012A2B02BE00000000003280CD(47), Gap Time: 10057ms
[15:33:48][V][uartex:105]: Receive data-> CAFD062F900168000000030000000001270127012A01850185018500000000000000012A2B02BE00000000003280CD(47), Gap Time: 10079ms
[15:33:48][W][component:237]: Component uartex took a long time for an operation (166 ms).
[15:33:48][W][component:238]: Components should block for at most 30 ms.
[15:33:48][D][uart_debug:114]: <<< CA:FD:06:2F:90:01:68:00:00:00:03:00:00:00:00:01:27:01:27:01:2A:01:85:01:85:01:85:00:00:00:00:00:00:00:01:2A:2B:02:BE:00:00:00:00:00:32:80:CD
[15:33:48][VV][scheduler:226]: Running interval '' with interval=10000 last_execution=7635 (now=17665)
[15:33:48][W][component:237]: Component uartex took a long time for an operation (100 ms).
[15:33:48][W][component:238]: Components should block for at most 30 ms.
[15:33:49][W][component:237]: Component uartex took a long time for an operation (100 ms).
[15:33:49][W][component:238]: Components should block for at most 30 ms.
The warnings start from the very beginning of the boot up.
Try changing the timeout. rx_timeout: 10ms
Always wait for data to be received during the timeout period.
It seems that something was missing from the previous explanation. If the checksum matches during data reception, the data is used immediately. However, since the loop runs repeatedly, when no data is received, it continues to wait for the timeout period, causing a 100ms delay.
Thinking about it again, I should modify it so that the timeout is applied only when actual data has been received at least once.
Yes - I was thinking the very same thing! Data is only returned after I send a command so nothing should need to time out until after the first byte is received.
After the end is detected or it timed out the data should be consumed - but again no time out until the next start header is detected.
I’ve modified the timeout mechanism. It no longer waits when there is no received data.
Thanks - that has really tidied up the log!!
I am still not convinced the CRC check is working. I put this in for the CRC calculation:
uartex:
rx_timeout: 150ms
tx_delay: 10ms
tx_timeout: 10ms
tx_retry_cnt: 3
rx_header: [0xCA, 0xFD, 0x06, 0x2F, 0x90]
rx_checksum: !lambda |-
uint32_t crc = 0;
for (int i = 0; i < len; i++)
{
crc += data[i];
ESP_LOGD("CRC","%#d %#x",i,data[i]);
}
ESP_LOGD("CRC END","%#x",crc);
return crc & 0x00FF;
Just to see what was going on!
I need to include the header bytes in the CRC calculation - but you have removed them before they get to the lambda. I only get the bytes after the header. I guess the same is true when you do the calculation with rx_checksum: add.
Can I have them back ![]()
I imagine we need an option to choose what is included in the CRC calculation.
Something like this, as an alternative to rx_checksum: add
rx_checksum:
include_header: true
type: add
This looks like a really nice component!
One question, that maybe is so obvious that I don’t see it…?
I’m looking for a drop in replacement of the old uart_readline sensor.
Or in other words, I need a text_sensor that just contain the received data.
I’m using the old uart_readline sensor in some quite complex cases there I clear the sensor to be able to see if the same command was received again, and I can also write directly to the sensor to mimic received data.
It is surely possible to do with the uartex: component, but it would be nice if it’s possible to just replace the old one right off as a first step.
So, I like to replace this…
text_sensor:
- platform: custom
lambda: |-
auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));
App.register_component(my_custom_sensor);
return {my_custom_sensor};
text_sensors:
id: "uart_readline"
…with something like this - but which works. ![]()
text_sensor:
- platform: uartex
id: "uart_readline"
lambda: return x; # This doesn't work.
So, how do I create a text_sensor that just contain the received data?
Could you try this example?
uartex:
rx_timeout: 10ms
#rx_footer: "\r\n" #add a termination character if one is present.
version:
disabled: False
error:
disabled: False
log:
disabled: False
text_sensor:
- platform: uartex
name: "text"
lambda: |-
return std::string(reinterpret_cast<const char*>(data), len);
That looks good and quite close to what I was beginning to try, but your lambda is much more neat and compact. ![]()
I will try it out tonight.
One more thig:
Will a received rx_footer: trig the “end of block” and start processing the data, or will it wait until the rx_timeout has run out?
If the timer will continue, can the rx_checksum be used for something like this?
uartex:
# rx_footer: "\r"
rx_checksum: !lambda |-
return 13; // End of a block if CR (\r) is received